Exposing Multiple Web Applications from a Home Server with Cloudflare Tunnel + Caddy

Published: (March 8, 2026 at 05:26 AM EDT)
3 min read
Source: Dev.to

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

LayerRole
Cloudflare TunnelConnects your home server to the internet (configured with the cloudflared command).
CaddyActs as a reverse proxy, adds security headers, and collects access logs.
App ServicesWeb 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 8xxx range (application execution ports)
  • Caddy: ports in the 9xxx range (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-Security and X-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

LayerProtection
CloudflareWAF, DDoS mitigation, automatic SSL
cloudflaredHides your home IP address
CaddyAdds security headers, logs requests
Application authenticationOTP/PIN or other access controls
Data protectionEncrypts 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

  1. Extract today’s entries from the JSON‑formatted Caddy logs.
  2. Aggregate status codes, services, IP addresses, and User‑Agent strings.
  3. Send the aggregated data to Gemini 2.5 Flash for pattern detection.
  4. 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.

0 views
Back to Blog

Related posts

Read more »