DocsGuidesDeployment

Deployment Guide

Learn how to deploy the TopGun server to production using Docker, Docker Compose, or Kubernetes.

Docker

TopGun provides a standardized Dockerfile for building the server. It uses a multi-stage build process to ensure a small image size.

Building the Image

terminal
# From the root of the repository
docker build -t topgun-server -f deploy/Dockerfile.server .

The Dockerfile handles:

  • Multi-stage Rust build using rust:1.85-bookworm
  • Compiling the Rust server binary (cargo build --release)
  • Minimal debian:bookworm-slim runtime image
  • Exposing ports 8080 (client), 9080 (cluster), 9090 (metrics)
  • Running as non-root user with health check

Docker Compose

For local development or simple deployments, you can use Docker Compose to run the TopGun Server alongside a PostgreSQL database.
docker-compose.yml
version: '3.8'

services:
  # PostgreSQL Database
  postgres:
    image: postgres:15-alpine
    container_name: topgun-postgres
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: postgres_password
      POSTGRES_DB: topgun
    ports:
      - "5432:5432"
    volumes:
      - postgres_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 5s
      timeout: 5s
      retries: 5

  # TopGun Rust Server
  server:
    build:
      context: .
      dockerfile: deploy/Dockerfile.server
    container_name: topgun-server
    depends_on:
      postgres:
        condition: service_healthy
    ports:
      - "8080:8080"
    environment:
      RUST_LOG: topgun_server=info
      DATABASE_URL: postgres://postgres:postgres_password@postgres:5432/topgun
    restart: unless-stopped

volumes:
  postgres_data:

Running with Compose

terminal
docker-compose up -d

Kubernetes (Helm)

For production Kubernetes clusters, a Helm chart is provided in deploy/k8s/chart.

Chart Structure

  • templates/statefulset.yaml- Manages the server pods (StatefulSet is recommended for stable network IDs)
  • templates/service.yaml- Exposes the HTTP/WebSocket API
  • templates/service-headless.yaml- Headless service for internal cluster discovery
  • values.yaml- Default configuration values

Deploying with Helm allows easy scaling of the server replicas. TopGun nodes automatically discover each other when running in the same cluster (configured via cluster.discovery).

Production Performance Settings

Recommended configuration for production workloads with high connection counts.
Production Server Setup
# Production deployment with PostgreSQL persistence
# Currently requires embedding the server in a Rust application
# (production CLI binary with env var config is planned)
#
# The Rust server includes built-in production optimizations:
# - Tower middleware pipeline (LoadShed, Timeout, Metrics)
# - Automatic backpressure via bounded channel capacity
# - Configurable operation timeouts and concurrency limits
# - Prometheus metrics endpoint at /metrics
#
# Key configuration structs:
#   NetworkConfig  -- host, port, TLS, CORS, connection settings
#   ServerConfig   -- node_id, timeouts, concurrency, partitions
#
# For full configuration, see: /docs/reference/server

Key Settings Explained

SettingDefaultPurpose
max_concurrent_operations1000Load shedding threshold for concurrent operations
default_operation_timeout_ms30000Maximum time for a single operation
outbound_channel_capacity256Per-connection backpressure buffer
request_timeout30sMaximum time for an HTTP request

Performance Tuning Guide

For detailed tuning guidance including high-throughput and low-latency configurations, see the Performance Tuning Guide.

TLS Configuration

For production deployments, enable TLS to encrypt all client and cluster communications.

Security Requirement

Always enable TLS in production. Without TLS, all data (including authentication tokens) is transmitted in plaintext and can be intercepted.

Docker Compose with TLS

The TOPGUN_TLS_* environment variables shown below are planned for the future production binary. Currently, TLS is configured programmatically via TlsConfig when embedding the server. See the Server API for the current programmatic approach.
docker-compose.tls.yml (planned)
version: '3.8'

services:
  postgres:
    image: postgres:15-alpine
    container_name: topgun-postgres
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: postgres_password
      POSTGRES_DB: topgun
    volumes:
      - postgres_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 5s
      timeout: 5s
      retries: 5

  server:
    build:
      context: .
      dockerfile: deploy/Dockerfile.server
    container_name: topgun-server
    depends_on:
      postgres:
        condition: service_healthy
    ports:
      - "443:443"       # HTTPS/WSS
      - "9443:9443"     # Cluster TLS
    environment:
      RUST_LOG: topgun_server=info
      TOPGUN_PORT: 443
      TOPGUN_CLUSTER_PORT: 9443
      DATABASE_URL: postgres://postgres:postgres_password@postgres:5432/topgun
      # TLS Configuration
      TOPGUN_TLS_ENABLED: "true"
      TOPGUN_TLS_CERT_PATH: /etc/topgun/tls/server.crt
      TOPGUN_TLS_KEY_PATH: /etc/topgun/tls/server.key
      TOPGUN_TLS_MIN_VERSION: TLSv1.3
      # Cluster TLS (mTLS)
      TOPGUN_CLUSTER_TLS_ENABLED: "true"
      TOPGUN_CLUSTER_TLS_CERT_PATH: /etc/topgun/tls/cluster.crt
      TOPGUN_CLUSTER_TLS_KEY_PATH: /etc/topgun/tls/cluster.key
      TOPGUN_CLUSTER_TLS_CA_PATH: /etc/topgun/tls/ca.crt
      TOPGUN_CLUSTER_MTLS: "true"
    volumes:
      - ./certs:/etc/topgun/tls:ro
    restart: unless-stopped

volumes:
  postgres_data:

Before starting, create your certificates in the ./certs directory:

terminal
# Create certs directory
mkdir -p certs

# Copy your certificates
cp /path/to/server.crt certs/
cp /path/to/server.key certs/
cp /path/to/ca.crt certs/

# For cluster mTLS (separate certs)
cp /path/to/cluster.crt certs/
cp /path/to/cluster.key certs/

# Start with TLS
docker-compose -f docker-compose.tls.yml up -d

Kubernetes TLS Secret

Store TLS certificates securely using Kubernetes Secrets.
k8s/tls-secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: topgun-tls
  namespace: topgun
type: kubernetes.io/tls
data:
  # Base64-encoded certificate and key
  tls.crt: LS0tLS1CRUdJTi...  # base64 -w0 server.crt
  tls.key: LS0tLS1CRUdJTi...  # base64 -w0 server.key
  ca.crt: LS0tLS1CRUdJTi...   # base64 -w0 ca.crt
---
# Create secret from files:
# kubectl create secret generic topgun-tls \
#   --from-file=tls.crt=./server.crt \
#   --from-file=tls.key=./server.key \
#   --from-file=ca.crt=./ca.crt \
#   -n topgun

Kubernetes Deployment with TLS

k8s/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: topgun
  namespace: topgun
spec:
  replicas: 3
  selector:
    matchLabels:
      app: topgun
  template:
    metadata:
      labels:
        app: topgun
    spec:
      containers:
      - name: topgun
        image: topgun:latest
        ports:
        - containerPort: 443
          name: https
        - containerPort: 9443
          name: cluster
        env:
        - name: TOPGUN_PORT
          value: "443"
        - name: TOPGUN_CLUSTER_PORT
          value: "9443"
        - name: TOPGUN_TLS_ENABLED
          value: "true"
        - name: TOPGUN_TLS_CERT_PATH
          value: "/etc/topgun/tls/tls.crt"
        - name: TOPGUN_TLS_KEY_PATH
          value: "/etc/topgun/tls/tls.key"
        - name: TOPGUN_TLS_MIN_VERSION
          value: "TLSv1.3"
        - name: TOPGUN_CLUSTER_TLS_ENABLED
          value: "true"
        - name: TOPGUN_CLUSTER_TLS_CA_PATH
          value: "/etc/topgun/tls/ca.crt"
        - name: TOPGUN_CLUSTER_MTLS
          value: "true"
        volumeMounts:
        - name: tls-certs
          mountPath: /etc/topgun/tls
          readOnly: true
      volumes:
      - name: tls-certs
        secret:
          secretName: topgun-tls

cert-manager Integration

For automatic certificate management, consider using cert-manager with Let’s Encrypt or your internal CA. See the Security Guide for detailed setup instructions.

Serverless Deployment

Deploy TopGun to serverless platforms using the HTTP sync protocol (POST /sync endpoint).

Serverless Edge Not Supported

The Rust TopGun server is a long-running process that maintains in-memory CRDT state, WebSocket connections, and cluster membership. It does not support serverless edge deployment (Vercel Edge Functions, AWS Lambda, Cloudflare Workers). Deploy TopGun as a persistent service (Docker, Kubernetes, or any platform supporting long-running processes) and connect from your edge functions using the TopGun client SDK. See the Server API reference for supported deployment modes.

Vercel Edge Function

Vercel Edge (Not Supported)
# The Rust TopGun server does not support serverless edge deployment.
# The server is a long-running process that maintains in-memory state,
# WebSocket connections, and cluster membership.
#
# For serverless environments, deploy TopGun as a persistent service
# and connect from your edge functions via the TopGun client SDK.
#
# Recommended deployment modes:
#   - Docker container (see docker-compose example above)
#   - Kubernetes StatefulSet (see k8s example above)
#   - Any platform that supports long-running processes
#
# See the Server API reference for deployment options:
# /docs/reference/server

AWS Lambda

AWS Lambda (Not Supported)
# AWS Lambda is not supported for the TopGun server.
# The Rust server requires persistent state and WebSocket connections.
#
# Deploy TopGun as an ECS/EKS service instead:
# - ECS Fargate with an Application Load Balancer (WebSocket support)
# - EKS with a StatefulSet for cluster deployments
#
# Your Lambda functions can connect as TopGun clients.
# See: /docs/reference/server

Cloudflare Worker

Cloudflare Worker (Not Supported)
# Cloudflare Workers are not supported for the TopGun server.
# The Rust server requires persistent state and WebSocket connections.
#
# Deploy TopGun as a container or VM-based service.
# Your Cloudflare Workers can connect as TopGun clients.
# See: /docs/reference/server

Client Configuration for Serverless

To connect a client to a serverless TopGun deployment, use HttpSyncProvider or AutoConnectionProvider with SyncEngine. These providers implement the IConnectionProvider interface and are used with SyncEngine directly — not with TopGunClient (which only accepts serverUrl and cluster config options).

Using HttpSyncProvider

import { HttpSyncProvider, SyncEngine } from '@topgunbuild/client';
import { HLC } from '@topgunbuild/core';
import { IDBAdapter } from '@topgunbuild/adapters';

const hlc = new HLC('client-1');
const provider = new HttpSyncProvider({
  url: 'https://your-api.vercel.app',
  clientId: 'client-1',
  hlc,
  authToken: 'your-jwt-token',
  syncMaps: ['todos'],
});

const engine = new SyncEngine({
  nodeId: 'client-1',
  connectionProvider: provider,
  storageAdapter: new IDBAdapter(),
});

Using AutoConnectionProvider

For environments where you are unsure if WebSocket is available, AutoConnectionProvider tries WebSocket first and falls back to HTTP:

import { AutoConnectionProvider, SyncEngine } from '@topgunbuild/client';
import { HLC } from '@topgunbuild/core';
import { IDBAdapter } from '@topgunbuild/adapters';

const hlc = new HLC('client-1');
const provider = new AutoConnectionProvider({
  url: 'https://your-api.vercel.app',
  clientId: 'client-1',
  hlc,
  authToken: 'your-jwt-token',
  maxWsAttempts: 3,
  syncMaps: ['todos'],
});

const engine = new SyncEngine({
  nodeId: 'client-1',
  connectionProvider: provider,
  storageAdapter: new IDBAdapter(),
});

Provider Configuration Reference

For the full list of configuration options for HttpSyncProvider and AutoConnectionProvider, see the Client API reference.