73 lines
3.2 KiB
Desktop File
73 lines
3.2 KiB
Desktop File
# zopu-agents.service — single Zopu intelligence runtime for the VDS.
|
|
#
|
|
# One process hosts both the Hono/Flue server and the AgentOS registry running
|
|
# in native envoy mode (Rivet Mode A):
|
|
#
|
|
# zopu-agents (this unit)
|
|
# └─ node /srv/zopu/current/packages/agents/dist/server.mjs
|
|
# ├─ Hono HTTP server on 127.0.0.1:3000
|
|
# ├─ Flue 2.0 conversation agents + SQLite at /srv/zopu/data/flue
|
|
# └─ AgentOS registry in envoy/native mode (registry.startAndWait)
|
|
#
|
|
# The AgentOS actor is hosted in-process: the Hono/Flue process is also the
|
|
# envoy that connects outbound to the Rivet Engine. There is no separate
|
|
# runner process and no Rivet HTTP handler route.
|
|
#
|
|
# The Rivet Engine is a SEPARATE private service on 127.0.0.1:6420, managed
|
|
# by its own unit/compose. This unit does not start or own it; it only waits
|
|
# for the engine health endpoint before binding (ExecStartPre below).
|
|
# RIVET_ENDPOINT is the engine control plane (http://127.0.0.1:6420).
|
|
#
|
|
# The release is a self-contained bundle under /srv/zopu/releases/<id> with
|
|
# /srv/zopu/current as the live symlink. This unit always runs `current`; the
|
|
# release script swaps it atomically, then the operator restarts this service.
|
|
|
|
[Unit]
|
|
Description=Zopu agents intelligence runtime (Hono + Flue + in-process envoy)
|
|
# Soft network ordering. The real gate on the separate Engine is the health
|
|
# probe in ExecStartPre. If the engine is itself a named systemd unit on this
|
|
# host, add an explicit ordering here, e.g.:
|
|
# After=rivet-engine.service
|
|
# Wants=rivet-engine.service
|
|
After=network-online.target
|
|
Wants=network-online.target
|
|
|
|
[Service]
|
|
Type=simple
|
|
User=zopu
|
|
Group=zopu
|
|
WorkingDirectory=/srv/zopu/current
|
|
|
|
# Secrets and runtime config live in /etc/zopu/agents.env (chmod 600, owner
|
|
# root:zopu). See agents.env.example for the full schema; never commit real
|
|
# values. NODE_ENV is pinned here so a release can never accidentally start in
|
|
# development mode.
|
|
Environment=NODE_ENV=production
|
|
EnvironmentFile=/etc/zopu/agents.env
|
|
|
|
# Wait for the separate Rivet Engine control plane to report healthy before
|
|
# binding. The engine is NOT managed by this unit; this probe is the startup
|
|
# dependency on its health. Bounded to ~60s.
|
|
ExecStartPre=/usr/bin/env bash -c 'i=0; until curl -fsS -o /dev/null http://127.0.0.1:6420/health; do i=$$((i+1)); [ "$$i" -ge 60 ] && { echo "rivet engine not healthy at http://127.0.0.1:6420/health" >&2; exit 1; }; sleep 1; done'
|
|
|
|
# Built release artifact. Node is the verified VDS install at
|
|
# /opt/zopu/node/bin/node (Node 24). PATH is anchored on that directory so the
|
|
# Node binary and its bundled toolchain (corepack/pnpm) resolve deterministically.
|
|
Environment=PATH=/opt/zopu/node/bin:/usr/local/bin:/usr/bin:/bin
|
|
ExecStart=/opt/zopu/node/bin/node /srv/zopu/current/packages/agents/dist/server.mjs
|
|
|
|
Restart=always
|
|
RestartSec=5
|
|
|
|
# --- Hardening ---------------------------------------------------------------
|
|
NoNewPrivileges=true
|
|
PrivateTmp=true
|
|
ProtectSystem=full
|
|
ProtectHome=true
|
|
# Writable state: Flue SQLite + project workspaces. The release tree under
|
|
# /srv/zopu/current is treated read-only at runtime.
|
|
ReadWritePaths=/srv/zopu/workspaces /srv/zopu/data
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|