Caddy is a powerful, extensible platform to serve your sites, services, and apps, written in Go.
For this server, Caddy acts as a reverse proxy to the containers. It also configures SSL automatically for each sub-domain. It's a core piece of the puzzle, along with Pi-hole (for local DNS) and Sablier (for container orchestration).
Pay particular attention to Labels section of the caddy.container file and similar labels on other containers.
Caddy is built manually using caddy-update.service to enable the following plugins:
- caddy-docker-proxy — to allow configuration via container labels
- sablier — to scale some containers to zero
- caddy-ratelimit
- caddy-cloudflare-ip
Place caddy-update.service and caddy-update.timer in ~/.config/systemd/user/. Eventually I will switch this to use a .build Quadlet (more info).
Tweak the settings to add your Cloudflare token and email.
CLOUDFLARE_API_TOKEN=
CADDY_INGRESS_NETWORKS=proxy
EMAIL=
CADDY_DOCKER_SCAN_STOPPED_CONTAINERS=true
CADDY_DOCKER_POLLING_INTERVAL=5s
CADDY_DOCKER_NO_SCOPE=truesudo firewall-cmd --zone=FedoraServer --add-service=http
sudo firewall-cmd --zone=FedoraServer --add-service=http --permanent
sudo firewall-cmd --zone=FedoraServer --add-service=https
sudo firewall-cmd --zone=FedoraServer --add-service=https --permanentfirewall-cmd --get-default-zone will let you know which zone you are currently using. Use sudo firewall-cmd --reload to reload the firewall.
You might see buffer warnings in your logs and this can be fixed using the following advice.
Edit the following file sudo nano /etc/sysctl.d/99-buffer-size.conf and add the following:
net.core.rmem_max=7500000
net.core.wmem_max=7500000Reload your config changes: sudo sysctl -p /etc/sysctl.d/99-buffer-size.conf and check they have been correctly set: sudo sysctl net.core.rmem_max and sudo sysctl net.core.wmem_max.
Every container with a web UI (that's most of them) has two domains. A local .lan for http traffic and a .com for https traffic.
The domain is a cheap one registered with Cloudflare that points to an internal IP address (192.168.11.2). Caddy uses the Cloudflare module to generate SSL certificates via DNS challenges. That means SSL on our local network using a proper domain name (e.g. https://miniflux.example.com). The domain works when we are on our home network or connect back via a VPN (WireGuard). There are plenty of other providers available too, so I will probably switch from Cloudflare at some point.
The .lan domains are just a backup. There is no SSL and they need to manually added to the Pi-hole (under Settings → Local DNS Records) in order to resolve (e.g. jellyfin.example.lan points to 192.168.11.2).
You can customise the domain name for each service within the .container or compose.yaml file. Look for the labels and adjust accordingly.