Files
felhom.eu/documentation/audits/evidence-backup-promise-2026-09-16/teardown-e1-hostpage.html
T
admin c18efc0610
gates / gates (push) Successful in 20s
teardown layer 1, a proper secret-leak check, and the fresh-box proof in both rows
VM 335 purged with its disks; demo-hp's own containers untouched; evidence pulled
off the box before the destroy, with the one thing I could not collect stated (the
agent journal — root SSH is refused on the appliance by design).

The leak check redone properly: six real secret VALUES as needles against all 41
evidence files, planted positive control matched 6/6, committed evidence matched 0.
The earlier „22" was the word „password" in labels — a word count, not a leak check.

R-537 and R-538 now carry the fresh-box proof: the labels on a box where off-site is
on, the refusal that pointed at the off-site route, and five photos returned
byte-identical.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
2026-09-16 19:51:54 +02:00

883 lines
41 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>tester-1-33b6a9 — Felhom Hub</title>
<link rel="stylesheet" href="/style.css?v=0.116.0">
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="display:none" aria-hidden="true">
<symbol id="i-triangle-alert" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3" /> <path d="M12 9v4" /> <path d="M12 17h.01" /></symbol>
<symbol id="i-check" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5" /></symbol>
<symbol id="i-server" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="20" height="8" x="2" y="2" rx="2" ry="2" /> <rect width="20" height="8" x="2" y="14" rx="2" ry="2" /> <line x1="6" x2="6.01" y1="6" y2="6" /> <line x1="6" x2="6.01" y1="18" y2="18" /></symbol>
<symbol id="i-settings" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9.671 4.136a2.34 2.34 0 0 1 4.659 0 2.34 2.34 0 0 0 3.319 1.915 2.34 2.34 0 0 1 2.33 4.033 2.34 2.34 0 0 0 0 3.831 2.34 2.34 0 0 1-2.33 4.033 2.34 2.34 0 0 0-3.319 1.915 2.34 2.34 0 0 1-4.659 0 2.34 2.34 0 0 0-3.32-1.915 2.34 2.34 0 0 1-2.33-4.033 2.34 2.34 0 0 0 0-3.831A2.34 2.34 0 0 1 6.35 6.051a2.34 2.34 0 0 0 3.319-1.915" /> <circle cx="12" cy="12" r="3" /></symbol>
<symbol id="i-x" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 6 6 18" /> <path d="m6 6 12 12" /></symbol>
<symbol id="i-info" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10" /> <path d="M12 16v-4" /> <path d="M12 8h.01" /></symbol>
<symbol id="i-hard-drive" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10 16h.01" /> <path d="M2.212 11.577a2 2 0 0 0-.212.896V18a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-5.527a2 2 0 0 0-.212-.896L18.55 5.11A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z" /> <path d="M21.946 12.013H2.054" /> <path d="M6 16h.01" /></symbol>
<symbol id="i-cpu" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 20v2" /> <path d="M12 2v2" /> <path d="M17 20v2" /> <path d="M17 2v2" /> <path d="M2 12h2" /> <path d="M2 17h2" /> <path d="M2 7h2" /> <path d="M20 12h2" /> <path d="M20 17h2" /> <path d="M20 7h2" /> <path d="M7 20v2" /> <path d="M7 2v2" /> <rect x="4" y="4" width="16" height="16" rx="2" /> <rect x="8" y="8" width="8" height="8" rx="1" /></symbol>
<symbol id="i-clock" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10" /> <path d="M12 6v6l4 2" /></symbol>
<symbol id="i-boxes" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M2.97 12.92A2 2 0 0 0 2 14.63v3.24a2 2 0 0 0 .97 1.71l3 1.8a2 2 0 0 0 2.06 0L12 19v-5.5l-5-3-4.03 2.42Z" /> <path d="m7 16.5-4.74-2.85" /> <path d="m7 16.5 5-3" /> <path d="M7 16.5v5.17" /> <path d="M12 13.5V19l3.97 2.38a2 2 0 0 0 2.06 0l3-1.8a2 2 0 0 0 .97-1.71v-3.24a2 2 0 0 0-.97-1.71L17 10.5l-5 3Z" /> <path d="m17 16.5-5-3" /> <path d="m17 16.5 4.74-2.85" /> <path d="M17 16.5v5.17" /> <path d="M7.97 4.42A2 2 0 0 0 7 6.13v4.37l5 3 5-3V6.13a2 2 0 0 0-.97-1.71l-3-1.8a2 2 0 0 0-2.06 0l-3 1.8Z" /> <path d="M12 8 7.26 5.15" /> <path d="m12 8 4.74-2.85" /> <path d="M12 13.5V8" /></symbol>
<symbol id="i-users" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2" /> <path d="M16 3.128a4 4 0 0 1 0 7.744" /> <path d="M22 21v-2a4 4 0 0 0-3-3.87" /> <circle cx="9" cy="7" r="4" /></symbol>
</svg>
<div class="container">
<header>
<h1>Felhom <span>Hub</span></h1>
<nav class="nav-links">
<a href="/" class="nav-link">Dashboard</a>
<a href="/configs" class="nav-link">Customers</a>
<a href="/apps" class="nav-link">Apps</a>
<a href="/hosts" class="nav-link active">Hosts</a>
<a href="/offsite" class="nav-link">Offsite</a>
<a href="/configuration" class="nav-link">Configuration</a>
</nav>
</header>
<a href="/hosts" class="back-link">&larr; Hosts</a>
<section class="card">
<div style="display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 0.5rem;">
<h2 style="margin: 0;">tester-1-33b6a9</h2>
<span class="status-badge status-badge-ok">ONLINE</span>
</div>
<div class="info-grid" style="margin-top: 1rem;">
<div class="info-item">
<span class="label">Host ID</span>
<span class="value" style="font-family: var(--font-mono)">tester-1-33b6a9</span>
</div>
<div class="info-item">
<span class="label">Customer</span>
<span class="value"><a href="/customers/tester-1">Tester 1</a></span>
</div>
<div class="info-item">
<span class="label">Agent Version</span>
<span class="value"><code>0.131.0</code></span>
</div>
<div class="info-item">
<span class="label">PBS wrapper</span>
<span class="value">matches vouched <code>104db0a4401f…</code></span>
</div>
<div class="info-item">
<span class="label">Enrolled</span>
<span class="value">2h ago</span>
</div>
<div class="info-item">
<span class="label">Last Report</span>
<span class="value">4 min ago</span>
</div>
<div class="info-item">
<span class="label">Desired Generation</span>
<span class="value">2</span>
</div>
</div>
</section>
<section class="card">
<h2>Vitals</h2>
<div class="info-grid">
<div class="info-item">
<span class="label">CPU</span>
<span class="value">0%</span>
</div>
<div class="info-item">
<span class="label">Memory</span>
<span class="value">29%</span>
</div>
<div class="info-item">
<span class="label">Disk (root fs)</span>
<span class="value">40%</span>
</div>
<div class="info-item">
<span class="label">Cloudflared</span>
<span class="value">inactive</span>
</div>
<div class="info-item">
<span class="label">Guests</span>
<span class="value">1/1 running</span>
</div>
</div>
</section>
<section class="card" style="padding: 0; overflow: hidden;">
<h2 style="padding: 1.25rem 1.25rem 0.5rem;">Guests</h2>
<table class="data-table">
<thead>
<tr>
<th>VMID</th>
<th>Name</th>
<th>Status</th>
<th>Controller</th>
<th>Last Seen</th>
</tr>
</thead>
<tbody>
<tr>
<td>9201</td>
<td>tester-1</td>
<td><span style="color: var(--green)">running</span></td>
<td>—</td>
<td>4 min ago</td>
</tr>
</tbody>
</table>
</section>
<section class="card" style="padding: 0; overflow: hidden;">
<h2 style="padding: 1.25rem 1.25rem 0.5rem;">Storage Targets</h2>
<table class="data-table">
<thead>
<tr>
<th>Name</th>
<th>Role</th>
<th>Type</th>
<th>State</th>
<th>Fill</th>
<th>Thin Pool</th>
<th>SMART</th>
<th>Temp</th>
<th>Wear</th>
</tr>
</thead>
<tbody>
<tr>
<td>felhom-pbs</td>
<td>—</td>
<td>pbs</td>
<td>attached</td>
<td>0%</td>
<td>—</td>
<td>UNKNOWN</td>
<td>—</td>
<td>—</td>
</tr>
<tr>
<td>local</td>
<td>—</td>
<td>local</td>
<td>attached</td>
<td>40%</td>
<td>—</td>
<td>UNKNOWN</td>
<td>0°C</td>
<td>—</td>
</tr>
<tr>
<td>local-lvm</td>
<td>—</td>
<td>lvmthin</td>
<td>attached</td>
<td>62%</td>
<td>62%</td>
<td>UNKNOWN</td>
<td>—</td>
<td>—</td>
</tr>
</tbody>
</table>
</section>
<section class="card" style="padding: 0; overflow: hidden;">
<h2 style="padding: 1.25rem 1.25rem 0.5rem;">Capabilities</h2>
<table class="data-table">
<thead>
<tr>
<th>Capability</th>
<th>Status</th>
<th>Feature / reason</th>
</tr>
</thead>
<tbody>
<tr>
<td>controllerswap-image-inspect <span class="badge badge-neutral">critical</span></td>
<td><span class="badge badge-ok">ok</span></td>
<td>controller-swap / managed auto-update</td>
</tr>
<tr>
<td>controllerswap-inspect <span class="badge badge-neutral">critical</span></td>
<td><span class="badge badge-ok">ok</span></td>
<td>controller-swap / managed auto-update</td>
</tr>
<tr>
<td>controllerswap-read <span class="badge badge-neutral">critical</span></td>
<td><span class="badge badge-ok">ok</span></td>
<td>controller-swap / managed auto-update</td>
</tr>
<tr>
<td>controllerswap-restart <span class="badge badge-neutral">critical</span></td>
<td><span class="badge badge-ok">ok</span></td>
<td>controller-swap / managed auto-update</td>
</tr>
<tr>
<td>controllerswap-write <span class="badge badge-neutral">critical</span></td>
<td><span class="badge badge-ok">ok</span></td>
<td>controller-swap / managed auto-update</td>
</tr>
<tr>
<td>disk-blkid <span class="badge badge-neutral">critical</span></td>
<td><span class="badge badge-ok">ok</span></td>
<td>disk data-bearing classify (format gate)</td>
</tr>
<tr>
<td>disk-lsblk <span class="badge badge-neutral">critical</span></td>
<td><span class="badge badge-ok">ok</span></td>
<td>disk topology read (format gate)</td>
</tr>
<tr>
<td>disk-lvs</td>
<td><span class="badge badge-ok">ok</span></td>
<td>thin-pool usage read</td>
</tr>
<tr>
<td>disk-mkfs-ext4 <span class="badge badge-neutral">critical</span></td>
<td><span class="badge badge-ok">ok</span></td>
<td>guarded format (ext4)</td>
</tr>
<tr>
<td>disk-mkfs-xfs</td>
<td><span class="badge badge-ok">ok</span></td>
<td>guarded format (xfs)</td>
</tr>
<tr>
<td>disk-smart</td>
<td><span class="badge badge-ok">ok</span></td>
<td>disk SMART health read</td>
</tr>
<tr>
<td>dnsmasq-enable</td>
<td><span class="badge badge-ok">ok</span></td>
<td>dnsmasq enable</td>
</tr>
<tr>
<td>dnsmasq-guest-domain</td>
<td><span class="badge badge-ok">ok</span></td>
<td>guest domain discovery</td>
</tr>
<tr>
<td>dnsmasq-guest-ip</td>
<td><span class="badge badge-ok">ok</span></td>
<td>guest LAN IP discovery</td>
</tr>
<tr>
<td>dnsmasq-install</td>
<td><span class="badge badge-ok">ok</span></td>
<td>dnsmasq package install</td>
</tr>
<tr>
<td>dnsmasq-reload</td>
<td><span class="badge badge-ok">ok</span></td>
<td>dnsmasq reload</td>
</tr>
<tr>
<td>dnsmasq-restart</td>
<td><span class="badge badge-ok">ok</span></td>
<td>dnsmasq restart (LAN-DNS self-heal)</td>
</tr>
<tr>
<td>dnsmasq-rm</td>
<td><span class="badge badge-ok">ok</span></td>
<td>dnsmasq drop-in remove (decommission)</td>
</tr>
<tr>
<td>dnsmasq-write</td>
<td><span class="badge badge-ok">ok</span></td>
<td>dnsmasq drop-in write</td>
</tr>
<tr>
<td>drive-bind <span class="badge badge-neutral">critical</span></td>
<td><span class="badge badge-ok">ok</span></td>
<td>drive attach (felhom-data bind under parent)</td>
</tr>
<tr>
<td>drive-umount <span class="badge badge-neutral">critical</span></td>
<td><span class="badge badge-ok">ok</span></td>
<td>drive detach (fail-closed unmount)</td>
</tr>
<tr>
<td>drives-chown-data</td>
<td><span class="badge badge-ok">ok</span></td>
<td>felhom-data guest-root chown</td>
</tr>
<tr>
<td>drives-mkdir-data</td>
<td><span class="badge badge-ok">ok</span></td>
<td>felhom-data namespace create</td>
</tr>
<tr>
<td>drives-mkdir-parent</td>
<td><span class="badge badge-ok">ok</span></td>
<td>stable parent dir create</td>
</tr>
<tr>
<td>drives-mkdir-sub</td>
<td><span class="badge badge-ok">ok</span></td>
<td>per-drive stable dir create</td>
</tr>
<tr>
<td>escrow-ceremony <span class="badge badge-neutral">critical</span></td>
<td><span class="badge badge-ok">ok</span></td>
<td>customer recovery-code ceremony (controller-driven)</td>
</tr>
<tr>
<td>guest-init-pid <span class="badge badge-neutral">critical</span></td>
<td><span class="badge badge-ok">ok</span></td>
<td>drive-gate guest-sees check (multi-drive concurrency)</td>
</tr>
<tr>
<td>guest-reboot</td>
<td><span class="badge badge-ok">ok</span></td>
<td>enroll activate-binds reboot</td>
</tr>
<tr>
<td>guesthook-delete-mp</td>
<td><span class="badge badge-ok">ok</span></td>
<td>dead mountpoint slot delete (C1 net)</td>
</tr>
<tr>
<td>guesthook-install</td>
<td><span class="badge badge-ok">ok</span></td>
<td>pre-start hook snippet install</td>
</tr>
<tr>
<td>guesthook-register</td>
<td><span class="badge badge-ok">ok</span></td>
<td>pre-start hook register</td>
</tr>
<tr>
<td>guestnet-dhclient-probe</td>
<td><span class="badge badge-ok">ok</span></td>
<td>guest DHCP-client liveness probe</td>
</tr>
<tr>
<td>guestnet-heal</td>
<td><span class="badge badge-ok">ok</span></td>
<td>guest DHCP-client restart (the 2026-07-20 heal)</td>
</tr>
<tr>
<td>guestnet-ifaces</td>
<td><span class="badge badge-ok">ok</span></td>
<td>guest interface-mode read</td>
</tr>
<tr>
<td>guestnet-route</td>
<td><span class="badge badge-ok">ok</span></td>
<td>guest default-route probe</td>
</tr>
<tr>
<td>mount-daemon-reload</td>
<td><span class="badge badge-ok">ok</span></td>
<td>systemd reload after unit write</td>
</tr>
<tr>
<td>mount-unit-disable</td>
<td><span class="badge badge-ok">ok</span></td>
<td>mount unit disable</td>
</tr>
<tr>
<td>mount-unit-enable</td>
<td><span class="badge badge-ok">ok</span></td>
<td>mount unit enable</td>
</tr>
<tr>
<td>mount-unit-install</td>
<td><span class="badge badge-ok">ok</span></td>
<td>fs-UUID mount unit install</td>
</tr>
<tr>
<td>mount-unit-stop</td>
<td><span class="badge badge-ok">ok</span></td>
<td>mount unit stop</td>
</tr>
<tr>
<td>netmount-reset-failed</td>
<td><span class="badge badge-ok">ok</span></td>
<td>NAS automount re-arm after start-limit (F10)</td>
</tr>
<tr>
<td>netmount-rmdir</td>
<td><span class="badge badge-ok">ok</span></td>
<td>removed-share mountpoint cleanup (F1)</td>
</tr>
<tr>
<td>parent-bind-mp8</td>
<td><span class="badge badge-ok">ok</span></td>
<td>parent bind into guest at provision</td>
</tr>
<tr>
<td>parent-make-private <span class="badge badge-neutral">critical</span></td>
<td><span class="badge badge-ok">ok</span></td>
<td>intermediary shared-parent peer-group isolation</td>
</tr>
<tr>
<td>parent-make-shared <span class="badge badge-neutral">critical</span></td>
<td><span class="badge badge-ok">ok</span></td>
<td>intermediary shared-parent propagation</td>
</tr>
<tr>
<td>parent-script-install</td>
<td><span class="badge badge-ok">ok</span></td>
<td>shared-parent boot script install</td>
</tr>
<tr>
<td>parent-self-bind <span class="badge badge-neutral">critical</span></td>
<td><span class="badge badge-ok">ok</span></td>
<td>intermediary shared-parent self-bind</td>
</tr>
<tr>
<td>parent-unit-enable</td>
<td><span class="badge badge-ok">ok</span></td>
<td>shared-parent boot-persistence enable</td>
</tr>
<tr>
<td>parent-unit-install</td>
<td><span class="badge badge-ok">ok</span></td>
<td>shared-parent boot unit install</td>
</tr>
<tr>
<td>pbsdr-create</td>
<td><span class="badge badge-ok">ok</span></td>
<td>PBS DR storage-entry create (K autogen)</td>
</tr>
<tr>
<td>pbsdr-grant</td>
<td><span class="badge badge-ok">ok</span></td>
<td>PBS DR storage ACL self-grant</td>
</tr>
<tr>
<td>pbsdr-read</td>
<td><span class="badge badge-ok">ok</span></td>
<td>PBS DR credential read (verify-loop auth probe)</td>
</tr>
<tr>
<td>pbsdr-reconcile</td>
<td><span class="badge badge-ok">ok</span></td>
<td>PBS DR storage-entry reconcile (set-only)</td>
</tr>
<tr>
<td>provision-chown</td>
<td><span class="badge badge-ok">ok</span></td>
<td>bootstrap mount guest-root chown</td>
</tr>
<tr>
<td>provision-config-mount</td>
<td><span class="badge badge-ok">ok</span></td>
<td>bootstrap config bind mount</td>
</tr>
<tr>
<td>provision-onboot</td>
<td><span class="badge badge-ok">ok</span></td>
<td>customer guest autostart (onboot)</td>
</tr>
<tr>
<td>pve:pool-read</td>
<td><span class="badge badge-ok">ok</span></td>
<td>stale-lock recovery scoping (pool ownership check)</td>
</tr>
<tr>
<td>pve:store-grant:felhom-pbs <span class="badge badge-neutral">critical</span></td>
<td><span class="badge badge-ok">ok</span></td>
<td>backup tier felhom-pbs readable by the agent (archive listing, restore-test candidacy)</td>
</tr>
<tr>
<td>pve:store-grant:local</td>
<td><span class="badge badge-ok">ok</span></td>
<td>backup tier local readable by the agent (archive listing, restore-test candidacy)</td>
</tr>
<tr>
<td>selfheal-networking-start</td>
<td><span class="badge badge-ok">ok</span></td>
<td>appliance networking recovery at boot (F12 defense in depth)</td>
</tr>
<tr>
<td>selfupdate-apply</td>
<td><span class="badge badge-ok">ok</span></td>
<td>agent self-update apply (A/B flip)</td>
</tr>
<tr>
<td>selfupdate-commit</td>
<td><span class="badge badge-ok">ok</span></td>
<td>agent self-update commit</td>
</tr>
<tr>
<td>selfupdate-rollback</td>
<td><span class="badge badge-ok">ok</span></td>
<td>agent self-update rollback</td>
</tr>
<tr>
<td>stalelock-unlock <span class="badge badge-neutral">critical</span></td>
<td><span class="badge badge-ok">ok</span></td>
<td>reboot-during-backup stale-lock recovery</td>
</tr>
<tr>
<td>wg-conf-install <span class="badge badge-neutral">critical</span></td>
<td><span class="badge badge-ok">ok</span></td>
<td>wg-felhom conf install</td>
</tr>
<tr>
<td>wg-disable</td>
<td><span class="badge badge-ok">ok</span></td>
<td>wg-quick@wg-felhom disable (revocation)</td>
</tr>
<tr>
<td>wg-enable <span class="badge badge-neutral">critical</span></td>
<td><span class="badge badge-ok">ok</span></td>
<td>wg-quick@wg-felhom enable</td>
</tr>
<tr>
<td>wg-handshake-read <span class="badge badge-neutral">critical</span></td>
<td><span class="badge badge-ok">ok</span></td>
<td>tunnel handshake-age read</td>
</tr>
<tr>
<td>wg-restart <span class="badge badge-neutral">critical</span></td>
<td><span class="badge badge-ok">ok</span></td>
<td>wg-quick@wg-felhom restart (conf change)</td>
</tr>
<tr>
<td>wg-tools-install</td>
<td><span class="badge badge-ok">ok</span></td>
<td>wireguard-tools package install</td>
</tr>
</tbody>
</table>
</section>
<section class="card">
<h2>Diagnostics — Log Bundles</h2>
<p class="hint" style="color: var(--text-muted); font-size: 0.85rem;">
Pull-based: the box ships its debug ring on its own next cycle — controller &le; one report interval (~15 min),
agent &asymp; one heartbeat. The pull is recorded in the box's own log (customer-visible). Bundles expire after 72 h.
</p>
<div style="display: flex; gap: 0.5rem; margin: 0.75rem 0;">
<form method="POST" action="/hosts/tester-1-33b6a9/request-logs" style="display: inline;">
<input type="hidden" name="_csrf" value="">
<input type="hidden" name="component" value="controller">
<button type="submit" class="btn btn-sm">Request controller logs</button>
</form>
<form method="POST" action="/hosts/tester-1-33b6a9/request-logs" style="display: inline;">
<input type="hidden" name="_csrf" value="">
<input type="hidden" name="component" value="agent">
<button type="submit" class="btn btn-sm">Request agent logs</button>
</form>
</div>
<div class="empty-state" style="border: none;">
<p>No log bundles. Use the request buttons above — the box delivers on its next cycle.</p>
</div>
</section>
<section class="card">
<h2>Network</h2>
<div class="info-grid">
<div class="info-item">
<span class="label">WireGuard</span>
<span class="value">
<code>10.77.0.5</code>
<span class="badge badge-ok" title="The box reports holding this address">confirmed</span>
</span>
</div>
</div>
<table class="data-table" style="margin-top: 0.75rem;">
<thead>
<tr><th>Interface</th><th>Address</th></tr>
</thead>
<tbody>
<tr>
<td><code>vmbr0</code></td>
<td><code>192.168.0.101/24</code></td>
</tr>
</tbody>
</table>
<p class="hint" style="color: var(--text-muted); font-size: 0.85rem; margin-top: 0.5rem;">
Every routable address the box holds, as the kernel sees it. Loopback and link-local are
excluded &mdash; including the <code>169.254.253.1</code> local-API island, which is identical on
every box. The PVE web console is at <code>https://&lt;the LAN address&gt;:8006</code>.
</p>
</section>
<section class="card">
<h2>Guest network
<span class="badge badge-ok" title="Every owned guest has an address, a default route and a live dhclient">healthy</span>
</h2>
<table class="data-table">
<thead>
<tr><th>Guest</th><th>State</th><th>Address</th><th>Route</th><th>dhclient</th><th>Repairs (1h)</th></tr>
</thead>
<tbody>
<tr>
<td><code>9201</code></td>
<td>
<span class="badge badge-ok" title="address, default route and dhclient all present">healthy</span>
</td>
<td><code>192.168.0.107</code> <span class="text-muted">(dhcp)</span></td>
<td>yes</td>
<td>yes</td>
<td>
<span class="text-muted">0</span>
</td>
</tr>
</tbody>
</table>
<p class="hint" style="color: var(--text-muted); font-size: 0.85rem; margin-top: 0.5rem;">
Last swept 2026-09-16T17:46:20Z. One row per owned <em>running</em> guest the watchdog has probed.
</p>
</section>
<section class="card">
<h2>DR / Backup</h2>
<div class="info-grid">
<div class="info-item">
<span class="label">DR Recipe</span>
<span class="value"><span style="color: var(--green)">present</span></span>
</div>
<div class="info-item">
<span class="label">Key Escrow</span>
<span class="value"><span style="color: var(--green)">present</span></span>
</div>
</div>
</section>
<section class="card">
<h2>Console access</h2>
<div class="info-grid">
<div class="info-item">
<span class="label">User</span>
<span class="value"><code>root@pam</code></span>
</div>
<div class="info-item">
<span class="label">Password set</span>
<span class="value">2h ago</span>
</div>
</div>
<div class="credential-box">
<code id="console-pw-tester-1-33b6a9">&bull;&bull;&bull;&bull;&bull;&bull;&bull;&bull;&bull;&bull;&bull;&bull;&bull;&bull;&bull;&bull;</code>
<button type="button" class="copy-btn" id="console-reveal-tester-1-33b6a9" data-reveal-url="/hosts/tester-1-33b6a9/reveal-recovery-credential" onclick="revealConsolePassword('tester-1-33b6a9')">Reveal</button>
<button type="button" class="copy-btn" id="console-copy-tester-1-33b6a9" onclick="copyConsolePassword('tester-1-33b6a9')">Copy</button>
</div>
<p class="hint" id="console-hint-tester-1-33b6a9" style="color: var(--text-muted); font-size: 0.85rem; margin-top: 0.5rem;">
Break-glass credential for the PVE web console at https://&lt;host-ip&gt;:8006 (realm: Linux PAM standard authentication). <strong>Copy</strong> puts it straight on the clipboard without showing it; <strong>Reveal</strong> displays it for 60&nbsp;s. Either one is recorded on the customer's event timeline. Last vaulted value — if root@pam was changed on the box without re-vaulting, this is stale.
</p>
</section>
<script>
var consolePwState = typeof consolePwState !== 'undefined' ? consolePwState : {};
var consolePwMask = '••••••••••••••••';
function consoleHint(hostID, msg) {
var h = document.getElementById('console-hint-' + hostID);
if (h) { h.textContent = msg; }
}
function maskConsolePassword(hostID) {
var st = consolePwState[hostID];
if (st && st.timer) { clearTimeout(st.timer); }
consolePwState[hostID] = null;
var code = document.getElementById('console-pw-' + hostID);
if (code) { code.textContent = consolePwMask; }
var reveal = document.getElementById('console-reveal-' + hostID);
if (reveal) { reveal.textContent = 'Reveal'; }
}
function fetchConsolePassword(hostID, onOK, onErr) {
var btn = document.getElementById('console-reveal-' + hostID);
fetch(btn.getAttribute('data-reveal-url'), {
method: 'POST',
headers: {'X-CSRF-Token': ''}
}).then(function(r){
if (!r.ok) { throw new Error('HTTP ' + r.status); }
return r.json();
}).then(function(d){ onOK(d.password); }).catch(onErr);
}
function showConsolePassword(hostID, pw) {
document.getElementById('console-pw-' + hostID).textContent = pw;
consolePwState[hostID] = {pw: pw, timer: setTimeout(function(){ maskConsolePassword(hostID); }, 60000)};
document.getElementById('console-reveal-' + hostID).textContent = 'Hide';
}
function revealConsolePassword(hostID) {
if (consolePwState[hostID]) { maskConsolePassword(hostID); return; }
document.getElementById('console-pw-' + hostID).textContent = 'Revealing…';
fetchConsolePassword(hostID, function(pw){
showConsolePassword(hostID, pw);
}, function(e){
document.getElementById('console-pw-' + hostID).textContent = consolePwMask;
consoleHint(hostID, 'Could not reveal the credential (' + e.message + '). The global-key curl path in the break-glass runbook §3.1 still works.');
});
}
function copyConsolePassword(hostID) {
var st = consolePwState[hostID];
if (st) { writeConsoleClipboard(hostID, st.pw); return; }
consoleHint(hostID, 'Copying…');
fetchConsolePassword(hostID, function(pw){
writeConsoleClipboard(hostID, pw);
}, function(e){
consoleHint(hostID, 'Could not copy the credential (' + e.message + '). The global-key curl path in the break-glass runbook §3.1 still works.');
});
}
function writeConsoleClipboard(hostID, pw) {
if (!navigator.clipboard || !navigator.clipboard.writeText) {
showConsolePassword(hostID, pw);
consoleHint(hostID, 'This browser will not give the page clipboard access, so the password is shown instead — copy it manually. It hides again in 60 s.');
return;
}
navigator.clipboard.writeText(pw).then(function(){
maskConsolePassword(hostID);
consoleHint(hostID, '✓ Copied ' + hostID + '\u2019s root@pam password to the clipboard. It stays there until you copy something else.');
}).catch(function(e){
showConsolePassword(hostID, pw);
consoleHint(hostID, 'The clipboard write was refused (' + (e && e.message ? e.message : 'no reason given') + '), so the password is shown instead — copy it manually. It hides again in 60 s.');
});
}
document.addEventListener('visibilitychange', function(){
if (document.visibilityState === 'hidden') {
for (var id in consolePwState) { if (consolePwState[id]) { maskConsolePassword(id); } }
}
});
</script>
<footer style="margin-top: 2rem; color: var(--text-muted); font-size: 0.8rem; text-align: center;">
Felhom Hub <span style="font-family: var(--font-mono)">0.116.0</span>
</footer>
</div>
</body>
</html>