Network Status
One hourly HTML status page for a mixed Debian-family fleet: it audits pending package updates on every host over SSH, separates security updates from normal ones, adds Ubuntu Pro security counts and Debian debsecan CVEs where the host provides them, and writes a single static page that Caddy serves at status...
WHAT IT DOES
Turns "what needs patching on my network?" into one page. For every
configured host it runs a read-only probe (no root, no package changes):
apt-get -s -qq dist-upgrade for pending updates, the apt security origin
for security classification, pro security-status --format json on Ubuntu
for standard/ESM security counts, and debsecan --format detail on Debian
when it is installed for CVE detail. Hosts that are not Debian-family are
reported as skipped instead of failing the sweep. Results are stored as
swamp data and rendered into one self-contained index.html.
The page is deliberately extensible: a tasks.json action list and the
addTask/removeTask methods let any other workflow add "other things I need to
do on the network" without changing this extension. The Debian audit is the
first provider, not a hard-coded one-off.
Serving is the last step of the bundled hourly workflow, following the same
pattern as @svendowideit/ebooks and @svendowideit/news: ensure-caddy-serve
reads the caddy model that already owns this machine, creates/updates a
dedicated status-caddy model carrying only its baseDomain and serviceName,
and calls serveSettings. Caddy derives the TLS subject and A record from the
route, so the route is idempotent and no caddy command is run in isolation.
It never starts a second Caddy service.
Prefer it over a local-only apt reporter when the targets are remote: the existing @aaronge/apt-inventory is the right tool for one host's local apt state, while this extension adds the fleet fan-out and the one-page status surface. It reuses @svendowideit/fleet-inventory for host discovery and @svendowideit/caddy for serving, so it does not invent another inventory or web server.
INSTALL
swamp extension pull @svendowideit/network-statusDEPENDENCIES
@svendowideit/caddy is an optional dependency for the static file_server
route and TLS/DNS; pull it separately to enable the workflow's serve step
(the step skips with a log when it is absent). @svendowideit/fleet-inventory
is optional and recommended: use its inventory as the host source. Every
target needs an OpenSSH server and a key or agent the swamp host can use; no
swamp install is required on the targets. Ubuntu Pro (pro) and debsecan are
optional per host and only add security detail; without them the apt
security-origin list is still shown.
RUN
# The whole pipeline: audit the fleet, render the page, then idempotently
# declare the Caddy route (setup and hourly refresh in one run).
swamp workflow run @svendowideit/network-status
# Audit this machine first. `local: true` skips SSH for the host running
# swamp, so a fresh install can prove the collector end to end.
swamp model @svendowideit/network-status method run audit status \
--input 'hosts:json=[{"name":"localhost","address":"localhost","local":true}]'
# Record a network-wide action item. Other workflows call this too; it
# re-renders the page immediately so the item is visible on the next load.
swamp model @svendowideit/network-status method run addTask status \
--input title="Renew the UPS battery" --input severity=medium \
--input detail="Runtime is below 10 minutes."
# Rebuild the page after changing the template or tasks.json without
# re-running the network sweep.
swamp model @svendowideit/network-status method run render statusCONFIGURE
Global arguments: hosts (array of {name,address,user,port,os,local} or
user@host strings), sshUser, identityFile, connectTimeoutSec,
commandTimeoutSec, parallel, securityOrigin (default -security),
outputDir, outputFile, tasksFile, pageTitle, statusHostname,
staleAfterHours, cveCheck, static tasks, caddyModelName (source caddy model;
empty auto-discovers the one that owns this machine), caddyRouteHostname and
caddyServeModel. Method arguments: audit takes hosts/cveCheck/parallel
overrides; ensure-caddy-serve takes model/hostname/serveRoot/serveModel;
addTask takes id/title/detail/severity/link/source/due; removeTask takes id;
clearTasks requires confirm=true. Precedence is per-call --input > model
global > schema default.
WHAT IT INSTALLS
Nothing on any target. The probe is read-only and runs without sudo; it
writes no package state. On the swamp host it writes the HTML page and
tasks file under outputDir and writes swamp resources. Serving is Caddy's
existing file_server route declared by ensure-caddy-serve -- this
extension starts no second web server, daemon or webhook. The hourly
schedule is the bundled workflow trigger evaluated by swamp serve. On the
first run caddy may take a while to reconcile the new DNS record and
certificate; that is expected.
Global Arguments
| Argument | Type | Description |
|---|---|---|
| hosts? | array | |
| sshUser? | string | |
| identityFile? | string | |
| connectTimeoutSec? | number | |
| commandTimeoutSec? | number | |
| parallel? | number | |
| securityOrigin? | string | |
| outputDir? | string | |
| outputFile? | string | |
| tasksFile? | string | |
| pageTitle? | string | |
| statusHostname? | string | |
| staleAfterHours? | number | |
| cveCheck? | boolean | |
| tasks? | array | |
| caddyModelName? | string | |
| caddyRouteHostname? | string | |
| caddyServeModel? | string |
| Argument | Type | Description |
|---|---|---|
| hosts? | array | |
| cveCheck? | boolean | |
| parallel? | number |
| Argument | Type | Description |
|---|---|---|
| model? | string | |
| hostname? | string | |
| serveRoot? | string | |
| serveModel? | string |
| Argument | Type | Description |
|---|---|---|
| id? | string | |
| title | string | |
| detail? | string | |
| severity? | enum | |
| link? | string | |
| source? | string | |
| due? | string |
| Argument | Type | Description |
|---|---|---|
| id | string |
| Argument | Type | Description |
|---|---|---|
| confirm? | boolean |
Resources
Hourly Debian-family package and security audit, followed by the idempotent Caddy serving setup. The audit step probes every configured host and writes one HTML page. The serve step then declares the page's file_server route via @svendowideit/caddy's normal additive reconcile: it reads the caddy model that already owns this machine, creates/updates a dedicated status-caddy model carrying only that model's baseDomain and serviceName, and lets caddy derive the TLS subject and A record from the ro
- Has README or module doc2/2earned
- README has a code example1/1earned
- README is substantive1/1earned
- Most symbols documented0/1missing
- No slow types (deprecated)1/1earned
- Dependencies pass trust audit1/2partial
- @std/assert--jsr:@std/assert@1 is a range; audited 1.0.19, the version the registry resolved
1 dependency found
- jsr:@std/assert@1 -- audited 1.0.19
- Docs keep secrets in a vault1/1earned
- Has description1/1earned
- Platform support declared (or universal)2/2earned
- License2/2earned
- Verified public repository2/2earned
Spawns a subprocess with Deno.Command().
- models/network_status.ts:508 — only ssh/sh are used, args come from the typed host config, and the probe is piped via stdin rather than interpolated into a command string — see README.
- models/network_status.ts:1284 — optional caddy peer discovered at runtime; args are fixed literals plus typed model names/hostnames, never a shell string — see README.