Files
MobilityOps/deploy/unraid
NuklearRabbit ae39a8947f
MobilityOps acceptance / backend (push) Failing after 45s
MobilityOps acceptance / frontend (push) Successful in 32s
MobilityOps acceptance / e2e (push) Skipped
M39: harden application and acceptance gates
2026-08-17 03:17:44 +02:00
..

Unraid deployment

MobilityOps is deployed from a committed source archive; the server does not need Gitea credentials. The portable compose.yaml is combined with compose.unraid.yaml; of the MobilityOps-owned services, only the web application is reachable from the LAN. The host's existing shared n8n remains available on its established port 5678.

Server layout

  • Directory: /mnt/user/appdata/mobilityops
  • Compose project: mobilityops
  • Web: http://192.168.10.150:1236 (1236 on the host to 80 in web)
  • API and PostgreSQL: Compose network only
  • Shared n8n: http://192.168.10.150:5678 (outside the MobilityOps Compose project)

Deploy

Create .env from .env.example, replace every placeholder secret, set MOBILITYOPS_ENV=production, set both public URLs to http://192.168.10.150:1236, and retain KNOWLEDGE_PROVIDER=demo while RAGcore is not available. Keep MCP_HUB_REGISTRATION_ENABLED=false until the central Hub is ready.

cd /mnt/user/appdata/mobilityops
./deploy/unraid/configure-env.sh \
  http://192.168.10.150:1236 \
  http://192.168.10.150:5678/webhook/mobilityops-return
docker compose -p mobilityops -f compose.yaml -f compose.unraid.yaml up --build -d db api web backup
docker compose -p mobilityops -f compose.yaml -f compose.unraid.yaml exec api \
  python -m app.cli seed --reset

Migrations run automatically in the API entrypoint. Import and publish the MobilityOps workflow into the existing n8n container:

./deploy/unraid/setup-existing-n8n.sh \
  n8n \
  http://192.168.10.150:1236/api/v1/integrations/n8n/return-callback

The callback token remains server-side and is never written to the repository. The bundled n8n service is retained only as a standalone fallback behind the explicit bundled-n8n Compose profile; it is not started in this deployment.

Operate

cd /mnt/user/appdata/mobilityops
docker compose -p mobilityops -f compose.yaml -f compose.unraid.yaml ps
docker compose -p mobilityops -f compose.yaml -f compose.unraid.yaml logs --tail=200
docker compose -p mobilityops -f compose.yaml -f compose.unraid.yaml exec api alembic current
docker logs --tail=200 n8n

Backup and restore

The backup service creates a backup immediately and then every 24 hours. Every dump is validated with pg_restore --list, receives a SHA-256 sidecar and is retained for 30 days with at least seven copies protected from pruning. Its healthcheck becomes unhealthy when no successful backup has been recorded for 26 hours. Configure BACKUP_SECONDARY_DESTINATION=/offsite plus an independently mounted MOBILITYOPS_BACKUP_SECONDARY_DIR for a second copy.

Create an additional on-demand backup or verify the newest scheduled backup:

./deploy/unraid/backup-postgres.sh
./deploy/unraid/verify-postgres-backups.sh

A restore is deliberately guarded and creates an additional safety backup before replacing the database:

./deploy/unraid/restore-postgres.sh \
  backups/postgres/mobilityops-YYYYMMDDTHHMMSSZ.dump \
  RESTORE-MOBILITYOPS

The restore stops the API, recreates only the configured MobilityOps database, restarts API/web and verifies the active Alembic revision. Test restores in a disposable environment before using a production backup for incident recovery.