version: '3.8' services: backend: build: ./backend ports: - "127.0.0.1:8030:8000" volumes: - ./backend:/app - backend_data:/app/data environment: - DATABASE_URL=${DATABASE_URL:-postgresql://fediversion:fediversion_password@db:5432/fediversion} - SECRET_KEY=${SECRET_KEY:-demo-secret-change-in-production} # Postal SMTP (primary) - SMTP_HOST=${SMTP_HOST} - SMTP_PORT=${SMTP_PORT:-25} - SMTP_USERNAME=${SMTP_USERNAME} - SMTP_PASSWORD=${SMTP_PASSWORD} - SMTP_USE_TLS=${SMTP_USE_TLS:-true} # AWS SES (fallback) - AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID} - AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY} - AWS_SES_REGION=${AWS_SES_REGION} # Common - EMAIL_FROM=${EMAIL_FROM:-noreply@fediversion.xyz} - FRONTEND_URL=${FRONTEND_URL:-https://fediversion.xyz} # Data Import API Keys - PHISHNET_API_KEY=${PHISHNET_API_KEY} - SETLISTFM_API_KEY=${SETLISTFM_API_KEY} - GRATEFULSTATS_API_KEY=${GRATEFULSTATS_API_KEY} command: sh start.sh depends_on: - db restart: unless-stopped healthcheck: test: [ "CMD", "python", "-c", "import httpx; httpx.get('http://localhost:8000/docs').raise_for_status()" ] interval: 30s timeout: 10s retries: 3 networks: - fediversion - traefik-public - postal-internal labels: - "traefik.enable=true" - "traefik.http.routers.fediversion-backend.rule=Host(`fediversion.runfoo.run`) && PathPrefix(`/api`)" - "traefik.http.routers.fediversion-backend.entrypoints=websecure" - "traefik.http.routers.fediversion-backend.tls.certresolver=letsencrypt" - "traefik.http.routers.fediversion-backend.priority=100" - "traefik.http.middlewares.fediversion-strip.stripprefix.prefixes=/api" - "traefik.http.routers.fediversion-backend.middlewares=fediversion-strip" - "traefik.http.routers.fediversion-backend.service=fediversion-backend-svc" - "traefik.http.services.fediversion-backend-svc.loadbalancer.server.port=8000" - "traefik.docker.network=traefik" # Direct routes for docs (no strip) - "traefik.http.routers.fediversion-backend-docs.rule=Host(`fediversion.runfoo.run`) && PathPrefix(`/docs`, `/openapi.json`)" - "traefik.http.routers.fediversion-backend-docs.entrypoints=websecure" - "traefik.http.routers.fediversion-backend-docs.tls.certresolver=letsencrypt" - "traefik.http.routers.fediversion-backend-docs.priority=100" - "traefik.http.routers.fediversion-backend-docs.service=fediversion-backend-svc" frontend: build: context: ./frontend dockerfile: Dockerfile ports: - "127.0.0.1:3030:3000" volumes: - ./frontend:/app - /app/node_modules environment: - NEXT_PUBLIC_API_URL=/api - INTERNAL_API_URL=http://backend:8000 depends_on: backend: condition: service_healthy restart: unless-stopped networks: - fediversion - traefik-public labels: - "traefik.enable=true" - "traefik.http.routers.fediversion-frontend.rule=Host(`fediversion.runfoo.run`) && !PathPrefix(`/api`, `/docs`, `/openapi.json`)" - "traefik.http.routers.fediversion-frontend.entrypoints=websecure" - "traefik.http.routers.fediversion-frontend.tls.certresolver=letsencrypt" - "traefik.http.routers.fediversion-frontend.priority=50" - "traefik.http.services.fediversion-frontend.loadbalancer.server.port=3000" - "traefik.docker.network=traefik" db: image: postgres:15-alpine environment: - POSTGRES_USER=fediversion - POSTGRES_PASSWORD=fediversion_password - POSTGRES_DB=fediversion volumes: - postgres_data:/var/lib/postgresql/data restart: unless-stopped healthcheck: test: [ "CMD-SHELL", "pg_isready -U fediversion -d fediversion" ] interval: 10s timeout: 5s retries: 5 networks: - fediversion db-backup: image: prodrigestivill/postgres-backup-local:15-alpine restart: unless-stopped volumes: - ./backups:/backups - postgres_data:/var/lib/postgresql/data:ro environment: - POSTGRES_HOST=db - POSTGRES_DB=fediversion - POSTGRES_USER=fediversion - POSTGRES_PASSWORD=fediversion_password - SCHEDULE=@daily - BACKUP_KEEP_DAYS=7 - BACKUP_KEEP_WEEKS=4 - BACKUP_KEEP_MONTHS=6 - HEALTHCHECK_PORT=80 depends_on: - db networks: - fediversion umami: image: ghcr.io/umami-software/umami:postgresql-latest restart: unless-stopped environment: - DATABASE_URL=postgresql://umami:umami_password@umami-db:5432/umami - APP_SECRET=${UMAMI_SECRET:-highly-secret-key-change-this} - TRACKER_SCRIPT_NAME=stats depends_on: - umami-db networks: - fediversion - traefik-public labels: - "traefik.enable=true" - "traefik.http.routers.fediversion-umami.rule=Host(`stats.fediversion.runfoo.run`)" - "traefik.http.routers.fediversion-umami.entrypoints=websecure" - "traefik.http.routers.fediversion-umami.tls.certresolver=letsencrypt" - "traefik.http.services.fediversion-umami.loadbalancer.server.port=3000" - "traefik.docker.network=${TRAEFIK_NETWORK:-traefik}" umami-db: image: postgres:15-alpine environment: - POSTGRES_USER=umami - POSTGRES_PASSWORD=umami_password - POSTGRES_DB=umami volumes: - umami_data:/var/lib/postgresql/data restart: unless-stopped networks: - fediversion volumes: postgres_data: backend_data: umami_data: networks: fediversion: traefik-public: name: ${TRAEFIK_NETWORK:-traefik} external: true postal-internal: name: postal_postal-internal external: true