Exposing Multiple Web Applications from a Home Server with Cloudflare Tunnel + Caddy
Source: Dev.to
Introduction
When publishing multiple web applications on a home server, obtaining a static IP address, managing SSL certificates, and handling complex security settings can become bottlenecks. This article explains a practical method to solve these challenges and securely expose several web applications using a combination of Cloudflare Tunnel, Caddy, and WSL2.
Architecture layers
| Layer | Role |
|---|---|
| Cloudflare Tunnel | Connects your home server to the internet (configured with the cloudflared command). |
| Caddy | Acts as a reverse proxy, adds security headers, and collects access logs. |
| App Services | Web applications (e.g., Streamlit) running on various ports. |
Caddy receives requests via the Cloudflare Tunnel and forwards them to the appropriate application. URLs follow the pattern service_name.example.org.
- App Services: ports in the
8xxxrange (application execution ports) - Caddy: ports in the
9xxxrange (reverse‑proxy ports) - URL naming convention:
{service_name}.example.org
How to Write a Caddyfile
In Caddy 2.x, the site address is declared first, followed by reverse‑proxy and logging directives.
:9530 {
log {
output file /var/log/caddy/access.log {
roll_size 10mb
roll_keep 30
}
format json
}
reverse_proxy localhost:8530 {
header_up X-Forwarded-Proto https
}
header {
Strict-Transport-Security "max-age=31536000"
X-Content-Type-Options "nosniff"
}
}
What this configuration does
- Reverse proxy: forwards traffic from port 9530 to the application listening on
localhost:8530. - Security headers: adds
Strict-Transport-SecurityandX-Content-Type-Options. - Access logging: writes JSON‑formatted logs to
/var/log/caddy/access.log, rolling when the file reaches 10 MiB and keeping the last 30 files.
Note: A generic
Content‑Security‑Policy: default-src 'self'may be too restrictive for apps like Streamlit that load external resources. Adjust the CSP per application as needed.
Security layers provided
| Layer | Protection |
|---|---|
| Cloudflare | WAF, DDoS mitigation, automatic SSL |
| cloudflared | Hides your home IP address |
| Caddy | Adds security headers, logs requests |
| Application authentication | OTP/PIN or other access controls |
| Data protection | Encrypts sensitive data with Fernet |
| Cloudflare Access (optional) | SSO and multi‑factor authentication |
Cron Setting (Daily Log Analysis)
A cron job runs each night to analyze Caddy’s access logs and send suspicious‑activity alerts via Gmail.
55 23 * * * /home/user/logger/daily_log_analyzer.py
Analysis workflow
- Extract today’s entries from the JSON‑formatted Caddy logs.
- Aggregate status codes, services, IP addresses, and User‑Agent strings.
- Send the aggregated data to Gemini 2.5 Flash for pattern detection.
- Notify any findings through Gmail.
By combining Cloudflare Tunnel with Caddy, you can expose services hosted on a home server without a static IP address while benefiting from automatic SSL, WAF/DDoS protection, and enterprise‑grade security headers. This setup makes personal development environments as secure as production‑grade deployments.