Agent
The agent is part of Vaicoa Pro and Vaicoa Team. To install it, see Install the agent.
The Vaicoa agent is an OS package, cloudviewer-agent, around the upstream
Vector collector. It sends metrics and warning log
lines from a Linux server to Vaicoa, and job reports through
cloudviewer-report. Free mode does not use it.
Supported systems
Section titled “Supported systems”| Family | Package manager | Package |
|---|---|---|
| Debian, Ubuntu | apt | .deb |
| RHEL family: Rocky Linux, AlmaLinux, CentOS Stream, Fedora | dnf or yum | .rpm |
| Requirement | |
|---|---|
| Architecture | x86-64 and Arm64 (such as Hetzner’s CAX servers). The package contains no compiled code (all / noarch); Vector’s repositories provide the collector for each architecture |
| Init system | systemd |
| Tools | curl. On Debian and Ubuntu also gpg, when the installer has to add Vector’s repository |
| Install | as root |
| Tested | the full install, from package to first data, has been tested on Ubuntu 24.04, Debian 12 and Rocky Linux 9 |
| Other systems | Alpine, NixOS and systems without systemd: the container image, or the files from the repository’s agent/ directory, installed by hand |
Packages and repositories
Section titled “Packages and repositories”| Package | cloudviewer-agent: a few KB of readable shell scripts and systemd units, no binaries of its own. Built from the open-source cloudviewer-app/cloudviewer-agent repository (Apache-2.0) |
| Version | <year>.<quarter>.<patch>, for example 2026.3.0 |
| Collector | the vector package (0.57.0 or later) from Vector’s own signed repository; cloudviewer-agent depends on it |
| Signing key | https://get.vaicoa.com/keys/cloudviewer.gpg |
| apt | deb [signed-by=/usr/share/keyrings/cloudviewer.gpg] https://get.vaicoa.com/apt stable main in /etc/apt/sources.list.d/cloudviewer.list |
| dnf, yum | /etc/yum.repos.d/cloudviewer.repo with baseurl=https://get.vaicoa.com/rpm, gpgcheck=1, repo_gpgcheck=1 |
| Vector, apt | https://apt.vector.dev/ stable vector-0 in /etc/apt/sources.list.d/vector.list, keys from keys.datadoghq.com in /usr/share/keyrings/datadog-archive-keyring.gpg |
| Vector, dnf | https://yum.vector.dev/stable/vector-0/$basearch/ in /etc/yum.repos.d/vector.repo |
| Updates | with the package manager: apt upgrade, dnf upgrade |
| Pinning Vector | Vector’s repositories keep every version, so apt preferences or dnf versionlock work |
The installer adds Vector’s repository only when vector is not installed
and no vector.list or vector.repo exists.
Install commands
Section titled “Install commands”# One server, with its token from Monitored Servers → Add server → One servercurl -fsSL https://get.vaicoa.com/agent | sh -s -- --token <agent_token>
# Hetzner Cloud servers, with a fleet token (Add server → Fleet enrollment)curl -fsSL https://get.vaicoa.com/agent | sh -s -- --enroll-token <fleet_token>
# Remove the agentcurl -fsSL https://get.vaicoa.com/agent | sh -s -- --uninstallThe installer checks for root, systemd and curl, detects apt, dnf or yum,
adds the repositories, installs cloudviewer-agent with the package manager
and runs cloudviewer-agent enroll. After that, nothing on the server is
managed by a script.
| Flag | Meaning |
|---|---|
--token <t> | Per-server agent token from the portal, shown once. Optional when /etc/cloudviewer-agent/agent.env already exists |
--enroll-token <t> | Fleet enrollment token. Hetzner Cloud servers only: the server identifies itself through the metadata service. Cannot be combined with --token |
--facade-url <u> | Vaicoa API base URL. Default https://api.vaicoa.com |
--uninstall | Remove the agent, its configuration, token and buffered data, through the package manager |
--help | Show the usage |
Pre-provisioned install (cloud-init, Ansible, Terraform user_data):
write CV_AGENT_TOKEN=<agent_token> (or CV_AGENT_ENROLL_TOKEN=<fleet_token>)
to /etc/cloudviewer-agent/agent.env, mode 0600, before installing the
package. The package then enrolls during installation. cloudviewer-agent enroll without flags does the same on a server that already has the
package.
Per-server token or fleet token
Section titled “Per-server token or fleet token”| Per-server token | Fleet enrollment token | |
|---|---|---|
| Created in | Monitored Servers → Add server → One server, one per server | Add server → Fleet enrollment, one per rollout, for one project |
| Servers | Any | Hetzner Cloud servers only: identified through the metadata service |
| On the server | In agent.env | Not stored. The server receives its own per-server token |
| Linked to the cloud server in your project | No, not yet | Yes |
| Agent charts, jobs and log lines on a cloud server’s detail screen | No | Yes |
| Retired when the cloud server is deleted through the Hetzner API | No | Yes |
| Dedicated servers | Yes, with their own detail screen | Not possible |
| Last used | Shown per token during a rotation | Enrollment tokens list, per token |
| Revoke | Revoke agent token: every token of the server stops working within about ten seconds | Revoke enrollment token: no new enrollments; registered servers keep reporting |
Fleet enrollment is refused, with a message, for an unknown or revoked token, when the plan’s server limit is reached, and for a server that is not in the token’s project.
Commands
Section titled “Commands”| Command | What it does |
|---|---|
cloudviewer-agent enroll --token <t> | Checks the token with Vaicoa, writes agent.env and the configuration, enables and starts the services. Run again with a new token, it replaces the token in place |
cloudviewer-agent enroll --enroll-token <t> | Fleet registration through the Hetzner Cloud metadata service, then the same as above with the server’s own new token. Does nothing on a server that is already enrolled |
cloudviewer-agent enroll | Enrolls from an existing agent.env |
cloudviewer-agent status | Enrolled or not, the state of the services, the configuration version and the Vector version. Exits with 3 when not enrolled |
cloudviewer-agent render | Rebuilds vector.yaml from the last parameters, without network. The package runs it on upgrades |
cloudviewer-agent uninstall | Unregisters the server, stops the services and removes configuration, token and data. The package stays installed |
cloudviewer-report | Job report wrapper, see Job reports API |
systemctl status cloudviewer-agent | The collector service |
enroll accepts --facade-url <u> and --quiet. enroll, render and
uninstall need root. Running enroll again is always safe.
Files, services and users
Section titled “Files, services and users”| Path | What |
|---|---|
/usr/bin/cloudviewer-agent | The commands above |
/usr/bin/cloudviewer-report | Job report wrapper |
/usr/libexec/cloudviewer-agent/fetch-config | Asks Vaicoa for the parameters, every minute |
/usr/libexec/cloudviewer-agent/render-config | Builds vector.yaml from the parameters |
/usr/libexec/cloudviewer-agent/fleet-enroll | Fleet registration |
/usr/lib/systemd/system/cloudviewer-agent.service | Vector, running the rendered configuration |
/usr/lib/systemd/system/cloudviewer-agent-config.service and .timer | The parameter check, every minute |
/usr/share/doc/cloudviewer-agent/README.md | The repository’s README |
/etc/cloudviewer-agent/agent.env | CV_AGENT_TOKEN and CV_AGENT_FACADE_URL. Mode 0600, owner cloudviewer-agent |
/etc/cloudviewer-agent/manifest | The last parameters received |
/etc/cloudviewer-agent/vector.yaml | The rendered configuration. Mode 0640, cloudviewer-agent:vector. Rewritten on every change; do not edit |
/etc/cloudviewer-agent/config.etag | Version of the last parameters |
/var/lib/cloudviewer-agent/ | Vector’s buffers and checkpoints, owner vector. Not /var/lib/vector, so a Vector of your own can run alongside |
dpkg -L cloudviewer-agent or rpm -ql cloudviewer-agent lists every file
the package installs.
| User | Runs | Can |
|---|---|---|
vector | cloudviewer-agent.service (the collector) | read journald and the auth log through its groups systemd-journal and adm; read, not write, its configuration. Created by the vector package |
cloudviewer-agent | cloudviewer-agent-config.service (the parameter check) | write /etc/cloudviewer-agent. Created by the package |
Nothing runs as root after enrollment. Only the commands you run yourself
(enroll, render, uninstall) do.
What it collects
Section titled “What it collects”| Data | Source | Plan |
|---|---|---|
| CPU, memory, load, disk I/O, network and filesystem usage per mount point, every 30 seconds | Vector’s host metrics | Pro and Team |
| System log lines with priority 0 to 4 (emergency to warning), from all units | journald | Pro and Team |
| SSH and sudo log lines | /var/log/auth.log or /var/log/secure, if the system writes one of them | Team, after an admin turns on Collect SSH and sudo log lines in the portal’s Log Collection |
| Job reports | cloudviewer-report or your own HTTP call | Pro and Team |
- The app charts memory, disk and load from the agent. CPU and network charts come from the Hetzner Cloud API, so only cloud servers have them.
- Your own services’ lines are included when they go to journald at warning
priority or higher, for example
logger -p user.warning -t backup "s3 sync retried 3 times, succeeded"orsystemd-cat -t myapp -p warning. Info-level lines are not sent. - Before a line leaves the server, the values after
authorization,bearer,password,passwd,secret,tokenandkey, and PEM private key blocks, are replaced with[REDACTED]. Vaicoa applies the same rules again when the line arrives. See log context. - Log lines are kept for 72 hours, at most 2,000 lines per server.
- Turning SSH and sudo lines off stops them at each server’s next parameter check, usually within a minute. Lines that arrive after that are refused.
- Nothing else: no application logs other than journald, no file contents, no process list.
- When the team’s plan no longer includes the agent, Vaicoa stops storing what it sends. Nothing changes on the server.
Limits per server
Section titled “Limits per server”| Limit | Value | Above it |
|---|---|---|
| Log lines | 120 a minute | Dropped. The app says that lines were rate-limited |
| Length of a log line | 2,048 bytes | Cut off |
| Metric samples | 10,000 a minute | Dropped. The app says that metrics were rate-limited |
| New metric series | 2,000 an hour | New series dropped; known series are still accepted |
| Stored log lines | 72 hours, at most 2,000 lines | Oldest removed first |
| Job reports | see Job reports API |
Each limit applies to one server. Other servers of the team are not affected.
Network egress
Section titled “Network egress”The agent only connects out. It opens no inbound port.
| Destination | Port | When |
|---|---|---|
api.vaicoa.com | 443 | Always: parameters every minute, metrics, log lines, job reports, registration and unregistration |
get.vaicoa.com | 443 | Install and update: the installer, the package repository, the signing key |
apt.vector.dev or yum.vector.dev | 443 | Install and update: the vector package |
keys.datadoghq.com | 443 | Install and update: Vector’s signing keys |
169.254.169.254 | 80 | Fleet enrollment only: the Hetzner Cloud metadata service, for the server’s id |
ghcr.io | 443 | Container and Kubernetes only: image and Helm chart |
The installer has no proxy option. An HTTPS_PROXY set for the services is
untested.
How configuration reaches your servers
Section titled “How configuration reaches your servers”Plan changes and settings from the portal reach your servers within a minute, without SSH access. Every minute, the agent asks Vaicoa for a small set of declared parameters, such as the plan and whether to send journald lines and SSH and sudo lines. It checks them against a fixed list of keys and values and builds its configuration locally from the template in the package. Anything else, such as an unknown key, an unknown version or a full configuration, is rejected, and the last working configuration stays.
No executable code is sent this way, and the token never travels in the parameters. Even if Vaicoa’s servers were compromised, an attacker could only change these documented settings, not run code on your servers.
States
Section titled “States”In the portal (Monitored Servers):
| Badge | Meaning |
|---|---|
| Waiting | Registered, no report yet |
| Connected | Last report less than 5 minutes ago |
| Stale | Last report 5 minutes to 1 hour ago |
| Offline | Last report more than 1 hour ago |
| Revoked | The server has no active token |
| Retired | A fleet-enrolled cloud server deleted from its Hetzner project, or the agent unregistered. Visible for 72 hours, then deleted with its data |
A fleet-enrolled server shows “self-registered via” and the token’s label. During a rotation, the row shows when the old and the new token were last used.
In the app, for dedicated servers:
| State | Meaning |
|---|---|
| Waiting for agent | No report yet |
| Agent connected | The agent reported within the last 5 minutes |
| Last seen … | The agent has not reported for more than 5 minutes; the time is that of its last report |
| Agent revoked | The server has no active token |
| Retired | As in the portal |
After 5 minutes without metrics, the server raises stopped reporting (Alert rules).
Removal
Section titled “Removal”| Action | Unregisters the server | Removes from the server |
|---|---|---|
apt purge cloudviewer-agent | yes | package, configuration, token, buffered data |
apt remove cloudviewer-agent | no | the package files only |
dnf remove cloudviewer-agent | yes | package, configuration, token, buffered data |
Installer with --uninstall | yes | runs the package manager as above |
cloudviewer-agent uninstall | yes | configuration, token, buffered data; the package stays |
| Remove server in the portal | removes it from monitoring | nothing; its token stops working |
helm uninstall cloudviewer-agent | no | the DaemonSet |
| Deleting a fleet-enrolled cloud server through the Hetzner API | retired automatically | n/a |
Unregistering is best effort. If the call fails, the command says so; check the portal and remove the server there if it does not show Retired. A retired server frees its plan slot at once.
What stays installed:
- Debian, Ubuntu: the
vectorpackage,/etc/apt/sources.list.d/cloudviewer.listandvector.list, and the keys in/usr/share/keyrings/. If you do not use Vector for anything else, runapt autoremoveand delete the two list files. - RHEL family:
/etc/yum.repos.d/cloudviewer.repoandvector.repo. dnf normally removesvectortogether with the agent. - The
cloudviewer-agentsystem user.
Verify what is installed
Section titled “Verify what is installed”dpkg -L cloudviewer-agent && dpkg --verify cloudviewer-agent # Debian, Ubunturpm -ql cloudviewer-agent && rpm -V cloudviewer-agent # RHEL familyThe first command lists every file of the package, the second reports files
that changed since installation. The token, parameters and buffers in
/etc/cloudviewer-agent/ and /var/lib/cloudviewer-agent/ are not part of
the package.
Container
Section titled “Container”For hosts without apt, dnf or systemd:
docker run -d --name cloudviewer-agent --restart always \ -e CV_AGENT_TOKEN=<agent_token> \ -v /proc:/host/proc:ro -v /sys:/host/sys:ro -v /:/host/root:ro \ -e PROCFS_ROOT=/host/proc -e SYSFS_ROOT=/host/sys \ ghcr.io/cloudviewer-app/cloudviewer-agent:<version>| Variable | Meaning |
|---|---|
CV_AGENT_TOKEN, CV_AGENT_TOKEN_FILE | Per-server agent token, or a file that holds it |
CV_AGENT_ENROLL_TOKEN, CV_AGENT_ENROLL_TOKEN_FILE | Fleet enrollment token, Hetzner Cloud only; the container must reach the metadata service |
CV_AGENT_FACADE_URL | Vaicoa API base URL. Default https://api.vaicoa.com |
The container checks for new parameters every 60 seconds, like the package. A wrong or revoked token stops it with a message in its log.
Kubernetes
Section titled “Kubernetes”| Chart | oci://ghcr.io/cloudviewer-app/charts/cloudviewer-agent |
| Shape | A DaemonSet: one pod per node, hostNetwork, read-only mounts of the node’s /proc, /sys and / |
| Credential | A Secret with the key enroll-token (a fleet token, for clusters) or token (a per-server token, single-node clusters only: one token on several nodes reports them all as the same server). If both exist, token wins |
| Values | existingSecret, enrollToken, token, facadeUrl, image.repository, image.tag, image.digest, image.pullPolicy, resources, tolerations, nodeSelector, podAnnotations, priorityClassName |
| Permissions | No ServiceAccount or RBAC; the pod only talks to Vaicoa |
| Nodes outside Hetzner Cloud | Cannot use a fleet token; their pods restart with a message that says so |
| Removal | helm uninstall cloudviewer-agent does not unregister the nodes. Nodes deleted from the Hetzner project retire on their own; remove the others in the portal |
Details: the chart README.