Skip to content

Deployment Guide

Deploy RevenProx in production environments.

Deployment Options

Bare Metal / VM

Direct installation on Linux servers.

Docker

Containerized deployment.

Kubernetes

Orchestrated container deployment.

Single Instance Deployment

Systemd Service

Create /etc/systemd/system/revenprox.service:

[Unit]
Description=RevenProx SSE Proxy
After=network.target

[Service]
Type=simple
User=revenprox
Group=revenprox
WorkingDirectory=/opt/revenprox
ExecStart=/opt/revenprox/sse-proxy --config /etc/revenprox/proxy.toml
Restart=always
RestartSec=5

# Resource limits
LimitNOFILE=1000000
LimitNPROC=65535

# Security
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/var/log/revenprox

[Install]
WantedBy=multi-user.target

Enable and start:

sudo systemctl daemon-reload
sudo systemctl enable revenprox
sudo systemctl start revenprox

Directory Structure

/opt/revenprox/
├── sse-proxy              # Binary
└── config/
    └── proxy.toml         # Default config

/etc/revenprox/
└── proxy.toml             # Production config

/var/log/revenprox/
└── proxy.log              # Log files

Docker Deployment

Dockerfile

FROM debian:bookworm-slim

RUN apt-get update && apt-get install -y \
    libnng1 \
    ca-certificates \
    && rm -rf /var/lib/apt/lists/*

COPY sse-proxy /usr/local/bin/
COPY config/proxy.toml /etc/revenprox/

EXPOSE 8080 5555

USER nobody

ENTRYPOINT ["/usr/local/bin/sse-proxy"]
CMD ["--config", "/etc/revenprox/proxy.toml"]

Docker Compose

version: '3.8'

services:
  revenprox:
    image: revenprox/sse-proxy:latest
    ports:
      - "8080:8080"
      - "5555:5555"
    volumes:
      - ./config:/etc/revenprox:ro
    environment:
      - LOG_LEVEL=info
    deploy:
      resources:
        limits:
          memory: 4G
          cpus: '2'
    ulimits:
      nofile:
        soft: 1000000
        hard: 1000000
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
      interval: 30s
      timeout: 10s
      retries: 3

Running Docker

# Build image
docker build -t revenprox/sse-proxy .

# Run container
docker run -d \
  --name revenprox \
  -p 8080:8080 \
  -p 5555:5555 \
  -v $(pwd)/config:/etc/revenprox:ro \
  --ulimit nofile=1000000:1000000 \
  revenprox/sse-proxy

Kubernetes Deployment

Deployment

apiVersion: apps/v1
kind: Deployment
metadata:
  name: revenprox
  labels:
    app: revenprox
spec:
  replicas: 3
  selector:
    matchLabels:
      app: revenprox
  template:
    metadata:
      labels:
        app: revenprox
    spec:
      containers:
      - name: revenprox
        image: revenprox/sse-proxy:latest
        ports:
        - containerPort: 8080
          name: http
        - containerPort: 5555
          name: nng
        resources:
          requests:
            memory: "2Gi"
            cpu: "1"
          limits:
            memory: "4Gi"
            cpu: "2"
        livenessProbe:
          httpGet:
            path: /health
            port: 8080
          initialDelaySeconds: 10
          periodSeconds: 30
        readinessProbe:
          httpGet:
            path: /health
            port: 8080
          initialDelaySeconds: 5
          periodSeconds: 10
        volumeMounts:
        - name: config
          mountPath: /etc/revenprox
          readOnly: true
      volumes:
      - name: config
        configMap:
          name: revenprox-config

Service

apiVersion: v1
kind: Service
metadata:
  name: revenprox
spec:
  type: LoadBalancer
  ports:
  - port: 80
    targetPort: 8080
    name: http
  selector:
    app: revenprox
---
apiVersion: v1
kind: Service
metadata:
  name: revenprox-peers
spec:
  clusterIP: None
  ports:
  - port: 5555
    name: nng
  selector:
    app: revenprox

ConfigMap

apiVersion: v1
kind: ConfigMap
metadata:
  name: revenprox-config
data:
  proxy.toml: |
    proxy_id = "${HOSTNAME}"
    log_level = "info"

    [http]
    bind_address = "0.0.0.0:8080"
    max_connections = 50000

    [jwt_verifier]
    webhook_url = "http://auth-service/verify"
    require_authentication = true

    [nng]
    listen_addresses = ["tcp://*:5555"]

    [limits]
    max_memory_mb = 4096
    max_cpu_percent = 80

Horizontal Pod Autoscaler

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: revenprox
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: revenprox
  minReplicas: 3
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70
  - type: Resource
    resource:
      name: memory
      target:
        type: Utilization
        averageUtilization: 80

Load Balancer Configuration

Nginx

upstream revenprox {
    least_conn;
    server proxy1.internal:8080;
    server proxy2.internal:8080;
    server proxy3.internal:8080;
    keepalive 1000;
}

server {
    listen 80;
    listen 443 ssl;

    location /events/ {
        proxy_pass http://revenprox;
        proxy_http_version 1.1;
        proxy_set_header Connection '';
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_buffering off;
        proxy_cache off;
        proxy_read_timeout 3600s;
        chunked_transfer_encoding off;
    }

    location /health {
        proxy_pass http://revenprox;
    }
}

HAProxy

frontend http
    bind *:80
    bind *:443 ssl crt /etc/ssl/certs/proxy.pem
    default_backend revenprox

backend revenprox
    balance leastconn
    option httpchk GET /health
    http-check expect status 200

    # SSE-specific settings
    timeout client 3600s
    timeout server 3600s
    timeout tunnel 3600s

    server proxy1 proxy1.internal:8080 check
    server proxy2 proxy2.internal:8080 check
    server proxy3 proxy3.internal:8080 check

AWS ALB

Key settings for SSE: - Idle timeout: 3600 seconds - Deregistration delay: 300 seconds - Stickiness: Disabled (clients can reconnect to any instance)

High Availability

Multi-Instance Setup

              ┌──────────────┐
              │ Load Balancer│
              └───────┬──────┘
        ┌─────────────┼─────────────┐
        │             │             │
   ┌────▼────┐   ┌────▼────┐   ┌────▼────┐
   │ Proxy 1 │◄─►│ Proxy 2 │◄─►│ Proxy 3 │
   └─────────┘   └─────────┘   └─────────┘
         NNG mesh for state sync

Configuration for HA

[nng]
listen_addresses = ["tcp://*:5555"]
peer_addresses = [
  "tcp://proxy1.internal:5555",
  "tcp://proxy2.internal:5555",
  "tcp://proxy3.internal:5555"
]
reconnect_interval_ms = 2000
heartbeat_interval_sec = 15

[distributed_state]
gossip_interval_sec = 10
peer_timeout_sec = 60

Security Considerations

TLS Termination

Terminate TLS at the load balancer:

server {
    listen 443 ssl http2;
    ssl_certificate /etc/ssl/certs/proxy.crt;
    ssl_certificate_key /etc/ssl/private/proxy.key;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:...;
}

Network Isolation

  • Keep NNG ports (5555) on internal network only
  • Expose only HTTP port (8080) through load balancer
  • Use network policies in Kubernetes

Secrets Management

Store sensitive configuration in secrets:

# Kubernetes Secret
apiVersion: v1
kind: Secret
metadata:
  name: revenprox-secrets
type: Opaque
stringData:
  jwt-webhook-url: "https://auth.internal/verify"

Rollout Strategies

Rolling Update

spec:
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 1
      maxSurge: 1

Blue-Green Deployment

  1. Deploy new version to "green" environment
  2. Test green environment
  3. Switch load balancer to green
  4. Keep blue as rollback

Canary Deployment

Route percentage of traffic to new version:

upstream revenprox {
    server proxy-v1:8080 weight=90;
    server proxy-v2:8080 weight=10;  # Canary
}

Next Steps