admin a08bd3cbd5
gates / gates (push) Failing after 5m29s
architecture: the system poster committed, its facts given a home, and a rule to keep them together
PART A -- the poster. documentation/architecture/felhom-system-poster.html
(307 KB). Secret scan first: ZERO IPv4, zero PEM blocks, zero ssh keys, zero
Bearer. The one EAA... match is base64 inside an embedded "mime":"font/woff2"
blob, not a Facebook token. "token"/"secret"/"password" appear 11 times and
every one is a NAME ("6. ep0 read token", "the hub seal key"); the poster
itself says "Names only; no secret values". All five long base64 blobs are
declared assets: 1 image/png, 3 text/javascript, 1 font/woff2.

It renders with NO network: the source mentions cdn.jsdelivr.net and Google
Fonts, but the loaded requests are only the HTML plus blob:/data: URLs -- the
bundler inlined everything. Measured, not assumed, and it matters: this is a
disaster-recovery document, so needing the internet to draw would be a defect.
No console errors.

The operator's three Claude Design fixes are all present: (a) no "WG" badge,
WireGuard only for the tunnel, no badge on the ep0-copy tile; (b) the box ->
ep0 arrow reads "encrypted on the box, sent through WireGuard"; (c) "Known
gaps" holds two items and NOT the household-keys sentence, which is now a
neutral "By design" note under the ep0 household namespace.

ONE FACT ON IT WAS WRONG. The felhom.eu tile said "served from DooPlex through
Cloudflare". It is not: Cloudflare is DNS only and the traffic goes direct --
measured this morning for the privacy notice, which states exactly that. The
poster would have contradicted a published page. Fixed in place (a label):
"served from DooPlex, Cloudflare DNS only". The first wording overflowed the
fixed-size tile, so it was shortened to fit and the evidence lives in the
facts file instead -- checked by re-rendering, not by hoping.

PART B -- the facts and the rule. DESIGN-PROMPT-...md is renamed
felhom-system-poster.facts.md (one home per fact), with the three fixes folded
in as explicit instructions so a regeneration cannot undo them, plus a new
"Badges" section saying a "WG" chip must never come back.

New rule, section 6 "The system poster stays true", added IDENTICALLY to all
five copies of unprompted-work.md (the four repos and the workspace root on
DooPlex; verified identical by diff before and after) and to
PROMPT-TEMPLATE.md's end-of-session checklist as a FIFTH coupled artifact.

scripts/poster_facts_gate.py WARNS when the facts file has a newer commit than
the poster. It never fails a push, deliberately: a refresh needs Claude Design
and the operator, --no-verify is forbidden here, so a blocking gate would leave
deleting it as the only way out. It compares COMMIT times, not mtimes, because
a checkout rewrites mtimes and every fresh clone would shout.

RED-PROOF -- and it found a real bug in the gate. The first run warned
correctly but exited 1: a single non-ASCII character in its own warning raised
UnicodeEncodeError on this cp1250 console. A gate whose entire contract is
"never fails a push" was failing pushes. Fixed (ASCII output + an encode
guard), and the decoy now asserts BOTH the warning and exit 0. Three branches
proven: facts newer -> warns, rc 0; poster newer -> quiet, rc 0; poster
missing -> "could not tell", rc 2, not a false all-clear.

The decoy itself was seen to fail, twice, on Linux (the suite needs fcntl and
cannot run on Windows): breaking the warning gives STALE_WARNS=False, and
making it exit 1 gives RC_STALE=1. All 80 felhom.eu decoys behave.

PART C -- do box reports pass through Cloudflare? NO. Two channels. DNS from
PUBLIC resolvers (not DooPlex's own, which answers the LAN address):
hub.felhom.eu is a CNAME to dooplex.hopto.org -> 37.191.56.193, not a
Cloudflare address, and no cf-ray comes back. The manifest: an ordinary k3s
Ingress, Cloudflare named only in a DNS setup comment. THE CONTROL that makes
the negative mean something: iso.felhom.eu resolves to 172.67.x / 104.21.x,
real Cloudflare addresses -- so the method does detect proxying.

So nothing is added to the Cloudflare row: the hub path does not touch it.
06-offsite-connectivity.md section 1 claimed the public edge is a
Cloudflare-Tunnel and "DooPlex has no public IP" -- both untrue today. Kept
and marked STALE with the measurement rather than rewritten, because that
paragraph is the reason ep0 exists and the argument needs its premise visible.
total-loss-of-dooplex.md's "today a CNAME to dooplex.hopto.org" is confirmed
correct.

Register: 137 before, 137 after, 0 opened, 0 closed -- every finding here was
small and fixed in the session.
2026-10-09 18:09:50 +02:00
…

felhom.eu

Website, manifests, and infrastructure for Felhőm.eu — a managed home-server service for Hungarian households.

Overview

This repository contains:

  • Website (website/) — Static HTML pages served at felhom.eu
  • Kubernetes manifests (manifests/) — All k3s deployments for the felhom.eu ecosystem
  • Assets (website/assets/) — Logo, images, OG images

The website runs on a single-node k3s cluster alongside the rest of the Felhőm management infrastructure (Healthchecks, Umami analytics, contact mailer).

Branding

Aspect Value
Brand name Felhőm.eu (with accent: ő)
Domain felhom.eu (without accent — domain limitation)
Tagline „Saját felhőd, saját szabályaid"
Controller product Felhő Felügyelő (customer-facing name)
Controller code name felhom-controller (backend/repo/container)
Language Hungarian throughout all customer-facing content
Contact email info@felhom.eu
Admin email admin@felhom.eu

Why "Felhőm"?

"Felhő" means "cloud" in Hungarian. The "m" suffix makes it possessive — "my cloud" (felhőm). The .eu domain is part of the brand identity and appears in the logo. The double meaning of "felhő" (tech cloud + weather cloud) is intentional and used in product naming (e.g., Felhő Felügyelő = "Cloud Supervisor/Inspector").

Website Pages

File URL Purpose
index.html / Landing page — hero, services, app preview, backup intro, contact
alkalmazasok.html /alkalmazasok Full application catalog (45+ apps with categories)
technologiak.html /technologiak Technology stack explanation (Docker, Felhő Felügyelő, Proxmox, Kubernetes)
biztonsagimentes.html /biztonsagimentes Backup strategy — 3-2-1 rule, monitoring, restore procedures
gyik.html /gyik FAQ — structured Q&A with JSON-LD schema
kapcsolat.html /kapcsolat Contact form + email, sends via contact-mailer API
szolgaltatasok-nonpublic.html /szolgaltatasok-nonpublic Pricing/services page (not linked in nav, robots disallowed)

All pages use:

  • Clean URLs — nginx serves .html files without extension (/gyik → gyik.html)
  • Unified CSS — each page contains the full CSS (no external stylesheet, for simplicity)
  • Responsive design — mobile hamburger menu, responsive grids
  • UTF-8 with BOM — all HTML files are saved as UTF-8-BOM for Hungarian character support
  • Umami analytics — privacy-friendly tracking script on every page

Infrastructure

Architecture

Internet
    │
    ▼
Cloudflare (DNS only, no proxy)
    │
    ▼ CNAME → dooplex.hopto.org
    │
Home network (dynamic IP via No-IP DynDNS)
    │
    ▼ Port forward 80/443
    │
k3s cluster (single node)
    ├── nginx-ingress (TLS termination via cert-manager + Let's Encrypt)
    │
    ├── felhom-system namespace:
    │   ├── felhom-webpage    (nginx + git-sync sidecar)
    │   ├── filebrowser       (files.felhom.eu — website file management)
    │   ├── contact-mailer    (Go app — /api/contact endpoint)
    │   ├── umami + umami-db  (stats.felhom.eu — web analytics)
    │   └── healthchecks      (status.felhom.eu — monitoring)
    │
    └── cert-manager (letsencrypt-prod cluster issuer)

Kubernetes Manifests

Manifest Services Subdomains
webpage.yaml nginx (website), FileBrowser, git-sync felhom.eu, www.felhom.eu, files.felhom.eu
contact-mailer.yaml Go HTTP server for contact form felhom.eu/api/* (path-based routing)
umami.yaml Umami v3 + PostgreSQL stats.felhom.eu
healthchecks.yaml Healthchecks status.felhom.eu

Website Deployment

The website uses a git-sync sidecar pattern:

  1. git-sync container polls this repository (sparse checkout: /website/ only)
  2. Syncs to a shared emptyDir volume
  3. nginx container serves from the synced content
  4. Changes pushed to this repo are live within minutes (no manual deployment)

FileBrowser at files.felhom.eu provides a web UI for quick edits to website files (emergency fixes, asset uploads) without needing git. It writes to a Longhorn PVC that the website nginx also reads from.

Storage

All persistent data uses Longhorn distributed storage:

  • filebrowser-files (1Gi, ReadWriteMany) — website files
  • filebrowser-db (100Mi) — FileBrowser SQLite database
  • umami-db-data (2Gi) — Umami PostgreSQL data
  • healthchecks-data (1Gi) — Healthchecks SQLite data

DNS Configuration (Cloudflare)

Domain: felhom.eu — Cloudflare DNS (free plan), DNS only mode (no proxy/orange cloud).

Records

Type Name Content Notes
CNAME felhom.eu dooplex.hopto.org Main website
CNAME www dooplex.hopto.org www redirect
CNAME files dooplex.hopto.org FileBrowser
CNAME stats dooplex.hopto.org Umami analytics
CNAME status dooplex.hopto.org Healthchecks
CNAME ntfy dooplex.hopto.org Push notifications
MX felhom.eu route{1,2,3}.mx.cloudflare.net Incoming email → Cloudflare Email Routing
MX send feedback-smtp.eu-west-1.amazonses.com Resend sending domain
TXT felhom.eu v=spf1 include:_spf.mx.clo... SPF for Cloudflare
TXT send v=spf1 include:amazonses... SPF for Resend
TXT cf2024-1._domainkey DKIM for Cloudflare Email Routing
TXT resend._domainkey DKIM for Resend
TXT _dmarc v=DMARC1; p=none; DMARC policy
TXT felhom.eu google-site-verification=... Google Search Console

Email

Incoming Email

Cloudflare Email Routing (free) handles all incoming mail:

  • info@felhom.eu → forwarded to personal Gmail
  • admin@felhom.eu → forwarded to personal Gmail
  • Catch-all → not configured

Outgoing Email (Transactional)

Resend (free tier) handles outgoing email via API:

  • Contact form submissions → sends formatted email to info@felhom.eu
  • Healthchecks alerts → sends to admin@felhom.eu
  • Sending domain: send.felhom.eu (verified with SPF, DKIM)
  • From address: Felhom.eu <info@felhom.eu>

Contact Form Flow

  1. User fills form on /kapcsolat
  2. JavaScript POST to /api/contact
  3. contact-mailer (Go, in k3s) validates + calls Resend API
  4. Email delivered to info@felhom.eu via Resend → Cloudflare Email Routing → Gmail

SEO

Google Search Console

  • Property: https://felhom.eu
  • Verified via DNS TXT record
  • Sitemap submitted: https://felhom.eu/sitemap.xml
  • 7 pages indexed (all public pages)

On-Page SEO

Every page includes:

  • <title> with Hungarian keywords + brand
  • <meta name="description"> with unique content per page
  • <meta name="keywords"> with relevant Hungarian terms
  • <link rel="canonical"> to prevent duplicate content
  • Open Graph tags (og:title, og:description, og:image, og:locale=hu_HU)
  • Twitter Card tags (summary_large_image)
  • JSON-LD structured data (LocalBusiness on index, Article on technologiak, FAQPage on gyik)

Technical SEO

  • robots.txt — allows all, disallows /szolgaltatasok-nonpublic, includes sitemap URL
  • sitemap.xml — lists all 6 public pages with priority + changefreq
  • Clean URLs (no .html extensions)
  • Static asset caching (7 day expiry for CSS/JS/images)
  • Security headers (X-Frame-Options, X-Content-Type-Options)

Analytics

Umami v3 (self-hosted, privacy-focused):

  • Dashboard: https://stats.felhom.eu
  • Tracking script: <script defer src="https://stats.felhom.eu/script.js" data-website-id="d419db57-...">
  • Cookie-free, GDPR compliant — no consent banner needed
  • Backend: dedicated PostgreSQL instance in k3s

Monitoring

Healthchecks (self-hosted):

  • Dashboard: https://status.felhom.eu
  • Monitors backup jobs, service health
  • Sends email alerts via Resend when checks fail

Development Workflow

Quick content edits

  1. Log into FileBrowser at https://files.felhom.eu
  2. Edit HTML files directly
  3. Changes are live immediately

Standard workflow

  1. Clone this repo from Gitea (gitea.dooplex.hu)
  2. Edit files locally
  3. Push to main branch
  4. git-sync sidecar picks up changes automatically (~1-2 min)

Adding a new page

  1. Create website/newpage.html (copy structure from existing page)
  2. Add to navigation in all pages' <nav> section
  3. Add to sitemap.xml with appropriate priority
  4. Push — clean URLs handle /newpage automatically
Repository Purpose
app-catalog-felhom.eu Docker Compose templates + .felhom.yml metadata for 45+ apps
felhom-controller felhom-controller Go app + customer deploy scripts
deploy-portainer Legacy — Portainer-based deploy scripts (deprecated)
homelab-manifests k3s cluster manifests for dooplex.hu services
misc-scripts Utility scripts (collect-repos.sh, etc.)

File Encoding

All HTML files in website/ are UTF-8 with BOM (byte order mark). This ensures proper Hungarian character rendering (á, é, í, ó, ö, ő, ú, ü, ű) across all tools and platforms. The BOM is the 3-byte sequence EF BB BF at the start of each file.

When editing files, ensure your editor preserves UTF-8-BOM encoding. VS Code: check "UTF-8 with BOM" in the bottom status bar.

S
Description
No description provided
Readme 174 MiB
Languages
Go 56.9%
HTML 18.8%
Python 13.5%
Shell 8.6%
CSS 2%
Other 0.2%