Platform Telemetry & Analytics Architecture (Phase 1)
Status: Phase 1 Complete (Infrastructure, Security, and Provisioning)
Last Updated: 2026-10-14
Backend Endpoint (Dev):https://analytics-dev.dotevolve.net
Backend Endpoint (Prod):https://analytics.dotevolve.net
1. Executive Summary
DotEvolve utilizes self-hosted Umami Analytics v2 to provide high-performance, privacy-first, cookieless telemetry across all platform services and marketing applications (Floorix, Govnix, Perfxcel, and DotPortal).
Phase 1 establishes the core infrastructure, multi-region secret management, automated provisioning, and disaster recovery:
1. Containerized Deployment: Umami v2 containerized on OCI compute instances (dev and prod), reverse-proxied via Nginx on port 3006.
2. Shared Database Topology: High-performance dedicated umami database residing inside the existing Supabase PostgreSQL container (supabase-db-dev / supabase-db-prod), avoiding container overhead.
3. Multi-Region OCI Vault Secrets: Ephemeral in-memory secret fetching across separate OCI Vaults (ap-mumbai-1 for Dev, ap-hyderabad-1 for Prod).
4. Two-Factor Authentication (2FA): Secured with 64-character AES-256 encryption keys (TWO_FACTOR_ENCRYPTION_KEY).
5. Catalog Provisioning: Pre-provisioned tracking Website IDs for all 11 applications and marketing websites with environment-aware domain routing.
6. Disaster Recovery: Daily automated compressed dumps shipped to Cloudflare R2 bucket dotevolve-analytics-backups.
7. Infrastructure Symlink Standard: Server /opt/dotevolve symlinks consolidated to point directly to /opt/dotevolve/repos/dot-infra.
2. Infrastructure Architecture & Topology
[ User Traffic & Clients ]
│
▼
┌───────────────────────────────────────┐
│ Cloudflare Edge Network │
│ (DNS, SSL/TLS, DDoS, WAF, Turnstile) │
└───────────────────┬───────────────────┘
│
┌───────────────────────┴───────────────────────┐
▼ ▼
┌──────────────────────────┐ ┌──────────────────────────┐
│ Development Server │ │ Production Server │
│ 161.118.170.25 │ │ 68.233.105.18 │
│ (ap-mumbai-1 OCI) │ │ (ap-hyderabad-1 OCI) │
├──────────────────────────┤ ├──────────────────────────┤
│ Nginx (:80, :443) │ │ Nginx (:80, :443) │
│ └─ analytics-dev.* │ │ └─ analytics.* │
│ │ proxy_pass │ │ │ proxy_pass │
│ ▼ │ │ ▼ │
│ dotevolve-umami (:3006) │ │ dotevolve-umami (:3006) │
│ │ PostgreSQL │ │ │ PostgreSQL │
│ ▼ │ │ ▼ │
│ supabase-db-dev (db: │ │ supabase-db-prod (db: │
│ umami) │ │ umami) │
└──────────────────────────┘ └──────────────────────────┘
2.1 Database Configuration
Umami connects directly to a dedicated umami database inside the existing Supabase PostgreSQL container rather than running a redundant database container:
- Connection string format:
postgresql://${UMAMI_DB_USER:-postgres}:${UMAMI_DB_PASSWORD}@${SUPABASE_DB_HOST:-supabase-db-dev}:5432/umami
umami
- Default Schema: public
- Tables: website, website_event, session, user, event_data, report, team, team_user.
2.2 Container Definition (docker-compose.umami.yml)
Located at dot-infra/docker-compose.umami.yml:
services:
umami:
image: ghcr.io/umami-software/umami:postgresql-latest
container_name: dotevolve-umami
restart: always
environment:
DATABASE_URL: postgresql://${UMAMI_DB_USER:-postgres}:${UMAMI_DB_PASSWORD:-${POSTGRES_PASSWORD}}@${SUPABASE_DB_HOST:-supabase-db-dev}:5432/umami
DATABASE_TYPE: postgresql
APP_SECRET: ${UMAMI_APP_SECRET:?UMAMI_APP_SECRET is required}
TWO_FACTOR_ENCRYPTION_KEY: ${TWO_FACTOR_ENCRYPTION_KEY}
PORT: "3000"
DISABLE_TELEMETRY: "1"
ports:
- "127.0.0.1:3006:3000"
healthcheck:
test: ["CMD", "wget", "-qO-", "http://127.0.0.1:3000/api/heartbeat"]
interval: 15s
timeout: 5s
retries: 5
start_period: 30s
networks:
- dotevolve-net
- supabase-net
3. Multi-Region OCI Vault Management
Secrets are managed via Oracle Cloud Infrastructure (OCI) Key Management & Vault Service. Dev and Prod operate in completely distinct OCI tenancies and geographical regions.
3.1 Vault Configuration Matrix
| Environment | OCI Region | Tenancy / Compartment OCID | Vault OCID | Master Encryption Key (MEK) OCID |
|---|---|---|---|---|
| Dev | ap-mumbai-1 |
ocid1.tenancy.oc1..aaaaaaaan6omrh3tidrk5q3nn7xgudt77bi76vj6v5g32fpcvhxxsrgh45ta |
ocid1.vault.oc1.ap-mumbai-1.fbvgjaqqaaavy.abrg6ljrk5ck7psktfowvfbjhg5web364w37weacl2pw5oqkzrptpcbxqcka |
ocid1.key.oc1.ap-mumbai-1.fbvgjaqqaaavy.abrg6ljrv7jm6kbekr57xrcx4xhrv6myhmuksxyasreugx5geycuav6kh2ea |
| Prod | ap-hyderabad-1 |
ocid1.tenancy.oc1..aaaaaaaai6vtxz3izayeqafcnbxt42vrx66eubjr2e4vhpvjsz6lrwa7clna |
ocid1.vault.oc1.ap-hyderabad-1.gfvgi66jaadvu.abuhsljr5bvqb3qj7cbvs5h6kwmnl33xe6mvums5z6i5j2ee5i52bmeqcxza |
ocid1.key.oc1.ap-hyderabad-1.gfvgi66jaadvu.abuhsljrnbl5drlboij7fciqb7zu7ntrsrkjl36yxmsea74puvjibwhbuyjq |
3.2 Umami Secret OCIDs
Development (oci_secrets_mapping.dev.env)
OCI_SECRET_ID_UMAMI_APP_SECRET="ocid1.vaultsecret.oc1.ap-mumbai-1.amaaaaaavlpmoriacfhh53gd35bc36pecyp422noargho6i2mqxks4fqkthq"
OCI_SECRET_ID_TWO_FACTOR_ENCRYPTION_KEY="ocid1.vaultsecret.oc1.ap-mumbai-1.amaaaaaavlpmoriakvc6ugbqqyaoxcisze5xu32wnxzg26qqw7ksbhswjukq"
OCI_SECRET_ID_UMAMI_DB_PASSWORD="ocid1.vaultsecret.oc1.ap-mumbai-1.amaaaaaavlpmoriadxqjfbeste7v2455lzwbwxcmostybhv6uqempw6clqaa"
Production (oci_secrets_mapping.prod.env)
OCI_SECRET_ID_UMAMI_APP_SECRET="ocid1.vaultsecret.oc1.ap-hyderabad-1.amaaaaaabdz4hmyavo2hk3iup6xyez3gux4s7lmpuk23u26lt2sx3lprenna"
OCI_SECRET_ID_TWO_FACTOR_ENCRYPTION_KEY="ocid1.vaultsecret.oc1.ap-hyderabad-1.amaaaaaabdz4hmyaxxyyhfoemiracz7vlqhxjsqd36tuh4cmziztcpj2ur6a"
OCI_SECRET_ID_UMAMI_DB_PASSWORD="ocid1.vaultsecret.oc1.ap-hyderabad-1.amaaaaaabdz4hmyar7dxpwo6bfdxa355cokd7hrhmwvhe3vlbcbwasu5iu5q"
3.3 Dynamic Ephemeral Secret Loading
At deployment time, secrets are never stored unencrypted on disk. The python helper scripts/fetch-vault-secrets.py fetches secrets into ephemeral subshell memory:
eval $(/home/ubuntu/lib/oracle-cli/bin/python3 scripts/fetch-vault-secrets.py /opt/dotevolve/.env.dev)
Exported shell variables take precedence in docker compose, securely injecting the credentials into container environments.
4. Two-Factor Authentication (2FA)
Umami requires an explicit AES-256 encryption key to enable TOTP 2FA. Without TWO_FACTOR_ENCRYPTION_KEY, the UI returns:
"Two-factor authentication is not available because the server is missing a valid TWO_FACTOR_ENCRYPTION_KEY. Contact your administrator for help."
Key Requirements
- Length: Exactly 64 hexadecimal characters (32 bytes).
- Generation:
openssl rand -hex 32 - Injection: Provided as
TWO_FACTOR_ENCRYPTION_KEYindocker-compose.umami.ymlvia OCI Vault.
With this key injected, users can navigate to Settings → Profile → Two-Factor Authentication in the Umami UI to scan the QR code and pair authenticator apps.
5. Website Tracking Catalog
All DotEvolve websites and applications are provisioned with dedicated website_id UUIDs.
| Application / Site | Dev Domain | Prod Domain | Dev website_id |
Prod Env Variable |
|---|---|---|---|---|
| Dot Portal | portal-dev.dotevolve.net |
portal.dotevolve.net |
e19e44a5-7e5e-4b32-85c5-a60be1a59f8a |
VITE_UMAMI_WEBSITE_ID_DOT_PORTAL |
| DotEvolve Marketing | dev.dotevolve.net |
dotevolve.net |
4db51fde-6361-4573-8016-b63a47f2d71a |
VITE_UMAMI_WEBSITE_ID_DOTEVOLVE |
| Floorix Admin | admin-dev.floorix.net |
admin.floorix.net |
e2368547-4caf-4ef7-8331-ef8e267e3aa2 |
VITE_UMAMI_WEBSITE_ID_FLOORIX_ADMIN |
| Floorix App | app-dev.floorix.net |
app.floorix.net |
b7e260f7-67f5-4f7e-93db-75c286aa6e54 |
VITE_UMAMI_WEBSITE_ID_FLOORIX_APP |
| Floorix Marketing | dev.floorix.net |
floorix.net |
cb383e39-7c23-414c-b670-373794f1d218 |
VITE_UMAMI_WEBSITE_ID_FLOORIX_NET |
| Govnix Admin | admin-dev.govnix.net |
admin.govnix.net |
f935e355-3a26-442f-bc3d-da4b748ddeca |
VITE_UMAMI_WEBSITE_ID_GOVNIX_ADMIN |
| Govnix App | app-dev.govnix.net |
app.govnix.net |
db563bc1-97ff-4151-a90e-5cb35ab45b5d |
VITE_UMAMI_WEBSITE_ID_GOVNIX_APP |
| Govnix Marketing | dev.govnix.net |
govnix.net |
5c332ad5-0b43-41c2-994b-57974d10878f |
VITE_UMAMI_WEBSITE_ID_GOVNIX_NET |
| Perfxcel Admin | admin-dev.perfxcel.com |
admin.perfxcel.com |
adddd066-ad94-46d5-9b0f-86dece904c81 |
VITE_UMAMI_WEBSITE_ID_PERFXCEL_ADMIN |
| Perfxcel App | app-dev.perfxcel.com |
app.perfxcel.com |
4a1b0acb-cf43-47e1-b906-c06c3c194a92 |
VITE_UMAMI_WEBSITE_ID_PERFXCEL_APP |
| Perfxcel Marketing | dev.perfxcel.com |
perfxcel.com |
eb7bf633-d1e2-4890-bd2f-f3a2f938e62a |
VITE_UMAMI_WEBSITE_ID_PERFXCEL_NET |
5.1 Automated Catalog Provisioning Script
The script scripts/seed-umami-websites.sh automates registration against Umami API:
# Target dev
UMAMI_URL="https://analytics-dev.dotevolve.net" TARGET_ENV="dev" ./scripts/seed-umami-websites.sh
# Target prod
UMAMI_URL="https://analytics.dotevolve.net" TARGET_ENV="prod" ./scripts/seed-umami-websites.sh
6. Server Directory Layout & Symlinks
To centralize infrastructure configuration and prevent repository drift, /opt/dotevolve/ on both Dev and Prod instances uses symlinks directly into /opt/dotevolve/repos/dot-infra/:
/opt/dotevolve/
├── .dockerignore ──> repos/dot-infra/.dockerignore
├── .env ──> .env.dev (or .env.prod)
├── .env.dev / .env.prod (local environment config)
├── docker-compose.yml ──> repos/dot-infra/docker-compose.yml
├── docker-compose.supabase.yml ──> repos/dot-infra/docker-compose.supabase.yml
├── docker-compose.umami.yml ──> repos/dot-infra/docker-compose.umami.yml
├── functions/ ──> repos/dot-infra/functions/
├── nginx/ ──> repos/dot-infra/nginx/
├── scripts/ ──> repos/dot-infra/scripts/
├── supabase/ ──> repos/dot-infra/supabase/
└── repos/
├── dot-infra/
├── dot-portal-api/
├── floorix-api/
├── govnix-api/
├── govnix-workflow-service/
└── perfxcel-api/
Updating infrastructure on a server requires only:
git -C /opt/dotevolve/repos/dot-infra pull
7. Automated Backups & Disaster Recovery
Umami database state is backed up automatically via scripts/backup-umami-to-r2.sh:
1. Executes pg_dump inside supabase-db-dev (or supabase-db-prod) targeting database umami.
2. Gzips the SQL archive locally to /opt/dotevolve/backups/umami/.
3. Uploads the compressed snapshot to Cloudflare R2 bucket dotevolve-analytics-backups.
4. Enforces a 14-day retention policy on local disk to prevent storage exhaustion.
5. Scheduled via cron daily at 02:30 UTC:
30 2 * * * /opt/dotevolve/scripts/backup-umami-to-r2.sh >> /opt/dotevolve/logs/umami-backup.log 2>&1
8. Phase 2 Completion: Centralized SDK Integration (@dotevolve/error-utils)
Phase 2 delivered the centralized telemetry engine inside @dotevolve/error-utils (v1.0.24):
- Universal Script Injector (initUmami): Asynchronously injects the 2KB tracker with double-injection prevention and SSR safety.
- SPA Route Tracking (useUmamiPageTracking): Automatically dispatches pageviews on client-side route transitions.
- Unified Dispatcher (usePageTracking, trackUnifiedEvent): Sends events and pageviews to both Umami and Google Analytics 4 concurrently.
- Cookieless & Compliant: Zero cookie banners required for Umami analytics.
- Debug & Mock Mode: Bypasses network calls during local and test runs (localhost, 127.0.0.1, test environments).
9. Phase 3: Application Rollout & Documentation Migration
Phase 3 executes the platform-wide integration across all 11 digital properties and transitions the documentation infrastructure to Cloudflare Pages:
1. Repository Configuration Standardization (Issue #32): Committed .npmrc (${NPM_TOKEN}) across all 22 workspace repositories to unblock private package downloads on Cloudflare Pages.
2. dot-docs Cloudflare Migration: Transitioned docs.dotevolve.net from Vercel to Cloudflare Pages with dedicated Umami tracking ID (cf4ee4d5-e66c-4cbf-ab53-8a90b9bb0b32).
3. Marketing Sites Activation: Active telemetry on govnix.net, floorix.net, and dotevolve.net.
4. Internal SPAs & Admin Integration: Rollout of initUmami() and useUmamiPageTracking across all 7 internal business applications.
For the comprehensive implementation plan and tracking catalog, see Phase 3 Rollout.