R-403 MIRROR GUARD - PASS, forced after the natural test evaporated. privatebin was injected hollow at 23:34 to meet the 03:30 mirror; the 02:30 db-dump re-made its tar, so by 03:30 the primary was complete and the guard had nothing to refuse. Forced instead on calibre-web through the real Tier-2 path: the guard fired and named itself - "unit leg SKIPPED ... The copy was PRESERVED rather than replaced with an empty one (R-403). The other legs continue." Secondary byte-identical, 23 files, tar sha d7e7f422. R-412 CORRECTED, AND I OVERSTATED IT WHEN I FILED IT. The first wording claimed the hollow unit sits in the store for a whole cycle because the volume-dump leg runs only on the backup schedule. That is WRONG. The 04:15 off-site run has its OWN pre-push dump leg - "Stopping calibre-web for safe volume dump", "Volume dump: ... -> 877.5 KB" - so a unit that is hollow when a run starts is REPAIRED before it is pushed. Measured twice: opengist and calibre-web both went in hollow and came out complete, and the snapshot pulled back from the store (6fee3b5a) holds the volume tar and all 17 userdata files. What remains real is narrower: the one hollow snapshot that DID reach the store was created when the unit was destroyed INSIDE a run that had already completed that app's dump leg. The race is real and was observed, and "backed up opengist (... 0 mandatory path(s))" is a success line over a backup holding none of the app's data either way. Severity HIGH -> LOW, with the correction stated in the row rather than quietly rewritten. Phase 6 interim: the observer is clean so far - db-dump 674ms, tier2-backup 3ms (a no-op, cause to be established not assumed), zero ERROR/WARN since 23:00. Also recorded: two of Phase 5's four injections were NOT performed, with the reasons established rather than asserted - there is no endpoint that reaches SetDisconnected and a hand-set flag would be reverted by the live monitor before 04:15; and a corrupted manifest provably never reaches the store because the capture rewrites it first.
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
.htmlfiles 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:
git-synccontainer polls this repository (sparse checkout:/website/only)- Syncs to a shared
emptyDirvolume nginxcontainer serves from the synced content- 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 filesfilebrowser-db(100Mi) — FileBrowser SQLite databaseumami-db-data(2Gi) — Umami PostgreSQL datahealthchecks-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 |
Incoming Email
Cloudflare Email Routing (free) handles all incoming mail:
info@felhom.eu→ forwarded to personal Gmailadmin@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
- User fills form on
/kapcsolat - JavaScript POST to
/api/contact contact-mailer(Go, in k3s) validates + calls Resend API- Email delivered to
info@felhom.euvia 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 URLsitemap.xml— lists all 6 public pages with priority + changefreq- Clean URLs (no
.htmlextensions) - 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
- Log into FileBrowser at
https://files.felhom.eu - Edit HTML files directly
- Changes are live immediately
Standard workflow
- Clone this repo from Gitea (
gitea.dooplex.hu) - Edit files locally
- Push to
mainbranch git-syncsidecar picks up changes automatically (~1-2 min)
Adding a new page
- Create
website/newpage.html(copy structure from existing page) - Add to navigation in all pages'
<nav>section - Add to
sitemap.xmlwith appropriate priority - Push — clean URLs handle
/newpageautomatically
Related Repositories
| 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.