Ga naar inhoud

Install strategy

How this repo behaves when a user clones it and runs it on a new machine. Intended for implementation engineers and people taking over the tool: what must work, what may fail, and how you can see afterwards what you got.

Philosophy — best-effort, opt-out per component

A fresh git clone + sudo bash bootstrap.sh should do what it can and report what didn't work on the current distro + runtime. Components are additive, not mutually required:

  • Failure of an optional component (rkhunter, logrotate-systemd) is no reason to stop the installer.
  • Failure of a required component (ClamAV scanner, signatures) is — bootstrap.sh returns non-zero so an ops flow notices.
  • Every install.sh prints per step what worked and what didn't; it ends with a print_summary showing the / status per component.
  • check.sh then independently reports the actual runtime state, not the intended one — drift between "we installed X" and "X is running now" becomes visible.

Audit trail: every deviation from the expected picture should be resolvable with check.sh output + a commit message in CHANGELOG.md. No silent skips, no hidden state.

Components and their status

Component Status Default source What happens if it's missing?
ClamAV (clamscan, clamd) Required distro stock pkg Installer aborts with exit 2 (critical function missing)
ClamAV scan daemon (clamd@scan on Alma; clamav-daemon on Arch/Ubuntu) Required distro stock Installer enable_clamav_services fails visibly; check.sh reports
ClamAV signatures via av-update.timer Required repo-shipped unit No fresh signatures → check.sh warning after 3+ days; cron mail on every run
rkhunter Optional distro stock (on Alma via EPEL) Installer prints an explanation, sets rkhunter_ok=0, continues; check.sh skips rkhunter sections
rkhunter property database (/var/lib/rkhunter/db/rkhunter.dat) Optional (requires rkhunter) generated by rkhunter --propupd in rkhunter_init check.sh (as root) reports ✗ rkhunter database not found with a retry hint
systemd timers (av-update, clamav-scan, rkhunter-check) Required if systemd repo-shipped units WSL without systemd: skip + WSL explanation; native without systemd: skip + manual commands
Logrotate config (/etc/logrotate.d/workstation-security) Required if systemd repo-shipped Logs grow unbounded — visible in du, not in check.sh
IR tooling (incident-token-revoke.sh, install-pm-cooldown.sh) Optional repo-shipped Not run during install; explicit user action

Failure modes per component

ClamAV (required)

  • Package unavailable → installer prints an error message + exit 2. Audit: it is a non-conformity on any framework that requires AV.
  • Daemon package missing (clamd on Alma, clamav-daemon on Ubuntu) → same.
  • freshclam signature download fails → installer logs freshclam_safe output; signatures can be fetched later via sudo bash common/update.sh or av-update.timer (04:00).
  • SELinux blocks clamscan on /home (Alma) → installer sets setsebool -P antivirus_can_scan_system 1. If setsebool is missing: warning, the scan would silently fail with "0 dirs / 0 files".

rkhunter (optional)

  • Package unavailable (e.g. EPEL not enabled on Alma) → installer prints the exact dnf/apt/pacman error (no 2>/dev/null mute), sets rkhunter_ok=0, continues.
  • rkhunter_init non-zero exit → the wrapper around rkhunter --update && rkhunter --propupd lives in common/install-base.sh::rkhunter_init and is defensive against rkhunter 1.4's deprecated-egrep quirk: both commands run under set +e, the return code is checked separately, and on non-zero the installer prints a retry hint (sudo rkhunter --propupd).
  • WSLrkhunter-check.sh explicitly skips (false positives on /proc and init); see threat-model.md for the reasoning.

Systemd timers

  • WSL without [boot] systemd=trueinstall-timers.sh skips cleanly with an opt-in instruction; manual scans/update via common/scan.sh and common/update.sh keep working.
  • Native without systemd (rare) → same skip path, generic warning.

freshclam-daemon redundancy (historical)

The OS-stock clamav-freshclam.service (long-running signature-update daemon) is not used by this repo — av-update.timer (04:00) is the only signature-update mechanism. disable_freshclam_daemon in install-base.sh disables it on installation. The re-enable risk per distro is in that function's comment and in CHANGELOG 2026-05-24. Reason: two mechanisms race on the freshclam log lock, and freshclam_safe cannot reliably restart the daemon after a stop.

Per OS × runtime — expected end picture

= works automatically. manual = installer prints an instruction, the user runs one command. skip = deliberately off, see threat-model.

Component Alma 10 native Arch native Ubuntu native WSL2 without systemd WSL2 with systemd
ClamAV scanner + signatures
ClamAV daemon manual
systemd timers skip + opt-in hint
check.sh services/timers skip with explanation
rkhunter pkg + init ✓ (via EPEL) ✓ (binary)
rkhunter-check.sh daily skip (deliberate) skip (deliberate)
IR-tool clipboard/URL ✓ + Windows hints ✓ + Windows hints

How check.sh fits into this strategy

check.sh is the canonical runtime report, not the installer's print_summary. Four statuses:

  • — component is running or fresh (audit evidence).
  • ! — deviation the user should resolve, but the system works (e.g. signatures 4 days old, rkhunter-db not readable without root). Counts in the final tally.
  • — critical deviation (scan daemon dead, signatures entirely gone). Counts in the final tally.
  • - — deliberately skipped (rkhunter on WSL, services on non-systemd).

The final block sums up every !/ so that a cron mail or audit screenshot immediately shows what to do. The exit code equals the number of problems (capped at 2 — bash exit codes above 125 have special meaning).

Manual fix-up after a partial install

Repeating bootstrap.sh is always safe — all installer paths are idempotent. But for targeted fixes:

check.sh says What to do
✗ <daemon> (inactive) sudo systemctl start <daemon>; check the journal for the crash reason
! ClamAV signatures (N days old) sudo bash common/update.sh — or wait until 04:00
✗ ClamAV signatures not found sudo freshclam (in disabled-daemon mode); reinstall if that fails
✗ rkhunter database not found sudo rkhunter --propupd — rebuild the property DB
! rkhunter database not readable No action needed — only root can read this file; run check.sh with sudo
✗ <timer> (inactive) sudo systemctl enable --now <timer>; check install-timers.sh output

When in doubt: sudo bash bootstrap.sh again — idempotent, and it prints per step what is already correct.

What this strategy does NOT attempt

  • No forced alignment. If a component is genuinely unavailable on a distro (e.g. a future Alma without EPEL rkhunter), we do not attempt a manual tarball install or vendoring. The installer skips it and check.sh reports it — the user decides.
  • No retries on network flakes. freshclam sometimes fails due to CDN blips; we rely on the daily timer for recovery.
  • No rollback. A failed install leaves the partial state behind. common/uninstall.sh exists to cleanly remove the repo's own units/logrotate config; OS packages remain unless the user removes them manually.
  • No "vendor your own clamav". If the distro-stock version is too old, that's a distro choice; we don't fork it.

Changing this strategy

A new component or a change in required/optional status comes together in four places:

  1. This doc — table + failure-mode paragraph.
  2. CHANGELOG.md — entry with date and reason.
  3. install.sh per OS — installer path for the new component.
  4. check.sh — runtime reporting (ws_ok/record_fail/ws_skip).

Forget one and you get drift between documentation and reality — exactly what this strategy tries to prevent.