Optional exports for root-only data
The agent runs as an unprivileged user and only ever reads files — that is what makes it safe to run on your servers. Almost everything it reports comes from world-readable sources: /proc for listening ports, package databases, web-server config, and the like.
A few facts, though, live in files only root can read. A firewall’s rule list is the clearest case: ufw keeps its rules in /etc/ufw/user.rules, mode 0640, so the agent can confirm a firewall is active but cannot enumerate its rules.
Rather than give the agent root — which would undo the one promise that makes it safe — you can opt in to exporting just those specifics into a file the agent reads.
The guarantee this keeps
Nothing about the agent changes. It still only reads a file; it gains no privilege, opens no port, runs no privileged command. The privileged part — dumping the data — is a command you run, once or from cron. If you never set it up, the agent simply reports a little less. This is the same read-only, least-privilege posture as everything else it does.
Firewall rules
Listening ports need no export — the agent reads them from /proc, always.
How much more it can tell on its own depends on your firewall:
- ufw keeps
/etc/ufw/ufw.confworld-readable, so whether it is enabled and its default incoming policy are read directly. Only the rule list (user.rules,0640) is root-only. - iptables-persistent saves to
/etc/iptables/rules.v4as0640 root:root, so the agent can see that iptables is configured but cannot read a single thing about it — not even whether it is active. Demerzel shows it as detected, state unreadable, and deliberately scores nothing from it rather than guessing. - nftables depends on how
/etc/nftables.confis shipped on your distribution.
In every case the agent distinguishes “there is no firewall” from “I am not allowed to look” — the second never counts against your Health Score.
To surface it, dump your rules into /etc/demerzel-exports/firewall.rules. Pick the command for your firewall:
# ufw
sudo mkdir -p /etc/demerzel-exports && sudo sh -c '/usr/sbin/ufw status verbose > /etc/demerzel-exports/firewall.rules'
# nftables
sudo mkdir -p /etc/demerzel-exports && sudo sh -c '/usr/sbin/nft list ruleset > /etc/demerzel-exports/firewall.rules'
# iptables
sudo mkdir -p /etc/demerzel-exports && sudo sh -c '/usr/sbin/iptables -S > /etc/demerzel-exports/firewall.rules'
To keep it current, run it from cron instead — for example, drop this in /etc/cron.d/demerzel-firewall:
*/30 * * * * root /usr/sbin/ufw status verbose > /etc/demerzel-exports/firewall.rules 2>/dev/null
Give the tool’s absolute path, as above: cron’s PATH has no /usr/sbin, and the file would stay empty.
/etc/demerzel/firewall.rules. That directory belongs to the agent's user, and a command run as root that writes into it would follow a link planted there. Move the export to /etc/demerzel-exports/, which only root can write, and delete the old file: sudo rm /etc/demerzel/firewall.rules. The agent reads both paths meanwhile.The agent picks the file up on its next run, and the server’s Firewall tab shows the rules, labelled from your export. Until then, that tab surfaces the exact command for you — you don’t have to remember it.
The same pattern, other data
This is a general mechanism, not a one-off. Any root-only fact can be surfaced the same way: you run a command that writes a readable summary, the agent reads it, the agent stays unprivileged.
Certificates are the next natural candidate — Let’s Encrypt keeps live certificates under /etc/letsencrypt/live/, which is also root-only. Today you don’t need to do anything for those: Demerzel already learns each host’s certificate by probing its TLS from the server side, so expiry and issuer show up without any on-host export. The export approach is simply there for the cases server-side probing can’t reach.
If there’s a root-only signal you’d like on your dashboard, this is the shape the answer will take — an export you opt into, never a more powerful agent.