# Infrastructure Services # Core services that other services depend on # Place in /opt/stacks/infrastructure/docker-compose.yml # NOTE: Traefik, Authelia, DuckDNS, and Gluetun have their own separate stacks # See /opt/stacks/traefik/, /opt/stacks/authelia/, etc. services: # Dockge - Docker Compose Stack Manager (PRIMARY - preferred over Portainer) # Access at: https://dockge.${DOMAIN} dockge: image: louislam/dockge:1 container_name: dockge restart: unless-stopped networks: - homelab-network - traefik-network ports: - "5001:5001" # Optional: direct access volumes: - /var/run/docker.sock:/var/run/docker.sock - /opt/stacks:/opt/stacks # Dockge manages stacks in this directory - /opt/dockge/data:/app/data environment: - DOCKGE_STACKS_DIR=/opt/stacks labels: - "homelab.category=infrastructure" - "homelab.description=Docker Compose stack manager (PRIMARY)" - "traefik.enable=true" - "traefik.http.routers.dockge.rule=Host(`dockge.${DOMAIN}`)" - "traefik.http.routers.dockge.entrypoints=websecure" - "traefik.http.routers.dockge.tls.certresolver=letsencrypt" - "traefik.http.routers.dockge.middlewares=authelia@docker" - "traefik.http.services.dockge.loadbalancer.server.port=5001" # Portainer - Docker management UI (SECONDARY - use Dockge instead) # Access at: https://portainer.${DOMAIN} portainer: image: portainer/portainer-ce:2.19.4 container_name: portainer restart: unless-stopped networks: - homelab-network - traefik-network volumes: - /var/run/docker.sock:/var/run/docker.sock - portainer-data:/data security_opt: - no-new-privileges:true labels: - "homelab.category=infrastructure" - "homelab.description=Docker container management UI (SECONDARY)" - "traefik.enable=true" - "traefik.http.routers.portainer.rule=Host(`portainer.${DOMAIN}`)" - "traefik.http.routers.portainer.entrypoints=websecure" - "traefik.http.routers.portainer.tls.certresolver=letsencrypt" - "traefik.http.routers.portainer.middlewares=authelia@docker" - "traefik.http.services.portainer.loadbalancer.server.port=9000" # Pi-hole - Network-wide ad blocker and DNS server # Access at: https://pihole.${DOMAIN} pihole: image: pihole/pihole:2024.01.0 container_name: pihole restart: unless-stopped networks: - homelab-network - traefik-network ports: - "53:53/tcp" # DNS TCP - "53:53/udp" # DNS UDP volumes: - /opt/stacks/pihole/etc-pihole:/etc/pihole - /opt/stacks/pihole/etc-dnsmasq.d:/etc/dnsmasq.d environment: - TZ=${TZ:-America/New_York} - WEBPASSWORD=${PIHOLE_PASSWORD:-changeme} - FTLCONF_LOCAL_IPV4=${SERVER_IP} dns: - 127.0.0.1 - 1.1.1.1 cap_add: - NET_ADMIN labels: - "homelab.category=infrastructure" - "homelab.description=Network-wide ad blocking and DNS" - "traefik.enable=true" - "traefik.http.routers.pihole.rule=Host(`pihole.${DOMAIN}`)" - "traefik.http.routers.pihole.entrypoints=websecure" - "traefik.http.routers.pihole.tls.certresolver=letsencrypt" - "traefik.http.routers.pihole.middlewares=authelia@docker" - "traefik.http.services.pihole.loadbalancer.server.port=80" # Watchtower - Automatic container updates # Runs silently in background, no UI watchtower: image: containrrr/watchtower:1.7.1 container_name: watchtower restart: unless-stopped networks: - homelab-network volumes: - /var/run/docker.sock:/var/run/docker.sock environment: - WATCHTOWER_CLEANUP=true - WATCHTOWER_INCLUDE_RESTARTING=true - WATCHTOWER_SCHEDULE=0 0 4 * * * # 4 AM daily - WATCHTOWER_NOTIFICATIONS=shoutrrr - WATCHTOWER_NOTIFICATION_URL=${WATCHTOWER_NOTIFICATION_URL} labels: - "homelab.category=infrastructure" - "homelab.description=Automatic Docker container updates" # Dozzle - Real-time Docker log viewer # Access at: https://dozzle.${DOMAIN} dozzle: image: amir20/dozzle:latest container_name: dozzle restart: unless-stopped networks: - homelab-network - traefik-network volumes: - /var/run/docker.sock:/var/run/docker.sock:ro environment: - DOZZLE_LEVEL=info - DOZZLE_TAILSIZE=300 - DOZZLE_FILTER=status=running labels: - "homelab.category=infrastructure" - "homelab.description=Real-time Docker log viewer" - "traefik.enable=true" - "traefik.http.routers.dozzle.rule=Host(`dozzle.${DOMAIN}`)" - "traefik.http.routers.dozzle.entrypoints=websecure" - "traefik.http.routers.dozzle.tls.certresolver=letsencrypt" - "traefik.http.routers.dozzle.middlewares=authelia@docker" - "traefik.http.services.dozzle.loadbalancer.server.port=8080" # Docker Proxy - Socket proxy for security # Used by services that need Docker socket access dockerproxy: image: tecnativa/docker-socket-proxy:latest container_name: dockerproxy restart: unless-stopped networks: - dockerproxy-network ports: - "127.0.0.1:2375:2375" volumes: - /var/run/docker.sock:/var/run/docker.sock:ro environment: - CONTAINERS=1 - SERVICES=1 - TASKS=1 - NETWORKS=1 - NODES=1 labels: - "homelab.category=infrastructure" - "homelab.description=Docker socket proxy for security" # Glances - System monitoring # Access at: https://glances.${DOMAIN} glances: image: nicolargo/glances:latest-full container_name: glances restart: unless-stopped networks: - homelab-network - traefik-network pid: host volumes: - /var/run/docker.sock:/var/run/docker.sock:ro - /opt/stacks/glances/config:/glances/conf environment: - GLANCES_OPT=-w labels: - "homelab.category=infrastructure" - "homelab.description=System and Docker monitoring" - "traefik.enable=true" - "traefik.http.routers.glances.rule=Host(`glances.${DOMAIN}`)" - "traefik.http.routers.glances.entrypoints=websecure" - "traefik.http.routers.glances.tls.certresolver=letsencrypt" - "traefik.http.routers.glances.middlewares=authelia@docker" - "traefik.http.services.glances.loadbalancer.server.port=61208" # Authentik - Alternative SSO/Identity Provider with Web UI # Access at: https://authentik.${DOMAIN} # NOTE: Authelia is the default SSO. Deploy Authentik only if you need a web UI for user management authentik-server: image: ghcr.io/goauthentik/server:2024.2.0 container_name: authentik-server restart: unless-stopped command: server networks: - homelab-network - traefik-network volumes: - /opt/stacks/authentik/media:/media - /opt/stacks/authentik/custom-templates:/templates environment: - AUTHENTIK_REDIS__HOST=authentik-redis - AUTHENTIK_POSTGRESQL__HOST=authentik-db - AUTHENTIK_POSTGRESQL__USER=${AUTHENTIK_DB_USER:-authentik} - AUTHENTIK_POSTGRESQL__NAME=${AUTHENTIK_DB_NAME:-authentik} - AUTHENTIK_POSTGRESQL__PASSWORD=${AUTHENTIK_DB_PASSWORD} - AUTHENTIK_SECRET_KEY=${AUTHENTIK_SECRET_KEY} - AUTHENTIK_ERROR_REPORTING__ENABLED=false labels: - "homelab.category=infrastructure" - "homelab.description=SSO/Identity provider with web UI (alternative to Authelia)" - "traefik.enable=true" - "traefik.http.routers.authentik.rule=Host(`authentik.${DOMAIN}`)" - "traefik.http.routers.authentik.entrypoints=websecure" - "traefik.http.routers.authentik.tls.certresolver=letsencrypt" - "traefik.http.routers.authentik.middlewares=authelia@docker" - "traefik.http.services.authentik.loadbalancer.server.port=9000" depends_on: - authentik-db - authentik-redis # Authentik Worker - Background task processor authentik-worker: image: ghcr.io/goauthentik/server:2024.2.0 container_name: authentik-worker restart: unless-stopped command: worker networks: - homelab-network volumes: - /opt/stacks/authentik/media:/media - /opt/stacks/authentik/certs:/certs - /opt/stacks/authentik/custom-templates:/templates environment: - AUTHENTIK_REDIS__HOST=authentik-redis - AUTHENTIK_POSTGRESQL__HOST=authentik-db - AUTHENTIK_POSTGRESQL__USER=${AUTHENTIK_DB_USER:-authentik} - AUTHENTIK_POSTGRESQL__NAME=${AUTHENTIK_DB_NAME:-authentik} - AUTHENTIK_POSTGRESQL__PASSWORD=${AUTHENTIK_DB_PASSWORD} - AUTHENTIK_SECRET_KEY=${AUTHENTIK_SECRET_KEY} - AUTHENTIK_ERROR_REPORTING__ENABLED=false labels: - "homelab.category=infrastructure" - "homelab.description=Authentik background worker" depends_on: - authentik-db - authentik-redis # Authentik Database - PostgreSQL authentik-db: image: postgres:16-alpine container_name: authentik-db restart: unless-stopped networks: - homelab-network volumes: - authentik-db-data:/var/lib/postgresql/data environment: - POSTGRES_USER=${AUTHENTIK_DB_USER:-authentik} - POSTGRES_PASSWORD=${AUTHENTIK_DB_PASSWORD} - POSTGRES_DB=${AUTHENTIK_DB_NAME:-authentik} labels: - "homelab.category=infrastructure" - "homelab.description=Authentik database" healthcheck: test: ["CMD-SHELL", "pg_isready -U ${AUTHENTIK_DB_USER:-authentik}"] interval: 10s timeout: 5s retries: 5 # Authentik Redis - Cache and message queue authentik-redis: image: redis:7-alpine container_name: authentik-redis restart: unless-stopped networks: - homelab-network volumes: - authentik-redis-data:/data command: --save 60 1 --loglevel warning labels: - "homelab.category=infrastructure" - "homelab.description=Authentik cache and messaging" healthcheck: test: ["CMD-SHELL", "redis-cli ping | grep PONG"] interval: 10s timeout: 3s retries: 5 volumes: portainer-data: driver: local authentik-db-data: driver: local authentik-redis-data: driver: local networks: homelab-network: external: true traefik-network: external: true dockerproxy-network: driver: bridge