Skip to content

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
- Database Name: 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_KEY in docker-compose.umami.yml via 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


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.