feat: single-node Zopu runtime deployment for Debian

Lane D deliverable: reproducible execution-plane deployment on a fresh
Debian dedicated server (~12 cores, 40 GB RAM, single-node).

Artifacts:
- bootstrap.sh: Docker Engine, Bun, repo clone, build, systemd install,
  firewall (deny-by-default), optional Tailscale, disk monitor cron
- .env.template: all 8 environment groups documented (Convex, Gitea,
  model gateway, AgentOS/RivetKit, Zopu agent, daemon, Docker sandbox,
  service auth)
- systemd units: zopu-daemon, zopu-agent (both Restart=always),
  zopu-health timer (60s), zopu-docker-cleanup timer (daily)
- scripts: health-check, update, rollback, docker-cleanup, disk-monitor
- Caddyfile: optional reverse proxy (documentation-only by default)
- README.md: full runbook with start/stop/log/update/rollback/cleanup
  procedures, topology documentation, and boundary notes

Verified topology (from installed RivetKit source):
- registry.start() boots an in-process RivetKit engine (envoy mode) with
  a native Rust sidecar at http://localhost:6420 (DEFAULT_ENDPOINT in
  chunk-YDUQHING.js line 4751). createClient() connects back to it.
- No separate Rivet Engine process required for single-node operation.
- Linux x64 sidecar packages (@rivet-dev/agentos-sidecar-linux-x64-gnu)
  are available as optional dependencies.

Docker / Orb boundary:
- Docker Engine installed and zopu user in docker group.
- No Docker-backed sandbox code wired; Orb lane contract not yet landed.
- Volume pruning omitted from docker-cleanup.sh to protect durable data.

Validated: bash -n on all 6 shell scripts; mocked health-check smoke
(nc-based TCP probes, mocked systemctl/docker); systemd unit structural
checks. No JS/TS/agent files changed.
This commit is contained in:
-Puter
2026-07-24 20:44:47 +05:30
parent b5c40755cf
commit 8f0b915f4b
15 changed files with 1193 additions and 0 deletions

View File

@@ -0,0 +1,83 @@
###############################################################################
# Zopu Runtime Deployment — Environment Template
#
# Copy to .env and fill in real values. Never commit .env to the repository.
# This file documents every environment group required by the single-node
# execution plane. Lines marked REQUIRED must be set before first start.
###############################################################################
# ---------------------------------------------------------------------------
# 1. Convex (control plane) — REQUIRED
# Convex is already deployed; provide the production deployment URL.
# ---------------------------------------------------------------------------
CONVEX_URL=https://your-deployment.convex.cloud
CONVEX_SITE_URL=https://your-deployment.convex.site
SITE_URL=http://localhost:5173
# ---------------------------------------------------------------------------
# 2. Self-hosted Git / Gitea — REQUIRED for issue lifecycle
# The agent daemon clones repos and creates PRs through Gitea.
# ---------------------------------------------------------------------------
GITEA_URL=https://git.openputer.com
GITEA_TOKEN=replace-with-gitea-api-token
# ---------------------------------------------------------------------------
# 3. Model gateway — REQUIRED
# All model calls route through this OpenAI-compatible endpoint.
# ---------------------------------------------------------------------------
AGENT_MODEL_PROVIDER=cheaptricks
AGENT_MODEL_NAME=glm-5.2
AGENT_MODEL_API=openai-completions
AGENT_MODEL_BASE_URL=https://ai.example.invalid/v1
AGENT_MODEL_API_KEY=replace-with-model-gateway-key
AGENT_MODEL_CONTEXT_WINDOW=262000
AGENT_MODEL_MAX_TOKENS=131072
# ---------------------------------------------------------------------------
# 4. AgentOS / RivetKit — OPTIONAL (defaults shown)
# registry.start() in the daemon boots an in-process RivetKit engine
# (envoy mode) backed by a native Rust sidecar. createClient() connects
# back to RIVET_ENDPOINT. No separate Rivet Engine process is required
# for single-node operation. Leave RIVET_ENDPOINT unset to use the
# library default (http://localhost:6420).
# ---------------------------------------------------------------------------
#RIVET_ENDPOINT=http://localhost:6420
# ---------------------------------------------------------------------------
# 5. Zopu agent service (Flue)
# FLUE_DB_TOKEN authenticates the Flue persistence adapter.
# PORT is the Flue Node HTTP server listen port.
# ---------------------------------------------------------------------------
FLUE_DB_TOKEN=replace-with-long-random-token
PORT=3583
# ---------------------------------------------------------------------------
# 6. Daemon identity
# ---------------------------------------------------------------------------
DAEMON_ID=zopu-dedicated
DAEMON_NAME=Zopu Dedicated Server
DAEMON_VERSION=0.0.0
DAEMON_HEARTBEAT_MS=15000
DAEMON_COMMAND_LEASE_MS=60000
# ---------------------------------------------------------------------------
# 7. Docker sandbox
# The zopu service user is added to the docker group during bootstrap.
# Orb sandboxes will use Docker for full-system isolation, but the Orb
# lane contract has not landed yet. Docker access is provisioned now so
# the boundary is ready; no Docker-backed sandbox code is wired today.
# ---------------------------------------------------------------------------
# No env vars required; Docker socket access is via group membership.
# ---------------------------------------------------------------------------
# 8. Service authentication / secrets
# These tokens authenticate inter-service calls. Generate strong randoms.
# ---------------------------------------------------------------------------
# Better Auth / Convex JWT secret (if the agent service needs to mint tokens):
#AUTH_SECRET=replace-with-64-char-hex
# ---------------------------------------------------------------------------
# 9. Private networking (Tailscale) — OPTIONAL
# When Tailscale is available, set the hostname for private DNS.
# ---------------------------------------------------------------------------
#TAILSCALE_HOSTNAME=zopu-runtime