A page-by-page review of the live site (1440px and 390px) found six defects and
two editorial questions. The operator answered three questions; the answers and
the evidence are in REPORT-review-2026-10-12.md.
Fixed:
- The contact form showed its consent error before any submit, on both pages:
#privacyError sits outside any .form-group and the hide rule was scoped to
.form-group. Scoped to the page. Checked: load (none) -> submit unticked
(shown) -> tick (gone), with no message sent.
- The consent checkbox is the site's own control now: 24px box, keyboard focus
ring, and a second <label for="privacy"> at 44x44 round it for touch.
- The contact page promised a reply within 24 hours while /feltetelek 1.1 §4
promises no reply time. Now 1-2 days usually, and no promise during the test.
- sitemap.xml was missing /szolgaltatasok and /en/services: 18 -> 20 URLs.
- The pre-shell mobile-menu script still ran on 20 pages and logged
"[mobile-menu] Missing elements" on every one. Removed.
- The sidebar's tester button was btn-outline while the hero's was btn-primary.
- The home page's "Mit tud a doboz ma?" was three bare links; each card now
carries 2-3 of the services page's own items, word for word.
- A plain Facebook link in the footer of all 22 pages. No script, widget or
pixel: the only external hosts any page refers to are still felhom.eu and
stats.felhom.eu.
Voice (operator ruling: "I" everywhere a person speaks): contact, tester and FAQ
pages in both languages, and the home and services pages that repeat the same
promises. An inclusive "we" (you and I, talking) stays plural, and the legal
texts are untouched. Each FAQ answer exists twice (JSON-LD + visible) and gate 18
holds them equal - it caught the five answers whose markup split the sentence.
Hero clip rebuilt: Immich first, so the poster is a wall of real photographs;
the Jellyfin scene starts after the demo's library wall (eleven pieces of poster
art whose licence cannot be quoted from a first-party source); 1.3s of blank
screen cut from the OnlyOffice scene. The film that plays, Caminandes 3:
Llamigos, is CC BY per Blender's own video platform ("licence": {"id": 1,
"label": "Attribution"}) - NOT public domain as website/CHANGELOG.md said
yesterday. That sentence is corrected in place and the film is credited under
the hero caption.
New gate 24: sitemap.xml lists every public page once, with its twin's hreflang
pair, and lists nothing else. Decoy: site/sitemap-missing-page, the exact shape
the reviewer found by hand.
site.css ?v=30; hero clip and poster ?v=2.
Felhom host scripts
Operator-side scripts for standing up a Felhom Proxmox host.
felhom-host-install.sh — Day-0 host bootstrap (operator-deploy)
Run on a freshly-PVE-installed box to fully automate Day-0: Proxmox API token →
hub host enrollment (single secret) → agent install (fetch + verify + install) →
agent config → golden → guest provision → verify. It composes already-proven mechanisms
(the pveum role/token sequence, the hub POST /host-enroll enrollment from option C, and
felhom-agent --selftest=provision). The agent renders bootstrap.json into the guest and
the controller pulls its own controller.yaml in-guest — the script never fetches that.
Since v1.1.0 (BUNDLE slice) the script also installs the agent itself: it fetches the
agent binary + golden from Gitea generic packages and verifies each artifact's sha256 against
the hub-vouched manifest (GET /api/v1/artifacts/{id}) before installing/using it. The fetch
credential is the git token already inside the customer's controller.yaml (config-retrieve) —
no new credential, and the checksum trust root is the hub, not Gitea.
Grounding: documentation/audits/SPIKE-day0-firstboot-handshake-2026-06-26.md.
Prerequisites (manual, before running)
- Install Proxmox VE 9.x on the box. During the installer, use Advanced → LVM
sizing so
local-lvm(thepve/datathin pool) has enough room for the appliance volumes — a useful box wants ≥ ~120 GiB free onlocal-lvm(rootfs 32G + Docker-data ~200G + user-data ~50G after grows). The script refuses below the hard minimum. - SSH into the box as root.
- Create the customer in the hub first (hub UI → new customer). The customer's retrieval passphrase (a 5-word Hungarian phrase) is the only secret you carry to the box.
That's it. The agent binary + golden are fetched + verified + installed by the script (provided the
operator has recorded the current artifact set in the hub UI → Configs → Day-0 artifacts, and
published them via felhom-agent/scripts/publish-agent.sh + configs/build-golden.sh). A local
golden, if present, is still used as a fallback.
Usage
curl -fsSL https://felhom.eu/scripts/felhom-host-install.sh -o felhom-host-install.sh
chmod +x felhom-host-install.sh
# secure no-echo passphrase prompt:
sudo ./felhom-host-install.sh --customer-id <customer>
# or from a 0600 file (no prompt):
sudo ./felhom-host-install.sh --customer-id <customer> --passphrase-file /root/.pass
# preview every mutating command without executing:
sudo ./felhom-host-install.sh --customer-id <customer> --dry-run
# resume after a fixed mid-way failure (skips completed steps):
sudo ./felhom-host-install.sh --customer-id <customer> --resume
The passphrase is read no-echo or from a 0600 file — never a CLI argument, never
echoed, never written to the state file or logs. The minted Proxmox-token secret and the
per-host hub api_key live only in the agent config (0600, root).
Key options
| Option | Default | Purpose |
|---|---|---|
--customer-id ID |
(required) | customer (must already exist in the hub) |
--vmid N |
9201 |
guest VMID to provision |
--golden VOLID |
newest vzdump-lxc-<golden-vmid> |
golden archive |
--rootfs/--datavol/--sysdata-grow N |
auto-compute | volume grows (GiB over the golden base 32/16/8) |
--passphrase-file PATH |
no-echo prompt | read passphrase from a 0600 file |
--preserve-from PATH |
— | merge non-Day-0 sections (PBS/local_api/privileged/authz) from an existing config |
--dry-run / --resume / --force |
off | preview / resume / clobber an existing vmid |
--mode provision|dr |
provision |
dr is a documented 10D stub (not implemented) |
Behaviour notes
- Idempotent + resumable. A step-state file (
/var/lib/felhom-install/state.json) records completed steps;--resumeskips them. A plain re-run refuses to clobber an existing--vmid(pass--forceto override). - Single-secret enrollment.
POST /host-enrollmints on first call (201) and reuses the credential on later calls (200) — re-running never orphans a running agent's key. The global operator key is never used. - Token automation. Creates/normalises the 16-priv
FelhomAgentrole, thefelhom-agent@pveuser + privsep token, and both ACL grants (user and token — the ACL is applied after the token exists, becausepveum user token removepurges it). - Agent install (v1.1.0). Fetches the binary from Gitea
(
/api/packages/admin/generic/felhom-agent/<ver>/felhom-agent), verifies its sha256 against the hub manifest, then installs the non-rootfelhom-agentservice user + binary + sudoers (0440,visudo -cf-validated) + the canonical systemd unit. Idempotent: same version already installed + service active → skips. A sha256 mismatch aborts the install (verify-before-use). The agent runs non-root (privileged.mode: "sudo"+ the sudoers allowlist), never as root. - Golden (v1.1.0). Uses a local golden when present; otherwise fetches it from Gitea
(
/api/packages/admin/generic/felhom-golden/<ver>/golden.tar.zst), verifies its sha256, and imports it into the archive storage's dump dir for the restore.--force-gitea-goldenforces the Gitea path even when a local golden exists. - DR mode (
--mode dr) is a documented seam only — it restores the customer's own PBS whole-CT snapshot instead of the golden. Not implemented (10D).
Productionization hooks (not done here)
- Serving: place this file where the felhom.eu site serves it at
https://felhom.eu/scripts/felhom-host-install.sh(a static route; verify on deploy). - Per-customer artifact pinning: the hub manifest currently returns the global current artifact
set for every customer; per-customer pinning is a future hook (
GET /api/v1/artifacts/{id}already takes the customer id). - Unit/sudoers integrity: the binary + golden are sha256-verified against the hub; the unit +
sudoers are fetched from the agent repo
main(canonical text) and the sudoers isvisudo -cf-validated.