From f818bd3eca62a4ec207fe78bb535ad8ecdeac5f0 Mon Sep 17 00:00:00 2001 From: Mohmmed Elfateh Sabry Date: Tue, 2 Dec 2025 00:12:32 +0200 Subject: [PATCH] Add docker-compose configuration for Traefik, Authelia, and associated services --- docker-compose.dev.yml | 337 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 337 insertions(+) create mode 100644 docker-compose.dev.yml diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml new file mode 100644 index 0000000..bdf20bb --- /dev/null +++ b/docker-compose.dev.yml @@ -0,0 +1,337 @@ +######################## +# Networks & Volumes +######################## +networks: + traefik_proxy: + name: traefik_proxy + +volumes: + traefik_letsencrypt: + traefik_logs: + portainer_data: + uptime_kuma_data: + umami_data: + pgadmin_data: + authelia_config: + authelia_db_data: + grafana_data: + prometheus_data: + alertmanager_data: + +######################## +# Services +######################## +services: + + ## ───────────────────────────────────────────── + ## Traefik — edge router + ACME (HTTP-01) + ## ───────────────────────────────────────────── + traefik: + image: traefik:latest + container_name: traefik + restart: unless-stopped + ports: + - "80:80" + - "443:443" + # Mail protocol ports for MailCow integration + - "25:25" # SMTP + - "465:465" # SMTPS + - "587:587" # Submission + - "143:143" # IMAP + - "993:993" # IMAPS + - "110:110" # POP3 + - "995:995" # POP3S + - "4190:4190" # ManageSieve + networks: [traefik_proxy] + environment: + TZ: "${TZ}" + command: + # Experimental plugins + - --experimental.plugins.traefik-umami-plugin.modulename=github.com/1cedsoda/traefik-umami-plugin + - --experimental.plugins.traefik-umami-plugin.version=v1.0.3 + + # Providers + - --providers.docker=true + - --providers.docker.exposedbydefault=false + + # Entrypoints + - --entrypoints.web.address=:80 + - --entrypoints.web.http.redirections.entrypoint.to=websecure + - --entrypoints.web.http.redirections.entrypoint.scheme=https + - --entrypoints.websecure.address=:443 + - --entrypoints.web.forwardedheaders.insecure=true + - --entrypoints.websecure.forwardedheaders.insecure=true + + # Mail protocol entrypoints for MailCow integration + - --entrypoints.smtp.address=:25 + - --entrypoints.smtps.address=:465 + - --entrypoints.submission.address=:587 + - --entrypoints.imap.address=:143 + - --entrypoints.imaps.address=:993 + - --entrypoints.pop3.address=:110 + - --entrypoints.pop3s.address=:995 + - --entrypoints.sieve.address=:4190 + + # Dashboard/API (internal) + - --api=true + - --api.dashboard=true + + # ACME via HTTP-01 (no registrar API needed) + - --certificatesresolvers.le.acme.email=${ACME_EMAIL} + - --certificatesresolvers.le.acme.storage=/letsencrypt/acme.json + - --certificatesresolvers.le.acme.httpchallenge=true + - --certificatesresolvers.le.acme.httpchallenge.entrypoint=web + # (Alt) Use TLS-ALPN-01 if port 80 is blocked: + # - --certificatesresolvers.le.acme.tlschallenge=true + + # Global timeouts for slow backends + - --serversTransport.forwardingTimeouts.dialTimeout=30s + - --serversTransport.forwardingTimeouts.responseHeaderTimeout=60s + - --serversTransport.forwardingTimeouts.idleConnTimeout=180s + + # Logs + - --accesslog.filepath=/var/log/traefik/access.log + - --accesslog.bufferingsize=100 + - --log.level=INFO + - --metrics.prometheus=true + volumes: + - /var/run/docker.sock:/var/run/docker.sock:ro + - traefik_letsencrypt:/letsencrypt + - traefik_logs:/var/log/traefik + labels: + - traefik.enable=true + + # Reusable security headers + - traefik.http.middlewares.security-headers.headers.stsSeconds=31536000 + - traefik.http.middlewares.security-headers.headers.stsIncludeSubdomains=true + - traefik.http.middlewares.security-headers.headers.stsPreload=true + - traefik.http.middlewares.security-headers.headers.browserXssFilter=true + - traefik.http.middlewares.security-headers.headers.contentTypeNosniff=true + - traefik.http.middlewares.security-headers.headers.referrerPolicy=no-referrer-when-downgrade + + # # Basic Auth middleware + # - traefik.http.middlewares.basic-auth.basicauth.users=${BASIC_AUTH_USERS} + + # Authelia middleware + - traefik.http.middlewares.authelia.forwardAuth.address=http://authelia:9091/api/authz/forward-auth + - traefik.http.middlewares.authelia.forwardAuth.trustForwardHeader=true + - traefik.http.middlewares.authelia.forwardAuth.authResponseHeaders=Remote-User,Remote-Groups,Remote-Email,Remote-Name + + # Traefik dashboard (protected) + - traefik.http.routers.traefik.rule=Host(`traefik.test.${DOMAIN}`) + - traefik.http.routers.traefik.entrypoints=websecure + - traefik.http.routers.traefik.tls.certresolver=le + - traefik.http.routers.traefik.service=api@internal + - traefik.http.routers.traefik.middlewares=authelia@docker,security-headers + + ## ───────────────────────────────────────────── + ## Authelia — authentication and authorization + ## ───────────────────────────────────────────── + authelia: + image: authelia/authelia:latest + container_name: authelia + restart: unless-stopped + networks: [traefik_proxy] + volumes: + - authelia_config:/config + environment: + TZ: "${TZ}" + AUTHELIA_DB_PASSWORD: "${AUTHELIA_DB_PASSWORD}" + AUTHELIA_JWT_SECRET: "${AUTHELIA_JWT_SECRET}" + AUTHELIA_SESSION_SECRET: "${AUTHELIA_SESSION_SECRET}" + depends_on: + - authelia-db + labels: + - traefik.enable=true + - traefik.http.routers.authelia.rule=Host(`auth.test.${DOMAIN}`) + - traefik.http.routers.authelia.entrypoints=websecure + - traefik.http.routers.authelia.tls.certresolver=le + - traefik.http.services.authelia.loadbalancer.server.port=9091 + + ## ───────────────────────────────────────────── + ## Authelia Database — PostgreSQL + ## ───────────────────────────────────────────── + authelia-db: + image: postgres:15-alpine + container_name: authelia-db + restart: unless-stopped + networks: [traefik_proxy] + environment: + POSTGRES_DB: authelia + POSTGRES_USER: authelia + POSTGRES_PASSWORD: ${AUTHELIA_DB_PASSWORD} + volumes: + - authelia_db_data:/var/lib/postgresql/data + + ## ───────────────────────────────────────────── + ## Portainer — Docker control plane + ## ───────────────────────────────────────────── + portainer: + image: portainer/portainer-ce:latest + container_name: portainer + restart: unless-stopped + networks: [traefik_proxy] + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - portainer_data:/data + labels: + - traefik.enable=true + - traefik.http.routers.portainer.rule=Host(`portainer.test.${DOMAIN}`) + - traefik.http.routers.portainer.entrypoints=websecure + - traefik.http.routers.portainer.tls.certresolver=le + - traefik.http.routers.portainer.middlewares=security-headers + - traefik.http.services.portainer.loadbalancer.server.port=9000 + + ## ───────────────────────────────────────────── + ## Uptime Kuma — status page / checks + ## ───────────────────────────────────────────── + uptime-kuma: + image: louislam/uptime-kuma:latest + container_name: uptime-kuma + restart: unless-stopped + volumes: + - uptime_kuma_data:/app/data + networks: [traefik_proxy] + labels: + - traefik.enable=true + - traefik.http.routers.kuma.rule=Host(`uptime.test.${DOMAIN}`) + - traefik.http.routers.kuma.entrypoints=websecure + - traefik.http.routers.kuma.tls.certresolver=le + - traefik.http.routers.kuma.middlewares=security-headers + - traefik.http.services.kuma.loadbalancer.server.port=3001 + + ## ───────────────────────────────────────────── + ## Umami — web analytics + ## ───────────────────────────────────────────── + umami: + image: ghcr.io/umami-software/umami:postgresql-latest + container_name: umami + restart: unless-stopped + networks: [traefik_proxy] + environment: + DATABASE_URL: postgresql://${UMAMI_DB_USER}:${UMAMI_DB_PASS}@umami-db:5432/${UMAMI_DB_NAME} + DATABASE_TYPE: postgresql + APP_SECRET: ${UMAMI_APP_SECRET} + depends_on: + - umami-db + labels: + - traefik.enable=true + - traefik.http.routers.umami.rule=Host(`umami.test.${DOMAIN}`) + - traefik.http.routers.umami.entrypoints=websecure + - traefik.http.routers.umami.tls.certresolver=le + - traefik.http.routers.umami.middlewares=security-headers + - traefik.http.services.umami.loadbalancer.server.port=3000 + + ## ───────────────────────────────────────────── + ## Umami Database — PostgreSQL + ## ───────────────────────────────────────────── + umami-db: + image: postgres:15-alpine + container_name: umami-db + restart: unless-stopped + networks: [traefik_proxy] + environment: + POSTGRES_DB: ${UMAMI_DB_NAME} + POSTGRES_USER: ${UMAMI_DB_USER} + POSTGRES_PASSWORD: ${UMAMI_DB_PASS} + volumes: + - umami_data:/var/lib/postgresql/data + + # ───────────────────────────────────────────── + # pgAdmin — PostgreSQL administration + # ───────────────────────────────────────────── + pgadmin: + image: dpage/pgadmin4:latest + container_name: pgadmin + restart: unless-stopped + networks: [traefik_proxy] + environment: + PGADMIN_DEFAULT_EMAIL: ${PGADMIN_DEFAULT_EMAIL} + PGADMIN_DEFAULT_PASSWORD: ${PGADMIN_DEFAULT_PASSWORD} + PGADMIN_CONFIG_SERVER_MODE: 'True' + PGADMIN_CONFIG_MASTER_PASSWORD_REQUIRED: 'False' + # Fix CSRF issues behind reverse proxy + PGADMIN_CONFIG_WTF_CSRF_CHECK_DEFAULT: 'False' + PGADMIN_CONFIG_WTF_CSRF_TIME_LIMIT: 'None' + PGADMIN_CONFIG_ENHANCED_COOKIE_PROTECTION: 'False' + # Trust proxy headers + PGADMIN_CONFIG_PROXY_X_HOST_COUNT: '1' + PGADMIN_CONFIG_PROXY_X_PREFIX_COUNT: '1' + volumes: + - pgadmin_data:/var/lib/pgadmin + labels: + - traefik.enable=true + - traefik.http.routers.pgadmin.rule=Host(`pgadmin.test.${DOMAIN}`) + - traefik.http.routers.pgadmin.entrypoints=websecure + - traefik.http.routers.pgadmin.tls.certresolver=le + - traefik.http.services.pgadmin.loadbalancer.server.port=80 + + ## ───────────────────────────────────────────── + ## Prometheus — monitoring + ## ───────────────────────────────────────────── + prometheus: + image: prom/prometheus:latest + container_name: prometheus + restart: unless-stopped + networks: [traefik_proxy] + volumes: + - ./prometheus.yml:/etc/prometheus/prometheus.yml + - ./rules.yml:/etc/prometheus/rules.yml + - prometheus_data:/prometheus + - /var/run/docker.sock:/var/run/docker.sock:ro + command: + - '--config.file=/etc/prometheus/prometheus.yml' + - '--storage.tsdb.path=/prometheus' + - '--web.console.libraries=/etc/prometheus/console_libraries' + - '--web.console.templates=/etc/prometheus/consoles' + - '--storage.tsdb.retention.time=200h' + - '--web.enable-lifecycle' + labels: + - traefik.enable=true + - traefik.http.routers.prometheus.rule=Host(`prometheus.test.${DOMAIN}`) + - traefik.http.routers.prometheus.entrypoints=websecure + - traefik.http.routers.prometheus.tls.certresolver=le + - traefik.http.routers.prometheus.middlewares=authelia@docker,security-headers + - traefik.http.services.prometheus.loadbalancer.server.port=9090 + + ## ───────────────────────────────────────────── + ## Grafana — visualization + ## ───────────────────────────────────────────── + grafana: + image: grafana/grafana:latest + container_name: grafana + restart: unless-stopped + networks: [traefik_proxy] + environment: + GF_SECURITY_ADMIN_PASSWORD: ${GRAFANA_ADMIN_PASSWORD} + volumes: + - grafana_data:/var/lib/grafana + labels: + - traefik.enable=true + - traefik.http.routers.grafana.rule=Host(`grafana.test.${DOMAIN}`) + - traefik.http.routers.grafana.entrypoints=websecure + - traefik.http.routers.grafana.tls.certresolver=le + - traefik.http.routers.grafana.middlewares=authelia@docker,security-headers + - traefik.http.services.grafana.loadbalancer.server.port=3000 + + ## ───────────────────────────────────────────── + ## Alertmanager — alert handling + ## ───────────────────────────────────────────── + alertmanager: + image: prom/alertmanager:latest + container_name: alertmanager + restart: unless-stopped + networks: [traefik_proxy] + volumes: + - ./alertmanager.yml:/etc/alertmanager/alertmanager.yml + - alertmanager_data:/alertmanager + command: + - '--config.file=/etc/alertmanager/alertmanager.yml' + - '--storage.path=/alertmanager' + labels: + - traefik.enable=true + - traefik.http.routers.alertmanager.rule=Host(`alertmanager.test.${DOMAIN}`) + - traefik.http.routers.alertmanager.entrypoints=websecure + - traefik.http.routers.alertmanager.tls.certresolver=le + - traefik.http.routers.alertmanager.middlewares=authelia@docker,security-headers + - traefik.http.services.alertmanager.loadbalancer.server.port=9093