Every rule in the authentication group of
stacks/observability/loki/rules/security.rules.yaml begins with the same
selector:
Only two hosts ever produce that label. saruman and morpheus produce none,
so all five rules are structurally blind to them — and those are the two hosts
where root can be reached with a password.
Measured
2026-09-04, against Loki from oracle, running the rules' own selector:
sum by (host) (count_over_time({log_type="authlog"} |~ `Accepted (password|publickey|keyboard-interactive)` [7d]))
oracle 110
prometheus 258
sum by (host) (count_over_time({host=~".+"} |~ `Accepted (password|publickey|keyboard-interactive)` [7d]))
Saruman 1
morpheus 43
oracle 361
prometheus 774
And directly:
{log_type="authlog", host=~"Saruman|morpheus"} → no results, 7 days
44 accepted SSH logins on those two hosts in a week, none of them visible to
SshBruteForce, SshBruteForceSevere, SshLoginFromUnexpectedSubnet,
SudoFailure or NewUserOrGroupCreated.
(The oracle/prometheus counts on the second query are inflated — those hosts
ship the same events by more than one route. The comparison that matters is
present-vs-absent, not the totals.)
Why each host misses
saruman — local.file_match "authlogs" in stacks/observability/alloy/config.alloy
hard-codes __path__ = "/var/log/auth.log", and loki.process "authlogs" is
the only thing that applies log_type = "authlog". saruman is Proxmox on
Debian 13 (node_uname_info → 7.0.14-12-pve), which is journald-only — there
is no /var/log/auth.log for that block to match. Its sshd lines do arrive,
via loki.source.journal, as log_type="journal", unit="ssh.service". So the
agent is working and the data is in Loki; only the label the rules key on is
absent.
morpheus — pfSense, not an Alloy host. It arrives through
loki.source.syslog "network" in syslog.alloy, which sets
log_type = "syslog" for everything it receives. Its sshd lines are in Loki
too, under that label.
So this is a labelling/selector mismatch, not a collection gap. Nothing is
missing from the store — the rules just cannot see it.
Why it is worth fixing rather than noting
The two invisible hosts are the worst two to lose:
morpheus is the firewall, and it takes root by password
(permitrootlogin yes, read on the host 2026-09-01). Its log shows
Accepted keyboard-interactive/pam for root from two Hicks addresses on
2026-09-02, so this is how the machine is actually used, not a latent setting.
saruman accepted root by password from a Hicks address on 2026-09-02.
A password-guessing run against root@morpheus produces no SshBruteForce at
any volume. This is the same shape as #223 — a rule that reads correctly and
cannot fire — and part of the same family as #170, where half the rules had
nowhere to go.
Two possible fixes
- Widen the rules. Replace
{log_type="authlog"} with a selector that also
admits saruman's journal and morpheus's syslog — e.g.
{log_type=~"authlog|syslog"} plus the ssh.service journal stream. Cheapest
change, but it widens what the line filters run against, so the
SshLoginFromUnexpectedSubnet exclusions want re-checking against pfSense's
line format.
- Fix the labels at the shipper. Add a journal-side path that stamps
log_type="authlog" on unit="ssh.service" (and the sudo/useradd lines
the other two rules want), and match the relevant pfSense lines in
loki.process "network_syslog", which already does per-line matching. More
work, but it keeps the rules simple and makes the label mean one thing.
Either way scripts/check_loki_rules.sh should grow a case that fails when a
monitored host produces zero lines for a rule's selector, because that is the
failure mode here: the rules are valid, they load, and they match nothing.
Related
Found while working Lemmiwinks
#114; recorded in that
vault's systems/ssh_access §6, which is documentation of the gap and not a fix
for it.
🤖 Generated with Claude Code
Every rule in the
authenticationgroup ofstacks/observability/loki/rules/security.rules.yamlbegins with the sameselector:
Only two hosts ever produce that label.
sarumanandmorpheusproduce none,so all five rules are structurally blind to them — and those are the two hosts
where
rootcan be reached with a password.Measured
2026-09-04, against Loki from
oracle, running the rules' own selector:And directly:
44 accepted SSH logins on those two hosts in a week, none of them visible to
SshBruteForce,SshBruteForceSevere,SshLoginFromUnexpectedSubnet,SudoFailureorNewUserOrGroupCreated.(The
oracle/prometheuscounts on the second query are inflated — those hostsship the same events by more than one route. The comparison that matters is
present-vs-absent, not the totals.)
Why each host misses
saruman—local.file_match "authlogs"instacks/observability/alloy/config.alloyhard-codes
__path__ = "/var/log/auth.log", andloki.process "authlogs"isthe only thing that applies
log_type = "authlog".sarumanis Proxmox onDebian 13 (
node_uname_info→7.0.14-12-pve), which is journald-only — thereis no
/var/log/auth.logfor that block to match. Itssshdlines do arrive,via
loki.source.journal, aslog_type="journal",unit="ssh.service". So theagent is working and the data is in Loki; only the label the rules key on is
absent.
morpheus— pfSense, not an Alloy host. It arrives throughloki.source.syslog "network"insyslog.alloy, which setslog_type = "syslog"for everything it receives. Itssshdlines are in Lokitoo, under that label.
So this is a labelling/selector mismatch, not a collection gap. Nothing is
missing from the store — the rules just cannot see it.
Why it is worth fixing rather than noting
The two invisible hosts are the worst two to lose:
morpheusis the firewall, and it takesrootby password(
permitrootlogin yes, read on the host 2026-09-01). Its log showsAccepted keyboard-interactive/pam for rootfrom two Hicks addresses on2026-09-02, so this is how the machine is actually used, not a latent setting.
sarumanacceptedrootby password from a Hicks address on 2026-09-02.A password-guessing run against
root@morpheusproduces noSshBruteForceatany volume. This is the same shape as #223 — a rule that reads correctly and
cannot fire — and part of the same family as #170, where half the rules had
nowhere to go.
Two possible fixes
{log_type="authlog"}with a selector that alsoadmits
saruman's journal andmorpheus's syslog — e.g.{log_type=~"authlog|syslog"}plus thessh.servicejournal stream. Cheapestchange, but it widens what the line filters run against, so the
SshLoginFromUnexpectedSubnetexclusions want re-checking against pfSense'sline format.
log_type="authlog"onunit="ssh.service"(and thesudo/useraddlinesthe other two rules want), and match the relevant pfSense lines in
loki.process "network_syslog", which already does per-line matching. Morework, but it keeps the rules simple and makes the label mean one thing.
Either way
scripts/check_loki_rules.shshould grow a case that fails when amonitored host produces zero lines for a rule's selector, because that is the
failure mode here: the rules are valid, they load, and they match nothing.
Related
routes these through the journal: on
sarumanthe delivered count matcheswhat the agent reports reading (160/160 lines in 24h), so nothing is lost
after the read, but hourly
cronshows 24 entries for 2026-09-03 and one eachfor the two days before, so capture there is complete only from 2026-09-03.
Worth settling before relying on journal-sourced auth alerting.
TerminalSegmentReachedInternalNetworkcannot fire. Same class ofdefect.
Both of the accepted
rootlogins above came from Hicks addresses.Found while working Lemmiwinks
#114; recorded in that
vault's
systems/ssh_access§6, which is documentation of the gap and not a fixfor it.
🤖 Generated with Claude Code