name: drivervault # TLS overlay — put a public hostname and a real certificate in front of the # stack. Layer it on top of either base file: # # docker compose -f docker-compose.prod.yml -f docker-compose.tls.yml up -d # # What it changes: # • Caddy terminates TLS on :443 and proxies everything to the Web App BFF, # which already carries /api/ and /ocpp/ through to the API Server. One # hostname serves browsers and chargers alike. # • The charger endpoint the panel hands out becomes wss://$DV_DOMAIN/ocpp/…, # so OCPP_REQUIRE_TLS goes back on and the control token stops crossing the # network in the clear. # # Requirements, none of which this file can arrange for you: # • DV_DOMAIN resolves to this host from the public internet, and ports 80 and # 443 reach it (Caddy needs :80 for the ACME challenge, and keeps it for the # redirect afterwards). # • The charger can resolve DV_DOMAIN too. On a LAN behind NAT that usually # means hairpin NAT or a split-DNS entry pointing the name at 10.2.1.10 — # otherwise the charger looks up a public address it cannot route to. services: caddy: image: "${CADDY_IMAGE:-caddy:2-alpine}" container_name: drivervault-caddy restart: unless-stopped depends_on: web-app: condition: service_healthy environment: DV_DOMAIN: "${DV_DOMAIN:?set DV_DOMAIN in .env}" # Let's Encrypt sends expiry warnings here if renewal ever stops working. DV_ACME_EMAIL: "${DV_ACME_EMAIL:?set DV_ACME_EMAIL in .env}" ports: - "80:80" - "443:443" volumes: - ./Caddyfile:/etc/caddy/Caddyfile:ro # Certificates live here. Keep the volume: wiping it re-issues on next # boot and Let's Encrypt rate-limits that. - caddy_data:/data - caddy_config:/config api-server: environment: # Derived from the one hostname, so there is a single thing to set. OCPP_REQUIRE_TLS: "true" OCPP_PUBLIC_URL: "wss://${DV_DOMAIN}" CORS_ALLOW_ORIGINS: "https://${DV_DOMAIN}" web-app: environment: # Caddy terminates TLS and says so in X-Forwarded-Proto. Believe it — # that header is now set by the proxy in front, not by whoever dialed in. TRUST_FORWARDED_PROTO: "true" volumes: caddy_data: caddy_config: