feat(relay): Phase1 foundation — P3 Postgres store + async capability verifier + compose
RELAY-PHASE1 Wave A (2/3) + E1 infra: - A1: createPgStores() Postgres adapter for all 9 P3 store ports + runMigrations(); writable-CTE atomic INV8 status swaps; 0002_routes.sql. 23/23 pg tests, 96.72% cov. - A3: real capability verifier delegating to relay-auth verifyCapabilityToken; sync->async seam across authz/provision/main. Full CP suite 15 files/101 pass, tsc clean. - E1: deploy/docker-compose.yml (Postgres16+Redis7, loopback-only) + .env.example. - docs: PLAN_RELAY_PHASE1.md file-level execution spec; PROGRESS_LOG RELAY-PHASE1 section.
This commit is contained in:
43
deploy/.env.example
Normal file
43
deploy/.env.example
Normal file
@@ -0,0 +1,43 @@
|
||||
# RELAY-PHASE1 env template. Copy to deploy/.env (gitignored) and fill. NEVER commit real secrets.
|
||||
# Convert relative → absolute paths on the VPS. See docs/PLAN_RELAY_PHASE1.md §3.
|
||||
|
||||
# ── Docker Compose (deploy/docker-compose.yml) ────────────────────────────────────────────────
|
||||
POSTGRES_DB=relay
|
||||
POSTGRES_USER=relay
|
||||
POSTGRES_PASSWORD= # REQUIRED — strong random
|
||||
|
||||
# ── Shared datastores (loopback; both processes) ─────────────────────────────────────────────
|
||||
PG_URL=postgres://relay:CHANGEME@127.0.0.1:5432/relay
|
||||
REDIS_URL=redis://127.0.0.1:6379
|
||||
|
||||
# ── Deployment identity ──────────────────────────────────────────────────────────────────────
|
||||
BASE_DOMAIN=term.example.com # your ICP-filed domain; browser hits <sub>.<BASE_DOMAIN>
|
||||
RELAY_NODE_ID=relay-1
|
||||
RELAY_TRUST_DOMAIN=relay.example.com # SPIFFE trust domain for agent certs
|
||||
|
||||
# ── P5 capability keypair — CONTROL-PLANE SIGNS, RELAY VERIFIES. Same public key on both. ────
|
||||
# Generate an Ed25519 keypair; keep the PRIVATE key only where tokens are minted (never on disk here).
|
||||
CAPABILITY_SIGN_PUBKEY_B64= # control-plane env: raw 32-byte Ed25519 pubkey, base64
|
||||
RELAY_AUTH_VERIFY_PUBKEY= # relay env: SAME key, base64url
|
||||
|
||||
# ── Control-plane (P3) ───────────────────────────────────────────────────────────────────────
|
||||
CP_BIND_HOST=127.0.0.1 # admin API stays loopback-only (front only via the relay)
|
||||
CP_BIND_PORT=8080
|
||||
CA_INTERMEDIATE_KMS_KEY_REF=dev-local # Phase 1: dev in-process signer accepts any ref (KMS → Phase 2)
|
||||
CA_INTERMEDIATE_CERT_PATH=/etc/relay/ca/intermediate.cert.pem
|
||||
NODE_MTLS_TRUST_BUNDLE_PATH=/etc/relay/ca/agent-ca.bundle.pem
|
||||
# HEARTBEAT_TTL_SEC=15 PAIRING_TTL_SEC=600 PAIRING_MAX_REDEEM_ATTEMPTS=5 (defaults)
|
||||
|
||||
# ── Relay data-plane (P1, relay-run Phase 1) ─────────────────────────────────────────────────
|
||||
BIND_HOST=0.0.0.0
|
||||
BIND_PORT=443 # browser WSS (open in the Aliyun security group)
|
||||
TLS_CERT_PATH=/etc/relay/tls/fullchain.pem # Let's Encrypt for <sub>.<BASE_DOMAIN>
|
||||
TLS_KEY_PATH=/etc/relay/tls/privkey.pem
|
||||
AGENT_BIND_PORT=8444 # agent mTLS (open in the security group)
|
||||
AGENT_CA_CERT_PATH=/etc/relay/ca/agent-ca.cert.pem # private enrollment CA — NOT Let's Encrypt
|
||||
AGENT_CA_CHAIN_PATH=/etc/relay/ca/agent-ca.bundle.pem
|
||||
|
||||
# ── Agent (P2) — runs on YOUR laptop, not the VPS. Shown here for reference. ──────────────────
|
||||
# RELAY_URL=wss://<sub>.term.example.com:8444
|
||||
# ENROLL_URL=https://<sub>.term.example.com/enroll (or the CP host)
|
||||
# HOST_ID=... SUBDOMAIN=<sub> LOCAL_TARGET_URL=ws://127.0.0.1:3000 STATE_DIR=~/.web-terminal-agent
|
||||
48
deploy/docker-compose.yml
Normal file
48
deploy/docker-compose.yml
Normal file
@@ -0,0 +1,48 @@
|
||||
# RELAY-PHASE1 · E1 — Postgres + Redis for the rendezvous-relay control-plane (P3) on the VPS.
|
||||
#
|
||||
# Both services bind to 127.0.0.1 ONLY — they are the relay's private state, never exposed on the
|
||||
# public interface (INV9-adjacent; open only :443 + AGENT_PORT in the cloud security group). The
|
||||
# control-plane / relay processes reach them over loopback.
|
||||
#
|
||||
# Usage on 8.138.1.192:
|
||||
# cp deploy/.env.example deploy/.env # then fill secrets
|
||||
# docker compose --env-file deploy/.env -f deploy/docker-compose.yml up -d
|
||||
#
|
||||
# PG_URL for the app = postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@127.0.0.1:5432/${POSTGRES_DB}
|
||||
# REDIS_URL for the app = redis://127.0.0.1:6379
|
||||
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:16
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
POSTGRES_DB: ${POSTGRES_DB:-relay}
|
||||
POSTGRES_USER: ${POSTGRES_USER:-relay}
|
||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD in deploy/.env}
|
||||
ports:
|
||||
- "127.0.0.1:5432:5432" # loopback-only
|
||||
volumes:
|
||||
- relay_pgdata:/var/lib/postgresql/data
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-relay} -d ${POSTGRES_DB:-relay}"]
|
||||
interval: 5s
|
||||
timeout: 3s
|
||||
retries: 10
|
||||
|
||||
redis:
|
||||
image: redis:7
|
||||
restart: unless-stopped
|
||||
command: ["redis-server", "--appendonly", "yes"]
|
||||
ports:
|
||||
- "127.0.0.1:6379:6379" # loopback-only
|
||||
volumes:
|
||||
- relay_redisdata:/data
|
||||
healthcheck:
|
||||
test: ["CMD", "redis-cli", "ping"]
|
||||
interval: 5s
|
||||
timeout: 3s
|
||||
retries: 10
|
||||
|
||||
volumes:
|
||||
relay_pgdata:
|
||||
relay_redisdata:
|
||||
Reference in New Issue
Block a user