services: postgresql: image: postgres:16-alpine container_name: sso_postgres restart: unless-stopped environment: POSTGRES_DB: authentik POSTGRES_USER: authentik POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} volumes: - postgres_data:/var/lib/postgresql/data healthcheck: test: - CMD-SHELL - pg_isready -U authentik interval: 10s timeout: 5s retries: 5 networks: - internal_net redis: image: redis:alpine container_name: sso_redis restart: unless-stopped healthcheck: test: - CMD - redis-cli - ping interval: 10s timeout: 5s retries: 5 networks: - internal_net authentik-server: image: ghcr.io/goauthentik/server:2026.8.3 container_name: authentik_server restart: unless-stopped command: server environment: AUTHENTIK_REDIS__HOST: redis AUTHENTIK_POSTGRESQL__HOST: postgresql AUTHENTIK_POSTGRESQL__USER: authentik AUTHENTIK_POSTGRESQL__NAME: authentik AUTHENTIK_POSTGRESQL__PASSWORD: ${AUTHENTIK_POSTGRESQL__PASSWORD} AUTHENTIK_SECRET_KEY: ${AUTHENTIK_SECRET_KEY} volumes: - authentik_media:/media - authentik_custom:/customtemplates ports: - 9000:9000 - 9444:9443 depends_on: - postgresql - redis networks: - internal_net authentik-worker: image: ghcr.io/goauthentik/server:2026.8.3 container_name: authentik_worker restart: unless-stopped command: worker environment: AUTHENTIK_REDIS__HOST: redis AUTHENTIK_POSTGRESQL__HOST: postgresql AUTHENTIK_POSTGRESQL__USER: authentik AUTHENTIK_POSTGRESQL__NAME: authentik AUTHENTIK_POSTGRESQL__PASSWORD: ${AUTHENTIK_POSTGRESQL__PASSWORD} AUTHENTIK_SECRET_KEY: ${AUTHENTIK_SECRET_KEY} volumes: - authentik_media:/media - authentik_custom:/customtemplates - /var/run/docker.sock:/var/run/docker.sock depends_on: - postgresql - redis networks: - internal_net gitea: image: gitea/gitea:latest container_name: gitea environment: - USER_UID=1000 - USER_GID=1000 - GITEA__service__ENABLE_PASSWORD_SIGNIN_FORM=false - GITEA__service__ENABLE_BASIC_AUTHENTICATION=false - GITEA__service__DISABLE_REGISTRATION=true - GITEA__service__ALLOW_ONLY_EXTERNAL_REGISTRATION=true - GITEA__service__SHOW_REGISTRATION_BUTTON=false - GITEA__oauth2_client__ENABLE_AUTO_REGISTRATION=true restart: unless-stopped ports: - 3000:3000 - 2222:22 volumes: - gitea_data:/data - /etc/timezone:/etc/timezone:ro - /etc/localtime:/etc/localtime:ro depends_on: - postgresql networks: - internal_net runner: image: gitea/act_runner:latest-dind-rootless container_name: gitea_runner restart: always privileged: true security_opt: - apparmor=rootlesskit volumes: - runner_data:/data ports: - 8181:8181 environment: - GITEA_INSTANCE_URL=http://gitea:3000 - GITEA_RUNNER_REGISTRATION_TOKEN=${GITEA_RUNNER_REGISTRATION_TOKEN} - DOCKER_HOST=unix:///var/run/user/1000/docker.sock - DOCKERD_ROOTLESS_ROOTLESSKIT_NET=slirp4netns - DOCKERD_ROOTLESS_ROOTLESSKIT_MTU=65520 depends_on: - gitea networks: - internal_net leantime_db: image: mysql:8.4 container_name: leantime_db restart: unless-stopped environment: MYSQL_ROOT_PASSWORD: ${LEANTIME_DB_ROOT_PASSWORD} MYSQL_DATABASE: leantime MYSQL_USER: leantime MYSQL_PASSWORD: ${LEANTIME_DB_PASSWORD} volumes: - leantime_db_data:/var/lib/mysql networks: - internal_net leantime: image: leantime/leantime:latest container_name: leantime restart: unless-stopped environment: LEAN_DB_HOST: leantime_db LEAN_DB_USER: leantime LEAN_DB_PASSWORD: ${LEANTIME_DB_PASSWORD} LEAN_DB_DATABASE: leantime LEAN_SESSION_PASSWORD: ${LEANTIME_SESSION_PASSWORD} volumes: - leantime_userfiles:/var/www/html/userfiles - leantime_public:/var/www/html/public/userfiles ports: - 8082:8080 depends_on: - leantime_db networks: - internal_net volumes: postgres_data: authentik_media: authentik_custom: gitea_data: runner_data: leantime_db_data: leantime_userfiles: leantime_public: networks: internal_net: driver: bridge