Caddy reverse proxy with HTTPS for a self-hosted AI dashboard

Front your agent dashboard with Caddy on port 443 with automatic HTTPS via Let's Encrypt, no certbot, no nginx config.

Prerequisites

  • A Linux host with a public IP and a domain pointed at it (A record)
  • An agent running on the host on a non-standard port (e.g. 8765)
  • Ports 80 and 443 open on the host firewall

Steps

  1. Install Caddy

    Use the official Debian/Ubuntu repository. Caddy 2.x is the version we want.

    sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https
    curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
    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
  2. Write the Caddyfile

    The simplest possible Caddyfile that fronts your agent on port 443 with auto-HTTPS.

    sudo tee /etc/caddy/Caddyfile <<'EOF'
    agent.yourdomain.com {
        reverse_proxy localhost:8765
    }
    EOF
    
    sudo systemctl reload caddy
  3. Verify HTTPS works

    Caddy will request a Let's Encrypt certificate automatically on first request. Check by curling.

    curl -I https://agent.yourdomain.com
    # Should return HTTP 200 or 401 (auth), the certificate should be valid.
  4. Lock down with basic auth (recommended even with Tailscale)

    Add basic auth on top of the agent's own auth as defence in depth.

    # Generate a hashed password:
    caddy hash-password
    # Enter your password, copy the output.
    
    sudo tee /etc/caddy/Caddyfile <<'EOF'
    agent.yourdomain.com {
        basicauth {
            admin <hashed-password-from-above>
        }
        reverse_proxy localhost:8765
    }
    EOF
    
    sudo systemctl reload caddy

Troubleshooting

Certificate fails to issue
Most common: the domain DNS doesn't actually point to this server (yet). Check `dig agent.yourdomain.com` returns the right IP. Also verify ports 80 and 443 are reachable from the public internet (`curl -I http://agent.yourdomain.com`).
Caddy reload fails
Check `caddy validate --config /etc/caddy/Caddyfile`. Most syntax errors show clearly there.

Where to go from here

Put the dashboard behind Tailscale instead of public auth: it's a stronger security boundary than basic auth. The Caddy + HTTPS setup is more useful for public services (status pages, API endpoints meant to be public).