services: web: build: . restart: unless-stopped ports: ["80:80", "443:443"] environment: SITE_ADDRESS: ${SITE_ADDRESS:-localhost} volumes: [caddy_data:/data, caddy_config:/config] depends_on: [tracker] tracker: build: { context: ., dockerfile: tracker/Dockerfile } restart: unless-stopped environment: DATABASE_URL: postgresql://tracker_rw:${TRACKER_PASSWORD}@db:5432/${POSTGRES_DB} TRACKER_SECRET: ${TRACKER_SECRET} SITE_HOST: ${SITE_HOST} volumes: ["./geoip:/data:ro"] depends_on: { db: { condition: service_healthy } } linkcheck: build: { context: ., dockerfile: tracker/Dockerfile } restart: unless-stopped command: ["sh", "-c", "while true; do python check_links.py; sleep 86400; done"] environment: DATABASE_URL: postgresql://tracker_rw:${TRACKER_PASSWORD}@db:5432/${POSTGRES_DB} KUMA_PUSH_URL: ${KUMA_LINKS_PUSH_URL:-} depends_on: { db: { condition: service_healthy } } db: image: postgres:16-alpine restart: unless-stopped environment: POSTGRES_USER: ${POSTGRES_USER} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} POSTGRES_DB: ${POSTGRES_DB} TRACKER_PASSWORD: ${TRACKER_PASSWORD} STATS_RO_PASSWORD: ${STATS_RO_PASSWORD} volumes: - pgdata:/var/lib/postgresql/data - ./db/init:/docker-entrypoint-initdb.d:ro # Published only on the WireGuard address, so the read-only user is reachable over WireGuard ports: ["${PG_BIND:-127.0.0.1:5432}:5432"] healthcheck: test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"] interval: 5s retries: 10 backup: build: { context: ., dockerfile: backup/Dockerfile } restart: unless-stopped environment: POSTGRES_USER: ${POSTGRES_USER} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} POSTGRES_DB: ${POSTGRES_DB} BACKUP_TARGET: ${BACKUP_TARGET} BACKUP_PORT: ${BACKUP_PORT:-22} KUMA_BACKUP_PUSH_URL: ${KUMA_BACKUP_PUSH_URL:-} volumes: ["./backup-ssh:/ssh:ro"] depends_on: { db: { condition: service_healthy } } kuma: image: louislam/uptime-kuma:1 restart: unless-stopped ports: ["${KUMA_BIND:-127.0.0.1:3001}:3001"] volumes: [kuma_data:/app/data] volumes: { pgdata: {}, caddy_data: {}, caddy_config: {}, kuma_data: {} }