services: traefik: image: traefik:v3.6 restart: unless-stopped ports: - "80:80" - "443:443" command: - --api.dashboard=false - --providers.docker=true - --providers.docker.exposedbydefault=false - --providers.docker.network=ops - --entrypoints.web.address=:80 - --entrypoints.websecure.address=:443 - --entrypoints.web.http.redirections.entrypoint.to=websecure - --entrypoints.web.http.redirections.entrypoint.scheme=https - --certificatesresolvers.cloudflare.acme.dnschallenge=true - --certificatesresolvers.cloudflare.acme.dnschallenge.provider=cloudflare - --certificatesresolvers.cloudflare.acme.email=${ACME_EMAIL} - --certificatesresolvers.cloudflare.acme.storage=/letsencrypt/acme.json environment: - CF_DNS_API_TOKEN=${CF_DNS_API_TOKEN} volumes: - /var/run/docker.sock:/var/run/docker.sock:ro - traefik-certs:/letsencrypt networks: - ops registry: image: registry:2 restart: unless-stopped ports: - "5000:5000" volumes: - registry-data:/var/lib/registry environment: - REGISTRY_STORAGE_DELETE_ENABLED=true networks: - ops forgejo: image: codeberg.org/forgejo/forgejo:11 restart: unless-stopped environment: - USER_UID=1000 - USER_GID=1000 - FORGEJO__server__DOMAIN=source.${DOMAIN} - FORGEJO__server__ROOT_URL=https://source.${DOMAIN} - FORGEJO__server__SSH_DOMAIN=source.${DOMAIN} - FORGEJO__server__SSH_PORT=22 - FORGEJO__server__SSH_LISTEN_PORT=2222 - FORGEJO__database__DB_TYPE=sqlite3 - FORGEJO__service__DISABLE_REGISTRATION=false - FORGEJO__service__ALLOW_ONLY_EXTERNAL_REGISTRATION=true - FORGEJO__webhook__ALLOWED_HOST_LIST=external,loopback,10.0.0.0/24 - FORGEJO__security__INSTALL_LOCK=true - FORGEJO__actions__ENABLED=false volumes: - forgejo-data:/data ports: - "2222:2222" labels: - traefik.enable=true - traefik.http.routers.forgejo.rule=Host(`source.${DOMAIN}`) - traefik.http.routers.forgejo.tls=true - traefik.http.routers.forgejo.tls.certresolver=cloudflare - traefik.http.services.forgejo.loadbalancer.server.port=3000 networks: - ops woodpecker: image: woodpeckerci/woodpecker-server:v3 restart: unless-stopped environment: - WOODPECKER_HOST=https://ci.${DOMAIN} - WOODPECKER_FORGEJO=true - WOODPECKER_FORGEJO_URL=https://source.${DOMAIN} - WOODPECKER_OPEN=true - WOODPECKER_FORGEJO_CLIENT=${WOODPECKER_FORGEJO_CLIENT} - WOODPECKER_FORGEJO_SECRET=${WOODPECKER_FORGEJO_SECRET} - WOODPECKER_AGENT_SECRET=${WOODPECKER_AGENT_SECRET} - WOODPECKER_ADMIN=${WOODPECKER_ADMIN} volumes: - woodpecker-data:/var/lib/woodpecker depends_on: - forgejo labels: - traefik.enable=true - traefik.http.routers.woodpecker.rule=Host(`ci.${DOMAIN}`) - traefik.http.routers.woodpecker.tls=true - traefik.http.routers.woodpecker.tls.certresolver=cloudflare - traefik.http.services.woodpecker.loadbalancer.server.port=8000 networks: - ops woodpecker-agent: image: woodpeckerci/woodpecker-agent:v3 restart: unless-stopped environment: - WOODPECKER_SERVER=woodpecker:9000 - WOODPECKER_AGENT_SECRET=${WOODPECKER_AGENT_SECRET} - WOODPECKER_BACKEND_DOCKER_NETWORK=writekit_ops - WOODPECKER_BACKEND_DOCKER_VOLUMES=/opt/writekit/.ssh:/mnt/ssh:ro - DOCKER_HOST=unix:///var/run/docker.sock volumes: - /var/run/docker.sock:/var/run/docker.sock depends_on: - woodpecker networks: - ops networks: ops: volumes: traefik-certs: registry-data: forgejo-data: woodpecker-data: