DEV Community

Dmitry Gordin
Dmitry Gordin

Posted on

Self-hosting nowadays is easier than never before

Cloudflare tunnel allows you to host from any machine without a white static IP address or any port-forwarding settings. E.g., you can tether Wi-Fi from your phone to a "server" PC and happily host anything to the public internet.

We'll focus on managing multiple services from different docker-compose files for convenience.

1. Cloudflare Setup

First, you need a domain name managed by Cloudflare. Let you figure out this yourself.

Then go to admin console → Zero Trust → Network → Tunnels → Create tunnel.
No need to install anything — we'll use Docker. Just take the token and save it to a .env file.

In "Public hostnames" you have two possibilities:

  • a specific domain name,
  • use * star to move managing subdomains to the Caddyfile.

Then specify where on local machine to forward requests: we'll use http://proxy:80 as destination - because this is our Caddy's container name in docker compose file.

When you first create a rule — it'll update DNS settings for you, but later if you manually change something — pay attention if corresponding changes are done in DNS.

2. Docker Network

To the technical part: we need to create a network that will be available between multiple docker-compose files:

sudo docker network create tunnel-proxy
Enter fullscreen mode Exit fullscreen mode

3. Base docker-compose.yml (cloudflared + caddy)

services:
  cloudflared:
    image: cloudflare/cloudflared:latest
    restart: unless-stopped
    command: tunnel --no-autoupdate run --token ${TUNNEL_TOKEN}
    environment:
      - TUNNEL_TOKEN=${TUNNEL_TOKEN}
    networks:
      - tunnel-proxy

  proxy:
    image: caddy:latest
    # tunnel is configured to forward requests to http://proxy:80
    container_name: proxy
    restart: unless-stopped
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile
      - caddy_data:/data
      - caddy_config:/config
    depends_on:
      - cloudflared
    networks:
      - tunnel-proxy

volumes:
  caddy_data:
  caddy_config:

# this network is created manually beforehand:
# sudo docker network create tunnel-proxy
networks:
  tunnel-proxy:
    external: true
Enter fullscreen mode Exit fullscreen mode

4. Caddyfile example

{
    admin off
    auto_https off
}

# inside tunnel everything is http on port 80
# https is done later by Cloudflare

http://hello.example.net:80 {
    # can serve content right away
    # refer to Caddy documentation for details
    respond "Hello, world!" 200
}

http://container-name.example.net:80 {
    # or reverse proxy to container from another docker-compose.yml
    reverse_proxy container-name:80
}
Enter fullscreen mode Exit fullscreen mode

Save your token from Cloudflare to .env file: TUNNEL_TOKEN=abcdefg

5. Another docker-compose.yml for your service

services:
  anything:
    # must match name in www/Caddyfile
    container_name: container-name
    # here's your service you want to host
    # caddy is just an example
    image: caddy:latest
    restart: unless-stopped
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile
      - caddy_data:/data
      - caddy_config:/config
    networks:
      - tunnel-proxy

volumes:
  caddy_data:
  caddy_config:

networks:
  tunnel-proxy:
    external: true
Enter fullscreen mode Exit fullscreen mode

Top comments (0)