Skip to content

Network / Deployment Topology

Production deployment (docker-compose.prod.yml) and trust boundaries.

flowchart TB
    subgraph internet[Public Internet]
        U[Users / browsers]
        WH[Webhook senders<br/>Stripe, Zoho]
    end

    subgraph host[Host / Cloud VM — trust boundary]
        direction TB
        NX[nginx<br/>:80 / :443 TLS]
        CS[CrowdSec<br/>IDS/IPS]
        FE[frontend<br/>Next.js container]
        BE[backend<br/>FastAPI container :8080 local-only]
        CW[celery-worker]
        CB[celery-beat]
        RD[(redis<br/>container, not exposed)]
    end

    subgraph managed[Managed services — external trust boundary]
        PG[(PostgreSQL / Supabase<br/>AES-256 at rest, daily backups, PITR)]
    end

    subgraph third[Third-party APIs]
        EXT[Stripe / Zoho / QuickBooks /<br/>NetSuite / Oracle / Google / LLM]
    end

    U -->|HTTPS 443| NX
    WH -->|HTTPS webhook| NX
    NX -. logs .-> CS
    CS -. ban decisions .-> NX
    NX --> FE
    NX --> BE
    BE --> RD
    CW --> RD
    CB --> RD
    BE -->|TLS| PG
    CW -->|TLS| PG
    BE -->|TLS, encrypted creds| EXT
    CW -->|TLS, encrypted creds| EXT

    classDef edge fill:#fde,stroke:#b36
    classDef store fill:#def,stroke:#36b
    class NX,CS edge
    class PG,RD store

Trust boundaries & controls

Boundary Control
Internet → Host nginx TLS 1.2+ termination; CrowdSec IDS/IPS (nginx, http-cve, base-http-scenarios); cloud firewall
Within Host Backend bound to 127.0.0.1:8080 (not publicly exposed); Redis not exposed; containers isolated
Host → Managed DB TLS; managed PostgreSQL encrypted at rest (AES-256); RLS per organization
Host → Third-party Outbound TLS; integration credentials encrypted at rest (AES-256-GCM)

Deployment services

redis, backend, celery-worker, celery-beat, frontend, nginx, crowdsec — defined in docker-compose.prod.yml. Only nginx is published to the public network; the backend's :8080 is bound to localhost for local/admin access only.