| name | running-and-testing-locally |
| description | Use when running the Nango application locally for development and browser testing - covers Docker services, dev commands, service URLs, and troubleshooting startup issues |
Running and Testing Nango Locally
Overview
Nango runs as a set of microservices (server, webapp, jobs, persist, orchestrator, metering, connect-ui) backed by Docker containers (PostgreSQL, Redis, Elasticsearch, ActiveMQ). Two terminal sessions are needed: one for TypeScript watch-build, one for running services.
Quick Reference
| Command | Purpose | When to use |
|---|
npm run dev:docker | Start Docker deps (DB, Redis, ES, ActiveMQ) | First step, once per session |
npm run dev:watch (alias dw) | TypeScript watch-build | Terminal 1 — always running |
npm run dev:watch:apps (alias dwa) | Run all services | Terminal 2 — full stack |
npm run dev:watch:web | Run server + webapp + connect-ui only | Terminal 2 — frontend work |
npm run dev:watch:headless (alias dwh) | Run backend services only (no UI) | Terminal 2 — backend work |
Service URLs
Step-by-Step Startup
npm install
if [ ! -f .env ]; then
cp .env.example .env
echo "NANGO_ENCRYPTION_KEY=$(openssl rand -base64 32)" >> .env
echo "FLAG_AUTH_ENABLED=true" >> .env
echo "FLAG_AUTH_ROLES_ENABLED=true" >> .env
fi
npm run dev:docker
npm run dev:watch
npm run dev:watch:apps
If .env already exists but is missing required settings, ensure the following are set:
NANGO_ENCRYPTION_KEY — required for persist service and Connect UI (openssl rand -base64 32 to generate)
FLAG_AUTH_ENABLED=true — required for login/signup UI to appear
FLAG_AUTH_ROLES_ENABLED=true — optional, enables RBAC
Wait for the TypeScript build to complete in Terminal 1 before starting services in Terminal 2. The server runs database migrations automatically on startup (NANGO_MIGRATE_AT_START defaults to true).
Selective Service Commands
Run individual services when you only need to restart one:
npm run server:dev:watch
npm run webapp:dev:watch
npm run connect-ui:dev:watch
npm run jobs:dev:watch
npm run persist:dev:watch
npm run orchestrator:dev:watch
npm run metering:dev:watch
Environment Configuration
The .env file at repo root configures local dev (copy from .env.example if it doesn't exist). Key settings:
SERVER_PORT=3003
NANGO_SERVER_URL=http://localhost:3003
NANGO_PUBLIC_SERVER_URL=http://localhost:3000
NANGO_PUBLIC_CONNECT_URL=http://localhost:3009
FLAG_AUTH_ENABLED=true
FLAG_AUTH_ROLES_ENABLED=true
FLAG_SERVE_CONNECT_UI=true
NANGO_LOGS_ENABLED="false"
ORCHESTRATOR_SERVICE_URL="http://localhost:3008"
NANGO_ENCRYPTION_KEY is required for the persist service and Connect UI to start (generate with openssl rand -base64 32 and add to .env).
Browser Testing Workflow
Capturing Server Logs for Verification URLs
When testing signup/email flows, the verification URL is logged to the server output. concurrently (used by dev:watch:apps) buffers child process output, so redirecting to a file doesn't reliably capture [srv] lines from a non-interactive shell. Two approaches:
Option A — Run the server separately with a Python PTY wrapper (autonomous):
Run the server process directly with a pseudo-TTY to avoid buffering, while running other services normally. The --watch flag is required so the server auto-restarts when files change (without it, code changes require a manual restart):
python3 -c "
import pty, os
pid, fd = pty.fork()
if pid == 0:
os.chdir('packages/server')
os.environ['DOTENV_CONFIG_PATH'] = './../../.env'
os.execvp('npx', ['npx', 'tsx', '--watch', '-r', 'dotenv/config', 'lib/server.ts'])
else:
with open('/tmp/nango-srv.log', 'wb') as f:
while True:
try:
data = os.read(fd, 4096)
if not data: break
f.write(data); f.flush()
except OSError: break
" &
npm run webapp:dev:watch > /dev/null 2>&1 &
npm run jobs:dev:watch > /dev/null 2>&1 &
npm run persist:dev:watch > /dev/null 2>&1 &
npm run orchestrator:dev:watch > /dev/null 2>&1 &
npm run metering:dev:watch > /dev/null 2>&1 &
npm run connect-ui:dev:watch > /dev/null 2>&1 &
Then grep: grep 'signup/verification' /tmp/nango-srv.log
Option B — Ask the user (simpler):
The user starts npm run dev:watch:apps in their own terminal. After signup, ask the user to find the verification URL in their terminal output by searching for signup/verification.
Standard Test Credentials
Always use the same credentials for local dev:
- Name:
Test User
- Email:
test@nango.dev
- Password:
TestPassword123!
Authentication Flow
Check the DB first to decide whether to sign in or sign up:
docker exec nango-db psql -U nango -d nango -c "SELECT id, email, email_verified FROM _nango_users WHERE email='test@nango.dev';"
- User exists + email_verified is true → sign in at http://localhost:3000/signin
- User exists + email_verified is false → need to verify email first (see Sign Up step 4+)
- No rows → proceed to Sign Up below
Sign Up (only if sign in fails)
- Navigate to http://localhost:3000/signup
- Fill in the signup form with the standard test credentials (Name, Email, Password). Password must contain: 8+ chars, uppercase, number, special character.
- After submitting, the page shows a "Please verify your email" banner
- In local dev, no email is actually sent. The server logs show the email content instead with
(EmailClient) prefix:
info (EmailClient) Email client not configured
info (EmailClient) The following email would have been sent:
info (EmailClient) test@nango.dev 'Verify your email address'
<a href="http://localhost:3000/signup/verification/<uuid>">...</a>
- Find the verification URL in the captured logs:
grep 'signup/verification' /tmp/nango-srv.log
- Open the verification URL (format:
http://localhost:3000/signup/verification/<uuid>) in the browser
- After verification, the app redirects to an onboarding survey ("How did you hear about Nango?") — click any option or "Skip for now" to proceed
- You land on the Getting Started page / dashboard with sidebar navigation (Integrations, Connections, Logs, Metrics, Environment settings)
General Notes
- With
FLAG_AUTH_ENABLED=true, you'll see the login/signup page
- On a fresh/empty database, you must sign up first to create the initial account
- For SSO/OAuth testing, ensure
WORKOS_API_KEY and WORKOS_CLIENT_ID are configured in .env
Testing Connect UI
- Ensure
NANGO_ENCRYPTION_KEY is set in .env
- Open http://localhost:3009 directly, or trigger it from the dashboard
- Connect UI is served by its own Vite dev server with hot reload
Docker Container Management
npm run dev:docker
docker compose --file dev/docker-compose.dev.yaml ps
docker compose --file dev/docker-compose.dev.yaml logs -f nango-db
docker compose --file dev/docker-compose.dev.yaml down
docker compose --file dev/docker-compose.dev.yaml down -v
npm run dev:docker
Fresh Database Reset
⚠ Always ask the user for confirmation before resetting the database. This is a destructive operation that deletes all data (users, connections, integrations, etc.).
Important: The PostgreSQL container uses a bind mount (dev/nango-data), not a named Docker volume. docker compose down -v does NOT reset the database — it only removes named volumes like Elasticsearch data.
To start fresh:
- Stop all running services (kill
dev:watch:apps or individual service processes)
- Drop all schemas in the database:
docker exec nango-db psql -U nango -d nango -c "
DROP SCHEMA public CASCADE;
CREATE SCHEMA public;
DROP SCHEMA IF EXISTS nango CASCADE;
DROP SCHEMA IF EXISTS nango_records CASCADE;
DROP SCHEMA IF EXISTS nango_runners CASCADE;
"
- Restart services — the server runs migrations automatically on startup, recreating all tables
- You will need to sign up again (no users exist after reset)
Product Flows
Step-by-step instructions for testing specific product features in the browser. Teammates: please add new flows here as you discover/test them — follow the template below.
No flows documented yet — add the first one!
Common Issues
| Issue | Symptom | Fix |
|---|
| Docker not running | Cannot connect to the Docker daemon | Start Docker Desktop |
| Port already in use | EADDRINUSE on startup | Kill the process on that port: lsof -ti:PORT | xargs kill |
| DB connection refused | Server crashes on startup | Check npm run dev:docker — wait for postgres to be ready |
| Stale TypeScript build | Runtime errors, missing modules | Stop dev:watch, run npm run ts-clean && npm run ts-build, restart |
| Webapp not loading | Blank page or 404 | Ensure dev:watch has finished initial build before starting dev:watch:apps |
| Missing node_modules | Cannot find module errors | Run npm install — required after branch switch |
| Persist crashes on startup | NANGO_ENCRYPTION_KEY invalid_type error | Set NANGO_ENCRYPTION_KEY in .env (openssl rand -base64 32) |
| Connect UI not working | 500 errors or session failures | Set NANGO_ENCRYPTION_KEY in .env |
| Can't log in on fresh DB | No account exists yet | Sign up first at http://localhost:3000/signup, then check server logs for the verification callback URL |
| Elasticsearch errors in logs | Logs-related warnings | Safe to ignore if NANGO_LOGS_ENABLED="false" — logs go to stdout instead |