120 lines
5.0 KiB
Markdown
120 lines
5.0 KiB
Markdown
# Zopu VDS agents deployment
|
|
|
|
This directory holds the systemd unit, environment template, and Caddy reverse-proxy config that run the Zopu intelligence runtime on the VDS. It supersedes the former container deployment for the agents process.
|
|
|
|
## Runtime topology
|
|
|
|
One Node process hosts the entire runtime:
|
|
|
|
```
|
|
zopu-agents.service
|
|
└─ node /srv/zopu/current/packages/agents/dist/server.mjs
|
|
├─ Hono server 127.0.0.1:3000
|
|
├─ Flue 2.0 agents SQLite at /srv/zopu/data/flue/flue.db
|
|
└─ AgentOS registry envoy, native runtime (in-process)
|
|
```
|
|
|
|
The process connects outbound to the **Rivet Engine**, a separate private service on `127.0.0.1:6420`, managed by its own unit/compose. This unit does not start or own it.
|
|
|
|
The Hono/Flue server handles Convex callbacks and dispatches to Flue agents. The **AgentOS actor is hosted in-process**: the same process is the envoy that owns the native Actor Runtime Socket (Rivet Mode A). There is no separate runner process and no Rivet HTTP handler route.
|
|
|
|
### Rivet endpoint
|
|
|
|
| Variable | Role | Value on this host |
|
|
| --- | --- | --- |
|
|
| `RIVET_ENDPOINT` | Engine **control plane** this process connects _to_ for actor metadata | `http://127.0.0.1:6420` |
|
|
|
|
## Files
|
|
|
|
- `zopu-agents.service` — systemd unit. Runs `/srv/zopu/current/packages/agents/dist/server.mjs` as user `zopu`, waits for engine health before binding, hardens the service, and restarts on failure.
|
|
- `agents.env.example` — template for `/etc/zopu/agents.env`. Contains the full validated env schema (Hono/Flue + in-process envoy) with no secrets.
|
|
- `../../scripts/release-agents.sh` — local build, upload, and atomic release promotion command. Each release includes this directory so the unit's `Documentation=` target remains valid.
|
|
- `Caddyfile` — source-controlled public ingress for `agents.zopu.puter.wtf`. Terminates TLS and forwards only `/health`, `/internal/project-setup`, and `/internal/agents/*` to `127.0.0.1:3000`.
|
|
|
|
## Prerequisites on the VDS
|
|
|
|
1. **Node 24** installed at `/opt/zopu/node/bin/node` (the verified VDS Node; the unit's `ExecStart` and `PATH` are anchored on this path). The release bundle ships its own `node_modules`; only the Node binary is expected from the host.
|
|
2. **`curl`** and **`bash`** on `PATH` (used by the `ExecStartPre` engine health probe).
|
|
3. A dedicated service user and group:
|
|
```sh
|
|
sudo useradd --system --no-create-home --shell /usr/sbin/nologin zopu
|
|
```
|
|
4. The two writable state trees, owned by `zopu`:
|
|
```sh
|
|
sudo mkdir -p /srv/zopu/data/flue /srv/zopu/workspaces
|
|
sudo chown -R zopu:zopu /srv/zopu/data /srv/zopu/workspaces
|
|
```
|
|
5. The **Rivet Engine** running and answering `http://127.0.0.1:6420/health`.
|
|
6. A release promoted by `scripts/release-agents.sh` to `/srv/zopu/releases/<release-id>`, with `/srv/zopu/current` symlinked to it. The release must contain `packages/agents/dist/server.mjs` and `deploy/vds/`.
|
|
|
|
## Install
|
|
|
|
```sh
|
|
# 1. Secrets
|
|
sudo install -d -m 0750 -o root -g zopu /etc/zopu
|
|
sudo cp agents.env.example /etc/zopu/agents.env
|
|
sudo chown root:zopu /etc/zopu/agents.env
|
|
sudo chmod 0600 /etc/zopu/agents.env
|
|
sudo "$EDITOR" /etc/zopu/agents.env # fill in every REPLACE-WITH-...
|
|
|
|
# 2. Unit
|
|
sudo install -m 0644 zopu-agents.service /etc/systemd/system/zopu-agents.service
|
|
sudo systemctl daemon-reload
|
|
sudo systemctl enable --now zopu-agents.service
|
|
```
|
|
|
|
## Verify
|
|
|
|
```sh
|
|
systemctl status zopu-agents.service
|
|
curl -fsS http://127.0.0.1:3000/health # {"service":"zopu-agents","status":"ok"}
|
|
```
|
|
|
|
### Public ingress (Caddy)
|
|
|
|
Caddy terminates TLS for `agents.zopu.puter.wtf` and forwards only the three paths the Convex backend calls to the internal agents worker (`127.0.0.1:3000`). The AgentOS actor registry runs in-process, so no `/internal/rivet/*` path is exposed on the agents listener. All other paths return `404`.
|
|
|
|
Install or update from this checked-in artifact:
|
|
|
|
```sh
|
|
# 1. Materialize the config
|
|
sudo install -m 0644 Caddyfile /etc/caddy/Caddyfile
|
|
|
|
# 2. Validate before applying
|
|
sudo caddy validate --config /etc/caddy/Caddyfile --adapter caddyfile
|
|
|
|
# 3. Reload the running Caddy (no restart needed)
|
|
sudo systemctl reload caddy
|
|
```
|
|
|
|
Verify the narrow public surface:
|
|
|
|
```sh
|
|
curl -fsS https://agents.zopu.puter.wtf/health # {"service":"zopu-agents","status":"ok"}
|
|
```
|
|
|
|
## Release switch
|
|
|
|
From the repository root on the build host, create and promote a release:
|
|
|
|
```sh
|
|
scripts/release-agents.sh <vds-host> <release-id>
|
|
```
|
|
|
|
The script atomically swaps `/srv/zopu/current`; it deliberately does **not** restart the service. After the upload succeeds, restart the unit:
|
|
|
|
```sh
|
|
sudo systemctl restart zopu-agents.service
|
|
```
|
|
|
|
Roll back by atomically replacing `current` with a symlink to a prior release, then restarting the service.
|
|
|
|
## Optional: explicit engine ordering
|
|
|
|
The unit already gates startup on the engine health endpoint via `ExecStartPre`. If the engine is itself a named systemd unit on this host, you may add a hard ordering by uncommenting/adding in the `[Unit]` section:
|
|
|
|
```ini
|
|
After=rivet-engine.service
|
|
Wants=rivet-engine.service
|
|
```
|