Mobile Operator Console
A mobile companion app for iGaming SREs and compliance ops — built on Cloudflare Access, OpenBao SSH CA, and YubiKey 5 NFC. Zero Teleport licences, zero new critical-path services, and a GLI-33 / SIGAP / LGPD audit trail that lands in Wazuh.
The Problem
On-call at 03:00 from a phone is a reality for every iGaming SRE. The dashboard works. But when a payment provider throws 502s mid-tournament, or a geofence trips on a cruise-ship IP block, the operator still needs a real shell — not just a status page. SSH from a laptop at a petrol station with a YubiKey hanging off a keyring is not a workflow; it is a liability.
At the same time, regulators do not care about your operational romance. SIGAP (Brazil), GLI-33, MGA Class 4, UKGC LCCP and LGPD all ask the same three questions: who authenticated, with what factor, and what did they do? Any mobile console that cannot answer those three questions in a forensic log is a compliance liability, not an asset.
The naive answer is to buy Teleport and move on. That answer is wrong at our scale (1–5 operators, ≤ 3 SSH targets) because it introduces a new critical-path dependency, a new per-user licence, and duplicates capabilities we already run. The architecture on this page is the answer we actually chose.
The App, Five Screens
Built with Expo (React Native) — same TypeScript codebase ships to iOS and Android. Screens captured on iPhone 17 (iOS 26 simulator). Each tab pulls live data from /api/v2/dash/* on new.acmetocasino.com behind Cloudflare Access; SSH actions go through the OpenBao SSH CA flow described below. Hostnames in the Terminal tab are redacted.


/incidents/list feed with severity filters and SLA countdowns.
/proc/stat delta, DB pool bar, Redis & Kafka health.

Decision Matrix: Cloudflare Access vs Teleport
Ten weighted criteria, scored 1 (poor) to 5 (excellent), against the five credible paths: Teleport (spec default), Cloudflare Access + OpenBao SSH CA (winner), OpenBao + VPN, Tailscale, and "mobile-responsive web only".
| Criterion | Weight | Teleport | CF + OpenBao | OpenBao + VPN | Tailscale | Mobile web |
|---|---|---|---|---|---|---|
| Security posture (FIDO2 + mTLS + short-lived) | 5 | 5 | 5 | 4 | 3 | 3 |
| Operational complexity (services to keep alive) | 4 | 2 | 4 | 4 | 4 | 5 |
| Compliance fit (GLI-33, MGA, SIGAP) | 5 | 5 | 4 | 4 | 3 | 4 |
| Team-size fit (1–5 operators) | 4 | 2 | 5 | 5 | 5 | 5 |
| Vendor lock-in | 3 | 2 | 3 | 5 | 3 | 5 |
| Cost (licence + infra + effort) | 4 | 2 | 5 | 5 | 4 | 5 |
| Mobile UX (terminal, push, biometric) | 4 | 5 | 4 | 3 | 4 | 3 |
| Time-to-first-release | 4 | 2 | 5 | 4 | 4 | 5 |
| Fits existing chapters (20, 20b, 24h) | 2 | 3 | 5 | 5 | 2 | 3 |
| Lock-out / single-point-of-failure exposure | 4 | 2 | 3 | 5 | 3 | 4 |
| Weighted total | 140 | 176 | 167 | 131 | 159 |
Option B wins on total score and on every "services to keep alive" and "time-to-release" criterion that matters at small team size.
Architecture
Everything in the diagram below is either (a) already running or (b) a small addition to an existing component. No new control-plane service is introduced.
Mobile Client · iOS 16+ / Android 13+
XTerm.js terminal embedded in a hardened WebView.
Device-bound passkey; private keys never leave the secure element.
FIDO2 roaming authenticator via NFC tap for phishing-resistant step-up.
Cloudflare Edge · Zero Trust gate
Policy engine in front of every origin. Deny-by-default.
- → OIDC via Google Workspace SSO
- → FIDO2 hardware-key policy (YubiKey required)
- → Device posture (OS version + mTLS client cert)
api.example.com → Cloudflare Worker → PROD origin
ssh.example.com → Cloudflare Tunnel → LAN
On-Prem LAN · Ops VLAN
- • SSH CA (15m short-lived certs)
- • PKI mobile role
- • HSM-sealed at rest
PKCS#11 · root signing · seal wrap
TrustedUserCAKeys verifies OpenBao-signed certs. Prod bastion on Ops VLAN.
auth.log + sshd session + auditd · Cloudflare Logpush (Access events).
Three-Layer Auth Flow
The spec as written listed five auth layers. Three is enough to satisfy OWASP MASVS-AUTH-1/2 and GLI-33, and each layer defends a different threat model.
1 · Passkey
Biometric-unlocked Passkey bound to Secure Enclave / StrongBox via expo-passkeys. Defends against stolen phone + weak screen lock. Never leaves the TEE.
2 · YubiKey + CF Access
Cloudflare Access enforces a FIDO2 hardware-key policy. NFC tap with YubiKey 5 NFC produces a signed assertion; Google Workspace SSO supplies identity. Result: an 8h CF_Authorization JWT.
3 · OpenBao SSH Cert
For privileged ops (SSH, drain, payout approve) the JWT is exchanged at OpenBao for a 15-minute SSH certificate signed by the SSH CA. Each target sshd trusts only that CA — no per-key authorized_keys.
Cloudflare API Token — Exact Scopes
Create one API token, used by the mobile backend Worker and by the deploy pipeline. Five permissions, no more:
| Scope | Why |
|---|---|
| Account.Access: Apps and Policies — Edit | Create / update Access applications for api and ssh hostnames. |
| Account.Cloudflare Tunnel — Edit | Create and rotate tunnel credentials for cloudflared on the ops host. |
| Zone.DNS — Edit | Manage CNAME records that point to the tunnel hostname. |
| Zone.Zone — Read | Look up zone id at deploy time. |
| Account.Workers Scripts — Edit | Deploy the mobile API gateway Worker. |
Implementation Highlights
Five code snippets that carry the design. All tokens, IDs and hostnames are placeholders: replace with your own before running.
OpenBao SSH CA bootstrap
sshd configuration on targets
Cloudflare Access application (Terraform)
cloudflared on the ops host
Mobile client — JWT → SSH cert exchange
Compliance Mapping
What each regulator asks for, and which piece of the stack answers it.
| Regime | Control | Answered by |
|---|---|---|
| SIGAP (Brazil) | Privileged access authentication & session record | CF Access FIDO2 log + Wazuh sshd session log |
| GLI-33 | Named operator, hardware-backed factor, audit trail | Google SSO identity + YubiKey + Wazuh |
| LGPD | Who accessed PII, when, purpose | CF Logpush to Wazuh + application-level audit on /api/v2/* |
| MGA Class 4 | Key custody & short-lived credentials | OpenBao SSH CA (15m TTL) sealed by YubiHSM 2 |
| UKGC LCCP | Separation of duties, least privilege | CF Access policies per application + OpenBao roles |
| OWASP MASVS | AUTH-1/2, NETWORK-1/2, STORAGE-1 | Passkey + mTLS + cert pinning + MMKV encrypted store |
Cost Comparison
Back-of-envelope annualised cost for a 5-operator team. "Verify with vendor" applies to every third-party number below — these are the right order of magnitude, not current quotes.
| Line item | CF + OpenBao | Teleport (Team tier) |
|---|---|---|
| Control-plane licences | $0 — CF Zero Trust free ≤ 50 seats | Per-user per month (verify with vendor) |
| Self-hosted services | OpenBao already running | Auth + Proxy + agents + Device Trust |
| YubiKey 5 NFC × 5 | ~$275 one-off | ~$275 one-off |
| Mobile app (Expo EAS) | $99/mo team | $99/mo team |
| Engineering time (setup) | 10–14 person-days | 15–20 person-days + ongoing upgrades |
| Migration cost if abandoned | Low — OpenBao and CF are open standards | High — RBAC + recordings live in Teleport |
Stack Summary
YubiKey 5 NFC · YubiHSM 2 · iPhone Secure Enclave / Android StrongBox
Cloudflare Access · Google Workspace SSO · OpenBao (SSH CA + PKI) · cloudflared
React Native · Expo SDK 51 · TypeScript · Zustand · TanStack Query · XTerm.js · MMKV
Wazuh SIEM · Cloudflare Logpush · sshd session log · auditd
Cloudflare Workers (mobile API) · Cloudflare Tunnel · Cloudflare WAF
Expo Push → FCM + APNs · critical-alert bypass for incident channels
Read the Full Chapter
This page is a condensed architecture brief. The full decision, gap analysis, phased rollout, risk register and runbooks live in the book.