Self-hosted Nango on Railway
Human.work uses the D-28 hybrid integration strategy: existing Shopify/Amazon integrations remain bespoke, while new OAuth SaaS vendors such as QuickBooks and Xero route through a single self-hosted Nango environment. Per-org isolation is enforced at the Nango connectionId layer using {org_slug}`-`{provider}.
Nango is Elastic License v2. OQ-203 must be ratified by Eusden before production rollout.
Railway shape
Create these services in the humanwork Railway project:
nango-serverfrom Docker imagenangohq/nango-server:hostednango-dbas Railway Postgres 16 with a persistent volume- reuse the existing humanwork Redis service via
REDIS_URL
Railway deployments
Railway project: humanwork (ee0b91b9-1c2b-4e4c-b457-5a3f9c5cbdd5) in the Humanity workspace.
| Railway env | Nango server | Nango DB | Redis | Public URL |
|---|---|---|---|---|
dev (0303be2d-a70d-4cbc-8f01-e80b6c855440) | nango-server (f3f28f14-8212-4295-8b4e-db7bddc3874c) | nango-db (1c0a05b5-b0ab-4f77-9ef2-9de9f1a4ea81) | redis-dev | https://nango-server-dev-e568.up.railway.app |
staging (e1e7f4d9-3819-4607-be1f-0c23b87cea59) | nango-server-staging (bfd6ed57-1ee6-4ff1-8fe2-55f0d03ae569) | nango-db-staging (fb8fcf1a-a18f-4812-adfb-ba6d2dbde824) | redis-staging | https://nango-server-staging-staging.up.railway.app |
production (caa0a321-13be-4ad6-a6ef-ad7a0a82f57b) | nango-server-production (a061cc92-107c-4ee5-b953-e0b94e76ed15) | nango-db-production (b86e1b80-7a7e-4a9d-8e8c-d0da387d2766) | redis | https://nango-server-production-production.up.railway.app |
Each Nango DB service runs postgres:16-alpine with a persistent Railway volume mounted at /var/lib/postgresql/data and PGDATA=/var/lib/postgresql/data/pgdata.
The api service in each Railway environment has NANGO_SERVER_URL and NANGO_SECRET_KEY configured from the matching Nango instance: dev uses the Nango dev API key; staging and production use their instance's Nango prod API key.
Required nango-server variables
NANGO_ENCRYPTION_KEY: 32-byte random secret. Do not rotate without taking anango-dbbackup and scheduling a maintenance window.NANGO_DB_USERNANGO_DB_PASSWORDNANGO_DB_HOSTNANGO_DB_NAMEREDIS_URL: existing humanwork Redis URLNANGO_DASHBOARD_USERNAMENANGO_DASHBOARD_PASSWORDNANGO_SERVER_URL: Railway internal/public service URL used by API servicesNANGO_PUBLIC_SERVER_URL: externally reachable URL for OAuth redirects
If customer-facing OAuth screens are needed, put Cloudflare in front of nango-server and set NANGO_PUBLIC_SERVER_URL to that hostname.
Humanwork API variables
Set these on the API service:
NANGO_SERVER_URLNANGO_SECRET_KEY
The NestJS NangoModule uses those to trigger Nango actions from /v1/agent-api/tools/:toolName registry dispatch.
Catalog & SA enablement
The SuperAdmin client Integrations tab searches the Nango provider catalog through the Humanwork API:
GET /v1/admin/integrations/catalog?q=<provider>
At the pinned self-hosted deployment (nangohq/nango-server:hosted), GET {NANGO_SERVER_URL}/providers is available as the canonical installable-provider catalog. An unauthenticated smoke against the dev Nango service returns 401 missing_auth_header rather than 404, so the backend uses that endpoint with Authorization: Bearer ${NANGO_SECRET_KEY}`` and caches the normalized catalog in process for one hour.
If a future pinned Nango image returns 404 for /providers, the backend falls back to https://docs.nango.dev/providers.json as the public catalog source.
SuperAdmin catalog selection is metadata-only: selecting a provider writes enabled=true to the org's tool_permissions row for that provider key. It does not modify api/src/agent-api/tool-registry.ts or wire dispatch. Agent-call handlers remain engineer-curated in the registry; SuperAdmin enablement only controls whether the client can see and start the provider connection flow.
Health checks
From another Railway service in the same project:
curl -f "$NANGO_SERVER_URL/health"
Dashboard smoke:
- Open the Railway-assigned domain or Cloudflare hostname.
- Log in with
NANGO_DASHBOARD_USERNAME/NANGO_DASHBOARD_PASSWORD. - Confirm the dashboard can list/create provider configs.
Database smoke from nango-server shell:
psql "postgresql://${NANGO_DB_USER}:${NANGO_DB_PASSWORD}@${NANGO_DB_HOST}/${NANGO_DB_NAME}" -c 'select 1'
Backup and rotation
Before changing NANGO_ENCRYPTION_KEY:
- Stop OAuth write traffic.
- Take a Railway Postgres backup of
nango-db. - Export the current
NANGO_ENCRYPTION_KEYinto the incident/change record. - Rotate the key only with a tested Nango re-encryption procedure.
- Validate existing connections by triggering a harmless action per provider.
No key rotation is allowed without a backup because encrypted connection credentials can become unrecoverable.
Open operational questions
- OQ-203: ratify Nango Elastic License v2 before production rollout.
- OQ-207: finalize tested encryption-key rotation and disaster-recovery procedure.