Back to All Lab Write-ups
HOMELAB SECURITY & PKI

Caddy as a TLS / HTTPS Reverse Proxy for Local Services

Implementing automatic TLS certificates, internal Certificate Authorities (CA), and DNS overrides for internal home lab services like CasaOS.

HomeLab Knowledge Base 7 min read Reverse Proxy, TLS, PKI, Linux

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 network), Caddy can act as a reverse proxy and provide TLS for them.
  • Local CA: Caddy includes a built-in Certificate Authority (CA) for issuing certificates to internal hostnames or IPs, so you still get HTTPS even without a public domain.

Step 1 – Installing Caddy

In this environment, CasaOS is running on Ubuntu 24.04/26.04 locally at 10.0.0.203:90.

CasaOS Dashboard on Port 90
Figure 1: CasaOS local web interface

SSH into the Ubuntu server and install Caddy from the official repository:

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
Installing Caddy on Ubuntu Server
Figure 2: Caddy installation package manager output

Step 2 – Create Caddyfile

The Caddyfile will host reverse proxy rules for CasaOS and any auxiliary containerized services running on the host:

/etc/caddy/Caddyfile
Editing /etc/caddy/Caddyfile
Figure 3: Initial Caddyfile configuration

Added reverse proxy entries mapping internal hostnames to specific internal service ports:

Configured Caddyfile Rules
Figure 4: Custom domain entries inside Caddyfile
Port Conflict Troubleshooting

Notice there was an Nginx service previously installed as a Docker container binding port 80. By default, CasaOS runs on port 80, but due to this conflict, it was moved to port 90.

When starting Caddy with sudo systemctl start caddy, it failed because port 443 was also occupied by the legacy Nginx container. Stopping and removing the container released port 443, enabling Caddy to start immediately.

Caddy systemctl status verification
Figure 5: Caddy service active and running

Step 3 – DNS Configuration

To allow client machines to resolve casaos.local to the server, configure the hosts file:

  • Linux / macOS: /etc/hosts
  • Windows: C:\Windows\System32\drivers\etc\hosts
Tip: Editing hosts file on Windows

Open Notepad as Administrator, navigate to C:\Windows\System32\drivers\etc\hosts (ensure "All Files *.*" is selected in file dialog), add the record, and save.

10.0.0.203   casaos.local

Step 4 – Certificate Authority (CA) Configuration

Export the internal Root Certificate generated by Caddy on the Ubuntu host:

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

The certificate must be imported into the trusted store of any client machine accessing the services. The easiest transfer method is downloading it directly via the CasaOS file manager GUI:

Exporting Root Certificate
Figure 6: Exporting caddy-root.crt

Importing into Windows Certificate Manager (certmgr.msc)

  1. Press Win + R, type certmgr.msc, and press Enter.
  2. In the left pane, expand Trusted Root Certification Authorities → Certificates.
  3. Right-click Certificates → All Tasks → Import.
  4. Browse to the downloaded caddy-root.crt file.
  5. Complete the wizard, ensuring it is placed in Trusted Root Certification Authorities.

Reload Caddy after any additions or changes:

sudo systemctl reload caddy

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

If you encounter a browser cache warning during the first connection:

Initial Certificate Warning
Figure 7: Initial certificate cache alert

Simply restarting the browser loads the newly imported root certificate:

Valid Trusted SSL Connection
Figure 8: Trusted HTTPS lock verified in browser address bar

All auxiliary internal services requiring secure HTTPS contexts now function seamlessly:

Internal Service 1 with TLS
Internal Service 2 with TLS
Internal Service 3 with TLS
Figure 9: Auxiliary local web applications operating over secure TLS

DNS & CA Configuration for Linux Client Machines

1. Host file configuration:

sudo nano /etc/hosts

# Add service hostnames:
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

2. Root Certificate Trust Store:

# Copy cert into system trust anchor directory:
sudo cp ~/caddy-root.crt /etc/pki/ca-trust/source/anchors/

# Update the system trust database:
sudo update-ca-trust extract

3. Test Connection:

https://casaos.local

Important Notes & Browser Considerations

  • Mozilla Firefox maintains its own internal CA store separate from the OS. To import:
    Go to Settings → Privacy & Security → Certificates → View Certificates → Authorities → Import, select caddy-root.crt, and check "Trust this CA to identify websites".
  • Chromium / Chrome / Edge on Linux (Fedora/RHEL/Ubuntu) utilizes the system trust store, so the update-ca-trust or update-ca-certificates command is sufficient.
Final Architecture Diagram
Figure 10: Complete Homelab TLS Architecture Diagram
All Articles Next Lab: pfSense + Proxmox