services: db: restart: unless-stopped api: restart: unless-stopped ports: !reset [] web: restart: unless-stopped ports: !override [] healthcheck: test: ["CMD", "wget", "-q", "-O", "/dev/null", "http://127.0.0.1/health"] interval: 10s timeout: 5s retries: 10 gateway: image: nginx:1.30.4-alpine@sha256:97d490c12ba55b4946b01546d1c3ed324e8d41ab1c9fcb2a616aa470620e5b46 restart: unless-stopped ports: - "1236:80" volumes: - ${MOBILITYOPS_GATEWAY_CONFIG:-./deploy/unraid/gateway.conf}:/etc/nginx/conf.d/default.conf:ro depends_on: web: condition: service_healthy healthcheck: test: ["CMD", "wget", "-q", "-O", "/dev/null", "http://127.0.0.1/health"] interval: 10s timeout: 5s retries: 10 networks: [mobilityops] n8n: # The review server already has a shared n8n instance. Keep the bundled service # available for an explicit fallback without starting a second instance by default. profiles: ["bundled-n8n"] restart: unless-stopped ports: !override - "127.0.0.1:15678:5678" healthcheck: test: [ "CMD", "node", "-e", "fetch('http://127.0.0.1:5678/healthz').then(r=>{if(!r.ok)process.exit(1)}).catch(()=>process.exit(1))", ] interval: 10s timeout: 5s retries: 20 backup: image: postgres:16-alpine@sha256:cf78e76683b9ca8c5733cbbdce6c9262b45b6767934dd0a95e671f9a0fc20685 restart: unless-stopped environment: POSTGRES_DB: ${POSTGRES_DB:-mobilityops} POSTGRES_USER: ${POSTGRES_USER:-mobilityops} PGPASSWORD: ${POSTGRES_PASSWORD:-mobilityops} BACKUP_DESTINATION: /backups BACKUP_SECONDARY_DESTINATION: ${BACKUP_SECONDARY_DESTINATION:-} BACKUP_INTERVAL_SECONDS: ${BACKUP_INTERVAL_SECONDS:-86400} BACKUP_RETENTION_DAYS: ${BACKUP_RETENTION_DAYS:-30} BACKUP_MINIMUM_COPIES: ${BACKUP_MINIMUM_COPIES:-7} BACKUP_RESTORE_DRILL_INTERVAL_SECONDS: ${BACKUP_RESTORE_DRILL_INTERVAL_SECONDS:-604800} command: ["/opt/mobilityops/scheduled-backup.sh"] volumes: - ./backups/postgres:/backups - ${MOBILITYOPS_BACKUP_SECONDARY_DIR:-./backups/offsite}:/offsite - ./deploy/unraid:/opt/mobilityops:ro depends_on: db: condition: service_healthy healthcheck: test: [ "CMD-SHELL", "find /backups/latest-success -mmin -1560 -print -quit | grep -q . && find /backups/latest-restore-drill -mmin -11520 -print -quit | grep -q .", ] interval: 30m timeout: 5s retries: 3 start_period: 5m networks: [mobilityops] offsite-backup: profiles: ["offsite"] image: ${MOBILITYOPS_BACKUP_TOOLS_IMAGE:-mobilityops-backup-tools:development} build: context: . dockerfile: deploy/unraid/Dockerfile.backup-tools args: VCS_REF: ${MOBILITYOPS_SOURCE_REVISION:-development} restart: unless-stopped entrypoint: ["/opt/mobilityops/sync-onedrive-backups.sh"] environment: POSTGRES_DB: ${POSTGRES_DB:-mobilityops} POSTGRES_USER: ${POSTGRES_USER:-mobilityops} PGPASSWORD: ${POSTGRES_PASSWORD:-mobilityops} POSTGRES_HOST: db BACKUP_DESTINATION: /backups BACKUP_OFFSITE_VERIFY_DIR: /offsite-verify BACKUP_OFFSITE_INTERVAL_SECONDS: ${BACKUP_OFFSITE_INTERVAL_SECONDS:-900} BACKUP_RESTORE_DRILL_INTERVAL_SECONDS: ${BACKUP_RESTORE_DRILL_INTERVAL_SECONDS:-604800} BACKUP_RETENTION_DAYS: ${BACKUP_RETENTION_DAYS:-30} RCLONE_CONFIG: /config/rclone/rclone.conf RCLONE_ONEDRIVE_REMOTE: ${RCLONE_ONEDRIVE_REMOTE:-onedrive} RCLONE_ONEDRIVE_PATH: ${RCLONE_ONEDRIVE_PATH:-FleetOps/backups} volumes: - ${MOBILITYOPS_BACKUP_DIR:-./backups/postgres}:/backups - ${MOBILITYOPS_OFFSITE_VERIFY_DIR:-./backups/offsite-verify}:/offsite-verify - ${MOBILITYOPS_RCLONE_CONFIG_DIR:-./.secrets/rclone}:/config/rclone - ./deploy/unraid:/opt/mobilityops:ro depends_on: db: condition: service_healthy healthcheck: test: [ "CMD-SHELL", "find /backups/latest-offsite-success -mmin -1560 -print -quit | grep -q . && find /backups/latest-offsite-restore-drill -mmin -11520 -print -quit | grep -q .", ] interval: 30m timeout: 5s retries: 3 start_period: 10m networks: [mobilityops]