Boring, proven building blocks — arranged for resilience.
Browser (Turbo Drive · nonce-based CSP · per-tab product header) │ HTTPS nginx edge — TLS · gzip · static cache │ Gunicorn (4 workers × 8 threads) ─── Flask app factory │ │ │ PostgreSQL Redis Scheduler sidecar (systemd) source of truth rate-limit + cron catalog: syncs, backups, + device cache shared cache cert scans, upgrade runbooks │ Streaming replica (TLS, mutual-CA) ──▶ standby node
Every appliance is harvested, normalized, cached and versioned through one shared pipeline.
FortiWeb / FortiADC / FortiAnalyzer
REST or JSON-RPC, SSH fallback
Canonical shape per device kind
Device store — DB-first reads
reports/<device>/_config.json
The REST/JSON-RPC endpoint map lives in a database registry, so a firmware upgrade that moves a URI is fixed from the UI — no redeploy.
Two-node active/standby clustering is built into the installer — not bolted on.
PostgreSQL streaming replication with enforced TLS and mutual certificate authentication; application data rsynced to the standby every 5 minutes with role guards, so a promoted standby never overwrites the primary.
The primary generates a single join key at install time; paste it on the secondary and replication, shared secrets and node certificates configure themselves. Each node mints its own leaf certificate locally.
Live database, portable backup bundles, git-versioned device configs and an external SFTP backup server — four independent copies across failure domains, summarized in a live coverage matrix.
Every internal channel is encrypted, and the app proves it with live probes — not assumptions.
The primary node operates a built-in certificate authority. Node certificates are issued, renewed nightly, and rolled back automatically if an import breaks the web front.
Replication and application connections run over TLS with mutual certificate verification — plain or cert-less connections are refused, and the policy (minimum protocol, ciphers) is tunable from the UI.
Node-to-node health checks ride HTTPS and carry a shared identity key, so each node can trust — and render — the other's state without SSH access.
A monitoring page shows one card per channel — app↔app, app↔DB, replication, git — with protocol, cipher, enforcement and authentication, each badge backed by a real probe.
Every write path lands in the audit log; risky operations go through Change Requests with maintenance-window approval gates.
Appliance credentials and integration secrets are Fernet-encrypted in the database; API tokens are scoped, owner-capped and product-bound.