Skip to content

Network Topology

All ports, protocols, and service-to-service communication paths across deployment environments.

4+1 View: Physical View

Port Map

Development (localhost)

┌─────────────────────────────────────────────────────────────────┐
│  Host (localhost loopback)                                        │
│                                                                   │
│  :3000 ──→ Frontend (Vite dev server)                           │
│  :5001 ──→ Backend (.NET API, debug access)                     │
│  :8000 ──→ Processing Engine (debug access)                     │
│  :8001 ──→ MkDocs (documentation site)                          │
│  :8002 ──→ MAST Proxy (debug access)                           │
│  :8333 ──→ SeaweedFS S3 Gateway (optional, profile=s3)         │
│  :27017 ─→ MongoDB (direct access for tools)                   │
│                                                                   │
│  All bound to localhost loopback — not accessible from network   │
└─────────────────────────────────────────────────────────────────┘

Staging (AWS EC2)

┌─────────────────────────────────────────────────────────────────┐
│  Internet                                                        │
│                                                                   │
│  :22  ──→ SSH (key-based auth)                                  │
│  :80  ──→ Frontend (nginx, public)                              │
│  :443 ──→ (allowed by SG, unused — no TLS in staging)          │
│                                                                   │
│  All other ports internal only (Docker network)                 │
└─────────────────────────────────────────────────────────────────┘

Production

┌─────────────────────────────────────────────────────────────────┐
│  Internet                                                        │
│                                                                   │
│  :22  ──→ SSH (key-based auth)                                  │
│  :80  ──→ HTTP → HTTPS redirect + ACME challenge                │
│  :443 ──→ Frontend (nginx, TLS termination)                     │
│                                                                   │
│  All other ports internal only (Docker network)                 │
└─────────────────────────────────────────────────────────────────┘

Internal Communication Map

flowchart TB
    subgraph External["External Network"]
        Client["Browser"]
        MAST["STScI MAST\narchive.stsci.edu"]
    end

    subgraph DockerNet["Docker: jwst-network (bridge)"]
        FE["Frontend\nnginx :3000"]
        BE["Backend\nASP.NET :5000"]
        PE["Processing Engine\nuvicorn :8000"]
        MP["MAST Proxy\nuvicorn :8000"]
        DB["MongoDB\n:27017"]
    end

    Client -->|"HTTP/HTTPS\n(host port)"| FE
    FE -->|"HTTP /api/*\nreverse proxy"| BE
    FE -->|"WebSocket /hubs/*\nupgrade + proxy"| BE
    BE -->|"HTTP POST\nJSON (snake_case)"| PE
    BE -->|"HTTP POST\nJSON (snake_case)"| MP
    BE -->|"MongoDB Wire Protocol\nTCP"| DB
    MP -->|"HTTPS\nastroquery"| MAST

    linkStyle 0 stroke:#2196f3,stroke-width:2
    linkStyle 1 stroke:#4caf50,stroke-width:2
    linkStyle 2 stroke:#ff9800,stroke-width:2
    linkStyle 3 stroke:#4caf50,stroke-width:2
    linkStyle 4 stroke:#4caf50,stroke-width:2
    linkStyle 5 stroke:#9c27b0,stroke-width:2
    linkStyle 6 stroke:#f44336,stroke-width:2

Protocol Details

Client ↔ Frontend (nginx)

Protocol Port Path Purpose
HTTP/HTTPS 80/443 /* Static assets (React SPA)
HTTP/HTTPS 80/443 /api/* Reverse proxy to backend
WebSocket 80/443 /hubs/* SignalR real-time updates

nginx routing rules: - / → serve static files; fallback to index.html (SPA routing) - /api/*proxy_pass http://backend:5000 - /hubs/*proxy_pass http://backend:5000 with WebSocket upgrade headers

Timeouts: - /api/*: connect 60s, send/read 300s - /hubs/*: read 3600s (long-lived WebSocket)

Frontend ↔ Backend

Protocol Transport Auth Casing
REST HTTP/1.1 via nginx proxy JWT Bearer token camelCase
SignalR WebSocket via nginx proxy JWT via ?access_token= query param camelCase

Backend ↔ Processing Engine

Protocol Transport Auth Casing Timeout
HTTP Direct TCP (Docker network) None (internal) snake_case 30 min attempt / 60 min total

Resilience: Polly retry (3x, 2s backoff) + circuit breaker for composite/mosaic calls.

Backend ↔ MAST Proxy

Protocol Transport Auth Casing Timeout
HTTP Direct TCP (Docker network) None (internal) snake_case 5 min

No Polly resilience — MAST operations use application-level retry (user re-submits).

Backend ↔ MongoDB

Protocol Transport Auth Port
MongoDB Wire Protocol TCP Username/password (SCRAM) 27017

Connection string: mongodb://admin:<password>@mongodb:27017

MAST Proxy ↔ STScI

Protocol Transport Auth Rate Limit
HTTPS Public internet None (public API) Backend enforces 30 req/min

Uses astroquery.mast library — communicates with archive.stsci.edu and mast.stsci.edu.

Security Headers

Applied by nginx in all environments:

Header Value Purpose
X-Content-Type-Options nosniff Prevent MIME sniffing
X-Frame-Options SAMEORIGIN Prevent clickjacking
X-XSS-Protection 1; mode=block XSS filter
Referrer-Policy strict-origin-when-cross-origin Limit referrer leakage

Production adds: | Header | Value | Purpose | |--------|-------|---------| | Strict-Transport-Security | max-age=31536000 | Force HTTPS for 1 year | | Content-Security-Policy | Restrictive policy | XSS/injection prevention |

CORS Configuration

Environment Allowed Origins
Development http://localhost:3000, http://localhost:5173 (+ loopback equivalents)
Staging http://<Elastic-IP>
Production https://yourdomain.com (must be explicitly set)

Policy: AllowAnyHeader(), AllowAnyMethod(), AllowCredentials().

DNS and TLS (Production)

yourdomain.com → A record → Elastic IP
                             ↓
                    nginx :443
                    ├── TLS 1.2 / TLS 1.3
                    ├── Ciphers: ECDHE-ECDSA-AES128-GCM-SHA256, ...
                    ├── OCSP Stapling: on
                    ├── Session cache: shared (50 MB)
                    └── Cert: /etc/nginx/ssl/fullchain.pem

Docker Network Architecture

flowchart TB
    subgraph Default["jwst-network (default bridge)"]
        FE["frontend"]
        BE["backend"]
        PE["processing-engine"]
        MP["mast-proxy"]
        DB["mongodb"]
        S3["seaweedfs-s3\n(profile: s3)"]
        Docs["docs"]
    end

    subgraph Shared["jwst-shared (external bridge)"]
        Agent1["Agent Stack 1\n(optional)"]
        Agent2["Agent Stack 2\n(optional)"]
    end

    Default <-->|"cross-network\n(when agents active)"| Shared
  • jwst-network: Default bridge network for all services — automatic DNS resolution by container name
  • jwst-shared: External bridge for multi-agent stacks (experimental, not actively used)

All services within jwst-network can reach each other by container name (e.g., http://backend:5000, http://processing-engine:8000).

Firewall Rules (AWS Security Group)

Rule Protocol Port Source Purpose
Inbound TCP 22 any SSH access
Inbound TCP 80 any HTTP traffic
Inbound TCP 443 any HTTPS traffic
Outbound All All any Internet access (MAST, package repos)

Recommendation for production: Restrict SSH to specific IP ranges.


Back to Architecture Overview