agent¶
Contributor documentation
This section explains how the Manager, Nodes, and cluster work internally and how to contribute to the opensource cluster itself. If you are a developer who just wants to run your own code on the cluster, see the Users documentation instead.
Node.js (TypeScript) check-in agent that reports host/service status to the manager and applies nginx and dnsmasq configuration. Installed on agent and manager containers. For deployment instructions, see Deploying Agents.
Architecture¶
A systemd timer launches the oneshot agent every 30 seconds. Each run checks in with the manager (POST /api/v1/agents), applies any config changes, and exits.
TypeScript sources live in agent/src (compiled to dist/), the locally rendered EJS templates in agent/templates, and the systemd service/timer units in agent/contrib/systemd. The agent/Makefile builds the opensource-agent package (see Release Pipeline). Service reloads and state queries go through the systemd D-Bus API; config validation uses nginx -t and dnsmasq --test.
Check-in Protocol¶
sequenceDiagram
participant Timer as systemd timer
participant Agent
participant Manager
Timer->>Agent: start (every 30s)
Agent->>Manager: POST /api/v1/agents<br/>{siteId, hostname, ipv4Address, services}<br/>If-None-Match: {etag}
alt Config changed
Manager-->>Agent: 200 OK + config snapshot + ETag
Agent->>Agent: Render templates, validate<br/>(nginx -t, dnsmasq --test)
Agent->>Agent: Apply + reload (rollback on failure)
Agent->>Manager: POST again (reports apply results)
Manager-->>Agent: 304 Not Modified
else No changes
Manager-->>Agent: 304 Not Modified
end
Agent->>Timer: exit
The check-in body carries system info and per-service status:
{
"siteId": 1,
"hostname": "agent",
"currentTime": 1771234560,
"ipv4Address": "172.17.0.2",
"services": {
"nginx": { "state": "active", "lastApply": "success" },
"dnsmasq": { "state": "active", "lastApply": "success" }
}
}
The manager records every check-in in the Agents table (shown on the web client's /agents page) and responds with the site's config snapshot as JSON. A strong ETag covers the snapshot; the agent stores it in /var/lib/opensource-agent/state.json and sends it back via If-None-Match, so unchanged configs cost a single 304 round trip.
Environment Variables¶
Read from the process environment (systemd loads /etc/environment). Set via container runtime (Docker ENV, Proxmox LXC config) — the base image's environment.sh service propagates them on boot.
| Variable | Required | Description |
|---|---|---|
SITE_ID |
Yes | Numeric site ID from the manager |
MANAGER_URL |
Yes | Base URL of the manager (e.g., http://192.168.1.10:3000) |
API_KEY |
No | Admin API key for remote agents. Not needed on the manager (localhost is trusted). |
STATE_DIRECTORY |
No | State directory, set by systemd via StateDirectory= (default /var/lib/opensource-agent) |
The agent Dockerfile defaults to SITE_ID=1 and MANAGER_URL=http://localhost:3000 so the manager container works without configuration.
Managed Services¶
| Service | Files | Test | Reload |
|---|---|---|---|
| nginx | /etc/nginx/nginx.conf |
nginx -t |
systemctl reload-or-restart nginx |
| dnsmasq | /etc/dnsmasq.conf, /var/lib/dnsmasq/{dhcp-hosts,hosts,dhcp-opts,servers} |
dnsmasq --test |
restart when /etc/dnsmasq.conf changed, otherwise SIGHUP |
Apply flow per service: render templates, skip if nothing changed, stage new files, run the test command, roll back on failure, then reload. Failures are reported as lastApply: "failure" at the next check-in.
To add a managed service, add a ManagedService entry in agent/src/apply.ts plus its template(s) under agent/templates/, and extend the config snapshot in create-a-container/utils/agent-config.js.
Running Manually¶
systemctl status opensource-agent.timer # timer state
journalctl -u opensource-agent.service # past runs
node /opt/opensource-server/agent/dist/index.js # single run by hand