# TLS using Caddy

We will use **Caddy** as a TLS/HTTPS reverse proxy in front of services like **CasaOS** or any other local web applications. Here’s how that works:

### 🔐 How Caddy Provides TLS

*   **Automatic HTTPS**: Caddy can automatically obtain and renew certificates from Let’s Encrypt or ZeroSSL for public domains.
    
*   **Local/internal services**: For apps that don’t have public DNS names (like CasaOS on your local LAB), Caddy can act as a **reverse proxy** and provide TLS for them.
    
*   **Local CA**: Caddy includes a built-in certificate authority for issuing certs to internal hostnames or IPs, so you can still get HTTPS even without a public domain.
    

Documentation used for this tutorial:

[caddyserver/caddy: Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS](https://github.com/caddyserver/caddy)

## Step 1 - Installing Caddy

CasaOS is running in Ubuntu 26.04 locally at `10.0.0.203:90`

![Caddy-1787757678951](https://cdn.hashnode.com/uploads/covers/6a2d385da5fd3fa75afcb460/be46e9df-9aee-46fe-a1e3-47ba457953c0.webp align="center")

SSH into the ubuntu server and install caddy:

```bash
sudo apt update
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo tee /etc/apt/trusted.gpg.d/caddy-stable.asc
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list
sudo apt update
sudo apt install caddy
```

## Step 2 - Create Caddyfile

This will host reverse proxy rules for CasaOS and the services running from it.

![Caddy for TLS-1787751933680](https://cdn.hashnode.com/uploads/covers/6a2d385da5fd3fa75afcb460/17c88ab2-4f94-4bf3-a08b-4ced76d362c8.webp align="center")

Added as extra entries so it looks like this:

![Caddy for TLS-1787752068447](https://cdn.hashnode.com/uploads/covers/6a2d385da5fd3fa75afcb460/36f3a187-c1e8-414f-97d2-6561b350ae47.webp align="center")

Notice there is a nginx service installed as a docker container aimed at port 80. This was a previous installation and the reason why CasaOS is running in port 90. By default, CasaOS was running in port 80.

When running Caddy in that configuration, I was getting an error when trying to run caddy using:

```bash
sudo systemctl start caddy
```

The error showed that the port 443 was being used by the previous nginx service. Removing the docker container freed the port and caddy service was able to start.

![Caddy for TLS-1787752329110](https://cdn.hashnode.com/uploads/covers/6a2d385da5fd3fa75afcb460/92649ccb-e2e3-4028-b1cf-3fcf6bc2a196.webp align="center")

## Step 3 - DNS Configuration

So that the client machine can resolve to the `casaos.local` that we configured in the Caddyfile, we need to edit the host file.

*   `/etc/hosts` (Linux/macOS)
    
*   `C:\Windows\System32\drivers\etc\hosts` (Windows)
    

> \[!tip\] Editing on Windows To edit the host file in Windows, just open Notepad as Admin and navigate to the file location. Edit and then save it.

```text
10.0.0.203   casaos.local
```

## Step 4 - Certificate Authority Configuration

Certificate in the Ubuntu machine:

```bash
sudo cat /var/lib/caddy/.local/share/caddy/pki/authorities/local/root.crt > ~/caddy-root.crt
```

The certificate needs to be exported into the client that is used to access CasaOS.  
The easiest way is to navigate into the directory via the CasaOS GUI and download it from there.

![Caddy for TLS-1787752702614](https://cdn.hashnode.com/uploads/covers/6a2d385da5fd3fa75afcb460/4bc52489-2c87-4f85-ac71-79ebacd1393f.webp align="center")

Open `certmgr.msc`:

1.  In the left pane, expand **Trusted Root Certification Authorities → Certificates**.
    
2.  Right-click **Certificates → All Tasks → Import**.
    
3.  Browse to the `caddy-root.crt` file you copied.
    
4.  Complete the wizard, making sure it goes into **Trusted Root Certification Authorities**.
    

Reload Caddy after adding any extra entries in the host file:

```bash
sudo systemctl reload caddy
```

You can now navigate from your client to `https://casaos.local`.

If you still see warnings like this one:

![Caddy for TLS-1787756055573](https://cdn.hashnode.com/uploads/covers/6a2d385da5fd3fa75afcb460/86e160c6-4ea0-4853-8176-4cd171ce2752.webp align="center")

Closing and reopening the web browser should fix it:

![Caddy for TLS-1787756092155](https://cdn.hashnode.com/uploads/covers/6a2d385da5fd3fa75afcb460/7374aa0e-291a-4858-99d9-b9deec065279.webp align="center")

Extra services will now work correctly. These are examples of services that require HTTPS in order to run locally:

![Caddy for TLS-1787757341128](https://cdn.hashnode.com/uploads/covers/6a2d385da5fd3fa75afcb460/2038f76c-b07d-4791-97e6-85195370f94a.webp align="center")

![Caddy for TLS-1787757353526](https://cdn.hashnode.com/uploads/covers/6a2d385da5fd3fa75afcb460/b3fb3f62-bbf2-40ac-b392-34ec23c9aa5e.webp align="center")

![Caddy for TLS-1787757375747](https://cdn.hashnode.com/uploads/covers/6a2d385da5fd3fa75afcb460/4ae0f1ff-0684-44ef-8541-d43b5268815d.webp align="center")

### **Note:**

#### DNS and CA configuration for linux machine

Step 1 - Host file configuration

Open the hosts file
```
sudo nano /etc/hosts
```

Add entries for the services required to have TLS
```
10.0.0.203   casaos.local
10.0.0.203   vaultwarden.local
10.0.0.203   actual.local
10.0.0.203   karakeep.local
10.0.0.203   nginx.local
```

Step 2 - Root Certificate

Copy the cert file into the systems trust store:
```
sudo cp ~/caddy-root.crt /etc/pki/ca-trust/source/anchors/
```

Update the trust db
```
sudo update-ca-trust extract
```

Step 3 - Restart browser to test

Visit your casaOS server
```
https://casaos.local
```

![Caddy-1787980665952](https://cdn.hashnode.com/uploads/covers/6a2d385da5fd3fa75afcb460/8c188af7-66e3-47dd-ac90-f03b5f2d3089.webp)


