Files
vps-control/agent/README.md
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

73 lines
3.4 KiB
Markdown

# 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
```bash
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.