cloudflare-access — the front door for every internal app (Zero Trust free plan)¶
Team embeddedera (auth domain embeddedera.cloudflareaccess.com). One login method: Google,
IdP named "EmbeddedEra Workspace" (OAuth client "Cloudflare Access" in GCP project embeddedera,
consent Internal → only @embeddedera.com accounts). One allow policy, copied onto every app:
adiaz@embeddedera.com, angelgdo7@gmail.com, yrosado@embeddedera.com. Onboarding never edits a gate by hand: onboard access-sync reconciles every gate to
people.yml × the department access: tokens (hourly cron, daily drift alert to ntfy), and
onboard access-app creates a new gate with its allow list built from the registry. A saved policy
template once re-admitted a removed address on a new gate — that is why templates are banned and
reconciliation exists. API note: PATCH returns 10405 for tokens; GET the policy, edit, PUT it whole.
Home screen¶
https://home.embeddedera.com is served by assistant.service on 127.0.0.1:8200 through the
plex tunnel. Source is ~/assistant/home.py plus ~/assistant/static/home.html and home.js;
deploy through the assistant sandbox branch, tests, promotion to main, and service restart. The old
embeddedera-home Pages project remains only as legacy preview history and is not the live custom-domain origin.
Tiles come from the department registry and include ERP, SOPs, Password vault, NAS/file browser,
Website, and Reporting. Reporting opens https://reports.embeddedera.com/ directly.
The data-driven overview links to stable Management and Quality paths and is the single place for
adding future report areas.
The NAS tile links to
http://files.lan (Filebrowser, LAN only) and the page carries copy-to-clipboard SMB paths
(smb://192.168.5.15/EmbeddedEra, \\192.168.5.15\EmbeddedEra, Storage-Snapshots read-only,
user angel) because browsers block smb:// links outright. Angel
rejected the Cloudflare App Launcher as the home screen on 2026-09-11 because the address bar
shows embeddedera.cloudflareaccess.com/#/Launcher (the launcher cannot live on our domain). The
launcher still exists at that address with the same tiles; it costs nothing.
Apps¶
| App | Domain | Backend | Notes |
|---|---|---|---|
| EmbeddedEra Store Development | dev.embeddedera.com/wp-admin* | tunnel plex → 127.0.0.1:8500 | Engineering registry token; public storefront remains outside Access; Google only |
| EmbeddedEra Store Login | dev.embeddedera.com/wp-login.php | tunnel plex → 127.0.0.1:8500 | Engineering registry token; hidden from launcher; Google only |
| EmbeddedEra ERP | erp.embeddedera.com | tunnel plex → 127.0.0.1:8100 |
header SSO into InvenTree, see inventree |
| EmbeddedEra SOPs | sop.embeddedera.com | Pages embeddedera-sop |
+ a second app gating *.embeddedera-sop.pages.dev previews |
| EmbeddedEra Engineering | engineering.embeddedera.com | Pages embeddedera-engineering |
Engineering + Administration; pages.dev previews also gated. Challenges and registry sync verified 2026-09-18; deployment/recovery: engineering-portal-handoff |
| EmbeddedEra Assistant | chat.embeddedera.com | tunnel → 127.0.0.1:8200 | same policy; the service then checks departments |
| Oddly Fitting Goods Office | oddly.embeddedera.com | tunnel plex → 127.0.0.1:8200 (assistant.service; host middleware maps / → /shop) | owner only (admin token); Etsy-shop pixel office; its AUD is the 4th entry of CF_ACCESS_AUD in ~/.config/assistant/env; every route also requires admin in the app |
| EmbeddedEra Admin | admin.embeddedera.com | tunnel → 127.0.0.1:8200 (same service, /admin) |
owner addresses only at the gate, plus the Administration department in the service |
| EmbeddedEra Reports | reports.embeddedera.com | tunnel → 127.0.0.1:3002 (Metabase overview/proxy) | canonical reporting site, see metabase |
| EmbeddedEra Sandbox ERP | sandbox.embeddedera.com | tunnel → 127.0.0.1:8300 | disposable copy; also sandbox.lan with password login as break-glass |
| EmbeddedEra Sandbox Assistant | chat-sandbox.embeddedera.com | tunnel → 172.18.0.1:8201 | production-touching actions refused by the service |
| The Real Cow | therealcow.embeddedera.com (+ a second app gating therealcow.pages.dev and *.therealcow.pages.dev) |
Pages therealcow, deployed by ~/.local/bin/therealcow-deploy [branch] |
not governed by access-sync: any @embeddedera.com (Google) + Access group "The Real Cow distributors" (one-time PIN), edited only by ~/.local/bin/therealcow-access; session 720h; /activity has its own owner-only gate 'The Real Cow Activity (owner only)'; activity log in D1 therealcow-activity; SOP-047 |
| App Launcher | embeddedera.cloudflareaccess.com | — | same policy |
Login page design (logo, colors, footer) and the org name are set with
PUT /accounts/{id}/access/organizations; token permission Access: Organizations, Identity
Providers, and Groups · Edit was added for it. Session 24 h. Instant redirect to Google
(auto_redirect_to_identity) was tried and rejected as disorienting — keep the branded page.
Guests (2026-09-12). Outside addresses can be invited to the sandbox only: onboard guest. One-time PIN is enabled on the two sandbox apps exclusively — every production gate still admits Google/@embeddedera.com alone. Invitations carry an expiry in people.yml; the hourly access-sync removes them when they lapse.
2026-09-19: Store development gate created with onboard access-app, registry-derived engineering allow list (currently adiaz@embeddedera.com). Added its name to APP_NAME_BY_TOKEN[engineering] in ~/.local/bin/onboard for hourly reconciliation. Gate created before DNS; anonymous storefront and admin redirect to Access, origin returns HTTPS canonical links and sandbox banner.
2026-09-20: Public review superseded the hostname-wide store gate. Existing EmbeddedEra Store Development app was narrowed to /wp-admin*; new hidden EmbeddedEra Store Login app protects /wp-login.php. Both remain governed by APP_NAME_BY_TOKEN[engineering] and access-sync reports both in sync. The public application itself enforces read-only/no-index behavior; the Tunnel, proxied DNS and loopback origin are unchanged.
2026-09-21: Added /reporting/ to the live Assistant-backed Home service as the stable reporting
hub. The Home Reports tile now opens it; Management, Quality and Technical report cards retain their
existing Access gates. An initial Pages deployment did not affect the live hostname; production
commit 4c76f3c corrected the serving target and added a route regression test.
2026-09-21: Consolidated published reporting at reports.embeddedera.com. The Reports Access app now
routes to the Metabase proxy on port 3002; Home points directly to it. The retired management hostname, its Access application, DNS record and tunnel
ingress were removed on 2026-09-22. Grafana stays
healthy on loopback port 3000 without a public tunnel route.
2026-10-21: Zone embeddedera.com has one WAF custom rule (block): paths /xmlrpc.php, /.env, /.git/, wp-config, /wp-content/debug.log. Store 504s with user agent nginx-ssl early hints are Cloudflare's own Early Hints fetches (origin status 0), not an outage.
2026-09-22: Added EmbeddedEra Android at android.embeddedera.com, Administration
registry token (owner only), created with onboard access-app before DNS/ingress.
Origin is the temporary localhost:6089 browser login session, off when idle.
Tunnel ingress requires Access JWT validation; origin independently verifies it.
App is included in APP_NAME_BY_TOKEN[admin] for hourly reconciliation. See
story-android and SOP-041. No existing ingress or email DNS records changed.
2026-09-27: Added Oddly Fitting Goods Office at oddly.embeddedera.com with onboard access-app --token admin (owner only), before any DNS or ingress; added to APP_NAME_BY_TOKEN[admin]; access-sync reports it in sync. DNS + tunnel ingress follow when the office ships. See ../../../projects/etsy-shop.
2026-09-27: oddly.embeddedera.com went live: office merged (assistant PR #16), its Access AUD added to CF_ACCESS_AUD, assistant.service restarted, cf-host add oddly.embeddedera.com http://127.0.0.1:8200 --yes (ingress + proxied CNAME). SOP-019 checks: no-session fetch of / and /api/state → 302 to the Access sign-in; access-sync 20 apps in sync; surfaces-check all pass.
2026-09-27 gotcha: a new hostname can look dead on the home LAN for up to 30 min because Pi-hole caches the NXDOMAIN from any lookup made before cf-host created the CNAME (SOA minimum 1800 s). After cf-host add, run docker exec pihole pihole reloaddns; phones may also need Wi-Fi toggled.
2026-09-27: Added EmbeddedEra HQ gate at hq.embeddedera.com (onboard access-app --token admin, owner only, app 32c0a976…) before any DNS/ingress; added to APP_NAME_BY_TOKEN[admin]; access-sync in sync. DNS + tunnel + its AUD in CF_ACCESS_AUD follow at deploy (same steps as oddly).
2026-09-27: hq.embeddedera.com live: HQ merged (assistant PR #32), AUD added (5th entry of CF_ACCESS_AUD), cf-host add hq.embeddedera.com http://127.0.0.1:8200, Pi-hole cache flushed right after (the NXDOMAIN gotcha). SOP-019 checks: no-session / and /api/state → 302 to Access; access-sync 21 in sync; surfaces-check pass. Home tiles for HQ and Oddly added (PR #33, departments.yml admin_work).
2026-10-27: cloudflared upgraded 2026.7.2 → 2026.10.4 (Cloudflare "Action Required": eMudhra intermediate CA compromise, fix needs ≥2026.10.2). Binary ~/.local/bin/cloudflared from the GitHub release, SHA-256 checked against the release notes; old binary kept as cloudflared.2026.7.2.bak. In-place swap + systemctl --user restart cloudflared-plex (~1 s gap); 4 connections re-registered, erp/home/reports/chat → 302 to Access. All ingress origins are plain http://, so the stricter origin cert check cannot bite. --no-autoupdate means upgrades are manual: watch Cloudflare security mail.