Search Console (3 months, read 2026-10-14): 48 impressions, 1 click, average position 73.6; the top query is „felhő tárhely" (19). No page on the site used the phrase — Google was showing the home page by accident. New pair /sajat-felho-tarhely + /en/own-cloud-storage: what cloud storage is and the three ways to have one; what to do when the Google or iCloud storage is full (the free clean-up first, linked to Google's and Apple's own help; the paid options second); a five-year cost table; where the data sits; who should NOT choose this; the closed test. Registered in site_gates.py TWINS/URL/SHELL, both URLs in sitemap.xml (22 -> 24). FAQPage JSON-LD derived from the visible text. Prices each read 2026-10-14 on the provider's own Hungarian page, with the URLs and the date in an HTML comment and a visible „Árak" line: Google AI Plus (2 TB) — Google One's 2 TB plan — 35 990 Ft/év (behind the „Éves" toggle; a plain fetch sees only the monthly 3 590 Ft), iCloud+ 2 TB 4 490 Ft/hó, Microsoft 365 Családi (2 TB shared, no longer 1 TB per person) 46 499 Ft/év. Felhom's own cost follows what the site already said (operator ruling): machine and install one-off, power, off-site storage monthly by volume, operation OPTIONAL, no fee during the closed test. Power is stated as an idle measurement (nyugalmi állapotban 7-9 W, ~75 kWh/év, from audits/night-power-2026-10-13) and the page says a year with daytime use is more; no daytime figure and no electricity tariff are given, because neither is measured or sourced. FAQ corrected (both languages, JSON-LD re-derived): the cost answer carried unsourced, undated prices and summed Spotify and a password manager into a storage comparison; and the page contradicted itself on electricity („havi néhány ezer forint" vs „évi 5.000–15.000 Ft"). App count 60 -> 62 in the four places that were stale. Three defects found on the rendered page and fixed: a .vs-row link fell back to the browser-default blue (contrast 1.99 -> 7.17); 24px of horizontal scroll at 390px because .method-pros li is a nowrap flex row and the new items contain links (each item's content wrapped in one span); .info-card and .method-pros were scoped to the pages that first used them. site.css ?v=31 on all 26 pages. The shared .content-section padding was NOT changed — it is identical on every page; the new page only lacked the alt-bg alternation, and now has it. R-1033 the apps page lags the catalog by two apps (plant-it, wger); R-1034 gate 17 checks the FAQ JSON-LD on two hard-coded pages only; R-1035 the SEO result, with dated checks on 2026-11-11 and 2026-12-09.
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.