title: "Installing the agent" description: "Install, upgrade, uninstall, and troubleshoot the BoxWatch agent." last_updated: "2026-05-24"
Installing the agent
The BoxWatch agent is a single bash script. It runs from cron, has no daemons, and uses standard Unix tools (curl, awk, df, top, ps, /proc). The whole thing is under 1000 lines and you can read it before installing — it lives at boxwatch.app/agent.sh.
Requirements
- Linux with
cronor any cron-compatible scheduler. The agent is designed for Linux because process monitoring and uptime checks rely on/proc. curlandcrontabavailable onPATH.jqis recommended. Without it, uptime-check config sync is skipped — basic metric collection still works.- Root or
sudo. The installer writes to/opt/boxwatchand installs a cron entry.
The installer attempts to install jq automatically on Debian/Ubuntu (apt-get), RHEL/Fedora (dnf, yum), and macOS (brew). If you're on something else, install jq manually before running the installer.
One-liner install
From your dashboard's Add server modal, copy the command. It looks like this:
curl -sL https://boxwatch.app/install.sh | bash -s YOUR_AGENT_KEYThis script:
- Downloads
agent.shto/opt/boxwatch/agent.sh. - Verifies the SHA256 checksum of the downloaded script against the version pinned in
install.sh. A mismatch aborts the install. - Writes
/opt/boxwatch/config(mode 600) withAGENT_KEYandAPI_URL. - Adds a
* * * * *cron entry that runs the agent every minute. - Runs the agent once to confirm it can reach the API.
On success you'll see your server appear in the dashboard within a minute or two.
Prefer not to pipe a key through your shell history? Use the env var form:
curl -sL https://boxwatch.app/install.sh | BOXWATCH_KEY=your_key bashThis avoids exposing the key in ps listings and in your ~/.bash_history.
Manual install
If you'd rather see each step:
# 1. Fetch the agent script
sudo mkdir -p /opt/boxwatch
sudo curl -sL https://boxwatch.app/agent.sh -o /opt/boxwatch/agent.sh
sudo chmod +x /opt/boxwatch/agent.sh
# 2. Write the config
sudo bash -c 'cat > /opt/boxwatch/config' <<'EOF'
AGENT_KEY=your_agent_key_here
API_URL=https://api.boxwatch.app
EOF
sudo chmod 600 /opt/boxwatch/config
# 3. Add the cron entry
(sudo crontab -l 2>/dev/null | grep -v "boxwatch/agent.sh"; echo "* * * * * /opt/boxwatch/agent.sh") | sudo crontab -
# 4. Run once to verify
sudo /opt/boxwatch/agent.shIf the last step prints nothing and tail /opt/boxwatch/agent.log shows no errors, you're done. Refresh the dashboard.
What the agent collects
On each tick it gathers:
- CPU, memory, and disk percentages from
top,free//proc/meminfo, anddf. - Load from
/proc/loadavg. - Network bytes from
/sys/class/net/*/statistics/. - Kernel uptime from
/proc/uptime. - Per-process CPU/RSS/start-time for any watched processes (Linux only — uses
/proc/<pid>/stat). - HTTP/TCP/TLS probe results for any uptime checks assigned to this server (requires
jq).
Everything is sent in a single POST to /agent/heartbeat.
Bandwidth and security
- ~500 bytes per heartbeat on a vanilla install. With 20 watched processes and 10 uptime checks, a heartbeat is around 5 KB.
- HTTPS only. There's no fallback to HTTP.
- The agent key is sent as the
X-Agent-Keyheader. It's stored on disk in/opt/boxwatch/configwith mode 600. - The agent never opens an inbound port. It only makes outbound HTTPS to
api.boxwatch.app.
Where things live
| Path | Purpose |
|---|---|
/opt/boxwatch/agent.sh | The agent script itself. |
/opt/boxwatch/config | AGENT_KEY and API_URL. Mode 600. |
/opt/boxwatch/agent.log | Last-run log, rotated at 1 MB. |
/opt/boxwatch/processes.cache | Names of watched processes, one per line. Synced from the API. |
/opt/boxwatch/uptime.cache | JSON array of uptime checks assigned to this host. Synced from the API. |
User's crontab (via crontab -l) | The * * * * * /opt/boxwatch/agent.sh entry. |
Upgrading
The agent script is versioned (currently 2.1, which includes uptime checks). To upgrade, re-run the install command:
curl -sL https://boxwatch.app/install.sh | bash -s YOUR_AGENT_KEYThe installer detects the existing install, downloads the new agent.sh, verifies the checksum, and replaces the file in place. Your config and cron entry are left untouched.
The server-side advertises the latest expected version in the dashboard's server detail page. If you see an "agent is out of date" banner, it means new features (process monitoring, uptime checks) won't work until you re-run the install.
Uninstalling
curl -sL https://boxwatch.app/uninstall.sh | bashThis removes the cron entry, deletes /opt/boxwatch, and exits. It does not delete the server from your dashboard — do that separately. If you don't remove the dashboard row, the agent key just stops being used.
Troubleshooting
No data appearing in the dashboard
Run the agent manually so you can see its output:
sudo /opt/boxwatch/agent.shIf it prints nothing, check /opt/boxwatch/agent.log and look for HTTP errors. The three most common causes:
- Outbound HTTPS blocked. Some hosting providers firewall outbound by default. Allow
api.boxwatch.appon port 443. - Typo in the agent key. Re-issue a key from the dashboard, then re-run the install.
- Cron isn't actually running.
systemctl status cron(orcrond) andtail /var/log/syslog | grep CRON.
"Auth failed" in the log
Your agent key has been rotated or the server was deleted. Re-issue a key in the dashboard's server detail page and update /opt/boxwatch/config.
Uptime checks don't run
jq is missing. Install it (apt-get install jq / dnf install jq) and wait a tick. The agent re-reads uptime.cache every run.
Cron mail spam
The cron entry runs the agent silently — output is redirected to the log file. If you see cron mail, something else on your host is logging to stderr. Confirm with:
sudo crontab -l | grep boxwatchYou should see exactly one line: * * * * * /opt/boxwatch/agent.sh.
The agent benefits from running as root: it can read RSS values from /proc/<pid>/status for all watched processes, and it picks up disks owned by other users. Running it as a less-privileged user works for basic metrics, but watched processes belonging to other users will report count = 0.