services: backend: &default_backend build: &default_backend_build context: . dockerfile: packages/backend/Dockerfile # these args configure private env vars for the backend and public env vars for the frontend args: &default_backend_build_args ADMIN_USER: ${ADMIN_USER} ADMIN_EMAIL: ${ADMIN_EMAIL} ADMIN_PASSWORD: ${ADMIN_PASSWORD} JWT_SECRET: ${JWT_SECRET} DOMAIN_NAME: ${DOMAIN_NAME} CACHE_DOMAIN: ${CACHE_DOMAIN} MEDIA_DOMAIN: ${MEDIA_DOMAIN} SMTP_HOST: ${SMTP_HOST} SMTP_USER: ${SMTP_USER} SMTP_PORT: ${SMTP_PORT} SMTP_PASSWORD: ${SMTP_PASSWORD} SMTP_FROM: ${SMTP_FROM} POSTGRES_USER: ${POSTGRES_USER} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} POSTGRES_DBNAME: ${POSTGRES_DBNAME} WEBPUSH_EMAIL: ${WEBPUSH_EMAIL} WEBPUSH_PRIVATE: ${WEBPUSH_PRIVATE} WEBPUSH_PUBLIC: ${WEBPUSH_PUBLIC} ENABLE_BSKY: ${ENABLE_BSKY} PDS_DOMAIN_NAME: ${PDS_DOMAIN_NAME} PDS_JWT_SECRET: ${PDS_JWT_SECRET} PDS_ADMIN_PASSWORD: ${PDS_ADMIN_PASSWORD} USE_WORKERS: false LOG_SQL_QUERIES: ${LOG_SQL_QUERIES:-} UPLOAD_LIMIT: ${UPLOAD_LIMIT:-} POSTS_PER_PAGE: ${POSTS_PER_PAGE:-} LOG_LEVEL: ${LOG_LEVEL:-} BLOCKLIST_URI: ${BLOCKLIST_URI:-} FRONTEND_PATH: ${FRONTEND_PATH:-} DISABLE_REQUIRE_SEND_EMAIL: ${DISABLE_REQUIRE_SEND_EMAIL:-} BLOCKED_IPS: ${BLOCKED_IPS:-} REVIEW_REGISTRATIONS: ${REVIEW_REGISTRATIONS:-} IGNORE_BLOCK_HOSTS: ${IGNORE_BLOCK_HOSTS:-} FRONTEND_LOGO: ${FRONTEND_LOGO:-} FRONTEND_API_URL: ${FRONTEND_API_URL:-} FRONTEND_MEDIA_URL: ${FRONTEND_MEDIA_URL:-} FRONTEND_CACHE_URL: ${FRONTEND_CACHE_URL:-} FRONTEND_CACHE_BACKUP_URLS: ${FRONTEND_CACHE_BACKUP_URLS:-} FRONTEND_SHORTEN_POSTS: ${FRONTEND_SHORTEN_POSTS:-} FRONTEND_DISABLE_PWA: ${FRONTEND_DISABLE_PWA:-} FRONTEND_MAINTENANCE: ${FRONTEND_MAINTENANCE:-} FRONTEND_SHORT_TITLE: ${FRONTEND_SHORT_TITLE:-} FRONTEND_LONG_TITLE: ${FRONTEND_LONG_TITLE:-} FRONTEND_DESCRIPTION: ${FRONTEND_DESCRIPTION:-} depends_on: db: condition: service_healthy redis: condition: service_started frontend: condition: service_started migration: condition: service_completed_successfully restart: unless-stopped environment: - NODE_ENV=production volumes: - ./packages/backend/uploads:/app/packages/backend/uploads - ./packages/backend/cache:/app/packages/backend/cache - frontend:/app/packages/frontend:ro migration: <<: *default_backend depends_on: db: condition: service_healthy redis: condition: service_started frontend: condition: service_started restart: no command: "npm exec tsx migrate.ts init-container" frontend: restart: unless-stopped build: context: . dockerfile: packages/frontend/Dockerfile args: DOMAIN_NAME: ${DOMAIN_NAME} PDS_DOMAIN_NAME: ${PDS_DOMAIN_NAME} CACHE_DOMAIN: ${CACHE_DOMAIN} MEDIA_DOMAIN: ${MEDIA_DOMAIN} ACME_EMAIL: ${ACME_EMAIL} FRONTEND_SHORT_TITLE: ${FRONTEND_SHORT_TITLE:-} FRONTEND_LONG_TITLE: ${FRONTEND_LONG_TITLE:-} FRONTEND_DESCRIPTION: ${FRONTEND_DESCRIPTION:-} CACHE_HOST: "cache:9000" ports: - 80:80 - 443:443 volumes: - "caddy:/data" - "frontend:/var/www/html/frontend" - ./packages/backend/uploads:/var/www/html/uploads - ./packages/caddy:/etc/caddy/config db: build: context: monitoring/database dockerfile: Dockerfile restart: unless-stopped shm_size: '2gb' environment: POSTGRES_USER: ${POSTGRES_USER} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} POSTGRES_DB: ${POSTGRES_DBNAME} POSTGRES_METRICS_USER: ${POSTGRES_METRICS_USER} POSTGRES_METRICS_PASSWORD: ${POSTGRES_METRICS_PASSWORD} POSTGRES_METRICS_DBNAME: ${POSTGRES_METRICS_DBNAME} volumes: - dbpg:/var/lib/postgresql/data adminer: image: adminer restart: unless-stopped redis: image: redis:7.2.4 restart: unless-stopped volumes: - redis:/data pds: image: ghcr.io/bluesky-social/pds:0.4 restart: unless-stopped profiles: - bluesky environment: PDS_HOSTNAME: ${PDS_DOMAIN_NAME} PDS_JWT_SECRET: ${PDS_JWT_SECRET} PDS_ADMIN_PASSWORD: ${PDS_ADMIN_PASSWORD} PDS_PLC_ROTATION_KEY_K256_PRIVATE_KEY_HEX: ${PDS_PLC_ROTATION_KEY_K256_PRIVATE_KEY_HEX} PDS_DATA_DIRECTORY: /pds PDS_BLOBSTORE_DISK_LOCATION: /pds/blocks PDS_BLOB_UPLOAD_LIMIT: 52428800 PDS_DID_PLC_URL: "https://plc.directory" PDS_BSKY_APP_VIEW_URL: "https://api.bsky.app" PDS_BSKY_APP_VIEW_DID: "did:web:api.bsky.app" PDS_REPORT_SERVICE_URL: "https://mod.bsky.app" PDS_REPORT_SERVICE_DID: "did:plc:ar7c4by46qjdydhdevvrndac" PDS_CRAWLERS: "https://bsky.network, https://atproto.africa" PDS_EMAIL_SMTP_URL: "smtps://${SMTP_USER}:${SMTP_PASSWORD}@${SMTP_HOST}:${SMTP_PORT}" PDS_EMAIL_FROM_ADDRESS: "${SMTP_USER}" LOG_ENABLED: true volumes: - pds:/pds pds_worker: <<: *default_backend profiles: - bluesky command: "npm exec tsx atproto.ts" cache: <<: *default_backend workers: <<: *default_backend build: <<: *default_backend_build args: <<: *default_backend_build_args USE_WORKERS: true deploy: mode: replicated replicas: 3 prometheus: restart: unless-stopped image: prom/prometheus:latest volumes: - ./monitoring/prometheus.yml:/etc/prometheus/prometheus.yml - prometheus_data:/prometheus command: - '--config.file=/etc/prometheus/prometheus.yml' - '--storage.tsdb.path=/prometheus' - '--web.console.libraries=/usr/share/prometheus/console_libraries' - '--web.console.templates=/usr/share/prometheus/consoles' cadvisor: restart: unless-stopped image: gcr.io/cadvisor/cadvisor:latest command: - '-port=8081' environment: CADVISOR_HEALTHCHECK_URL: http://localhost:8081/healthz volumes: - /:/rootfs:ro - /var/run:/var/run:rw - /sys:/sys:ro - /var/lib/docker/:/var/lib/docker:ro node-exporter: restart: unless-stopped image: prom/node-exporter:latest volumes: - /proc:/host/proc:ro - /sys:/host/sys:ro - /:/rootfs:ro command: - '--path.procfs=/host/proc' - '--path.sysfs=/host/sys' - '--collector.filesystem.ignored-mount-points="^/(sys|proc|dev|host|etc)($$|/)"' grafana: build: context: monitoring/grafana dockerfile: Dockerfile volumes: - grafana_data:/var/lib/grafana restart: unless-stopped environment: GF_SERVER_HTTP_PORT: 2345 GF_SECURITY_ADMIN_PASSWORD: ${GF_SECURITY_ADMIN_PASSWORD} GF_USERS_ALLOW_SIGN_UP: false GF_SMTP_ENABLED: true GF_SMTP_HOST: ${SMTP_HOST}:${SMTP_PORT} GF_SMTP_FROM_ADDRESS: ${SMTP_FROM} GF_SERVER_DOMAIN: ${DOMAIN_NAME} GF_SMTP_FROM_NAME: ${SMTP_FROM} GF_SMTP_USER: "${SMTP_USER}" GF_SMTP_PASSWORD: "${SMTP_PASSWORD}" POSTGRES_METRICS_USER: ${POSTGRES_METRICS_USER} POSTGRES_METRICS_PASSWORD: ${POSTGRES_METRICS_PASSWORD} POSTGRES_METRICS_DBNAME: ${POSTGRES_METRICS_DBNAME} pgwatch: build: context: monitoring/pgwatch dockerfile: Dockerfile args: POSTGRES_USER: ${POSTGRES_USER} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} POSTGRES_DB: ${POSTGRES_DBNAME} restart: unless-stopped environment: POSTGRES_METRICS_USER: ${POSTGRES_METRICS_USER} POSTGRES_METRICS_PASSWORD: ${POSTGRES_METRICS_PASSWORD} POSTGRES_METRICS_DBNAME: ${POSTGRES_METRICS_DBNAME} command: - "--web-disable=all" - "--sources=/sources.yaml" - "--sink=postgresql://${POSTGRES_METRICS_USER}:${POSTGRES_METRICS_PASSWORD}@db:5432/${POSTGRES_METRICS_DBNAME}" depends_on: db: condition: service_healthy volumes: dbpg: caddy: pds: frontend: redis: prometheus_data: grafana_data: