Skip to main content
Skip to main content

Local Development with Zerops

Develop locally with hot reload while connecting to Zerops managed services (DB, cache, storage) via VPN. ZCP generates .env with real credentials. Deploy to Zerops with zerops_deploy which uses zcli push under the hood.


Setup

Prerequisites

  • zcli installed: npm i -g @zerops/zcli or docs.zerops.io/references/cli
  • VPN: WireGuard (installed by zcli automatically on first zcli vpn up)
  • Project-scoped token: Create in Zerops GUI → Settings → Access Tokens → Custom access per project

Configuration

// .mcp.json (in project root)
{
"mcpServers": {
"zcp": {
"command": "zcp",
"env": { "ZCP_API_KEY": "<project-scoped-token>" }
}
}
}

Workflow

1. Connect to Zerops services

zcli vpn up <project-id>
  • All services accessible by hostname (e.g., db, cache)
  • One project at a time — switching disconnects the current
  • Env vars NOT available via VPN — use .env file instead

2. Load credentials

ZCP writes .env via zerops_env action="generate-dotenv" (it merges three input channels — project envVariables, zerops.yaml run.envVariables, and .env.local — into one resolved file):

db_hostname=db
db_port=5432
db_password=<actual-password>
db_connectionString=postgresql://db:<actual>@db:5432

Don't hand-edit .env directly — the next generate-dotenv refuses with a diff if it finds keys it didn't produce. Put manual overrides in .env.local (a no-touch input channel that survives regeneration), or pass force=true.

3. Develop locally

Start your dev server as usual — hot reload works against Zerops managed services over VPN.

4. Deploy to Zerops

zerops_deploy targetService="appstage"

Uses zcli push under the hood. Blocks until build completes.


zerops.yml for Local Mode

The same zerops.yml works for both local push and container deploy:

zerops:
- setup: appstage
build:
base: nodejs@22
buildCommands:
- npm ci
- npm run build
deployFiles: ./dist
run:
start: node dist/server.js
ports:
- port: 3000
httpSupport: true
envVariables:
DB_URL: ${db_connectionString}

${hostname_varName} references are resolved by Zerops at container runtime — they work regardless of push source (local or container).


Connection Troubleshooting

SymptomDiagnosisFix
nc -zv db 5432 times outVPN not connectedzcli vpn up <project-id>
VPN connected, still timeoutWrong projectzcli vpn up <correct-project-id>
Connected but auth failsStale .envRegenerate: zerops_env action="generate-dotenv"
Service unreachableService stoppedzerops_manage action="start" serviceHostname="db"

Diagnostic sequence

  1. zerops_discover service="db" — is service RUNNING?
  2. nc -zv db 5432 -w 3 — network reachable?
  3. Compare .env vs zerops_env action="generate-dotenv" preview=true (or zerops_discover includeEnvValues=true for stored values — includeEnvs returns key templates, not resolved values) — credentials current?

Multi-Project

Each project directory has its own .mcp.json + .zcp/state/. VPN is one per machine — switch manually.


Gotchas

  1. .env contains secrets: Add to .gitignore immediately — never commit
  2. Object storage (S3): Uses HTTPS apiUrl — may work without VPN but not fully verified. Include VPN as fallback