Skip to main content

Gateway

The Gateway service (edd-cloud-gateway) is the main entry point for all external traffic. It handles TLS termination, HTTP/HTTPS routing, and SSH tunneling.

Protocol Support

ProtocolStatusNotes
HTTP/1.1SupportedPlain HTTP and after TLS termination
HTTPS/TLSSupportedTLS 1.2+, SNI-based routing
SSHSupportedUsername-based container routing
WebSocketSupportedProxied over HTTP/1.1
HTTP/2Not supportedTLS config only advertises HTTP/1.1
gRPCNot supportedRequires HTTP/2
HTTP Keep-AliveSupported60s idle timeout, backend connection pooling

TLS Handling

  • TLS Termination: For static routes (core services), gateway terminates TLS and proxies plain HTTP to backends
  • TLS Passthrough: For container routes (*.compute.cloud.eddisonso.com), raw TLS is forwarded to the container's LoadBalancer
  • SNI Extraction: Reads SNI from TLS ClientHello to determine routing before handshake

Container domains follow the pattern <container-id>.compute.cloud.eddisonso.com - the gateway detects these by checking for .compute.cloud. in the SNI.

Multi-Protocol Detection (Ports 8000-8999)

The gateway auto-detects protocols on extra ports by inspecting the first bytes:

  • SSH- → SSH protocol
  • 0x16 → TLS handshake
  • GET, POST, etc. → Plain HTTP

Features

  • TLS Termination: Handles HTTPS with automatic certificate management
  • Dynamic Routing: Routes based on host and path prefix from PostgreSQL
  • Route Caching: LRU cache (100 entries) for O(1) route lookups
  • Response Caching: In-memory LRU cache for small GET 200 responses (500MB cap, 30s TTL) to reduce backend load for hot files
  • SSH Tunneling: Provides SSH access to containers via port 2222
  • WebSocket Support: Proxies WebSocket connections for real-time features
  • HTTP→HTTPS Redirect: Automatic upgrade for core services
  • Client IP Forwarding: Injects X-Forwarded-For header with real client IP for backend services

Architecture

External ports are mapped as follows:

  • Port 22 → Internal 2222 (SSH)
  • Port 80 → Internal 18080 (HTTP, redirects to HTTPS)
  • Port 443 → Internal 8443 (HTTPS/TLS)
  • Ports 8000-8999 → Internal 8000-8999 (Container ingress)

Routing

Routes are stored in the static_routes PostgreSQL table:

CREATE TABLE static_routes (
id SERIAL PRIMARY KEY,
host TEXT NOT NULL,
path_prefix TEXT NOT NULL,
target TEXT NOT NULL,
strip_prefix BOOLEAN DEFAULT false,
priority INTEGER DEFAULT 0
);

Route Matching

  1. Routes are sorted by priority (descending)
  2. Host must match exactly
  3. Path must start with path_prefix
  4. First matching route wins

Route Cache

The gateway uses an LRU (Least Recently Used) cache to optimize route lookups:

  • Cache Size: 100 entries
  • Key: host + path
  • Hit: O(1) lookup, bypasses route matching
  • Miss: Linear scan through routes, result cached
  • Invalidation: Cache cleared on route table reload

This means repeated requests to the same endpoints are served with minimal overhead, regardless of the total number of routes.

Response Cache

The gateway caches small GET 200 responses in memory to reduce backend load for frequently accessed files:

  • Cache Size: 500 MB total capacity
  • Entry Limit: 1 MB per cached response
  • TTL: 30 seconds
  • Key: host:path (e.g., storage.cloud.eddisonso.com:/api/files/123)
  • Eligibility: Only caches responses that:
    • Use GET method
    • Return status 200
    • Have body ≤ 1 MB
    • Do not have Set-Cookie header
    • Do not have Cache-Control: no-store
  • Invalidation: Cache entries are automatically invalidated when mutating requests (PUT/POST/DELETE/PATCH) are made to the same path
  • Background Cleanup: Expired entries removed every 5 minutes

Cache hits are served directly from memory without backend round-trips, significantly improving latency for hot files. Mutating requests immediately evict cached entries for the same path, ensuring fresh content on subsequent GET requests.

Browser Caching: The gateway adds Cache-Control: no-store to all cached responses to prevent browser-side caching. This ensures browsers always fetch from the gateway cache (which invalidates on mutations) rather than serving stale content from their own cache after a file is deleted or modified.

Example Routes

HostPath PrefixTarget
storage.cloud.eddisonso.com/simple-file-share-backend:80
compute.cloud.eddisonso.com/edd-compute:80
health.cloud.eddisonso.com/cluster-monitor:80

Container Routing

Container traffic is routed separately from static routes. When a request comes in for <container-id>.compute.cloud.eddisonso.com:

  1. Gateway extracts the container ID from the hostname
  2. Looks up the container's ingress rules from the database
  3. Maps the external port to the target port
  4. Forwards traffic to lb.<namespace>.svc.cluster.local:<target-port>

Ingress Rules

Each container can have multiple ingress rules mapping external ports to internal ports:

External PortTarget PortURL
80808080http://<id>.compute.cloud.eddisonso.com:8080/
8443443https://<id>.compute.cloud.eddisonso.com:8443/

The gateway reloads container and ingress data every 5 seconds to pick up new rules.

SSH Tunneling

The gateway provides SSH access to containers:

ssh <container-id>@compute.cloud.eddisonso.com

SSH keys are managed through the Compute API and stored in PostgreSQL.

Configuration

FlagDescriptionDefault
-ssh-portSSH listen port2222
-http-portHTTP listen port18080
-https-portHTTPS listen port8443
-tls-certTLS certificate path-
-tls-keyTLS private key path-
-fallbackFallback IP for unmatched routes-

The gateway also listens on ports 8000-8999 for container ingress traffic using multi-protocol detection.

Route Configuration

Routes can be configured via a routes.yaml file mounted as a ConfigMap:

routes:
- host: storage.cloud.eddisonso.com
path: /
target: simple-file-share-backend:80
strip_prefix: false

- host: storage.cloud.eddisonso.com
path: /sse/progress
target: simple-file-share-backend:80
strip_prefix: false

- host: compute.cloud.eddisonso.com
path: /
target: edd-compute:80
strip_prefix: false

- host: cloud.eddisonso.com
path: /
target: simple-file-share-frontend:80
strip_prefix: false

Updating Routes

  1. Edit edd-gateway/routes.yaml
  2. Apply the ConfigMap:
    kubectl create configmap gateway-routes \
    --from-file=routes.yaml \
    --dry-run=client -o yaml | kubectl apply -f -
  3. Restart the gateway:
    kubectl rollout restart deployment/gateway

Route Parameters

ParameterDescription
hostDomain to match (e.g., storage.cloud.eddisonso.com)
pathPath prefix to match (e.g., /compute)
targetBackend service and port (e.g., edd-compute:80)
strip_prefixIf true, removes the path prefix before forwarding

Health Check

GET /healthz → 200 OK
GET /readyz → 200 OK