Troubleshooting
The four questions that cover most support cases. Start every session the same way:
sudo ezyshield doctorDoctor is read-only and each check prints a hint with the exact fix. The sections below map the common symptoms to the checks that diagnose them.
"The daemon runs but nothing is detected"
Detection needs a log source, a matching parser, and events actually flowing.
collectors: configured(doctor) — zero collectors means nothing is ever read. Add acollectors:section (or re-runezyshield init).journald: readable(doctor) — the journald collector runs as theezyshielduser, which needs thesystemd-journalgroup. The hint gives theusermodfix.- Wrong unit or path. Debian names the SSH unit
ssh, RHELsshd; afilecollector needs the access log for HTTP rules. Compare your config against what's really logging:sudo ezyshield scanlists listening services and their log sources. - Still quiet?
ezyshield statusshowsCollectorsState: DEGRADEDwith the failing collector named when a source repeatedly errors;ezyshield watchconfirms events the moment parsing works.
"A collector is configured but cannot read its source"
A collector can be configured, started, and still read nothing. The usual cause is permissions on the source itself: a kind: docker collector on a host where the ezyshield service user cannot reach the Docker Engine socket, or a journald collector without the systemd-journal group. Detection on that source is dead while enforcement looks perfectly healthy.
Two checks answer this together:
[FAIL] docker: socket access
hint: service user ezyshield (uid 999) cannot read+write /var/run/docker.sock
(owner 0:994, mode 0660) -- the configured docker collectors observe NOTHING.
Access paths, cheapest privilege first: (1) collect a host-mounted log file
instead of the container's stream (no docker privilege at all); (2) expose a
read-only, filtered Docker socket proxy to ezyshield; (3) add ezyshield to the
'docker' group -- that group is root-equivalent on this host ...
[FAIL] collectors: observation state
hint: DEGRADED — a configured collector is NOT reading its source
(docker:proxy-web is not reading (5 consecutive failures: docker: permission
denied on /var/run/docker.sock)); nothing from that source is detected,
however healthy enforcement looks ...docker: socket accessevaluates the service user, not the account running doctor. An operator who is in thedockergroup would otherwise read a green check for access the daemon does not have.collectors: observation stateasks the running daemon what it is actually reading.ezyshield statusshows the same verdict as aCollectorsState: DEGRADEDbanner naming the collector and its last error, and the daemon writes acollector_degradedaudit row plus one critical notification when a source stops being read.- Pick an access path by what it costs: a host-mounted log file needs no Docker privilege at all; a read-only, filtering socket proxy exposes only what it is configured to expose; the
dockergroup is root-equivalent on the host (a member can start a privileged container), so grant it deliberately and only while docker collectors are configured.
service user: docker group reports the membership when it exists; when it does not, docker: socket access is the check with the verdict, because another path may already grant the access.
"A ban is recorded but the IP is not blocked"
The worst failure mode — and the one most instrumented.
ezyshield statusfirst:EnforcementStateis the honest answer.DRY-RUNmeansarmed: false— recorded bans are simulated by design.DEGRADEDnames the failing backend.enforcer: socket connectivity(doctor) — the helper is down or its socket unreachable:systemctl status ezyshield-enforcer.enforcer: netlink probe(doctor) — the helper runs but its sandbox lost netlink access (a modified unit): the hint names theRestrictAddressFamiliesfix.firewall: ezyshield nftables table(doctor) — the table is GONE while bans are active: something flushed the ruleset (see the firewall coexistence guide);systemctl restart ezyshield-enforcer ezyshieldrecreates and re-syncs.bans: ban_ineffective diagnostics(doctor) — the daemon itself flags bans that kept generating events after the grace period.
"Permission errors on the socket"
dial unix /run/ezyshield/ezyshield.sock: connect: permission deniedThe control socket is root:ezyshield, mode 0660 — membership in the ezyshield group is the access control.
id— are you in theezyshieldgroup?ezyshield initadds the installing admin; for anyone else:sudo usermod -aG ezyshield <user>then re-login.- Socket missing entirely → the daemon isn't running (
systemctl status ezyshield);exit code 3from any CLI command means exactly "daemon unreachable". ezyshield-enforcer.service: runtime directory/ezyshield.service: runtime directory(doctor) — a stripped unit never creates/run/ezyshield*; the hint carries the drop-in fix.
"The journald source is not matched"
Events exist in journalctl -u ssh but EzyShield sees nothing.
- The collector's
unit:must match the exact unit name —sshvssshdagain.systemctl list-units 'ssh*'settles it. journald: readable(doctor) — reads the journal as the daemon's identity; a PASS here plus silence usually means the unit name.- Container setups: journald inside the container is not the host's journal — run the collector where the logs are, or use a
filecollector on a mounted log.
Escalation paths
- False positive banning real users →
sudo ezyshield allow <ip>(allowlist always wins), then tune viarules.d. - Everything on fire →
sudo ezyshield disable --all(removes every block, disarms, keeps history — see the CLI reference). - Bug reports: attach
ezyshield doctor --jsonandezyshield status --jsonoutput — both are safe to share (no secrets).