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.

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).

Any systemd distribution
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.sh

On 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.

Debian, Ubuntu
sudo apt install ./argus-server_<version>_amd64.deb
OptionEffect
--port 8790another dashboard port (default 8787); kept on upgrade
--net-sensoralso install the optional packet sensor and firewall reader
--no-startinstall without starting the service
--skip-verifydo 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.

Linux
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 SHA256SUMS

ssh-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.

ReleaserKey fingerprint
chrisnkunoSHA256: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.

Windows PowerShell
$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 SHA256SUMS

Desktop 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.

  1. 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.
  2. 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.
  3. On the server, give the app its own token: argus desktop pair --name desktop. The token is shown once.
  4. 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.
  5. 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.
Linux: save the token
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
Windows PowerShell: save the 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 warningWhat 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 open

Then 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:8787

What Argus checks

CommandQuestion it answersHow often
argus backdoorWhat grants a way back in: SSH keys and config, sudo rules, accounts, systemd units, cron?1 h
argus bruteforceIs anything guessing passwords?1 h
argus loginsWho logged in, from a new network, with a new key, or right after failed guesses?5 min
argus webshellIs there a command dispatcher in a web server's document root?6 h
argus hiddenIs anything hiding from the process list: procfs, raw syscalls, signals, eBPF, kernel modules, ftrace hooks?5 min
argus scanWhat runs now, and what is new since the baseline?1 min
argus firewallWhich services are exposed, declared or not, and does the firewall let them in?40 min
argus implantCan anything read traffic or reach past the firewall?1 h
argus containersWhich containers are privileged, exposed, or carry secrets in their environment?15 min
argus secretsWhich credentials are sitting in plain text on disk?12 h
argus pkgverifyWere packaged binaries, PAM, sshd or sudo changed on disk?daily
patchesWhich security fixes exist but are not installed? Is a reboot pending?1 h
argus netflowPort scans, probing and floods against this server (opt-in sensor)1 min
argus coverageIs 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

SeverityMeaning
criticalact now: something can already reach in, or nothing can reach you
higha concrete weakness or a sign of compromise to look at today
mediuma gap to close: missing fixes, undeclared services, reduced visibility
lowcontext worth knowing: inventory, optional features not enabled
okchecked 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 3f9a2c1d

Alerts

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.

KeyChannel
resend_api_key, alert_from, alert_toemail through Resend
webhook_url, webhook_secretJSON POST (Slack- and Discord-compatible text), signed
ntfy_url, ntfy_tokenan ntfy topic on your phone
syslog: trueone 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_severitycritical, high (default) or medium
config.json
{
  "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:

verify (Python)
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 channel

Phone 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.

  1. On the server, run argus notify pair. It shows a 10-character code, valid for 10 minutes.
  2. On the phone, open argus.archymedes.xyz, choose “Add a server” and type the code.
  3. 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.
  4. 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 delivery

By 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:

config.json
{ "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).

prometheus.yml
scrape_configs:
  - job_name: argus
    static_configs:
      - targets: ['127.0.0.1:8787']
MetricMeaning
argus_up / argus_live / argus_healthythe daemon answers / its scheduler makes progress / required evidence is current
argus_security_scoreposture 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
alert rules
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_seconds

Incoming 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 serverWhen
HTTPS GETs of public threat feeds and your distribution's security dataon their schedules
alerts, on the channels you configurewhen something changes
sealed envelopes to the phone relayonly after you pair a phone
one heartbeat GET a minuteonly 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

PathWhat
/opt/argus/binthe program and its libraries, root-owned and read-only
/opt/argus/verification.jsonthe installed copy's verification report
/var/lib/arguswhat Argus records: baseline, findings, history
/var/lib/argus/.argus/config.jsonalert channels, heartbeat, relay settings
/etc/argus/argus.envthe dashboard port
/etc/argus/services.confthe services this server is meant to expose
/etc/systemd/system/argus.servicethe service
/usr/local/bin/argusthe command line (runs as argus, via sudo)
systemctl status argus
journalctl -u argus -f

Server 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.

  1. Install the server edition and let it run for a week.
  2. Activate the key on the server (it asks Polar whether the key is valid, nothing else).
  3. Write the report: owner-only, never overwriting a file.
On the server
argus licence activate ARGUS-REVIEW-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
argus licence status
argus review --out review.txt

Without 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 --purge

The 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 seeDo 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 codeanswer no on the server and pair again; do not pair when the codes differ
no notifications on iPhoneadd Argus to the Home Screen first, then turn notifications on in its Settings
“notify: python3-cryptography is not installed”sudo apt install python3-cryptography