Tutorial Self-Hosting
Use Caddy as a reverse proxy on a local server

Using Caddy as a local reverse proxy with Docker

Setting up a local server often requires an efficient way to route incoming web traffic to various internal Docker containers. By combining Caddy and Docker, you can establish a clean, automated reverse proxy system that handles routing effortlessly.

Setting up the Caddy reverse proxy

To begin, organize your shared core services in a dedicated directory on your server. Create and navigate into the designated directory for Caddy by running the following commands in your terminal:

mkdir -p /srv/core-and-shared/caddy
cd /srv/core-and-shared/caddy

Next, define your container configuration. Create the compose.yaml file inside your /srv/core-and-shared/caddy/ directory using your preferred text editor.

/srv/core-and-shared/caddy/compose.yaml:

services:
  caddy:
    image: caddy:2-alpine
    container_name: caddy
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
      - "443:443/udp"
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile:ro
      - caddy-data:/data
      - caddy-config:/config
    networks:
      - ingress
      - caddy

volumes:
  caddy-data:
  caddy-config:

networks:
  ingress:
    name: ingress
    external: true
  caddy:
    name: caddy

Now, configure your routing rules and server blocks. Create the Caddyfile in the same directory to handle incoming requests and map them to your local services.

/srv/core-and-shared/caddy/Caddyfile:

http://<domain> {
    respond "Hello World!"
}

Bring up your Caddy container in detached mode to start the service:

docker compose up -d

Verify that the proxy is responding correctly by making an HTTP request to your configured endpoint:

curl https://<domain>

Integrating Cloudflare Tunnels

If you need to make your local services accessible externally without opening firewall ports, you can pair your setup with a secure tunnel.

To learn how to securely expose a local server to the internet using Cloudflare Tunnel and Docker Compose without port forwarding or opening firewall ports, check out the following guide:

Expose a local server with Cloudflare Tunnel

Expose a local server with Cloudflare Tunnel

Learn how to securely expose a local Linux server to the internet using Cloudflare Tunnel and Docker Compose with step-by-step instructions.

Prepare a separate directory for the tunnel configuration and set up its corresponding compose file:

mkdir -p /srv/core-and-shared/cloudflared/
cd /srv/core-and-shared/cloudflared/

/srv/core-and-shared/cloudflared/compose.yaml:

services:
  cloudflared:
    image: cloudflare/cloudflared:latest
    container_name: cloudflared
    restart: unless-stopped
    command: tunnel --no-autoupdate run --token ${TUNNEL_TOKEN} --url http://caddy:80
    networks:
      - ingress

networks:
  ingress:
    name: ingress
    external: true

Launch the tunnel using Docker Compose:

curl https://<domain>

To explore alternative proxy deployment strategies and hardening techniques for production environments, read through this related tutorial:

Secure Docker services with Caddy on a VPS

Secure Docker services with Caddy on a VPS

Learn how to secure Docker services on a VPS using Caddy as a reverse proxy, external Docker networks, custom Caddyfiles, and optional Cloudflare tunnels.