Files
DizelBadCoder c4dc19cd41
Some checks failed
CI / containers (push) Has been cancelled
CI / agent (push) Has been cancelled
CI / backend (push) Has been cancelled
CI / frontend (push) Has been cancelled
git init
2026-09-19 19:31:36 +03:00
..
2026-09-19 19:31:36 +03:00
2026-09-19 19:31:36 +03:00
2026-09-19 19:31:36 +03:00
2026-09-19 19:31:36 +03:00
2026-09-19 19:31:36 +03:00
2026-09-19 19:31:36 +03:00

VPS Agent

The agent is a Rust system daemon with two Tokio workers, no database, no metric history, and no periodic polling. It exposes authenticated semantic JSON APIs and never accepts commands or shell fragments.

Build and test

cargo fmt --manifest-path Cargo.toml --check
cargo clippy --manifest-path Cargo.toml --all-targets -- -D warnings
cargo test --manifest-path Cargo.toml
cargo build --manifest-path Cargo.toml --release

The release profile enables thin LTO, strips symbols, uses one codegen unit, and aborts on panic. Output is one binary at target/release/vps-agent.

Configuration and permissions

Use config/config.toml as the reference. Configuration belongs at /etc/vps-agent/config.toml, owned root:vps-agent mode 0640. The application token belongs at /etc/vps-agent/credentials/control-plane.token, owned by the vps-agent service user and mode 0600. Generate at least 32 random bytes. Do not put credentials in TOML.

The default bind is loopback. For remote use, select only the VPS WireGuard IP; an unspecified address is rejected. TLS can be enabled with PEM certificate/key paths. WireGuard plus the application token is the recommended v1 mode.

API

Send Authorization: Bearer TOKEN on every /v1 request. /healthz is public and returns liveness only. The complete route table is in ../docs/architecture.md. Limits default to 64 KiB bodies, 32 concurrent calls, five-second requests, 10 read rps, 2 write rps, and burst 20.

System data comes from /proc and /sys; fixed ip, nft/iptables, fail2ban-client, wg, and systemctl invocations augment it. User input is never part of a command string. Jail names and IPs are validated, and systemd names must exactly match the configuration allow-list.

/v1/logs is disabled by default. When enabled, it streams bounded, cursor-paginated JSON from journalctl for [logs].allowed_units only. The backend polls and retains these rows; Grafana never calls the endpoint. The vps-agent user normally needs membership in systemd-journal. That membership widens what the local process can read, so the installer does not add it and an administrator must opt in after review.

systemd and privilege

Install packaging/vps-agent.service. It caps memory at 64 MiB, CPU at 10%, tasks at 64, removes all capabilities, sets NoNewPrivileges, and enables filesystem/kernel/namespace hardening. The agent logs to journald and does not write successful polls or metrics to disk.

Read APIs work unprivileged on ordinary supported distributions. Process owners may be absent due to /proc permissions. Fail2Ban changes and service restarts will return an error unless the administrator adds narrowly scoped polkit/sudo policy; the installer deliberately grants none. Firewall is read-only in v1.

Lifecycle and troubleshooting

Use ../scripts/vps-agentctl.sh for install, update, rollback, and removal. Check systemctl status vps-agent and journalctl -u vps-agent --since today. Validate the bind address, token permissions, WireGuard route, and executable availability. Rotate a token atomically and restart both ends as described in the security doc.

Resource targets are <=30 MiB idle RSS, near-zero idle CPU and no steady disk writes. Measure on the target distribution with systemctl status, systemd-cgtop, and /proc/PID/status; macOS development builds are not a valid resource benchmark.