Docker-based development environment for mesh-router-backend with hot reload and integrated testing.
- Docker and Docker Compose
- Firebase service account JSON file
-
Add Firebase credentials:
# Copy your service account to the config directory cp /path/to/your/serviceAccount.json ../config/serviceAccount.json -
Configure environment:
# Copy the example env file cp .env.example .env # Edit .env and set your server domain # SERVER_DOMAIN=nsl.sh
-
Start the development server:
# Linux/Mac ./start.sh # Windows PowerShell .\start.ps1
-
Access the API:
http://localhost:8192
| Script | Description |
|---|---|
start.sh / start.ps1 |
Start dev environment with logs |
stop.sh / stop.ps1 |
Stop containers (use --clean to remove volumes) |
test.sh / test.ps1 |
Run the test suite |
# Linux/Mac
./test.sh
# Windows PowerShell
.\test.ps1
# Or manually
docker compose up -d
docker compose exec mesh-router-backend pnpm testIP Registration API
POST /ip/:userid/:sig
✔ should register Host IP with valid signature
✔ should reject invalid signature
✔ should reject missing hostIp in body
✔ should reject invalid IP format
✔ should reject non-existent user
✔ should accept valid IPv6 address
✔ should update existing IP with new value
GET /resolve/:domain
✔ should resolve domain to IP
✔ should return 404 for unknown domain
✔ should return 404 for domain without IP registered
✔ should handle case-insensitive domain lookup
11 passing
backend-dev/
├── Dockerfile.dev # Node 22 Alpine + pnpm (thin image)
├── docker-compose.yml # Service definition with volume mounts
├── entrypoint-dev.sh # Smart startup script
├── start.sh / start.ps1 # Start dev environment
├── stop.sh / stop.ps1 # Stop dev environment
├── test.sh / test.ps1 # Run tests
├── .env.example # Environment template
├── .gitignore # Excludes secrets
└── README.md # This file
| Volume | Purpose |
|---|---|
..:/app |
Source code (hot reload) |
node_modules |
Named volume for dependencies (performance) |
pnpm-store |
pnpm cache (faster installs) |
../config:/app/config |
Firebase service account |
| Variable | Description | Default |
|---|---|---|
SERVER_DOMAIN |
Server domain suffix for all user domains (e.g., nsl.sh) |
Required |
NODE_ENV |
Node environment | development |
GOOGLE_APPLICATION_CREDENTIALS |
Path to Firebase service account | /app/config/serviceAccount.json |
Create a .env file from the example:
cp .env.example .env
# Edit .env and set SERVER_DOMAIN=your-domain.comThe dev server uses tsc-watch for automatic TypeScript compilation and restart on file changes:
- Edit any
.tsfile insrc/ - Save the file
- TypeScript recompiles automatically
- Server restarts with new code
# Follow logs
docker compose logs -f
# Last 100 lines
docker compose logs --tail 100docker compose exec mesh-router-backend bash# Install dependencies
pnpm install
# Build only
pnpm build
# Run tests
pnpm test
# Lint
pnpm lint| Method | Endpoint | Auth | Description |
|---|---|---|---|
| GET | /available/:domain |
Public | Check domain availability |
| GET | /domain/:userid |
Public | Get user's domain info |
| POST | /domain |
Firebase | Register/update domain |
| DELETE | /domain |
Firebase | Delete domain |
| GET | /verify/:userid/:sig |
Public | Verify domain ownership |
| Method | Endpoint | Auth | Description |
|---|---|---|---|
| POST | /routes/:userid/:sig |
Ed25519 Signature | Register routes for a user |
| GET | /routes/:userid |
Public | Get routes for a user |
| DELETE | /routes/:userid/:sig |
Ed25519 Signature | Delete routes for a user |
| GET | /resolve/v2/:domain |
Public | Resolve domain to routes |
# Check domain availability
curl http://localhost:8192/available/myname
# Resolve domain to routes (v2 API)
curl http://localhost:8192/resolve/v2/myname
# Response: {"userId":"abc123","domainName":"myname","serverDomain":"<SERVER_DOMAIN>","routes":[{"ip":"10.77.0.5","port":443,"priority":1}],"routesTtl":580}
# Register routes (requires signature)
curl -X POST http://localhost:8192/routes/{userid}/{signature} \
-H "Content-Type: application/json" \
-d '{"routes": [{"ip": "10.77.0.5", "port": 443, "priority": 1}]}'
# Response: {"message":"Routes registered successfully.","routes":[...],"domain":"myname.<SERVER_DOMAIN>"}Note:
serverDomainin responses comes from theSERVER_DOMAINenvironment variable.
-
Check if port 8192 is in use:
lsof -i :8192 # Linux/Mac netstat -ano | findstr 8192 # Windows
-
Check Docker logs:
docker compose logs
- Ensure
serviceAccount.jsonexists in../config/ - Check the file is valid JSON
- Verify the service account has Firestore access
# Clean and reinstall
./stop.sh --clean
./start.sh# Check compilation manually
docker compose exec mesh-router-backend pnpm build# Stop containers, keep volumes (node_modules preserved)
./stop.sh
# Full cleanup (removes node_modules volume)
./stop.sh --clean