services: caddy: # Prebuilt custom Caddy — includes every DNS provider CaddyUI supports # (for ACME DNS-01), the CrowdSec bouncer, and the rate-limit module. This # is the published build of Dockerfile.caddy, so fleet nodes pull one image # instead of each running xcaddy. To customise the module set, uncomment the # `build:` block below (and keep or change the image tag) and run # `docker compose build caddy`. image: applegater/caddyui-caddy:stable # build: # context: . # dockerfile: Dockerfile.caddy container_name: caddyui-caddy restart: unless-stopped ports: - "80:80" - "443:443" - "443:443/udp" volumes: - caddy_data:/data - caddy_config:/config - caddy_logs:/var/log/caddy environment: CADDY_ADMIN: 0.0.0.0:2019 # Timezone for Caddy access logs and cert-renewal timestamps. Any # IANA zone name works (America/New_York, Europe/London, Asia/Tokyo, # UTC, …). Defaults to UTC when unset. CaddyUI honors the same # TZ var — pair them so log timestamps line up across both containers. TZ: ${TZ:-UTC} # Cloudflare API token for DNS-01 challenges (wildcard certs). # Read by the Caddyfile `tls { dns cloudflare {env.CF_API_TOKEN} }`. CF_API_TOKEN: ${CF_API_TOKEN} command: - /bin/sh - -c - | mkdir -p /config/caddy [ -f /config/caddy/autosave.json ] || echo '{}' > /config/caddy/autosave.json exec caddy run --config /config/caddy/autosave.json --resume --adapter json networks: - caddyui caddyui: # Local build. Pass CADDYUI_VERSION to stamp the version string the UI # shows — e.g. `CADDYUI_VERSION=v2.5.11 docker compose up -d --build`. # Defaults to "dev" when unset, which is why a fresh `docker compose up` # shows version "dev". For the published release image instead, swap # this block for `image: applegater/caddyui:latest` and drop `build:`. build: context: . args: VERSION: ${CADDYUI_VERSION:-dev} image: caddyui:latest container_name: caddyui restart: unless-stopped depends_on: - caddy ports: - "8081:8080" volumes: - caddyui_data:/data # Mount the same Caddyfile Caddy reads so paste-import can auto-load # snippet definitions. Read-only — caddyui never writes it. - ./Caddyfile:/etc/caddy/Caddyfile:ro # File-path certificates (Certificates → New → "file path") name files # inside the *Caddy* container. Mount the same directory here, read-only # and at the same path, and CaddyUI reads expiry/issuer straight from the # file. Without it CaddyUI falls back to a live TLS probe of Caddy. # - ./certs:/certs:ro # Certificate export (Certificates → edit a managed certificate → Export # to a directory): mount Caddy's data volume here read-only and enter # /caddy-data as the server's Data directory (Caddy Fleet → edit), plus # a writable directory the consuming service also mounts. # - caddy_data:/caddy-data:ro # - ./exports:/exports # Caddy keeps that volume private to its own user (root, mode 0700), so # for certificate export CaddyUI has to run as root too — uncomment # `user: "0:0"` below (the data mount stays read-only). Without it export # fails with "permission denied". # user: "0:0" # needed only for certificate export (see above) environment: CADDYUI_DB: /data/caddyui.db CADDYUI_LISTEN: :8080 CADDY_ADMIN_URL: http://caddy:2019 CADDYFILE_PATH: /etc/caddy/Caddyfile # Push DB state to Caddy on every startup so `docker compose restart` # rehydrates routes from the CaddyUI DB. Safe: SyncCaddy bails out when # the DB is empty, so first-boot won't wipe an existing Caddyfile. CADDYUI_SYNC_ON_START: "1" # Timezone for log timestamps and server-side date rendering in the # UI. Any IANA zone name works (America/New_York, Europe/London, # Asia/Tokyo, UTC, …). Defaults to UTC when unset. You can also # override per-user from Settings → Timezone; the DB value wins # over this env var when both are set. TZ: ${TZ:-UTC} # Escape hatch for the admin panel IP allowlist (Settings → Security). # Uncomment and restart if a saved allowlist locks you out: this value # overrides the stored list, and "off" disables the gate entirely while # you get back in. What you saved in the UI is left untouched, so # commenting this out again restores it. Leave it unset normally. # CADDYUI_ADMIN_ALLOWLIST: "off" networks: - caddyui volumes: caddy_data: caddy_config: caddy_logs: caddyui_data: networks: caddyui: driver: bridge