backend/api/rest/server.go:
- NewServer() now delegates to loadJWTSecret(), which:
- Rejects JWT_SECRET < 32 bytes (log.Fatal).
- Requires JWT_SECRET when APP_ENV=production or GO_ENV=production.
- Generates a 32-byte crypto/rand ephemeral secret in dev only.
- Treats rand.Read failure as fatal (removes the prior time-based
fallback that was deterministic and forgeable).
- Default Content-Security-Policy rewritten:
- Drops 'unsafe-inline' and 'unsafe-eval'.
- Drops private CIDRs (192.168.11.221:854[5|6]).
- Adds frame-ancestors 'none', base-uri 'self', form-action 'self'.
- CSP_HEADER is required in production; fatal if unset there.
backend/api/rest/server_security_test.go (new):
- Covers the three loadJWTSecret() paths (valid, whitespace-trimmed,
ephemeral in dev).
- Covers isProductionEnv() across APP_ENV / GO_ENV combinations.
- Asserts defaultDevCSP contains no unsafe directives or private CIDRs
and includes the frame-ancestors / base-uri / form-action directives.
scripts/*.sh:
- Removed 'L@kers2010' default value from SSH_PASSWORD / NEW_PASSWORD in
7 helper scripts. Each script now fails with exit 2 and points to
docs/SECURITY.md if the password isn't supplied via env or argv.
EXECUTE_DEPLOYMENT.sh, EXECUTE_NOW.sh:
- Replaced hardcoded DB_PASSWORD='L@ker$2010' with a ':?' guard that
aborts with a clear error if DB_PASSWORD (and, for EXECUTE_DEPLOYMENT,
RPC_URL) is not exported. Other env vars keep sensible non-secret
defaults via ${VAR:-default}.
README.md:
- Removed the hardcoded Database Password / RPC URL lines. Replaced with
an env-variable reference table pointing at docs/SECURITY.md and
docs/DATABASE_CONNECTION_GUIDE.md.
docs/DEPLOYMENT.md:
- Replaced 'PASSWORD: SSH password (default: L@kers2010)' with a
required-no-default contract and a link to docs/SECURITY.md.
docs/SECURITY.md (new):
- Full secret inventory keyed to the env variable name and the file that
consumes it.
- Five-step rotation checklist covering the Postgres role, the Proxmox
VM SSH password, JWT_SECRET, vendor API keys, and a gitleaks-based
history audit.
- Explicit note that merging secret-scrub PRs does NOT invalidate
already-leaked credentials; rotation is the operator's responsibility.
Verification:
- go build ./... + go vet ./... pass clean.
- Targeted tests (LoadJWTSecret*, IsProduction*, DefaultDevCSP*) pass.
Advances completion criterion 2 (Secrets & config hardened). Residual
leakage from START_HERE.md / LETSENCRYPT_CONFIGURATION_GUIDE.md is
handled by PR #2 (doc consolidation), which deletes those files.
4.3 KiB
Deployment Guide
Production Deployment
Prerequisites
- SSH access to production server (192.168.11.140)
- Password for root user
sshpassinstalled (or use SSH keys)
Quick Deploy
For the current frontend, use the Next standalone deploy path:
# From explorer-monorepo root
./scripts/deploy-next-frontend-to-vmid5000.sh
This builds frontend/, uploads the standalone bundle, installs the
solacescanscout-frontend.service unit, and starts the frontend on
127.0.0.1:3000 inside VMID 5000.
Nginx should keep the existing explorer API routes and proxy / plus /_next/
to the frontend service. Use
nginx-next-frontend-proxy.conf
inside the explorer server block after /api, /api/config/*, /explorer-api/*,
/token-aggregation/api/v1/*, /snap/, and /health.
Legacy Static Deploy
The historical static SPA deploy path is deprecated. The old scripts
./scripts/deploy.sh and ./scripts/deploy-frontend-to-vmid5000.sh now fail
fast with a deprecation message and intentionally point operators back to the
canonical Next.js deploy path.
Manual Deploy
# Canonical Next deployment:
./scripts/deploy-next-frontend-to-vmid5000.sh
# Compatibility assets only:
# frontend/public/index.html
# frontend/public/explorer-spa.js
Environment Variables
The canonical Next deployment script uses its own VM/host defaults and deploy
workflow. Prefer reviewing scripts/deploy-next-frontend-to-vmid5000.sh
directly instead of relying on the older static script env contract below.
Historical static-script environment variables:
IP: Production server IP (required; no default)DOMAIN: Domain name (required; no default)SSH_PASSWORD: SSH password (required; no default; previous hardcoded default has been removed — see SECURITY.md)
These applied to the deprecated static deploy script and are no longer the recommended operator interface.
Mission-control and Track 4 runtime wiring
If you are deploying the Go explorer API with the mission-control additions enabled, set these backend env vars as well:
RPC_URL- Chain 138 RPC for Track 1 and mission-control status/SSE dataTOKEN_AGGREGATION_BASE_URL- used byGET /api/v1/mission-control/liquidity/token/{address}/poolsBLOCKSCOUT_INTERNAL_URL- used byGET /api/v1/mission-control/bridge/traceEXPLORER_PUBLIC_BASE- public base URL returned in bridge trace linksCCIP_RELAY_HEALTH_URL- optional relay probe URL, for examplehttp://192.168.11.11:9860/healthzCCIP_RELAY_HEALTH_URLS- optional comma-separated named relay probes, for examplemainnet=http://192.168.11.11:9860/healthz,bsc=http://192.168.11.11:9861/healthz,avax=http://192.168.11.11:9862/healthzMISSION_CONTROL_CCIP_JSON- optional JSON-file fallback for relay health snapshotsOPERATOR_SCRIPTS_ROOT- root directory for Track 4 script executionOPERATOR_SCRIPT_ALLOWLIST- comma-separated allowlist forPOST /api/v1/track4/operator/run-scriptOPERATOR_SCRIPT_TIMEOUT_SEC- optional per-script timeout in seconds
For nginx, include nginx-mission-control-sse.conf inside the same server block that proxies /explorer-api/, and update the proxy_pass target if your Go API is not listening on 127.0.0.1:8080.
Quick verification
curl -N https://explorer.d-bis.org/explorer-api/v1/mission-control/stream
curl "https://explorer.d-bis.org/explorer-api/v1/mission-control/bridge/trace?tx=0x..."
curl "https://explorer.d-bis.org/explorer-api/v1/mission-control/liquidity/token/0x93E66202A11B1772E55407B32B44e5Cd8eda7f22/pools"
# Optional relay probe from the explorer host:
curl http://192.168.11.11:9860/healthz
Rollback
If deployment fails, rollback to previous version:
ssh root@192.168.11.140
ls -1dt /opt/solacescanscout/frontend/releases/* | head
For the Next standalone path, restart the previous release by repointing
/opt/solacescanscout/frontend/current to the prior release and restarting
solacescanscout-frontend.
Testing
After deployment, test the explorer:
./scripts/test.sh
Or manually:
curl -k -I https://explorer.d-bis.org/