Skip to content

Instantly share code, notes, and snippets.

@zuedev
Last active January 26, 2026 17:20
Show Gist options
  • Select an option

  • Save zuedev/7c312195b2401e5e776bb4d64cf83346 to your computer and use it in GitHub Desktop.

Select an option

Save zuedev/7c312195b2401e5e776bb4d64cf83346 to your computer and use it in GitHub Desktop.
Caddy docker-compose.yaml that writes an inline Caddyfile from an environment variable at runtime.
# Use a modern compose version
version: '3.8'
services:
caddy:
image: caddy:latest
restart: unless-stopped
ports:
# Port 80 for HTTP and ACME (Let's Encrypt) challenges
- "80:80"
# Port 443 for HTTPS
- "443:443"
# Port 443/udp for HTTP/3
- "443:443/udp"
volumes:
# This named volume is crucial for persisting Caddy's state,
# especially SSL certificates from Let's Encrypt.
- caddy_data:/data
environment:
# Define the Caddyfile content as a multi-line env variable
CADDYFILE_CONTENT: |
# --- Your Caddyfile Configuration Goes Here ---
# Example 1: Simple "Hello World" on port 80
# (Great for local testing)
:80 {
respond "Hello, world from an ENV variable!"
}
# Example 2: Automatic HTTPS for your domain
# (Uncomment and replace with your domain)
#
# your-domain.com {
# # Serves static files from this directory
# root * /usr/share/caddy
# file_server
# }
# Override the default command to:
# 1. Write the environment variable content to the Caddyfile
# 2. Run Caddy with that config file
command: >
sh -c "echo \"$$CADDYFILE_CONTENT\" > /etc/caddy/Caddyfile &&
caddy run --config /etc/caddy/Caddyfile"
# This top-level block defines the named volume used above
volumes:
caddy_data:
# 'external: false' (the default) means Docker will manage this volume
@nv6
Copy link

nv6 commented Jan 26, 2026

Thanks 🙏 This led me to a similar solution injecting the Caddyfile as an inline config:

services:
  caddy:
    image: caddy:latest
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
      - "443:443/udp"
    
    volumes:
      - caddy_data:/data

    configs:
      - source: caddyfile
        target: /opt/Caddyfile

    command: >
      sh -c "cat /opt/Caddyfile > /etc/caddy/Caddyfile && 
        caddy run --config /etc/caddy/Caddyfile --adapter caddyfile"

configs:
  caddyfile:
    content: |
      # --- Your Caddyfile Configuration Goes Here ---
      # Example 1: Simple "Hello World" on port 80
      # (Great for local testing)
      :80 {
        respond "Hello, world from an ENV variable!"
      }
      # Example 2: Automatic HTTPS for your domain
      # (Uncomment and replace with your domain)
      #
      # your-domain.com {
      #   # Serves static files from this directory
      #   root * /usr/share/caddy
      #   file_server
      # }

volumes:
  caddy_data:

@zuedev
Copy link
Author

zuedev commented Jan 26, 2026

Careful using docker compose configs @nv6 -- They don't update once set without renaming the config entry key.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment