Deployment Guide
Learn how to deploy the TopGun server to production using Docker, Docker Compose, or Kubernetes.
Docker
Building the Image
# 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-slimruntime image - Exposing ports
8080(client),9080(cluster),9090(metrics) - Running as non-root user with health check
Docker Compose
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
docker-compose up -d Kubernetes (Helm)
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 APItemplates/service-headless.yaml- Headless service for internal cluster discoveryvalues.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
# 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
| Setting | Default | Purpose |
|---|---|---|
max_concurrent_operations | 1000 | Load shedding threshold for concurrent operations |
default_operation_timeout_ms | 30000 | Maximum time for a single operation |
outbound_channel_capacity | 256 | Per-connection backpressure buffer |
request_timeout | 30s | Maximum 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
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
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.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:
# 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
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
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
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
# 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 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 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.