Documentation and install guides
Pick a host type: the command and its options, what the agent reads, what it never touches and how to remove it.
Installing, by host type
The steps are the ones in the dashboard. The real command, with the host’s key, appears there when you add the host, and the secret is shown only once.
VPS with agent
- root (or sudo -i)
- curl, openssl, sha256sum
- python3, for remediation
- outbound HTTPS to valinor.sbs
- In the dashboard pick “Add a host”, type “VPS with agent”, with the server address (IP or domain).
- Copy the install command generated there and run it on the server, as root. The key and the secret travel in environment variables, not in the URL.
- The installer sends the first report and tells you whether the dashboard received it. From then on the agent reports by itself, every 5 minutes.
- Optional: remediation. You switch it on at install time and in the dashboard; without both, no command runs.
Shared hosting
- a terminal in the account (SSH or cPanel)
- a crontab in the account
- curl, openssl, sha256sum
- no root
- In the dashboard pick “Add a host”, type “Shared hosting”, with the site’s domain.
- Run the install command from the account terminal (SSH or Terminal in cPanel), without root.
- The installer adds a line to the account crontab and finds the webroot by itself (public_html, www, htdocs).
- The first sweep inventories the files in instalments; until it finishes, nothing shows up as a “new file”.
External site
- just the domain
- optionally, a word from the page
- In the dashboard pick “Add a host”, type “External site”.
- Type the domain and, optionally, a text the page must contain: that also catches a suspended-account page or a defaced site, which still answer 200.
- The HTTP probe starts within the first minute. The rarer checks (every 6 or 12 hours) make their first run staggered, within their own interval.
cPanel/WHM reseller
- access to WHM
- an API token with list-accts
- In WHM, create an API token. The minimum is the list-accts privilege, enough for accounts and their sites.
- In the dashboard pick “Add a host”, type “cPanel/WHM reseller”, with the WHM address, and save the token.
- The accounts appear as hosts at the first sync (every 30 minutes), and those with a delegated domain get probes.
- Optional: install the agent on every account with one command, or let new accounts enroll themselves.
curl -fsSL https://valinor.sbs/…/install.sh | \ VPSDASH_KEY='<key>' \ VPSDASH_SECRET='<secret>' sh
The shape of the command. The real one, with the host’s key and secret, is generated in the dashboard. Options go after sh -s --: an --enable-actions placed straight after sh is rejected by the shell before it reads the installer.
--enable-actions: Remediation: blocking an IP (24 h), killing a process, quarantining files, restarting the web server. Each one waits for your approval. Without python3 they stay off.--disable-service-restart: Remediation without the web server restart.--enable-self-update: Updates from the dashboard, only with a version whose fingerprint is signed. On a VPS it needs root and systemd-run. The dashboard form ticks it by default.
What the agent reads, and what never leaves the machine
For each source: what reaches the dashboard and what stays on the server. Files are compared in the dashboard by fingerprint, not by content.
- Logins (/var/log/auth.log · /var/log/secure · journal). What it sends: The IPs and users of successful logins, key fingerprints, failure counts, accounts created or changed. What it never sends: Passwords and the full contents of the log.
- Firewall (nft · firewall-cmd · ufw · iptables). What it sends: The rules (without counters), the number of blocks from the counters, the top 3 source IPs from the log. What it never sends: The traffic itself.
- Processes (ps · /proc/<pid>). What it sends: PID, user, executable path, CPU, command line (200 characters at most). What it never sends: Process memory and file descriptors.
- Connections (ss). What it sends: Outbound connections to mining ports, and the listening TCP and UDP sockets. What it never sends: The traffic itself.
- Temporary directories (/tmp · /var/tmp · /dev/shm). What it sends: The name, size and SHA256 of new executables. What it never sends: The contents of the files.
- Cron and timers (/etc/crontab · /etc/cron.d · cron.{hourly,daily,…} · systemd timers). What it sends: The cron lines, script names with a short hash, timer names and state. What it never sends: The contents of the scripts.
- SSH keys, accounts, sudo (sshd -T · /etc/passwd · /etc/group · /etc/sudoers*). What it sends: Key fingerprints only, account names, members of the groups that amount to root, sudo rules. What it never sends: The key material, private or public.
- Web logs (nginx / apache access.log). What it sends: Per source address: request and status counts, distinct paths, the most used user agent, login attempts and a few URLs that look like a backdoor call. What it never sends: The full log.
- Mail (maillog · mail.log · exim mainlog · journal). What it sends: Only where postfix, exim or dovecot runs. Per source address: failed logins and the service; per account: how many messages it handed in; the queue length. What it never sends: Correspondents, subjects, message bodies, the user names typed in failed logins.
- Site files (webroot (shared hosting) · nginx and apache document roots (VPS)). What it sends: Paths and truncated SHA256 for PHP, HTML, JS and server configuration files; on a known injection pattern, the matched fragment (40 characters) and its line. What it never sends: The contents of the files.
Plus load, memory, disk and uptime. No .env, no environment variables, no databases. On shared hosting the agent sees only the site files, the access logs, the account cron and the quota.
Remediation: what it can do, and only with your approval
By default the agent executes nothing. Remediation takes two separate switches, and every command waits for a person.
Installed with --enable-actions. Channel enabled in the dashboard. Channel off. The agent refuses any command, however correctly signed.
- Block an IP: VPS (root): IPv4, expires by itself after 24 h; Shared hosting: No, needs root
- Kill a process: VPS (root): With the process identity checked again; Shared hosting: No, needs root
- Quarantine files: VPS (root): From /tmp, /var/tmp, /dev/shm; Shared hosting: From the account webroot, with restore
- Restart the web server: VPS (root): nginx, Apache, LiteSpeed, PHP-FPM, after testing the configuration; Shared hosting: No, needs root
- Update its own script: VPS (root): Only with --enable-self-update; Shared hosting: Only with --enable-self-update
- Anything else: VPS (root): Never; Shared hosting: Never
Always refused: the machine’s own address, the gateway, the DNS resolvers, the current SSH session, the dashboard address, systemd and sshd, any symlink. The emergency exit, local and with no network: vpsdash-agent.sh --unblock-all.
Day-to-day operation
The commands on the machine, for an agent installed as root. On shared hosting everything lives in ~/.vpsdash-agent.
Is it running?
systemctl status vpsdash-agent.timer
The timer starts the agent at the chosen interval (5 minutes by default), at low priority. Between runs no process is left.
What it did
journalctl -u vpsdash-agent -n 50 /opt/vpsdash-agent/vpsdash-agent.sh --once --verbose
The log of the last runs, then a manual run with details. The dashboard’s answer to the last report is kept in /var/lib/vpsdash-agent/last_send.
What it sends
/opt/vpsdash-agent/vpsdash-agent.sh --dry-run
Prints exactly what would be sent to the dashboard, without sending anything. Run it any time.
Check the link
/opt/vpsdash-agent/vpsdash-agent.sh --check
The exit code says where the problem is: 0 accepted, 3 the key, the secret or the clock, 4 the dashboard does not answer (name, connection, TLS), 5 any other answer (suspended subscription, rate limit).
Update
/opt/vpsdash-agent/vpsdash-agent.sh --version
From the dashboard, with the “Update to …” button on the host page, if the agent has --enable-self-update; it picks the command up within 5 minutes. Otherwise the dashboard gives you a one-time command that reuses the keys already on the machine. What it was allowed to do stays the same.
Uninstall
systemctl disable --now vpsdash-agent.timer vpsdash-agent-poll.timer /opt/vpsdash-agent/vpsdash-agent.sh --unblock-all rm -rf /opt/vpsdash-agent /etc/vpsdash-agent /var/lib/vpsdash-agent /etc/systemd/system/vpsdash-agent.* /etc/systemd/system/vpsdash-agent-poll.* systemctl daemon-reload
Then revoke the host’s key in the dashboard. On shared hosting: crontab -l | grep -v vpsdash-agent | crontab - and rm -rf ~/.vpsdash-agent.
The security model
One key per host, revocable
Every host has its own key and secret. The secret is shown once, at creation. You rotate or revoke it from the dashboard at any time, and reports with a revoked key are rejected at once.
Signed reports
Every report is signed HMAC-SHA256 with the machine’s secret. The dashboard rejects wrong signatures, clocks more than 5 minutes off and any nonce already used.
The secret never travels in the URL
It reaches the machine in environment variables, so it never lands in web server logs, and it stays in agent.conf with mode 600. With python3 installed it does not show in the process list either.
Signed commands, from a closed list
With --enable-actions, the agent runs only commands from the list, signed with its secret and tied to the current request, so they cannot be replayed. Never an arbitrary shell.
Common problems
The installer says “Installed, but NOT verified”
The agent is installed and keeps trying at every interval: nothing has to be removed, only the cause fixed. Run --check: 3 means the key, the secret or a clock more than 5 minutes off, 4 that the machine cannot reach the dashboard (DNS, a firewall on port 443, an old CA bundle), 5 a suspended subscription or a rate limit.
I added --enable-actions, but remediation does not work
Options go after sh -s --. An --enable-actions pasted straight after sh is rejected by the shell, and the install changes nothing. Then: without python3 remediation stays off, and the channel must also be enabled in the dashboard.
The host shows as “Silent agent”
The dashboard opens an incident after three intervals without a report (15 minutes at the default interval). The usual causes: a rotated or revoked key, a machine with no outbound HTTPS, a stopped timer. Reports that cannot leave wait in a local queue (up to 50, for seven days) and are sent once the link is back.
I rotated the key and the agent went silent
Rotating revokes the old key at once. Run the new command the dashboard shows on the machine: the new secret is shown only once.
On shared hosting, the traffic tab is empty
The agent reads the access logs from the places cPanel uses; on other control panels the tab can stay empty, and the host page says why. It looks for the webroot in public_html, www, htdocs, httpdocs and domains/*/public_html; otherwise you set it at enrolment.
WHM refuses the token (403)
Check the exact WHM user name, that the token was copied whole and that it has the list-accts privilege. The address must be the server that runs WHM (port 2087), not a site hosted on it.