version: "3.9" networks: traefik-network: name: traefik-network external: true # this network isolates Gitea server-runner communication from other services gitea-network: name: gitea-network services: server: image: docker.gitea.com/gitea:1.25.3-rootless networks: - traefik-network - gitea-network restart: always stop_grace_period: 1m # Allow Gitea time to shut down gracefully # Standalone Compose resource limits (commonly honored by Docker Compose v2) cpus: "1.0" mem_limit: 2g mem_reservation: 512m pids_limit: 512 healthcheck: test: ["CMD", "wget", "-q", "--spider", "http://localhost:3000/api/healthz"] interval: 30s timeout: 5s retries: 3 start_period: 200s volumes: - /home/knee-cola/docker/d-gitea/data:/var/lib/gitea - /home/knee-cola/docker/d-gitea/config:/etc/gitea - /etc/timezone:/etc/timezone:ro - /etc/localtime:/etc/localtime:ro # HTTP handled by Traefik; expose is optional but clarifies intent expose: - "3000" ports: - "2222:2222" # SSH port environment: # Ensure Gitea generates correct URLs (adjust if you terminate TLS at Traefik) - GITEA__server__DOMAIN=gitea.budakova.org - GITEA__server__ROOT_URL=https://gitea.budakova.org/ - GITEA__server__PROTOCOL=http # Traefik handles TLS - GITEA__server__SSH_PORT=2222 - GITEA__server__SSH_DOMAIN=git.budakova.org # CloudFlare tunnel hostname for SSH access (must not collide with web console hostname) # Enable Docker Registry support - GITEA__packages__ENABLED=true # Set public URL detection to auto so that server # supports multiple hostnames (for registry and web console) - GITEA__server__PUBLIC_URL_DETECTION=auto labels: - traefik.enable=true - traefik.docker.network=traefik-network - traefik.http.services.gitea.loadbalancer.server.port=3000 # Web Console - traefik.http.routers.gitea.rule=Host(`gitea.budakova.org`) - traefik.http.routers.gitea.entrypoints=http # using `http` - see notes below # Note: NOT using `https` entrypoint since CloudFlare does SSL offloading # Also CloudFlare tunnel rejects Let's Encrypt cert since it sees # the server as running at https://10.10.1.200:443 and NOT as `gitea.budakova.org` # - traefik.http.routers.gitea.entrypoints=https # - traefik.http.routers.gitea.tls=true # - traefik.http.routers.gitea.tls.certresolver=letsencrypt # Registry (only /v2) # Note: here we can use `https` since it's not published via CloudFlare # but via local IP address - traefik.http.routers.gitea-registry.entrypoints=https - traefik.http.routers.gitea-registry.rule=Host(`registry.budakova.org`) && PathPrefix(`/v2`) - traefik.http.routers.gitea-registry.tls=true - traefik.http.routers.gitea-registry.tls.certresolver=letsencrypt - traefik.http.routers.gitea-registry.service=gitea runner: image: docker.io/gitea/act_runner:0.2.13 networks: - gitea-network restart: always depends_on: - server # Resource limits for CI/CD runner cpus: "2.0" mem_limit: 4g mem_reservation: 1g pids_limit: 512 environment: CONFIG_FILE: /config.yaml # use service name `server` since both services are on the same `gitea-network` GITEA_INSTANCE_URL: "http://server:3000/" GITEA_RUNNER_REGISTRATION_TOKEN: "${REGISTRATION_TOKEN:-cOUnze8BFR5OhW30pcdfCL4oSvSXbsd4PUqDzo6Y}" GITEA_RUNNER_NAME: "${GITEA_RUNNER_NAME:-gitea-runner-1}" volumes: - /home/knee-cola/docker/d-gitea/runner-config.yaml:/config.yaml - /home/knee-cola/docker/d-gitea/runner-data:/data - /var/run/docker.sock:/var/run/docker.sock