From a7f897a7ddd386c9f49cb1f0fae248b5ae135559 Mon Sep 17 00:00:00 2001 From: kisfenyo Date: Mon, 12 Oct 2026 22:09:10 +0200 Subject: [PATCH] Audit: selfh.st survey 2023-2025 read against Felhom; R-989 filed Read-only. fetch.py + tables.py (stdlib), TABLE.md (45 charts, % of respondents), FELHOM.md (apps, features, reasons, hardware, trends, ten ranked recommendations), METHOD.md (hashes, counts, matching, MIT licence, limits). Survey files are not committed. One register row (R-989) and one STATUS line ask the operator to rule on the recommendations. --- STATUS.md | 6 +- .../selfhst-survey-2026-10-12/FELHOM.md | 122 +++ .../selfhst-survey-2026-10-12/METHOD.md | 40 + .../audits/selfhst-survey-2026-10-12/TABLE.md | 718 ++++++++++++++++++ .../audits/selfhst-survey-2026-10-12/fetch.py | 42 + .../selfhst-survey-2026-10-12/tables.py | 246 ++++++ documentation/backlog/OPEN-ITEMS.md | 3 +- 7 files changed, 1175 insertions(+), 2 deletions(-) create mode 100644 documentation/audits/selfhst-survey-2026-10-12/FELHOM.md create mode 100644 documentation/audits/selfhst-survey-2026-10-12/METHOD.md create mode 100644 documentation/audits/selfhst-survey-2026-10-12/TABLE.md create mode 100644 documentation/audits/selfhst-survey-2026-10-12/fetch.py create mode 100644 documentation/audits/selfhst-survey-2026-10-12/tables.py diff --git a/STATUS.md b/STATUS.md index e3e039fb..16b136f2 100644 --- a/STATUS.md +++ b/STATUS.md @@ -2,7 +2,11 @@ **Ready for the first real tester (Tester-2): yes. Tester 2 (a laptop) is off; nothing was sent to it.** -**Updated 2026-10-12 (evening): demo-hp, demo-felhom and Tester 1 run agent 0.154.0 and controller 0.309.0. The open-items list is at 117 (2026-10-12 night; the new row is the Usenet pair, R-988). Reports: `REPORT-newapps-2026-10-12.md`, `REPORT-disk-evening-2026-10-12.md`, `REPORT-answers-2026-10-12.md`, `REPORT-m3-2026-10-11.md`, `REPORT-redesign-2026-10-10.md`, `REPORT-testers-2026-10-10.md`, `REPORT-register-shrink-2026-10-10.md`, `REPORT-new-apps-2026-10-10.md`, `REPORT-release-2026-10-10.md`, `REPORT-break-the-circle-2026-10-09.md`, `REPORT-dooplex-survival-2026-10-09.md`, `REPORT-day4-2026-10-09.md`.** +**Updated 2026-10-12 (evening): demo-hp, demo-felhom and Tester 1 run agent 0.154.0 and controller 0.309.0. The open-items list is at 118 (2026-10-12 night; the newest row is the survey reading, R-989). Reports: `REPORT-newapps-2026-10-12.md`, `REPORT-disk-evening-2026-10-12.md`, `REPORT-answers-2026-10-12.md`, `REPORT-m3-2026-10-11.md`, `REPORT-redesign-2026-10-10.md`, `REPORT-testers-2026-10-10.md`, `REPORT-register-shrink-2026-10-10.md`, `REPORT-new-apps-2026-10-10.md`, `REPORT-release-2026-10-10.md`, `REPORT-break-the-circle-2026-10-09.md`, `REPORT-dooplex-survival-2026-10-09.md`, `REPORT-day4-2026-10-09.md`.** + +## Monday 2026-10-12 (night): what 4,000 self-hosters do, against Felhom + +- **Waiting on you — decide later:** read `documentation/audits/selfhst-survey-2026-10-12/FELHOM.md` §6 (ten ranked ideas from the selfh.st survey) and say yes, no or later to each (R-989). If you do nothing: nothing changes; the research ages. ## Monday 2026-10-12 (night): the two download clients are live, and the Usenet pair is written down diff --git a/documentation/audits/selfhst-survey-2026-10-12/FELHOM.md b/documentation/audits/selfhst-survey-2026-10-12/FELHOM.md new file mode 100644 index 00000000..ae1df3ca --- /dev/null +++ b/documentation/audits/selfhst-survey-2026-10-12/FELHOM.md @@ -0,0 +1,122 @@ +# selfh.st survey 2023–2025 — what it means for Felhom + +Read-only, 2026-10-12. Numbers are **% of the year's respondents** (2023: 1,869 · 2024: 3,655 · 2025: 4,081), +from `TABLE.md` section **T*n***; each section cites its year's URL. The crowd is hobby users, not households +(`METHOD.md` limits). Catalog = the 62 template folders of `app-catalog-felhom.eu/templates/` at `cb4ececf1f`. + +## 1. Apps (2025 Software charts + Favorite Software) + +`✓ name` = we ship that template · `✗` = we do not · `n/a` = not a server app a household box would run. + +| App | 2025 % | Source | Catalog | +|---|---|---|---| +| Home Assistant | 62.7 deploy · 14.4 fav | T30, T33 | ✓ home-assistant | +| Jellyfin | 60.9 · 12.8 fav | T25, T33 | ✓ jellyfin | +| Nextcloud (+ Nextcloud Notes 7.9) | 30.3 · 2.9 fav | T26, T28, T33 | ✓ nextcloud | +| Plex | 29.9 · 5.1 fav | T25, T33 | ✓ plex | +| Syncthing | 25.9 · 0.8 fav | T26, T33 | ✗ | +| Obsidian | 25.5 | T28 | n/a (desktop app; its sync server is a separate project) | +| Minecraft (game server) | 25.5 | T32 | ✓ crafty-controller | +| Gitea | 20.8 · 0.7 fav | T29, T33 | ✓ gitea | +| AudioBookshelf | 20.6 · 2.3 fav | T25, T33 | ✓ audiobookshelf | +| Navidrome | 16.1 · 1.0 fav | T25, T33 | ✓ navidrome | +| Forgejo | 15.0 | T29 | ✗ | +| Synology | 13.5 | T26 | n/a (NAS product) | +| FileBrowser / FileBrowser Quantum | 11.8 / 5.1 | T26 | built into every box (not a template; R-917 row text) | +| Immich | 10.5 fav | T33 | ✓ immich | +| Authelia | 9.6 | T27 | ✗ | +| Pocket ID | 7.6 | T27 | ✗ | +| BookStack | 7.4 | T28 | ✓ bookstack | +| GitLab | 7.4 | T29 | ✗ | +| authentik | 6.6 | T27 | ✗ | +| Joplin | 6.6 | T28 | ✗ | +| Pangolin | 5.9 auth · 7.1 proxy · 0.6 fav | T27, T19, T33 | ✗ (tunnel/proxy; Felhom has its own) | +| Kodi | 5.8 | T25 | n/a (player, not a server) | +| Trilium · Memos · Wiki.js | 4.5 · 4.1 · 3.8 | T28 | ✗ | +| Keycloak · Tinyauth · Zitadel | 3.9 · 2.7 · 1.1 | T27 | ✗ | +| Emby | 3.7 · 0.6 fav | T25, T33 | ✓ emby | +| Docmost · Outline | 3.5 · 3.2 | T28 | ✓ docmost · ✓ outline | +| Vaultwarden | 3.7 fav | T33 | ✓ vaultwarden | +| Seafile · AFFiNE · SilverBullet · DokuWiki · Logseq | 2.9 · 2.5 · 2.4 · 2.3 · 2.2 | T26, T28 | ✗ | +| SFTPGo · ownCloud · Subsonic · PeerTube · MkDocs · Resilio · Gogs | 2.2 · 2.0 · 2.0 · 1.8 · 1.8 · 1.3 · 0.4 | T25, T26, T28, T29 | ✗ | +| Paperless-ngx | 2.1 fav | T33 | ✓ paperless-ngx | +| *arr | 2.0 fav | T33 | ✓ radarr, ✓ sonarr (others ✗) | +| FreshRSS · Pi-hole · Miniflux · AdGuard Home | 1.3 · 1.2 · 0.7 · 0.5 fav | T33 | ✗ | +| Actual Budget · RomM · Mealie · n8n · Homepage · Glance · Karakeep | 1.0 · 1.0 · 0.7 · 0.7 · 0.7 · 0.6 · 0.5 fav | T33 | ✓ actualbudget, romm, mealie, n8n, homepage, glance, karakeep | +| Proxmox · Komodo | 0.6 · 0.5 fav | T33 | n/a (host OS / container manager — Felhom's own role) | + +**Catalog gap — above 5 %, not shipped, a server app:** Syncthing 25.9 (T26) · Forgejo 15.0 (T29) · +Authelia 9.6, Pocket ID 7.6, authentik 6.6 (T27, sign-on layers) · GitLab 7.4 (T29) · Joplin server 6.6 (T28) · +Pangolin 5.9 (T27; a tunnel, overlaps Felhom's own). Nothing was added. + +## 2. Our features against what people do + +| Area | Crowd, 2025 | Felhom | Source | +|---|---|---|---| +| Backup | Onsite 74.8, cloud 51.5, **offsite 25.2, none 13.3** | three automatic nightly tiers (on-drive, second drive, encrypted off-site to a Hetzner Storage Box) + whole-guest copies, local daily and off-site weekly — **a selling point: only 1 in 4 does off-site** | T8; `07-backup-architecture.md` :373-382 | +| Backup cloud | Backblaze 15.0, Google Drive 12.6, **Hetzner 9.1 (rising)** | Hetzner Storage Box | T9; `07` :379 | +| Remote access | VPN 71.1, reverse proxy 66.6, forwarded ports 17.7 | Cloudflare Tunnel, no open port, no customer VPN; TLS ends at Cloudflare (R-904 deferred) | T18; `01-topology-and-trust.md` :202-210 | +| Reverse proxy | NPM 20.6, **Traefik 18.4**, Caddy 14.7, CF Tunnels 13.8 | Traefik behind the tunnel | T19; `01` :113, :143-145 | +| Domain | 87.9 have their own | every customer has their own domain | T20; `01` :210 | +| OS | Linux 81.3, **Proxmox 44.9**, HA OS 29.4 | Proxmox host + one Debian LXC + Docker | T7; `01` :56-59 | +| Containers | 96.3 use them, Docker 89.1 | Docker inside the guest | T10, T13 | +| App updates | **manual 45.1**, both 40.3, automatic 14.6 | automatic, watched — **a selling point** | T16; `website/index.html` :156 | +| Container manager | 51.5 use one (Portainer 32.7) | the Felhom dashboard does this job | T14, T15 | +| NAS | 67.8 run one | NAS as extra storage (FAQ), SMB shares on the box | T5; `website/gyik.html` :77-80 | + +## 3. Reasons for self-hosting + +| Rank 2025 | Reason | 2023 → 2025 | Our pitch names it? | +|---|---|---|---| +| 1 | Hobby | 95.5 → 94.6 | no — fine: a household that buys care is not tinkering | +| 2 | Privacy | 79.7 → 86.3 | **yes** (`index.html` :233-234) | +| 3 | Cost | 54.6 → 63.6 | **yes** (:229-230, no subscription) | +| 4 | Convenience | – → 63.3 (2024: 55.0) | **yes** (:114-116, :213, :221) | +| 5 | Education | 83.0 → 60.6 | no — fine, same reason as Hobby | +| 6 | Flexibility | 69.7 → 58.2 | **yes** (:237-242, capacity and control) | +| 7 | Business | 12.5 → 12.9 | home page no; `technologiak.html` rack setup only | + +Source T3. The pitch already names the four reasons a buyer can share. Caution: Convenience was added as an +option in 2024; some of the 2023 Education/Flexibility votes may have moved to it. + +## 4. Hardware + +**No document states Felhom's supported hardware** (finding). What exists: FAQ advice (N100 mini PC, 16–32 GB, +`website/gyik.html` :77-80; an old PC "often yes", :85-88), three example setups (`technologiak.html` :375-447), +BYO Proxmox (`documentation/runbooks/day0-install.md` :18-21), and the installer ISO, which is x86_64-only +(`scripts/iso/iso-repack.sh` :31; inferred — no document says it). + +| Crowd class (T4) | 2025 % | Felhom | +|---|---|---| +| Consumer hardware | 57.8 | in (mini PC is the recommendation) | +| Low-powered device | 50.0 | **partly out** — x86 N100-class in; ARM boards out (Raspberry Pi OS is 24.0, T7) | +| Custom build | 37.8 | in (tower example) | +| Cloud VPS | 34.2 | **out** — not offered | +| Desktop PC | 31.7 | in, case by case (FAQ :85-88) | +| Enterprise hardware | 20.0 | in (rack example, "business") | +| Server cluster | 13.7 | **out** — not documented; one host per household | +| Laptop | 10.5 | not documented (a tester laptop exists, STATUS) | +| Mobile device | 2.3 | **out** | + +## 5. Trends 2023 → 2025 that matter to Felhom (≥ 5 points) + +| Change | Points | Table | +|---|---|---| +| Cloud VPS as hosting hardware 2.7 → 34.2 (2024 → 2025; not asked 2023) — a 13× jump, may be a change in how the option was offered | +31.5 | T4 | +| Home Assistant OS 0.4 → 29.4 (2024 → 2025); Home Assistant use 56.5 → 62.7 | +29.0 | T7, T30 | +| Reasons move from learning to practical: Education −22.4, Flexibility −11.5, Cost +9.0, Privacy +6.6 | −22.4 … +9.0 | T3 | +| Jellyfin 46.1 → 60.9, Plex 39.5 → 29.9; Immich as favourite 2.2 → 10.5 | +14.8 / −9.6 / +8.3 | T25, T33 | +| Backup "None" 6.2 → 13.3 (2024 → 2025) | +7.1 | T8 | + +## 6. Recommendations (ranked; none acted on) + +1. Write one supported-hardware page: x86_64 only, minimum RAM and disk, no ARM, no cloud VPS, BYO Proxmox status — §4, T4. +2. Put "off-site, encrypted, automatic backup" in the home page's *why* list, with the 1-in-4 figure — T8 Offsite 25.2. +3. Consider Syncthing for the catalog (the largest gap, 25.9) — T26. +4. Say in the FAQ what the catalog Home Assistant (container) lacks against Home Assistant OS (add-ons) — T7 HA OS 29.4, T30. +5. Name automatic, watched app updates as a reason in the pitch — T16 Automatic 14.6. +6. Use the privacy figure as input to R-904 (TLS ends at Cloudflare): privacy is reason 2 and rising — T3 Privacy 86.3, T18 VPN 71.1. +7. Consider a Joplin server template for notes (Obsidian users need a separate sync) — T28 Joplin 6.6. +8. Consider Forgejo beside Gitea (Forgejo 15.0 is the second git server after Gitea 20.8) — T29. +9. Keep single sign-on (Authelia / Pocket ID / authentik) as a later idea; low household value today — T27. +10. Do not chase Cloud VPS until the T4 jump is confirmed by the 2026 survey — T4 Cloud VPS 34.2. diff --git a/documentation/audits/selfhst-survey-2026-10-12/METHOD.md b/documentation/audits/selfhst-survey-2026-10-12/METHOD.md new file mode 100644 index 00000000..1482a61f --- /dev/null +++ b/documentation/audits/selfhst-survey-2026-10-12/METHOD.md @@ -0,0 +1,40 @@ +# Method — selfh.st survey read, 2026-10-12 + +**Fetched** 2026-10-12 by `fetch.py` to `~/research-cache/selfhst-survey/` (outside every repo; not committed). + +| Year | Data file | Bytes | SHA-256 | Matches the spec | +|---|---|---|---|---| +| 2023 | `https://raw.githubusercontent.com/selfhst/cdn/main/assets/surveys/annual/2023-results.json` | 10362 | `714350e5e4b8f3ccbc7ce8c1348122a9b7a4ae8167abaf2c051d3dcc9911f03f` | yes | +| 2024 | `…/2024-results.json` | 14290 | `289c5161e5b6b5684ac6c751c16e73dd0dc42490c5c0d24517a6c1f891da4832` | yes | +| 2025 | `…/2025-results.json` | 20428 | `e083094ad7f8cb6721f7059c6c73e8779273717bb3d4c1f14dbd744dc0d0229e` | yes | + +**Respondents.** 2025: **4,081**, stated as completed responses on `https://selfh.st/survey/2025-results/`. +2023 and 2024 pages give only rounded numbers ("just shy of 1,900", "~3,700" — `https://selfh.st/survey/2023-results/`, +`…/2024-results/`). The exact figures used, **1,869** and **3,655**, are the column sum of the first, mandatory, +single-choice question (personal / enterprise / both). The same method gives exactly 4,081 for 2025. + +**Shapes.** 2023/2024: top-level `charts`, each with an `id`. 2025: `categories[].charts[]`, no `id`, five +categories, 39 charts. Some 2025 charts carry a `commentary` field (not copied). + +**Percentages.** Multi-select charts: % of the year's respondents. Single-choice charts (marked in `TABLE.md`): +% of the column sum, because the question went to a subset or not everyone answered. Favourite software is one +answer per person but the chart drops small counts, so it is % of respondents. + +**Matching across years.** 2023/2024 by `id` (same titles). 2025 by question meaning, a hand-written map in +`tables.py` (`MATCH_2025`); both titles are printed in every section. Answer labels mapped by hand where the +wording changed (`ALIAS`, e.g. Yes → Deploy, Generic Linux → Linux, Docker - Individual → Container (Separate), +2023 Paperless → Paperless-ngx, 2024 "Trilum" → Trilium); labels that differ only in case are merged and listed. + +**Unmatched (no same question in 2025):** 2023 offsite-backup yes/no (T40), 2023 Kubernetes (T41 — 2024/2025 +ask about any orchestration), 2023 media-streaming yes/no (T42), 2024 smart-home protocols (T43), 2024 +ActivityPub yes/no and platforms (T44, T45). 2025-only: Management Platforms, Authentication, Git. + +**Licence.** The results page shows no licence. The data repository `github.com/selfhst/cdn` is **MIT** +(GitHub API `license.spdx_id = MIT`; `LICENSE` reads "MIT License, Copyright (c) 2025 selfh.st"). We commit no +survey file and no survey prose; only our own counts derived from it, each cited to its URL. + +**Limits.** Hobby users, mostly technical (Technology career 80.6 %, T36), self-selected through the selfh.st +newsletter and community, not households buying a service. Multi-select counts: a column passes 100 %. Open-text +charts (favourites) omit small answers. **Country:** the JSON files carry no country data, but the **2024 results +page has a country table** (HTML only, not in `tables.py`): United States 964, Germany 430 … **Hungary 19**. +2023 and 2025 pages have none. diff --git a/documentation/audits/selfhst-survey-2026-10-12/TABLE.md b/documentation/audits/selfhst-survey-2026-10-12/TABLE.md new file mode 100644 index 00000000..11ebd432 --- /dev/null +++ b/documentation/audits/selfhst-survey-2026-10-12/TABLE.md @@ -0,0 +1,718 @@ +# selfh.st self-hosting survey 2023–2025 — tables + +Generated by `tables.py` from the files `fetch.py` downloads. Do not edit by hand. + +| Year | Respondents | Results page | Data file | +|---|---|---|---| +| 2023 | 1,869 | https://selfh.st/survey/2023-results/ | https://raw.githubusercontent.com/selfhst/cdn/main/assets/surveys/annual/2023-results.json | +| 2024 | 3,655 | https://selfh.st/survey/2024-results/ | https://raw.githubusercontent.com/selfhst/cdn/main/assets/surveys/annual/2024-results.json | +| 2025 | 4,081 | https://selfh.st/survey/2025-results/ | https://raw.githubusercontent.com/selfhst/cdn/main/assets/surveys/annual/2025-results.json | + +Values are **% of the year's respondents** (multi-select: a column can pass 100 %). +Charts marked *single-choice* show **% of the column sum** instead. +`2025 n` is the raw 2025 response count. `–` = not asked that year (or not matched). + +## T1. Primary Purpose + +Titles — 2023: Do you self-host for personal or enterprise purposes? · 2024: Do you self-host for personal or enterprise purposes? · 2025: Primary Purpose + +*Single-choice: % of the column sum.* + +| label | 2023 | 2024 | 2025 | 2025 n | +|---|---|---|---|---| +| Personal | 83.4 | 83.1 | 83.7 | 3,417 | +| Both | 16.2 | 16.6 | 16.1 | 656 | +| Enterprise | 0.4 | 0.4 | 0.2 | 8 | + +## T2. Unique Users + +Titles — 2023: Approximately how many unique users are registered across your applications? · 2024: Approximately how many unique users are registered across your applications? · 2025: Unique Users + +*Single-choice: % of the column sum.* + +Note: 2023 buckets 11-15 and 16-20 are kept apart; 2024/2025 ask 11-20. + +| label | 2023 | 2024 | 2025 | 2025 n | +|---|---|---|---|---| +| 1 user | 22.1 | 20.9 | 27.6 | 1,123 | +| 2 users | 23.1 | 25.5 | 21.0 | 854 | +| 3 users | 12.5 | 13.7 | 12.6 | 513 | +| 4 users | 10.3 | 10.0 | 9.9 | 401 | +| 5 users | 10.7 | 10.3 | 8.5 | 346 | +| 6 users | 4.3 | 4.3 | 4.9 | 200 | +| 7 users | 1.6 | 1.8 | 4.2 | 171 | +| 8 users | 2.2 | 2.3 | 4.2 | 170 | +| 9 users | 0.5 | 0.6 | 2.7 | 109 | +| 10 users | 6.2 | 2.8 | 2.1 | 86 | +| 11-20 users | – | 4.9 | 1.9 | 77 | +| 21+ users | 2.1 | 2.8 | 0.5 | 19 | +| 11-15 users | 2.6 | – | – | – | +| 16-20 users | 2.0 | – | – | – | + +## T3. Reasons for Self-Hosting + +Titles — 2023: Why do you self-host? · 2024: Why do you self-host? · 2025: Reasons for Self-Hosting + +| label | 2023 | 2024 | 2025 | 2025 n | +|---|---|---|---|---| +| Hobby | 95.5 | 94.8 | 94.6 | 3,862 | +| Privacy | 79.7 | 84.0 | 86.3 | 3,520 | +| Cost | 54.6 | 56.7 | 63.6 | 2,596 | +| Convenience | – | 55.0 | 63.3 | 2,584 | +| Education | 83.0 | 63.9 | 60.6 | 2,474 | +| Flexibility | 69.7 | 59.8 | 58.2 | 2,374 | +| Business | 12.5 | 8.7 | 12.9 | 525 | +| Other | 3.7 | 2.2 | 2.6 | 106 | + +## T4. Hardware Options + +Titles — 2023: Select the hardware option(s) used to deploy your self-hosted software. · 2024: Select the hardware option(s) used to deploy your self-hosted software. · 2025: Hardware Options + +Note: 2023 'Custom-built', 'Enterprise', 'Mobile phone' matched to the 2024/2025 wording. + +| label | 2023 | 2024 | 2025 | 2025 n | +|---|---|---|---|---| +| Consumer hardware | – | 45.8 | 57.8 | 2,358 | +| Low-powered device | 52.7 | 54.7 | 50.0 | 2,039 | +| Custom build | 43.8 | 35.5 | 37.8 | 1,542 | +| Cloud VPS | – | 2.7 | 34.2 | 1,394 | +| Desktop PC | 44.6 | 35.9 | 31.7 | 1,295 | +| Enterprise hardware | 26.1 | 22.5 | 20.0 | 817 | +| Server cluster | 15.8 | 14.7 | 13.7 | 560 | +| Laptop | 12.8 | 12.0 | 10.5 | 429 | +| Mobile device | 1.8 | 2.5 | 2.3 | 94 | +| Other | 7.7 | 1.3 | 1.9 | 78 | + +## T5. Network-Attached Storage + +Titles — 2023: Do you deploy a network-attached storage device? · 2024: Do you deploy a network-attached storage device? · 2025: Network-Attached Storage + +*Single-choice: % of the column sum.* + +| label | 2023 | 2024 | 2025 | 2025 n | +|---|---|---|---|---| +| Deploy | 63.2 | 63.0 | 67.8 | 2,768 | +| Don't Deploy | 36.8 | 37.0 | 32.2 | 1,313 | + +## T6. Sensitive Data + +Titles — 2023: Do you avoid self-hosting sensitive or important data? · 2024: Do you avoid self-hosting sensitive or important data? · 2025: Sensitive Data + +*Single-choice: % of the column sum.* + +| label | 2023 | 2024 | 2025 | 2025 n | +|---|---|---|---|---| +| Don't Avoid | 77.2 | 82.8 | 82.7 | 3,373 | +| Avoid | 22.8 | 17.2 | 17.3 | 708 | + +## T7. Operating Systems + +Titles — 2023: Which operating system(s) are installed on your server(s)? · 2024: Which operating system(s) are installed on your server(s)? · 2025: Operating Systems + +| label | 2023 | 2024 | 2025 | 2025 n | +|---|---|---|---|---| +| Linux | 79.5 | 86.7 | 81.3 | 3,317 | +| Proxmox | 38.2 | 43.2 | 44.9 | 1,832 | +| Home Assistant OS | – | 0.4 | 29.4 | 1,199 | +| Raspberry Pi OS | 29.6 | 27.1 | 24.0 | 979 | +| TrueNAS | 15.6 | 14.5 | 19.0 | 774 | +| Unraid | 10.3 | 10.7 | 10.1 | 412 | +| DiskStation Manager | – | 2.9 | 9.8 | 398 | +| Windows Desktop | 11.6 | 9.3 | 9.1 | 373 | +| Windows Server | 9.6 | 6.3 | 5.7 | 232 | +| BSD | 4.9 | 6.2 | 5.6 | 229 | +| Open Media Vault | – | 1.1 | 5.0 | 204 | +| macOS | 3.2 | 3.5 | 4.9 | 199 | +| ESXi | 5.4 | 3.1 | – | – | +| XCP-ng | – | 0.5 | – | – | +| Other | 9.4 | 2.0 | 8.3 | 340 | + +## T8. Backup Strategies + +Titles — 2024: Which backup strategies have you deployed for your self-hosted data? · 2025: Backup Strategies + +| label | 2023 | 2024 | 2025 | 2025 n | +|---|---|---|---|---| +| Onsite | – | 79.2 | 74.8 | 3,054 | +| Cloud | – | 52.7 | 51.5 | 2,100 | +| Offsite | – | 23.6 | 25.2 | 1,029 | +| None | – | 6.2 | 13.3 | 542 | +| Other | – | – | 1.2 | 51 | + +## T9. Cloud Storage Providers + +Titles — 2023: Which cloud storage service(s) are you subscribed to for backups? · 2024: Which cloud storage service(s) are you subscribed to for backups? · 2025: Cloud Storage Providers + +| label | 2023 | 2024 | 2025 | 2025 n | +|---|---|---|---|---| +| Backblaze | 15.4 | 16.2 | 15.0 | 613 | +| Google Drive | 11.7 | 13.7 | 12.6 | 514 | +| Hetzner | – | 5.1 | 9.1 | 371 | +| Microsoft OneDrive | 6.5 | 8.5 | 6.8 | 277 | +| iCloud | – | 4.8 | 5.3 | 215 | +| Proton Drive | – | 1.3 | 4.0 | 165 | +| Dropbox | 2.8 | 3.0 | 2.4 | 96 | +| Cloudflare R2 | – | 0.6 | 1.7 | 70 | +| BorgBase | – | 2.1 | 1.7 | 68 | +| Mega | 1.4 | 1.9 | 1.5 | 63 | +| pCloud | – | 0.8 | 1.2 | 51 | +| iDrive | – | 0.9 | – | – | +| Storj | – | 0.7 | – | – | +| Veeam | – | 0.7 | – | – | +| Box | – | 0.5 | – | – | +| CrashPlan | – | 0.5 | – | – | +| Wasabi | – | 0.5 | – | – | +| Amazon S3 | 4.5 | – | – | – | +| Other | 18.0 | 6.3 | 23.1 | 942 | + +## T10. Container Population + +Titles — 2023: Do you use containers to deploy self-hosted software? · 2024: Do you use containers to deploy self-hosted software? · 2025: Container Population + +*Single-choice: % of the column sum.* + +| label | 2023 | 2024 | 2025 | 2025 n | +|---|---|---|---|---| +| Deploy | 94.3 | 95.8 | 96.3 | 3,932 | +| Don't Deploy | 5.7 | 4.2 | 3.7 | 149 | + +## T11. Containers vs Bare Metal + +Titles — 2023: Do you prefer container installations to bare metal? · 2024: Do you prefer container installations to bare metal? · 2025: Containers vs Bare Metal + +*Single-choice: % of the column sum.* + +Note: 2025 added a third answer (Depends); 2024 and 2025 asked only container users. + +| label | 2023 | 2024 | 2025 | 2025 n | +|---|---|---|---|---| +| Containers | 79.5 | 88.1 | 69.1 | 2,720 | +| Depends | – | – | 26.5 | 1,041 | +| Bare Metal | 20.5 | 11.9 | 4.4 | 174 | + +## T12. Container Orchestration + +Titles — 2024: Do you use an orchestration platform to deploy containers? · 2025: Container Orchestration + +*Single-choice: % of the column sum.* + +| label | 2023 | 2024 | 2025 | 2025 n | +|---|---|---|---|---| +| No | – | 75.0 | 76.9 | 3,024 | +| Yes | – | 25.0 | 23.1 | 910 | + +## T13. Container Platforms + +Titles — 2023: Which container platform(s) do you use for deployment? · 2024: Which container platform(s) do you use for deployment? · 2025: Container Platforms + +| label | 2023 | 2024 | 2025 | 2025 n | +|---|---|---|---|---| +| Docker | 89.8 | 89.5 | 89.1 | 3,637 | +| LXC | 27.3 | 29.1 | 30.8 | 1,256 | +| Podman | 9.8 | 10.1 | 10.9 | 446 | +| Other | 4.8 | 2.6 | 3.5 | 142 | + +## T14. Management Software + +Titles — 2023: Do you deploy management software to administer your containers? · 2024: Do you deploy management software to administer your containers? · 2025: Management Software + +*Single-choice: % of the column sum.* + +| label | 2023 | 2024 | 2025 | 2025 n | +|---|---|---|---|---| +| Use | 49.7 | 54.6 | 51.5 | 2,022 | +| Don't Use | 50.3 | 45.4 | 48.5 | 1,908 | + +## T15. Management Platforms + +Titles — 2025: Management Platforms + +| label | 2023 | 2024 | 2025 | 2025 n | +|---|---|---|---|---| +| Portainer | – | – | 32.7 | 1,336 | +| Dockge | – | – | 10.4 | 425 | +| Komodo | – | – | 7.5 | 308 | +| Coolify | – | – | 1.5 | 60 | +| Other | – | – | 9.4 | 385 | + +## T16. Update Methodology + +Titles — 2023: How do you manage container updates? · 2024: How do you manage container updates? · 2025: Update Methodology + +*Single-choice: % of the column sum.* + +Note: 2025 was deployed as multi-select by mistake (column sum 4,113 > 3,930 asked). + +| label | 2023 | 2024 | 2025 | 2025 n | +|---|---|---|---|---| +| Manual | 58.1 | 54.1 | 45.1 | 1,855 | +| Depends / Both | – | 29.2 | 40.3 | 1,658 | +| Automatic | 41.9 | 16.7 | 14.6 | 600 | + +## T17. Firewalls + +Titles — 2023: Do you deploy a firewall aside from the router provided by your ISP? · 2024: Do you deploy a firewall aside from the router provided by your ISP? · 2025: Firewalls + +*Single-choice: % of the column sum.* + +| label | 2023 | 2024 | 2025 | 2025 n | +|---|---|---|---|---| +| Non-ISP | 55.9 | 51.7 | 58.7 | 2,393 | +| ISP | 44.1 | 48.3 | 41.3 | 1,686 | + +## T18. Remote Access + +Titles — 2023: How do you access your self-hosted software remotely? · 2024: How do you access your self-hosted software remotely? · 2025: Remote Access + +| label | 2023 | 2024 | 2025 | 2025 n | +|---|---|---|---|---| +| VPN | 68.2 | 77.0 | 71.1 | 2,902 | +| Reverse Proxy | 65.9 | 62.9 | 66.6 | 2,716 | +| Forwarded Ports | – | 23.0 | 17.7 | 721 | +| Only via LAN | 17.5 | 14.2 | 12.5 | 510 | +| Other | – | 0.5 | 6.7 | 273 | + +## T19. Reverse Proxies + +Titles — 2023: Which web server(s) do you deploy for proxied services? · 2024: Which web server(s) do you deploy for proxied services? · 2025: Reverse Proxies + +Merged spelling/case variants: 2023 'Nginx' = 'NGINX' + +| label | 2023 | 2024 | 2025 | 2025 n | +|---|---|---|---|---| +| NGINX Proxy Manager | – | 31.1 | 20.6 | 842 | +| Traefik | 21.3 | 24.1 | 18.4 | 751 | +| Caddy | 10.9 | 18.1 | 14.7 | 598 | +| Cloudflare Tunnels | 17.1 | 19.3 | 13.8 | 563 | +| NGINX | 50.1 | 28.3 | 12.9 | 528 | +| Pangolin | – | – | 7.1 | 290 | +| HAProxy | 5.4 | 5.0 | 3.1 | 128 | +| Apache | 6.6 | 8.5 | 2.4 | 97 | +| SWAG | – | 4.2 | 2.3 | 95 | +| Zoraxy | – | 0.7 | – | – | +| Other | 4.0 | 1.6 | 3.2 | 131 | + +## T20. Registered Domains + +Titles — 2023: Do you utilize a custom domain for your self-hosted applications? · 2024: Do you utilize a custom domain for your self-hosted applications? · 2025: Registered Domains + +*Single-choice: % of the column sum.* + +| label | 2023 | 2024 | 2025 | 2025 n | +|---|---|---|---|---| +| Custom Domain | 85.7 | 88.8 | 87.9 | 3,586 | +| No Domain | 14.3 | 11.2 | 12.1 | 495 | + +## T21. Domain Registrars + +Titles — 2023: Which registrar(s) do you purchase or lease your custom domains from? · 2024: Which registrar(s) do you purchase or lease your custom domains from? · 2025: Domain Registrars + +| label | 2023 | 2024 | 2025 | 2025 n | +|---|---|---|---|---| +| Cloudflare | 19.1 | 30.3 | 34.9 | 1,423 | +| Namecheap | 13.1 | 18.5 | 16.0 | 651 | +| Porkbun | 6.8 | 12.9 | 12.8 | 523 | +| OVH | 3.0 | 4.9 | 6.0 | 246 | +| GoDaddy | 2.5 | 3.6 | 3.0 | 124 | +| DuckDNS | 1.4 | 5.3 | 2.8 | 113 | +| Squarespace | – | – | 2.4 | 97 | +| Netcup | – | 1.8 | 2.1 | 85 | +| IONOS | 1.1 | 2.0 | 2.1 | 84 | +| Hetzner | 0.8 | 2.0 | 2.0 | 82 | +| Gandi | 2.0 | 2.5 | 1.5 | 62 | +| Strato | 1.2 | 1.4 | 1.4 | 57 | +| Google Domains | 4.3 | 3.3 | – | – | +| Hover | 0.9 | 1.2 | – | – | +| INWX | 0.7 | 1.1 | – | – | +| NameSilo | 0.8 | 1.0 | – | – | +| DreamHost | – | 0.7 | – | – | +| Other | 15.3 | 17.8 | 21.1 | 863 | + +## T22. E-mail + +Titles — 2023: Are you self-hosting any components of an e-mail server? · 2024: Are you self-hosting any components of an e-mail server? · 2025: E-mail + +*Single-choice: % of the column sum.* + +| label | 2023 | 2024 | 2025 | 2025 n | +|---|---|---|---|---| +| Don't Self-Host | 85.7 | 83.8 | 86.2 | 3,516 | +| Self-Host | 14.3 | 16.2 | 13.8 | 562 | + +## T23. E-mail Components + +Titles — 2024: Which e-mail server components are you self-hosting? · 2025: E-mail Components + +| label | 2023 | 2024 | 2025 | 2025 n | +|---|---|---|---|---| +| Sending | – | 14.6 | 11.8 | 482 | +| Receiving | – | 13.4 | 11.5 | 469 | +| Client | – | 9.7 | 8.1 | 331 | + +## T24. Database Deployment + +Titles — 2023: How do you deploy databases for self-hosted applications? · 2024: How do you deploy databases for self-hosted applications? · 2025: Database Deployment + +Note: Single-choice in 2023/2024, multi-select in 2025 (sum 5,004): % of respondents. + +| label | 2023 | 2024 | 2025 | 2025 n | +|---|---|---|---|---| +| Container (Separate) | 62.1 | 70.8 | 84.0 | 3,430 | +| Container (Shared) | 15.7 | 15.1 | 21.6 | 883 | +| Bare Metal (Shared) | 6.7 | 7.6 | 8.6 | 349 | +| Bare Metal (Separate) | 9.3 | 6.5 | 8.4 | 342 | + +## T25. Media Streaming + +Titles — 2023: Which of the platforms below do you deploy to stream media content? · 2024: Which of the platforms below do you deploy to stream media content? · 2025: Media Streaming + +| label | 2023 | 2024 | 2025 | 2025 n | +|---|---|---|---|---| +| Jellyfin | 46.1 | 53.9 | 60.9 | 2,487 | +| Plex | 39.5 | 35.0 | 29.9 | 1,219 | +| AudioBookshelf | – | 18.4 | 20.6 | 840 | +| Navidrome | – | 13.6 | 16.1 | 656 | +| Kodi | 6.5 | 7.6 | 5.8 | 237 | +| Emby | 4.1 | 3.6 | 3.7 | 149 | +| Subsonic | – | 2.7 | 2.0 | 81 | +| PeerTube | – | 2.1 | 1.8 | 74 | +| Lightweight Music Server | – | 0.8 | – | – | +| Ampache | – | 0.6 | – | – | +| Other | 6.7 | 6.0 | 6.6 | 268 | + +## T26. File Storage and Syncing + +Titles — 2024: Which of the platforms below do you deploy for remote file storage, access, or syncing? · 2025: File Storage and Syncing + +| label | 2023 | 2024 | 2025 | 2025 n | +|---|---|---|---|---| +| Nextcloud | – | 35.8 | 30.3 | 1,236 | +| Syncthing | – | 29.5 | 25.9 | 1,058 | +| Synology | – | 2.8 | 13.5 | 550 | +| FileBrowser | – | 13.5 | 11.8 | 481 | +| FileBrowser Quantum | – | – | 5.1 | 207 | +| Seafile | – | 3.2 | 2.9 | 118 | +| SFTPGo | – | 0.6 | 2.2 | 90 | +| ownCloud | – | 2.3 | 2.0 | 83 | +| Resilio | – | 0.5 | 1.3 | 53 | +| FileStash | – | 0.8 | – | – | +| FileRun | – | 0.5 | – | – | +| Other | – | 5.3 | 12.0 | 488 | + +## T27. Authentication + +Titles — 2025: Authentication + +| label | 2023 | 2024 | 2025 | 2025 n | +|---|---|---|---|---| +| Authelia | – | – | 9.6 | 390 | +| Pocket ID | – | – | 7.6 | 310 | +| authentik | – | – | 6.6 | 268 | +| Pangolin | – | – | 5.9 | 241 | +| Keycloak | – | – | 3.9 | 158 | +| Tinyauth | – | – | 2.7 | 111 | +| Zitadel | – | – | 1.1 | 46 | +| Other | – | – | 18.1 | 737 | + +## T28. Note-Taking / Documentation + +Titles — 2024: Which of the platforms below do you deploy for documentation or note-taking? · 2025: Note-Taking / Documentation + +| label | 2023 | 2024 | 2025 | 2025 n | +|---|---|---|---|---| +| Obsidian | – | 18.8 | 25.5 | 1,041 | +| Nextcloud Notes | – | 10.4 | 7.9 | 321 | +| BookStack | – | 11.1 | 7.4 | 303 | +| Joplin | – | 8.2 | 6.6 | 268 | +| Trilium | – | 5.1 | 4.5 | 182 | +| Memos | – | 4.9 | 4.1 | 167 | +| Wiki.js | – | 5.8 | 3.8 | 156 | +| Docmost | – | 2.1 | 3.5 | 141 | +| Outline | – | 3.1 | 3.2 | 132 | +| AFFiNE | – | 1.5 | 2.5 | 101 | +| SilverBullet | – | 1.7 | 2.4 | 99 | +| DokuWiki | – | 3.5 | 2.3 | 93 | +| Logseq | – | 3.1 | 2.2 | 89 | +| MkDocs | – | 0.5 | 1.8 | 75 | +| HedgeDoc | – | 1.9 | – | – | +| StandardNotes | – | 1.0 | – | – | +| AppFlowy | – | 0.9 | – | – | +| AnyType | – | 0.9 | – | – | +| Docusaurus | – | 0.9 | – | – | +| TiddlyWiki | – | 0.8 | – | – | +| MediaWiki | – | 0.6 | – | – | +| SiYuan | – | 0.5 | – | – | +| FlatNotes | – | 0.4 | – | – | +| XWiki | – | 0.3 | – | – | +| Other | – | 3.4 | 13.9 | 568 | + +## T29. Git + +Titles — 2025: Git + +| label | 2023 | 2024 | 2025 | 2025 n | +|---|---|---|---|---| +| Gitea | – | – | 20.8 | 849 | +| Forgejo | – | – | 15.0 | 613 | +| GitLab | – | – | 7.4 | 302 | +| Gogs | – | – | 0.4 | 18 | +| Other | – | – | 2.5 | 101 | + +## T30. Home Automation + +Titles — 2023: Do you deploy any self-hosted software for smart home or home automation purposes? · 2024: Do you deploy any self-hosted software for smart home or home automation purposes? · 2025: Home Automation + +*Single-choice: % of the column sum.* + +| label | 2023 | 2024 | 2025 | 2025 n | +|---|---|---|---|---| +| Deploy | 56.5 | 59.8 | 62.7 | 2,548 | +| Don't Deploy | 43.5 | 40.2 | 37.3 | 1,516 | + +## T31. Game Servers + +Titles — 2023: Are you self-hosting any game servers? · 2024: Are you self-hosting any game servers? · 2025: Game Servers + +*Single-choice: % of the column sum.* + +| label | 2023 | 2024 | 2025 | 2025 n | +|---|---|---|---|---| +| Don't Host | 62.8 | 67.6 | 67.8 | 2,765 | +| Host | 37.2 | 32.4 | 32.2 | 1,316 | + +## T32. Games + +Titles — 2024: List the games you're deploying a game server for. · 2025: Games + +| label | 2023 | 2024 | 2025 | 2025 n | +|---|---|---|---|---| +| Minecraft | – | 24.9 | 25.5 | 1,041 | +| Valheim | – | 3.3 | 5.2 | 214 | +| Satisfactory | – | 4.3 | 5.2 | 212 | +| Factorio | – | 3.2 | 5.1 | 208 | +| Terraria | – | 2.1 | 4.0 | 163 | +| Palworld | – | 2.1 | 3.2 | 131 | +| Foundry VTT | – | 0.4 | 2.6 | 107 | +| Project Zomboid | – | 1.1 | 2.1 | 84 | +| 7 Days to Die | – | 1.1 | 1.7 | 69 | +| ARK | – | 0.9 | 1.7 | 68 | +| V Rising | – | 0.8 | 1.6 | 66 | +| Counter-Strike | – | 0.9 | 1.5 | 60 | +| Space Engineers | – | 0.5 | 1.3 | 53 | +| Arma | – | 0.9 | – | – | +| Minetest | – | 0.6 | – | – | +| Enshrouded | – | 0.5 | – | – | +| Assetto Corsa | – | 0.5 | – | – | +| Vintage Story | – | 0.3 | – | – | +| Other | – | 7.9 | 7.7 | 315 | + +## T33. Favorite Software + +Titles — 2023: What is your favorite self-hosted application? · 2024: What is your favorite self-hosted application? · 2025: Favorite Software + +Note: One answer per person, open text; each year omits small counts, so % is of all respondents. 2023 'Paperless' matched to 'Paperless-ngx'; 2024 'Trilum' read as Trilium. + +Merged spelling/case variants: 2024 'AudioBookshelf' = 'Audiobookshelf'; 2024 'Pi-Hole' = 'Pi-hole' + +| label | 2023 | 2024 | 2025 | 2025 n | +|---|---|---|---|---| +| Home Assistant | 12.4 | 12.6 | 14.4 | 588 | +| Jellyfin | 10.4 | 13.5 | 12.8 | 522 | +| Immich | 2.2 | 7.5 | 10.5 | 429 | +| Plex | 8.9 | 8.8 | 5.1 | 208 | +| Vaultwarden | 7.9 | 5.8 | 3.7 | 152 | +| Nextcloud | 7.7 | 4.6 | 2.9 | 118 | +| Audiobookshelf | 1.1 | 2.4 | 2.3 | 94 | +| Paperless-ngx | 2.0 | 2.5 | 2.1 | 85 | +| *arr | 2.4 | 3.0 | 2.0 | 81 | +| FreshRSS | 1.2 | 0.9 | 1.3 | 52 | +| Pi-hole | 2.4 | 1.2 | 1.2 | 50 | +| Actual Budget | – | 0.8 | 1.0 | 42 | +| Navidrome | 1.3 | 1.0 | 1.0 | 41 | +| RomM | – | – | 1.0 | 41 | +| Syncthing | 0.9 | 1.0 | 0.8 | 32 | +| Homepage | – | 0.9 | 0.7 | 29 | +| Mealie | – | 0.6 | 0.7 | 29 | +| n8n | – | 0.4 | 0.7 | 29 | +| Gitea | 2.0 | 1.5 | 0.7 | 28 | +| Miniflux | 0.9 | 1.0 | 0.7 | 27 | +| Emby | – | 0.7 | 0.6 | 26 | +| Proxmox | 0.9 | 1.0 | 0.6 | 25 | +| Pangolin | – | – | 0.6 | 25 | +| Glance | – | – | 0.6 | 24 | +| Karakeep | – | – | 0.5 | 22 | +| Komodo | – | – | 0.5 | 22 | +| AdGuard Home | 0.7 | 0.6 | 0.5 | 20 | +| Forgejo | – | 0.9 | – | – | +| Authentik | – | 0.5 | – | – | +| GitLab | – | 0.5 | – | – | +| Matrix | – | 0.5 | – | – | +| Firefly III | – | 0.5 | – | – | +| Uptime Kuma | – | 0.4 | – | – | +| Frigate NVR | – | 0.4 | – | – | +| Tiny Tiny RSS | – | 0.4 | – | – | +| Trilium | – | 0.4 | – | – | +| BookStack | 0.8 | – | – | – | +| Portainer | 0.7 | – | – | – | +| Grafana | 0.6 | – | – | – | +| Authelia | 0.6 | – | – | – | + +## T34. Age Range + +Titles — 2023: What is your age range? · 2024: What is your age range? · 2025: Age Range + +*Single-choice: % of the column sum.* + +Note: 2023/2024 bucket 10-19 matched to 2025 12-19. + +| label | 2023 | 2024 | 2025 | 2025 n | +|---|---|---|---|---| +| 30-39 years-old | 37.5 | 38.3 | 37.8 | 1,532 | +| 20-29 years-old | 34.8 | 31.5 | 29.9 | 1,210 | +| 40-49 years-old | 16.7 | 19.5 | 20.8 | 844 | +| 50-59 years-old | 4.6 | 6.4 | 7.1 | 287 | +| 12-19 years-old | 5.8 | 3.4 | 3.1 | 125 | +| 60-69 years-old | 0.6 | 0.9 | 1.3 | 53 | + +## T35. Gender + +Titles — 2023: What is your gender? · 2024: What is your gender? · 2025: Gender + +*Single-choice: % of the column sum.* + +| label | 2023 | 2024 | 2025 | 2025 n | +|---|---|---|---|---| +| Male | 96.2 | 95.6 | 95.6 | 3,839 | +| Female | 2.5 | 2.4 | 1.9 | 77 | +| Non-Binary | – | 1.8 | 1.9 | 77 | +| Other | 1.4 | 0.2 | 0.5 | 21 | + +## T36. Career Field + +Titles — 2023: If employed, do you work in a technical field? · 2024: If employed, do you work in a technical field? · 2025: Career Field + +*Single-choice: % of the column sum.* + +| label | 2023 | 2024 | 2025 | 2025 n | +|---|---|---|---|---| +| Technology | 79.2 | 81.8 | 80.6 | 3,227 | +| Non-Technology | 20.8 | 18.2 | 19.4 | 778 | + +## T37. Mobile OS + +Titles — 2023: What is your primary mobile device's operating system? · 2024: What is your primary mobile device's operating system? · 2025: Mobile OS + +*Single-choice: % of the column sum.* + +| label | 2023 | 2024 | 2025 | 2025 n | +|---|---|---|---|---| +| Android | 70.5 | 67.0 | 66.7 | 2,715 | +| iOS | 28.1 | 31.6 | 31.8 | 1,295 | +| GrapheneOS | – | 0.7 | – | – | +| Other | 1.4 | 0.7 | 1.5 | 62 | + +## T38. Donations + +Titles — 2023: Have you donated to a self-hosted project in the last year? · 2024: Have you donated to a self-hosted project in the last year? · 2025: Donations + +*Single-choice: % of the column sum.* + +| label | 2023 | 2024 | 2025 | 2025 n | +|---|---|---|---|---| +| Haven't Donated | 61.8 | 60.0 | 59.1 | 2,393 | +| Donated | 31.9 | 40.0 | 40.9 | 1,657 | +| Prefer not to answer | 6.3 | – | – | – | + +## T39. Education + +Titles — 2023: What is the highest level of education you have completed? · 2024: What is the highest level of education you have completed? · 2025: Education + +*Single-choice: % of the column sum.* + +| label | 2023 | 2024 | 2025 | 2025 n | +|---|---|---|---|---| +| Bachelor's Degree | 40.3 | 39.0 | 40.7 | 1,607 | +| Master's Degree | 19.7 | 21.6 | 22.6 | 893 | +| Some college | 17.3 | 15.9 | 16.6 | 655 | +| HS Diploma / GED | 12.3 | 11.7 | 7.4 | 293 | +| Associate's Degree | 1.5 | 5.4 | 5.6 | 221 | +| Doctorate | 2.1 | 3.2 | 3.1 | 122 | +| No formal schooling | 1.8 | 1.8 | 2.8 | 109 | +| VoTech Program | 5.0 | 1.3 | 1.2 | 46 | + +# Unmatched charts (asked in 2023 and/or 2024, no same question in 2025) + +## T40. Are you utilizing hosted cloud storage for offsite backups? + +Titles — 2023: Are you utilizing hosted cloud storage for offsite backups? + +*Single-choice: % of the column sum.* + +| label | 2023 | 2024 | 2025 | 2025 n | +|---|---|---|---|---| +| No | 53.9 | – | – | – | +| Yes | 46.1 | – | – | – | + +## T41. Do you deploy Kubernetes to manage your self-hosted software? + +Titles — 2023: Do you deploy Kubernetes to manage your self-hosted software? + +*Single-choice: % of the column sum.* + +| label | 2023 | 2024 | 2025 | 2025 n | +|---|---|---|---|---| +| No | 89.6 | – | – | – | +| Yes | 10.4 | – | – | – | + +## T42. Do you deploy any self-hosted software for purposes related to media streaming? + +Titles — 2023: Do you deploy any self-hosted software for purposes related to media streaming? + +*Single-choice: % of the column sum.* + +| label | 2023 | 2024 | 2025 | 2025 n | +|---|---|---|---|---| +| Yes | 81.6 | – | – | – | +| No | 18.4 | – | – | – | + +## T43. Which smart home communication standards and protocols are you utilizing in your self-hosted ecosystem? + +Titles — 2024: Which smart home communication standards and protocols are you utilizing in your self-hosted ecosystem? + +| label | 2023 | 2024 | 2025 | 2025 n | +|---|---|---|---|---| +| WiFi | – | 52.1 | – | – | +| Zigbee | – | 38.5 | – | – | +| MQTT | – | 32.7 | – | – | +| Bluetooth | – | 22.7 | – | – | +| ESP | – | 19.5 | – | – | +| Z-Wave | – | 12.0 | – | – | +| Matter | – | 9.9 | – | – | +| NFC | – | 7.4 | – | – | +| Thread | – | 6.2 | – | – | +| Other | – | 0.6 | – | – | + +## T44. Do you deploy any self-hosted ActivityPub platforms? + +Titles — 2024: Do you deploy any self-hosted ActivityPub platforms? + +*Single-choice: % of the column sum.* + +| label | 2023 | 2024 | 2025 | 2025 n | +|---|---|---|---|---| +| No | – | 90.2 | – | – | +| Yes | – | 9.8 | – | – | + +## T45. Which ActivityPub platform(s) do you deploy? + +Titles — 2024: Which ActivityPub platform(s) do you deploy? + +| label | 2023 | 2024 | 2025 | 2025 n | +|---|---|---|---|---| +| Mastodon | – | 3.2 | – | – | +| PeerTube | – | 1.1 | – | – | +| Lemmy | – | 1.0 | – | – | +| GoToSocial | – | 0.7 | – | – | +| Pixelfed | – | 0.5 | – | – | +| Akkoma | – | 0.2 | – | – | +| Other | – | 1.3 | – | – | diff --git a/documentation/audits/selfhst-survey-2026-10-12/fetch.py b/documentation/audits/selfhst-survey-2026-10-12/fetch.py new file mode 100644 index 00000000..fb5ca0c9 --- /dev/null +++ b/documentation/audits/selfhst-survey-2026-10-12/fetch.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python3 +"""Download the selfh.st annual survey results (2023-2025) to a cache outside every repo. + +Prints bytes and SHA-256 for each file. The files are not committed (spec §9.2). +""" +import hashlib +import os +import sys +import urllib.request + +BASE = "https://raw.githubusercontent.com/selfhst/cdn/main/assets/surveys/annual/{}-results.json" +CACHE = os.path.expanduser("~/research-cache/selfhst-survey") +# Prefixes/suffixes of the hashes the reviewer recorded on 2026-10-12. +EXPECTED = { + 2023: ("714350e5e4b8f3cc", "f03f", 10362), + 2024: ("289c5161e5b6b568", "4832", 14290), + 2025: ("e083094ad7f8cb67", "229e", 20428), +} + + +def main(): + os.makedirs(CACHE, exist_ok=True) + rc = 0 + for year, (pre, suf, size) in EXPECTED.items(): + url = BASE.format(year) + try: + with urllib.request.urlopen(url, timeout=30) as r: + data = r.read() + except Exception as e: # continue with the years that can be read (spec §13) + print(f"{year} FETCH FAILED {url}: {e}") + rc = 1 + continue + with open(os.path.join(CACHE, f"{year}-results.json"), "wb") as f: + f.write(data) + h = hashlib.sha256(data).hexdigest() + ok = h.startswith(pre) and h.endswith(suf) and len(data) == size + print(f"{year} bytes={len(data)} sha256={h} {'MATCH' if ok else 'DIFFERS from spec'}") + return rc + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/documentation/audits/selfhst-survey-2026-10-12/tables.py b/documentation/audits/selfhst-survey-2026-10-12/tables.py new file mode 100644 index 00000000..4032f0f2 --- /dev/null +++ b/documentation/audits/selfhst-survey-2026-10-12/tables.py @@ -0,0 +1,246 @@ +#!/usr/bin/env python3 +"""Build TABLE.md from the cached selfh.st survey results (2023-2025). + +Reads ~/research-cache/selfhst-survey/-results.json (written by fetch.py). +Writes TABLE.md next to this script. Stdlib only. + +Percent rule (spec §1, §8): +- multi-select charts: % of the year's respondent count; +- single-choice charts (marked "single"): % of the column sum, because the + question was asked to a subset or answered by fewer than all respondents. +""" +import json +import os + +CACHE = os.path.expanduser("~/research-cache/selfhst-survey") +OUT = os.path.join(os.path.dirname(os.path.abspath(__file__)), "TABLE.md") +YEARS = (2023, 2024, 2025) +PAGE = "https://selfh.st/survey/{}-results/" +DATA = "https://raw.githubusercontent.com/selfhst/cdn/main/assets/surveys/annual/{}-results.json" + +# Respondent count per year. 2025: the results page states 4,081 completed responses. +# 2023/2024: the pages give only rounded numbers ("just shy of 1,900", "~3,700"); the exact +# figure is the column sum of the first, mandatory, single-choice question (Primary Purpose), +# which is 4,081 in 2025 too - the same method reproduces the stated 2025 number. +RESPONDENTS = {2023: 1869, 2024: 3655, 2025: 4081} + +# 2025 title -> the 2023/2024 chart id it asks the same question as. None = 2025 only. +MATCH_2025 = { + "Primary Purpose": "personal-enterprise", + "Unique Users": "unique-users", + "Reasons for Self-Hosting": "why-self-host", + "Hardware Options": "hardware", + "Network-Attached Storage": "deploy-nas", + "Sensitive Data": "sensitive-data", + "Operating Systems": "operating-system", + "Backup Strategies": "backup-strategy", + "Cloud Storage Providers": "backup-cloud", + "Container Population": "deploy-containers", + "Containers vs Bare Metal": "prefer-containers", + # 2023 asked about Kubernetes only, 2024/2025 about any orchestration: 2023 kept separate. + "Container Orchestration": "orchestration-platform", + "Container Platforms": "container-platform", + "Management Software": "container-manager", + "Management Platforms": None, + "Update Methodology": "container-updates", + "Firewalls": "deploy-firewall", + "Remote Access": "remote-access", + "Reverse Proxies": "web-server", + "Registered Domains": "custom-domain", + "Domain Registrars": "domain-registrar", + "E-mail": "email-server", + "E-mail Components": "email-components", + "Database Deployment": "deploy-database", + "Media Streaming": "media-server", + "File Storage and Syncing": "file-sync", + "Authentication": None, + "Note-Taking / Documentation": "documentation-notes", + "Git": None, + "Home Automation": "smart-home", + "Game Servers": "deploy-game", + "Games": "game-server", + "Favorite Software": "favorite-app", + "Age Range": "age-range", + "Gender": "gender", + "Career Field": "employment-field", + "Mobile OS": "mobile-os", + "Donations": "donate-project", + "Education": "education-level", +} +# 2023's Kubernetes question differs from the later orchestration question. +NOT_MATCHED_2023 = {"orchestration-platform"} + +# Single-choice charts -> % of column sum. Keyed by 2023/2024 id (or 2025 title when 2025-only). +SINGLE = { + "personal-enterprise", "unique-users", "deploy-nas", "sensitive-data", "offsite-backups", + "deploy-containers", "prefer-containers", "orchestration-platform", "container-manager", + "container-updates", "deploy-firewall", "custom-domain", "email-server", "stream-media", + "smart-home", "deploy-game", "host-activitypub", "age-range", "gender", "employment-field", + "mobile-os", "donate-project", "education-level", +} + +# Old label -> 2025 label, per chart, where the wording changed but the answer is the same. +# Labels that differ only in case are merged automatically (and listed in the output). +ALIAS = { + "deploy-nas": {"Yes": "Deploy", "No": "Don't Deploy"}, + "sensitive-data": {"Yes": "Avoid", "No": "Don't Avoid"}, + "deploy-containers": {"Yes": "Deploy", "No": "Don't Deploy"}, + "prefer-containers": {"Yes": "Containers", "No": "Bare Metal"}, + "container-manager": {"Yes": "Use", "No": "Don't Use"}, + "container-updates": {"Both": "Depends / Both"}, + "deploy-firewall": {"Yes": "Non-ISP", "No": "ISP"}, + "custom-domain": {"Yes": "Custom Domain", "No": "No Domain"}, + "email-server": {"Yes": "Self-Host", "No": "Don't Self-Host"}, + "smart-home": {"Yes": "Deploy", "No": "Don't Deploy"}, + "deploy-game": {"Yes": "Host", "No": "Don't Host"}, + "employment-field": {"Yes": "Technology", "No": "Non-Technology"}, + "donate-project": {"Yes": "Donated", "No": "Haven't Donated"}, + "gender": {"Man": "Male", "Woman": "Female"}, + "education-level": {"Some college, no degree": "Some college"}, + "age-range": {"10-19 years-old": "12-19 years-old"}, + "operating-system": {"Generic Linux": "Linux"}, + "hardware": {"Custom-built": "Custom build", "Enterprise": "Enterprise hardware", + "Mobile phone": "Mobile device"}, + "deploy-database": {"Docker - Individual": "Container (Separate)", + "Docker - Shared": "Container (Shared)", + "Bare Metal - Individual": "Bare Metal (Separate)", + "Bare Metal - Shared": "Bare Metal (Shared)"}, + "favorite-app": {"Paperless": "Paperless-ngx", "*arr Stack": "*arr", "Trilum": "Trilium"}, +} +# Notes printed under a section heading. +NOTES = { + "unique-users": "2023 buckets 11-15 and 16-20 are kept apart; 2024/2025 ask 11-20.", + "prefer-containers": "2025 added a third answer (Depends); 2024 and 2025 asked only container users.", + "container-updates": "2025 was deployed as multi-select by mistake (column sum 4,113 > 3,930 asked).", + "age-range": "2023/2024 bucket 10-19 matched to 2025 12-19.", + "favorite-app": ("One answer per person, open text; each year omits small counts, so % is of all " + "respondents. 2023 'Paperless' matched to 'Paperless-ngx'; 2024 'Trilum' read as Trilium."), + "deploy-database": "Single-choice in 2023/2024, multi-select in 2025 (sum 5,004): % of respondents.", + "hardware": "2023 'Custom-built', 'Enterprise', 'Mobile phone' matched to the 2024/2025 wording.", +} + + +def charts_of(year): + path = os.path.join(CACHE, f"{year}-results.json") + if not os.path.exists(path): + return None + with open(path, encoding="utf-8") as f: + d = json.load(f) + if "charts" in d: + return d["charts"] + return [c for cat in d["categories"] for c in cat["charts"]] + + +def series(chart, alias): + out, merged = {}, [] + canon = {} + for lab, val in zip(chart["labels"], chart["datasets"][0]["data"]): + lab = alias.get(lab, lab) + key = lab.lower() + if key in canon and canon[key] != lab: + merged.append(f"{lab} = {canon[key]}") + canon.setdefault(key, lab) + out[key] = out.get(key, 0) + val + return out, canon, merged + + +def pct(v, denom): + return f"{100.0 * v / denom:.1f}" if denom else "–" + + +def main(): + per_year = {y: charts_of(y) for y in YEARS} + missing = [y for y in YEARS if per_year[y] is None] + by_id = {y: {c["id"]: c for c in (per_year[y] or [])} for y in (2023, 2024)} + + # Build the section list: 2025 order first, then the 2023/2024 charts nobody matched. + sections = [] + used = {2023: set(), 2024: set()} + for c25 in per_year[2025] or []: + cid = MATCH_2025.get(c25["title"]) + c23 = by_id[2023].get(cid) if cid and cid not in NOT_MATCHED_2023 else None + c24 = by_id[2024].get(cid) if cid else None + for y, c in ((2023, c23), (2024, c24)): + if c: + used[y].add(c["id"]) + sections.append({"key": cid or c25["title"], "charts": {2023: c23, 2024: c24, 2025: c25}}) + unmatched = [] + for cid in list(by_id[2023]) + [i for i in by_id[2024] if i not in by_id[2023]]: + c23 = by_id[2023].get(cid) if cid not in used[2023] else None + c24 = by_id[2024].get(cid) if cid not in used[2024] else None + if c23 or c24: + unmatched.append({"key": cid, "charts": {2023: c23, 2024: c24, 2025: None}}) + + L = ["# selfh.st self-hosting survey 2023–2025 — tables", "", + "Generated by `tables.py` from the files `fetch.py` downloads. Do not edit by hand.", "", + "| Year | Respondents | Results page | Data file |", "|---|---|---|---|"] + for y in YEARS: + L.append(f"| {y} | {RESPONDENTS[y]:,} | {PAGE.format(y)} | {DATA.format(y)} |") + L += ["", "Values are **% of the year's respondents** (multi-select: a column can pass 100 %).", + "Charts marked *single-choice* show **% of the column sum** instead.", + "`2025 n` is the raw 2025 response count. `–` = not asked that year (or not matched).", ""] + if missing: + L.append(f"**Missing years (download failed): {missing}.**\n") + + def emit(num, sec, section_list_name): + ch = sec["charts"] + key = sec["key"] + single = key in SINGLE + alias = ALIAS.get(key, {}) + titles = [f"{y}: {ch[y]['title']}" for y in YEARS if ch[y]] + rows, canon_all, merged_all, denom = {}, {}, [], {} + for y in reversed(YEARS): # 2025 first, so its spelling is the shown label + if not ch[y]: + continue + s, canon, merged = series(ch[y], alias) + merged_all += merged + for k, v in canon.items(): + if k in canon_all and canon_all[k] != v: + merged_all.append(f"{y} '{v}' = '{canon_all[k]}'") + canon_all.setdefault(k, v) + denom[y] = sum(s.values()) if single else RESPONDENTS[y] + for k, v in s.items(): + rows.setdefault(k, {})[y] = v + L.append(f"## T{num}. {ch[2025]['title'] if ch[2025] else ch[2024]['title'] if ch[2024] else ch[2023]['title']}") + L.append("") + L.append("Titles — " + " · ".join(titles)) + L.append("") + if single: + L.append("*Single-choice: % of the column sum.*") + L.append("") + if key in NOTES: + L.append(f"Note: {NOTES[key]}") + L.append("") + if merged_all: + L.append("Merged spelling/case variants: " + "; ".join(sorted(set(merged_all)))) + L.append("") + L.append("| label | 2023 | 2024 | 2025 | 2025 n |") + L.append("|---|---|---|---|---|") + + def sortkey(k): + r = rows[k] + return (k == "other", -r.get(2025, -1), -r.get(2024, -1), -r.get(2023, -1)) + for k in sorted(rows, key=sortkey): + r = rows[k] + cells = [pct(r[y], denom[y]) if y in r else "–" for y in YEARS] + n = f"{r[2025]:,}" if 2025 in r else "–" + L.append(f"| {canon_all[k]} | {' | '.join(cells)} | {n} |") + L.append("") + + n = 0 + for sec in sections: + n += 1 + emit(n, sec, "matched") + L += ["# Unmatched charts (asked in 2023 and/or 2024, no same question in 2025)", ""] + for sec in unmatched: + n += 1 + emit(n, sec, "unmatched") + + with open(OUT, "w", encoding="utf-8") as f: + f.write("\n".join(L).rstrip() + "\n") + print(f"wrote {OUT}: {n} sections ({len(sections)} from 2025, {len(unmatched)} unmatched)") + return 1 if missing else 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/documentation/backlog/OPEN-ITEMS.md b/documentation/backlog/OPEN-ITEMS.md index 930caa37..f6209ea3 100644 --- a/documentation/backlog/OPEN-ITEMS.md +++ b/documentation/backlog/OPEN-ITEMS.md @@ -244,7 +244,7 @@ stopping line that lies. | **R-814** | Hub & operator | P4 | `PBS-storage-1` (u629193, box 611421) still `status=active`, 19.9 MB | **VERIFY** (2026-10-03 triage: a July watch row with no id; given R-814. WAITING-ON-OPERATOR — no record found that the box was deleted.) — WAITING-ON-OPERATOR | operator console | Delete the box | operator | | **R-844** | Hub & operator | P4 | **The household's OS-update line exists only on the hub's customer timeline.** 2026-10-04: the box itself has no event surface for agent results (the controller UI shows no timeline), so `os_update_applied` is a hub customer event (info: recorded, never mailed). Its stored text is the hub's English sentence; the hu/en bundle text (`mail.event.os_update_applied`) is used only if it is ever mailed. Fix direction: a controller-side line (the controller already polls the agent's local API) when the box gets a household timeline. `audits/os-guest-lane-2026-10-04/partG/hub-customer-timeline-demo-hp.txt` | **READY — owner: CC** **2026-10-05 (burn-down night): NEEDS A DESIGN** — a household timeline on the box does not exist yet. | — | — | CC | -## Business & legal — 11 rows (P2 4, P3 2, P4 5) +## Business & legal — 12 rows (P2 4, P3 2, P4 6) | ID | Category | Sev | What | State | Blocked on | Next action | Owner | |---|---|---|---|---|---|---|---| @@ -259,6 +259,7 @@ stopping line that lies. | **R-919** | Business & legal | P3 | **On a phone the Facebook Page cuts the left edge of the cover: the „s” of „saját szabályaid” and the „f” of „felhom.eu” are gone.** MEASURED 2026-10-08 on the live Page in Chrome DevTools device mode, Pixel 9 (412 × 924, mobile user agent, after a reload so Facebook serves the mobile bundle): `audits/facebook-page-setup-2026-10-08/C2-phone-headline-cut-closeup.png`. The mobile Page header is **412 × 274 = 1,504:1**, so Facebook keeps our cover's full height and shows only the centre **938 px of its 1640 px width (57,2 %)** — **351 px cut from each side**. `marketing/facebook/build.py` builds to a safe area of the centre **1028 × 544** (306 px clear of each edge), which is **45 px wider per side than the phone actually shows**; the light text in `out/cover-c.png` runs from x 333 to x 997, and the left crop edge is x 351, so the first **18 px** of the text are cut. Covers A and B are built from the same safe area and will have the same edge. Two further facts this measurement establishes: **Meta's own help page is wrong about its own rendering** — it states the mobile cover is 2,4:1 where the Page header measures 1,504:1 — and the mobile profile circle is far bigger than assumed (172 px, centred, overlapping the bottom 112 px of the 274 px cover, i.e. source x 637–1030 × y 369–624 is hidden). Not re-cropped on Facebook, per the task's fence. **-- 2026-10-09, FIXED in the build:** `marketing/facebook/build.py` now takes the phone view from the measurement (`PHONE_HDR = (412, 274)` -> the centre 938 px), so SAFE is (391, 40)-(1249, 584) and the phone profile circle is the measured CENTRED box (637, 369, 393) rather than a left-anchored one. Every cover is drawn in a derived `BAND` (408, 48)-(1249, 340), and a `cap` check holds each headline's capital at >= 4 % of the cover height. The red-proof runs on EVERY build (`control_old_window`): it draws the headline where the old 640 x 360 assumption put it, x 328, and the check must reject it -- the phone's crop edge is x 351, so 23 px were cut. Against the three covers as committed at `a76207945e` the new check convicted 3 of 3 (A 23/22 px over the left/right edges, B 63/58 px plus 1017 content pixels under the phone circle, C 63/82 px plus 1778). The profile pictures are untouched -- sha256 identical before and after. **-- 2026-10-09 (operator refinements, same day):** the profile picture now carries the logo MARK only (the lettering was unreadable at 176 px; the mark grew 69 % -> 76 % of the circle, canvas 932 -> 648), and the covers set the headline the way `site.css` sets `.page-index .hero-text h1` (Bold 700, letter-spacing -0.03em, not ExtraBold 800 untracked) with „felhom.eu” drawn from the logo's OWN lettering instead of typed. No geometry changed; every R-919 check and the red-proof stand. **-- 2026-10-09 (second measurement):** a phone has TWO views and they disagree. SIGNED IN the sides are cut (confirmed on the operator's REAL phone, Chrome/Android: the window solves to x 351..1298 against the emulator's 351..1289 - the left edge to the pixel). SIGNED OUT the FULL width is shown but the cover is top-anchored and only the top 525 px survives (the bottom 99 px is cut; the file's blue top rule is still visible, which is how the side was established), with a much bigger, higher circle at x 486..1150 from y 232. `build.py` now carries both views, models the circles as DISCS rather than rectangles running to the bottom, and splits the artwork into a READ layer (must survive every view) and a DECOR layer (may be cropped or covered; the build reports the cost - B 39 %, C 62 %). The two-view geometry convicted all three then-current covers before the redraw (A 908 px under a circle, B 1715, C 1962). Covers redrawn: C is the operator's laptop idea with the dashboard at 640 px (was 370), B's motif grown to match. **-- 2026-10-09 (the APP measured):** the operator checked the live Page in Facebook Lite and in Chrome on his phone. Solved against the laptop frame, both give a visible window of x 349..1290 / 349..1291 - the LITE APP CROPS EXACTLY LIKE SIGNED-IN MOBILE WEB, and both agree with the emulator's 351..1289. Their circle is at x 645..1021 from y 451, LOWER than the emulator's 369, so that figure was pessimistic rather than wrong. Five views measured; the signed-out one stays the binding constraint. Cover C redrawn to the operator's layout (wordmark 88 px on top, gap, catchphrase) - one line, not his two, because two measured 392 text pixels behind the signed-out circle („saját szabályaid” read „saját szab”) and sizing them to fit drops the capital to the 25 px floor. | **VERIFY -- rebuilt on `main` 2026-10-09. The app IS now measured and the cover renders correctly there; what is left is the operator's look at the NEW cover in the app after uploading it.** | — | Operator: upload the rebuilt cover-c (and the profile picture if not already), then confirm in the Facebook app that the wordmark and the catchphrase are whole. Close on that word | CC | | **R-920** | Business & legal | P4 | **The Messenger „Gyakori kérdések" automation does not exist for this Page, so `COPY.md` §5 — four questions with answers condensed from `gyik.html` — has nowhere to go.** FOUND 2026-10-09 (Page details task, `audits/facebook-page-details-2026-10-09/`). SEARCHED, not assumed absent: the create-automation catalogue („Az összes automatizálás") holds exactly THREE templates — Automatikus válasz, Távolléti üzenet, A megválaszolatlan üzenetek azonosítása (`B5-no-faq-template-all-three.jpg`); the template search for „kérdés" answers **„Nincs a keresésnek megfelelő automatizálási sablon."** while the POSITIVE CONTROL „üzenet" returns two, so the search works and the term genuinely misses; the existing instant-reply automation carries only channel, message and media — no FAQ and no quick replies; and the business-portfolio settings have no messaging/FAQ entry. The copy is written, sourced line by line to `gyik.html` and committed as `marketing/facebook/COPY.md` §5, ready to paste unchanged the day the feature appears. **Same shape as R-917** (§2 has nowhere to go), and the same cause: Meta removed a Page field this project had planned copy for. **Options for the operator:** (a) leave §5 unused until Meta brings the feature back; (b) fold the four answers into the Messenger welcome message (§3) — it holds 500 characters and today uses 120, so one or two would fit, not four; (c) publish them as a pinned FAQ post once the app is Live (R-915); (d) ask Meta support whether the FAQ automation still exists for this Page type. Recommended (a) with (c) later — the welcome message stays short, and the website's own `gyik.html` already answers these. | **DEFERRED — operator chose (c) on 2026-10-09:** park the text and publish it as a post once posting starts. Not a defect, and not waiting on CC | nothing — **UNBLOCKED 2026-10-09**: R-915 is closed, the app is Live, so posting can start whenever the operator wants | When posting starts: publish `COPY.md` §5 (the four Messenger FAQ answers) as one later post. If nothing is done: the text stays in `COPY.md` unused, which the operator has accepted | operator | | **R-930** | Business & legal | P3 | **The site's primary call-to-action fails WCAG AA: white on `--blue` #0083D8 measures 4.01:1 at 16px/600, against a 4.5:1 floor.** MEASURED 2026-10-10 in the browser, on the LIVE home page and on the redesign preview: identical, so this is **pre-existing and site-wide**, not a regression of the redesign. It is the „Jelentkezem tesztelőnek" button and every `.cta-button` on every page. `.cta-button-secondary` is fine (7.17:1). Three fixes, all needing the operator because each touches brand: (a) darken `--blue` until the ratio clears 4.5 (changes a token used across hub, controller and website); (b) make the label 700 weight at 18.66px+, which moves it into WCAG's „large text" band where 3:1 applies and 4.01 passes, at the cost of a bigger button everywhere; (c) accept it and record the decision. **Not changed unilaterally**: `felhom-web-design` §6 puts a new accent colour behind the operator's word. | **WAITING-ON-OPERATOR** — filed 2026-10-10 by the home-page redesign session; evidence `audits/redesign-2026-10-10/AUDIT.md` | operator's choice between (a), (b), (c) | pick one of the three | operator | +| **R-989** | Business & legal | P4 | **Operator: read `documentation/audits/selfhst-survey-2026-10-12/FELHOM.md` §6 and rule on each recommendation.** READ-ONLY research 2026-10-12: the selfh.st self-hosting survey 2023–2025 (1,869 / 3,655 / 4,081 respondents, hobby users) against our catalog, features, pitch and hardware. Ten ranked recommendations, none acted on; the top three: a supported-hardware page (none exists — finding, §4), off-site backup as a *why* reason in the pitch (only 25.2 % of the crowd backs up off-site), Syncthing as the largest catalog gap (25.9 %). Tables: `TABLE.md`; method and limits: `METHOD.md`. | **WAITING-ON-OPERATOR** — filed 2026-10-12 | the operator's reading | Operator: rule on each of the ten (yes / no / later). If nothing is done: nothing changes; the research ages (the 2026 survey replaces it) | operator | ## Process & tooling — 19 rows (P3 6, P4 13)