Commit Graph

5 Commits (265136fc42c49fe17273616332b4f297a24b098b)

Author SHA1 Message Date
boban 4248c83c42 Fresh-install bug batch: prod poller, installer UX, switcher/firewall polish
Prod metrics poller: docker-compose.prod.yml gains a `metrics` service
(clusev:poll-metrics --interval=15). The poller previously existed only in the
dev supervisor config, so on a customer install no process ever promoted a
server out of 'pending' (Initialisierung) or refreshed CPU/MEM — fresh
installs sat at 0% forever. The service inherits the hardened *image anchor.

Installer output: new run_logged() helper routes noisy steps (apt, docker
build/pull, compose up, migrate, caches) into install.log at the repo root —
TTY gets a spinner + "ok" lines, non-TTY gets start/ok lines, failures tail
the last 40 log lines and abort. Secret-bearing steps (APP_KEY, admin
password) deliberately stay out of the log. update.sh shares the same log via
CLUSEV_INSTALL_LOG and redirects git pull/verify-commit detail into it. The
log is initialized symlink-safely (mktemp + atomic rename -T) because the
repo root belongs to the unprivileged clusev user after install (Codex
finding); /install.log is gitignored so updates never conflict.

Server switcher: an empty fleet now renders an explanatory empty state with a
role-gated "Server hinzufügen" CTA instead of an empty dropdown panel.

Servers/groups headers: the raw <a> buttons (unconditional min-h-11) are
replaced with x-btn, aligning them with the h-8 accent button + status pill.

Firewall panel: the rules box is hidden for ANY inactive firewall (previously
only firewalld — an inactive ufw showed a misleading rules table via `ufw
show added`), with a tool-agnostic hint + Aktivieren action; the add-rule
trigger is gated on active. hardeningApplied now performs an in-place
security re-read (OS profile + hardening + firewall + fail2ban) instead of a
full-page skeleton reload, with a wire:loading cue and toggles disabled while
it runs — the state can no longer be re-toggled against stale data.
SshKeyProvision drops its redundant hardeningApplied (credentialChanged
already full-reloads).

Hardening modal: failure output limit 200 → 400 so the 202-char root-lockout
guard message renders unclipped; the root-login description now states that
PermitRootLogin no blocks both password and key logins.

Command palette: chords g o (Verfügbarkeit) + g b (Bedrohungen).

Codex-reviewed (one finding: symlink-following log init — fixed + re-verified
clean). 760 tests.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-08 18:57:04 +02:00
boban 7ec2c065bb fix(hardening): guard against root-login self-lockout
Disabling SSH root login (PermitRootLogin no) severs Clusev's OWN access when it
connects AS root — afterwards neither key nor password reaches root. The
password-auth toggle already guards against self-lockout; the root toggle did not.
Refuse to disable root login while the active credential's username is root, with a
clear message: add a non-root sudo user + key and switch Clusev to it first.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 00:41:50 +02:00
boban b847b80ab6 feat(ssh): SshKeyProvisioner — generate+install key, verify, switch credential, then disable password (rollback-safe)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-14 21:57:45 +02:00
boban 37efa64b9d fix(ssh): require an exec marker in the connection probe
Auth success alone does not prove the server can run commands (a server that
authenticates but rejects exec channels would be accepted, yet every fleet
operation runs commands). The probe now echoes a unique marker and requires it
in the output — proving exec works, while still tolerating servers that omit
the optional exit-status packet.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-14 10:46:59 +02:00
boban ec1516184e i18n: complete DE/EN localization (modals, shell, backend) + v0.3.0
- modals: wire 5 hard-coded views + 10 components to lang/{de,en}/modals.php
- shell: command-palette (incl. app.js cmdk(nav,actions) refactor), server-item,
  toaster fallback
- backend: new lang/{de,en}/backend.php; localize Hardening/Firewall/Fail2ban/
  Maintenance services, OsProfile, plus FleetService + CredentialVault errors
- fix: localized page <title> on Dashboard/Servers index+show (->title(), the
  Livewire-3 way; the stray title() methods were never auto-called)
- fix: topbar inline @php() was swallowed by Blade's raw-block precompiler up to a
  later @endphp -> 500 on every authed page; converted to block @php ... @endphp
- versions: localize changelog section labels via a canonical heading map
- translation-quality pass: Unlock, Add credentials, clearer auth/notify copy

Bump 0.2.1 -> 0.3.0; CHANGELOG.

Verified: Pint clean; npm build OK; R12 all routes HTTP 200 + 0 console errors in
BOTH locales (titles/nav/labels switch language); 589 used keys resolve in de+en
with full group parity; Codex review clean; adversarial DE/EN audit (0 high).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-13 23:27:42 +02:00