Caddy
Docker Compose deployment guide for Caddy on Ubuntu.
Caddy is a modern web server and reverse proxy that automatically obtains and renews HTTPS certificates.
This makes it an excellent choice for self-hosted applications and homelab environments.
Official project:
Create the Project Folder
mkdir -p ~/docker/caddy
cd ~/docker/caddy
Create the Docker Compose File
Create:
nano docker-compose.yml
Paste:
services:
caddy:
image: caddy:latest
container_name: caddy
ports:
- "80:80"
- "443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- ./data:/data
- ./config:/config
restart: unless-stopped
Create the Caddyfile
Create:
nano Caddyfile
Paste:
example.com {
reverse_proxy 192.168.1.100:8080
}
Replace:
example.comwith your domain name192.168.1.100:8080with the IP address and port of the application you want to publish
Start Caddy
Run:
docker compose up -d
Configure DNS
Create an A record pointing your domain or subdomain to your public IP address.
Example:
Type: A
Name: jellyfin
Content: YOUR_PUBLIC_IP
Result:
https://jellyfin.example.com
When traffic reaches Caddy, it will automatically request and renew HTTPS certificates.
Access Your Application
Open:
https://your-domain.com
or
https://your-subdomain.example.com
Example Reverse Proxy Configurations
Jellyfin:
jellyfin.example.com {
reverse_proxy 192.168.1.100:8096
}
Vaultwarden:
vaultwarden.example.com {
reverse_proxy 192.168.1.100:8122
}
Paperless-ngx:
paperless.example.com {
reverse_proxy 192.168.1.100:8456
}
Home Assistant:
homeassistant.example.com {
reverse_proxy 192.168.1.100:8123
}
Notes
- Ports 80 and 443 must be accessible from the internet
- DNS records must point to your public IP address
- HTTPS certificates are managed automatically
- No manual certificate renewal is required
- Most homelab users run a single Caddy instance for all services
Advanced Example (Reference Only)
This is my current deployment.
It includes:
- Automatic HTTPS via Caddy
- Multiple reverse proxies
- Dynamic DNS updates through Cloudflare
- Automatic DNS updates when the public IP address changes
services:
caddy:
image: caddy:latest
container_name: caddy
stop_grace_period: 30s
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- ./data:/data
- ./config:/config
cloudflare-ddns:
image: oznu/cloudflare-ddns:latest
container_name: cloudflare-ddns
restart: unless-stopped
environment:
- API_KEY=your_cloudflare_api_token
- ZONE=example.com
- SUBDOMAIN=*
- PROXIED=false
Example Caddyfile:
jellyfin.example.com {
reverse_proxy 192.168.1.100:8096
}
vaultwarden.example.com {
reverse_proxy 192.168.1.100:8122
}
paperless.example.com {
reverse_proxy 192.168.1.100:8456
}
homeassistant.example.com {
reverse_proxy 192.168.1.100:8123
}
Why My Setup Differs from the Basic Example
My homelab uses Caddy as a central reverse proxy for all internet-facing services.
Combining Caddy with Cloudflare Dynamic DNS provides:
- Automatic HTTPS certificates
- Automatic certificate renewal
- Centralised reverse proxy management
- Automatic DNS updates after ISP IP changes
- Simple configuration and maintenance
For most users, the basic deployment shown earlier in this guide is sufficient. This advanced example is included as a reference for readers who want to explore a more complete homelab setup.
Conclusion
Caddy is one of the easiest reverse proxies to deploy and maintain.
For homelab users, it provides automatic HTTPS, simple configuration, and reliable reverse proxy functionality with very little ongoing maintenance.