Documentation · updated 2026-11-03
Argus
Install, configure and run Argus on Linux servers and Windows: checks, findings, alerts, encrypted phone notifications, Prometheus metrics and the security model.
This documentation is available in English.
What Argus is
Argus watches a machine for the ways something could take or keep control of it: new SSH keys and accounts, persistence in systemd and cron, logins from new networks, hidden processes, web shells, exposed services, fixes that were never installed. It runs on the machine it protects, keeps its evidence there, and sends nothing anywhere unless you turn on a feature that says it does.
- Linux server edition: one native program, run as a system service under its own unprivileged account, for Ubuntu, Debian, RHEL-family and any systemd distribution on x86-64.
- Windows edition: being rebuilt as a native program; not in the current release.
- Phone app: argus.archymedes.xyz, an installable web app that receives your servers' alerts, end-to-end encrypted.
- Desktop app: a window, tray icon and notifications for a server you run, on Linux and Windows. It watches nothing itself.
Argus reports; it does not block, kill or change anything on its own. It has no kernel component, so a rootkit already in the kernel could lie to it: its cross-checks are built to make that visible, not impossible.
Install on a Linux server
Argus is one native program for x86-64 Linux with systemd and glibc 2.28 or newer (RHEL/Alma/Rocky 8+, Debian 10+, Ubuntu 20.04+). It needs no Python or other runtime. Verify the download first (see Verify a download).
curl -fsSLO https://www.archymedes.xyz/downloads/argus/argus-server-linux-x86_64.tar.gz
tar -xzf argus-server-linux-x86_64.tar.gz
sudo ./argus-server/install.shOn Debian and Ubuntu the same program also comes as a package, argus-server_<version>_amd64.deb (the exact name is on the download panel and in SHA256SUMS). Its post-install step runs the same installer.
sudo apt install ./argus-server_<version>_amd64.deb| Option | Effect |
|---|---|
| --port 8790 | another dashboard port (default 8787); kept on upgrade |
| --net-sensor | also install the optional packet sensor and firewall reader |
| --no-start | install without starting the service |
| --skip-verify | do not refuse a copy that fails its own verification (not recommended) |
Every download is a compiled program and the files it needs (its libraries, unit files, the dashboard's styles and data). It contains no source code: each release passes a content gate that refuses source, bytecode, source maps and build paths before it is signed, and the site checks it again before serving it.
The installer creates the argus system account, copies the program to /opt/argus/bin owned by root, verifies the installed copy (property checks and model checks; the report is /opt/argus/verification.json), records a baseline of the server as it is now and starts the service. A copy that fails verification is not installed and the previous installation is kept.
Verify a download
Every release is built by CI from a tagged commit, checked so that it contains no source code, and signed by an Argus releaser. Check both the checksum and the signature before you install.
curl -fsSLO https://www.archymedes.xyz/downloads/argus/SHA256SUMS
curl -fsSLO https://www.archymedes.xyz/downloads/argus/SHA256SUMS.sig
curl -fsSLO https://www.archymedes.xyz/downloads/argus/allowed_signers
ssh-keygen -Y verify -f allowed_signers -I "$(ssh-keygen -Y find-principals -f allowed_signers -s SHA256SUMS.sig)" -n argus-release -s SHA256SUMS.sig < SHA256SUMS
sha256sum --check --ignore-missing SHA256SUMSssh-keygen must print Good "argus-release" signature. Then compare the key's fingerprint (ssh-keygen -lf on the key in allowed_signers) with the release fingerprints below, which are published here and in the Argus repository, not only next to the files.
| Releaser | Key fingerprint |
|---|---|
| chrisnkuno | SHA256:ko2Tu8iRZYa2tAc1v9+L41bGDz1VMg/O5cp+ZOE35rk |
On Windows, in PowerShell, in the folder with the download. The signature check uses the OpenSSH client that comes with Windows 10 and 11 (Settings › System › Optional features › OpenSSH Client) and must print Good "argus-release" signature; the two hashes must then be identical.
$b = "https://www.archymedes.xyz/downloads/argus/"
foreach ($f in "SHA256SUMS", "SHA256SUMS.sig", "allowed_signers") { Invoke-WebRequest -UseBasicParsing "$b$f" -OutFile $f }
cmd /c "ssh-keygen -Y verify -f allowed_signers -I chrisnkuno -n argus-release -s SHA256SUMS.sig < SHA256SUMS"
(Get-FileHash argus-desktop-windows-x64.exe).Hash.ToLower()
Select-String argus-desktop-windows-x64.exe SHA256SUMSDesktop app (Linux and Windows)
The desktop app is a window, tray icon and notifications for an Argus server you run. It watches nothing itself: it shows the server's dashboard through an SSH tunnel, talks only to 127.0.0.1, and never sees the dashboard's own credentials. The Windows edition of Argus, which watches the PC itself, is being rebuilt as a native program and is not in the current release.
- Download it from the download panel and verify it (see Verify a download). Windows: argus-desktop-windows-x64.exe. Linux: argus-desktop_<version>_amd64.deb.
- Install it. Windows: the .exe needs no installer; keep it in a folder of your own and open it once, and it adds ARGUS-1 to the Start menu. Linux: sudo apt install ./argus-desktop_<version>_amd64.deb.
- On the server, give the app its own token: argus desktop pair --name desktop. The token is shown once.
- Save the token, on its own line, as client.token in the app's folder: %APPDATA%\local.jarvis.desktop on Windows, ~/.config/local.jarvis.desktop on Linux. On Linux the app refuses a token file others can read: chmod 600 it.
- Open the tunnel and keep it open while you use the app: ssh -N -L 8787:127.0.0.1:8787 your-server. Then open ARGUS-1.
mkdir -p ~/.config/local.jarvis.desktop
nano ~/.config/local.jarvis.desktop/client.token # paste the token, save
chmod 600 ~/.config/local.jarvis.desktop/client.token$d = "$env:APPDATA\local.jarvis.desktop"
New-Item -ItemType Directory -Force $d | Out-Null
Set-Content -NoNewline -Encoding ascii "$d\client.token" (Read-Host "Paste the token")| Windows warning | What to do |
|---|---|
| “Windows protected your PC” (SmartScreen) | The app is not code-signed yet. Select More info, check the app is argus-desktop-windows-x64.exe, then Run anyway. |
| Edge: “isn't commonly downloaded” | Select … › Keep › Show more › Keep anyway |
| No Run anyway button, or “Smart App Control blocked an app” | This PC's policy blocks every unsigned program. The app cannot run there until it is code-signed. Do not turn Smart App Control or Windows Security off for Argus. |
argus desktop clients lists the paired apps and argus desktop revoke ID withdraws one; a revoked app asks to be paired again.
First steps
argus status # is Argus running and current?
argus investigate # everything, in one report
argus outstanding # what is still openThen do these four things; Argus reports each of them until they are done.
- Declare what the server is for: edit /etc/argus/services.conf (written at install with every listener commented out), uncomment the services this server provides, then run argus services. Until then, every exposed port is reported as undeclared.
- Set up at least one alert channel (see Alerts). With none, Argus reports at critical that nothing can reach you.
- Pair your phone: argus notify pair (see Phone notifications).
- Set an off-box heartbeat, so a dead server pages you (see Heartbeat).
The dashboard listens on the server's loopback only. From your own machine:
ssh -N -L 8787:127.0.0.1:8787 your-server
# then open http://127.0.0.1:8787What Argus checks
| Command | Question it answers | How often |
|---|---|---|
| argus backdoor | What grants a way back in: SSH keys and config, sudo rules, accounts, systemd units, cron? | 1 h |
| argus bruteforce | Is anything guessing passwords? | 1 h |
| argus logins | Who logged in, from a new network, with a new key, or right after failed guesses? | 5 min |
| argus webshell | Is there a command dispatcher in a web server's document root? | 6 h |
| argus hidden | Is anything hiding from the process list: procfs, raw syscalls, signals, eBPF, kernel modules, ftrace hooks? | 5 min |
| argus scan | What runs now, and what is new since the baseline? | 1 min |
| argus firewall | Which services are exposed, declared or not, and does the firewall let them in? | 40 min |
| argus implant | Can anything read traffic or reach past the firewall? | 1 h |
| argus containers | Which containers are privileged, exposed, or carry secrets in their environment? | 15 min |
| argus secrets | Which credentials are sitting in plain text on disk? | 12 h |
| argus pkgverify | Were packaged binaries, PAM, sshd or sudo changed on disk? | daily |
| patches | Which security fixes exist but are not installed? Is a reboot pending? | 1 h |
| argus netflow | Port scans, probing and floods against this server (opt-in sensor) | 1 min |
| argus coverage | Is Argus itself running, current and not blind? | 10 min |
argus baseline records the server as known-good (the installer runs it once); argus scan then reports what drifted from it.
Findings and severity
| Severity | Meaning |
|---|---|
| critical | act now: something can already reach in, or nothing can reach you |
| high | a concrete weakness or a sign of compromise to look at today |
| medium | a gap to close: missing fixes, undeclared services, reduced visibility |
| low | context worth knowing: inventory, optional features not enabled |
| ok | checked and clean: a result, not the absence of one |
Unknown is never clean. A check that could not read its source reports that it could not, and a collector that stops running is reported as failing; the absence of findings is not proof of safety.
When a finding is expected, confirm it so it stops counting against you. A confirmation needs a reason and lasts 90 days by default; it never hides a worse finding of the same kind.
argus ack list
argus ack 3f9a2c1d --reason "deploy key for CI, rotated monthly" --days 30
argus ack --revoke 3f9a2c1dAlerts
Settings live in /var/lib/argus/.argus/config.json (owner-only; on Windows %USERPROFILE%\.argus\config.json). Every channel is optional and independent: a failing channel never stops another. Critical findings and monitoring outages are sent immediately; other changes must be seen twice and are grouped into an hourly digest.
| Key | Channel |
|---|---|
| resend_api_key, alert_from, alert_to | email through Resend |
| webhook_url, webhook_secret | JSON POST (Slack- and Discord-compatible text), signed |
| ntfy_url, ntfy_token | an ntfy topic on your phone |
| syslog: true | one line per alert to the local journal; counts only while a log forwarder runs |
| (after argus notify pair) | the Argus phone app, end-to-end encrypted |
| alert_min_severity | critical, high (default) or medium |
{
"webhook_url": "https://hooks.example.com/argus",
"webhook_secret": "a-long-random-string",
"ntfy_url": "https://ntfy.sh/your-private-topic"
}Webhook requests carry X-Argus-Timestamp and X-Argus-Signature: sha256= followed by the hex HMAC-SHA256 of the timestamp, a dot and the raw body, keyed with webhook_secret. Verify it before trusting a message:
import hmac, hashlib
expected = "sha256=" + hmac.new(secret.encode(), ts.encode() + b"." + body, hashlib.sha256).hexdigest()
ok = hmac.compare_digest(expected, request.headers["X-Argus-Signature"])argus alert --test # send a test on every configured channelPhone notifications
The Argus app at argus.archymedes.xyz receives your servers' alerts. There is no account: your phone makes its own keys, and each server seals every alert for your phone alone. The relay stores and forwards ciphertext; it and the push services (Apple, Google, Mozilla) see sizes and times, never the text.
- On the server, run argus notify pair. It shows a 10-character code, valid for 10 minutes.
- On the phone, open argus.archymedes.xyz, choose “Add a server” and type the code.
- Both screens then show a 6-digit code. On the server, answer yes only if they are identical. This is what stops anyone in between, the relay included, from slipping in a device of their own.
- Turn on notifications in the app. On iPhone, first add Argus to the Home Screen (Share › Add to Home Screen): iOS delivers web notifications only to Home Screen apps (iOS 16.4 or later).
argus notify pair --label web-1 # pair a phone
argus notify devices # paired phones
argus notify revoke 3_tjEilD # stop sealing for one (an id prefix is enough)
argus notify test # send a test
argus notify status # relay, devices, last deliveryBy default the lock screen shows only the severity and the server (“A high alert on web-1”); the text appears when you open the app. Settings › Show alert titles on the lock screen changes that. If a phone is lost, run argus notify revoke on each server: it can read nothing more.
One phone can pair with many servers; each pairing uses separate keys, so the relay cannot link your servers through your phone.
Heartbeat: when the server goes silent
Every alert channel runs on the server, so a server that dies pages no one by itself. Create a dead-man check with any service you trust (healthchecks.io, an Uptime Kuma push monitor, Better Stack, or your own) and give Argus its ping URL:
{ "heartbeat_url": "https://hc-ping.com/your-check-uuid" }Argus sends one HTTPS GET a minute and nothing about the server; the service alerts you when the pings stop. The URL is treated as a secret and never appears in logs or findings. Five failures in a row are reported as medium.
Updates and fixable vulnerabilities
Once a day Argus downloads your release's own security data (Ubuntu USN or Debian OVAL; public files, nothing about the server is sent) and compares it with what is installed. It reports only fixes that exist and are not installed, one line per source package:
- high, per package: a vulnerability on CISA's known-exploited list (KEV) is fixed but not installed;
- medium: a summary of the other packages with security fixes not installed;
- medium: fixes available only through Ubuntu Pro (ESM), listed separately, since apt upgrade cannot install them;
- medium: package lists older than 7 days (updates unknown), or a reboot pending for over a day, including a newer kernel installed but not running.
Argus never installs anything. On RPM systems it reports pending security advisories only.
Prometheus and Grafana
GET /metrics on the dashboard port serves the Prometheus text format. Labels are only severities and collector names; no finding text, address or path is ever exported. It is bound to loopback like the dashboard, so scrape it with an agent on the server (Grafana Alloy, Prometheus agent, vmagent).
scrape_configs:
- job_name: argus
static_configs:
- targets: ['127.0.0.1:8787']| Metric | Meaning |
|---|---|
| argus_up / argus_live / argus_healthy | the daemon answers / its scheduler makes progress / required evidence is current |
| argus_security_score | posture score 0–100, higher is better (not a compromise verdict) |
| argus_findings_open{severity} | findings not covered by an acknowledgement |
| argus_findings_acknowledged{severity} | findings covered by one |
| argus_collector_observed{job} | 1 once the collector has reported |
| argus_collector_last_run_age_seconds{job} | seconds since it last reported (absent if never) |
| argus_collector_failing{job} | 1 when its last run recorded an error |
argus_findings_open{severity="critical"} > 0
argus_live == 0
argus_collector_failing == 1
argus_collector_observed == 0
argus_collector_last_run_age_seconds > 3 * argus_collector_interval_secondsIncoming packets (optional)
install.sh --net-sensor adds two small units under their own argus-net account: a packet sensor that reads headers only (the kernel truncates every packet to its header, so no payload ever reaches it) and a firewall reader that lists the ruleset every 5 minutes. Argus then reports port scans, probing of undeclared services, SYN and ICMP floods against a per-port baseline, and DNS-tunnelling-shaped queries, aggregated per source network so internet background noise does not page you.
Without it, Argus states that inbound packets and firewall rules are not observed; it never reports them as clean.
How Argus protects itself and your data
- Its own account. The argus account runs the daemon with three read-only capabilities (CAP_SYS_PTRACE, CAP_DAC_READ_SEARCH, CAP_SYSLOG) and clears them before launching anything. It can read the machine, not change it.
- Sealed code. /opt/argus/app is owned by root; the launcher checks this on every start and drops its capabilities if anything there is writable by another account.
- Verified installs. Every build and every install runs the shipped property checks and model checks; a copy that fails is refused.
- Private dashboard. It listens on 127.0.0.1 only and checks the Host header against DNS rebinding; state-changing requests need a per-start token.
- Bounded inputs. Downloaded feeds and archives are decompressed under hard byte limits, so a decompression bomb is refused rather than inflated.
- Polite under load. It takes a small CPU and IO share under contention and is capped at 1 GB of memory.
| What leaves the server | When |
|---|---|
| HTTPS GETs of public threat feeds and your distribution's security data | on their schedules |
| alerts, on the channels you configure | when something changes |
| sealed envelopes to the phone relay | only after you pair a phone |
| one heartbeat GET a minute | only if you set heartbeat_url |
Resource use
Measured on a fresh Ubuntu 24.04 server with 1 vCPU and 1.5 GB of RAM (2026-10-25): the daemon used 55 MB of memory (158 MB for the whole service including cached files), and 3.2% of one CPU in steady state after its first full pass. Installation took 6 to 17 seconds. Its state directory was 7 MB after the first 30 minutes.
Files
| Path | What |
|---|---|
| /opt/argus/bin | the program and its libraries, root-owned and read-only |
| /opt/argus/verification.json | the installed copy's verification report |
| /var/lib/argus | what Argus records: baseline, findings, history |
| /var/lib/argus/.argus/config.json | alert channels, heartbeat, relay settings |
| /etc/argus/argus.env | the dashboard port |
| /etc/argus/services.conf | the services this server is meant to expose |
| /etc/systemd/system/argus.service | the service |
| /usr/local/bin/argus | the command line (runs as argus, via sudo) |
systemctl status argus
journalctl -u argus -fServer Review and licence keys
The server edition is free and stays free: observation, evidence, alerts and checks never depend on a licence. The Argus Server Review ($149 per server, archymedes.xyz/en/solutions/argus/#pricing) is a report of one week on one server: what happened that week, and every area Argus could not see. It is bought on Polar's checkout page; the licence key (ARGUS-REVIEW-…) is in the receipt email.
argus licence and argus review need the release after 2026.10.30-2. Until it is published, the review is prepared with you by the Archymedes team.
- Install the server edition and let it run for a week.
- Activate the key on the server (it asks Polar whether the key is valid, nothing else).
- Write the report: owner-only, never overwriting a file.
argus licence activate ARGUS-REVIEW-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
argus licence status
argus review --out review.txtWithout a key, argus review prints a preview: every area's state, the counts and the blind spots, without the individual findings. Argus Watch ($9 per server per month) keeps the weekly report going after the review. The review is not a security audit, a penetration test or a certification.
Upgrade and uninstall
Install a newer package or run the newer archive's install.sh: the port, services.conf, the network sensor, your settings and history are kept, and a new copy that fails verification leaves the running one in place.
sudo apt remove argus-server # stop and remove, keep the history
sudo apt purge argus-server # also delete history, settings and accounts
sudo /opt/argus/uninstall.sh # archive installs
sudo /opt/argus/uninstall.sh --purgeThe desktop app: on Linux, sudo apt remove argus-desktop. On Windows, run argus-desktop-windows-x64.exe --remove-shortcut to take it out of the Start menu, then delete the .exe and %APPDATA%\local.jarvis.desktop. Revoke its token on the server with argus desktop revoke ID.
Troubleshooting
| You see | Do this |
|---|---|
| “no alert channel can reach you” (critical) | configure email, a webhook, ntfy or pair a phone; then argus alert --test |
| “exposed services are not declared” | uncomment the services in /etc/argus/services.conf, then argus services |
| “package lists are stale” | enable apt-daily or unattended-upgrades so the server learns about fixes |
| “collector … is failing” | argus coverage shows why; journalctl -u argus for details |
| the phone shows a different 6-digit code | answer no on the server and pair again; do not pair when the codes differ |
| no notifications on iPhone | add Argus to the Home Screen first, then turn notifications on in its Settings |
| “notify: python3-cryptography is not installed” | sudo apt install python3-cryptography |