Docs/Guides/Hybrid Gateway Deployment

Hybrid Gateway Deployment Playbook

Step-by-step guide for deploying a SatGate hybrid gateway on customer infrastructure with cloud dashboard integration.

What This Guide Covers

Deploy a SatGate gateway on your own infrastructure while connecting to the cloud dashboard for management. This hybrid approach gives you data locality and control while maintaining centralized visibility and configuration.

🏢
On Your Infrastructure

Gateway binary, Redis, TLS, network policies — full control

☁️
Cloud Dashboard

Management UI, token minting, audit logs, real-time config push

1. Prerequisites

Infrastructure Requirements

  • Linux server (Ubuntu 22.04+ recommended) with root access
  • 4GB+ RAM, 2+ CPU cores
  • Domain name pointed at server (A record)
  • Ports 80, 443, 8080 available

Software Requirements

  • Go 1.22+ (for building) OR pre-built binary
  • Redis 7+ installed and running
  • Caddy or nginx for TLS termination
  • Enterprise tenant at cloud.satgate.io

2. Build the Gateway Binary

Build the enterprise gateway with hybrid features enabled. The -tags enterprise flag is required for cloud sync and dashboard integration.

Clone and Build

# Clone the enterprise repository
git clone https://github.com/SatGate-io/satgate-enterprise.git
cd satgate-enterprise/gateway
# Cross-compile for Linux x86_64 (from Mac/Windows)
GOOS=linux GOARCH=amd64 go build -tags enterprise \
  -o satgate-gateway ./cmd/gateway
# For ARM64 servers (AWS Graviton, Raspberry Pi, etc.)
GOOS=linux GOARCH=arm64 go build -tags enterprise \
  -o satgate-gateway ./cmd/gateway

⚠️ Important

• The -tags enterprise flag enables hybrid features (cloud sync, dashboard tokens)

• Cross-compilation is required when building on Mac/Windows for Linux deployment

• Verify the binary architecture matches your server: file satgate-gateway

3. Deploy to Server

Copy the binary to your server and set up the directory structure.

# Copy binary to server
scp satgate-gateway user@your-server:/tmp/
# SSH to server and install
ssh user@your-server
sudo mv /tmp/satgate-gateway /usr/local/bin/
sudo chmod +x /usr/local/bin/satgate-gateway
sudo mkdir -p /etc/satgate
# Create service user
sudo useradd --system --shell /bin/false satgate
sudo chown satgate:satgate /etc/satgate

💡 Tip

Verify the binary works: sudo -u satgate /usr/local/bin/satgate-gateway --version

4. Configure the Gateway

Create the gateway configuration. Most settings (enforcement mode, budgets, tokens) are managed from the cloud dashboard and pushed automatically via WebSocket — you only need to define local upstreams and routes here.

Create Configuration File

# /etc/satgate/hybrid-gateway.yaml
server: listen: :8080 mcp: enabled: true path: /mcp # HTTP route upstreams (optional — for proxying to APIs) upstreams: anthropic: url: https://api.anthropic.com timeout: 300s routes: - name: anthropic-proxy match: pathPrefix: /anthropic/v1 upstream: anthropic policy: kind: public stripPrefix: /anthropic

💡 Simplified by Design

Most configuration (enforcement mode, budgets, tokens) is managed from the cloud dashboard and pushed to your gateway automatically via WebSocket. You only need to define local upstreams and routes in this file.

🔒 Security Note

Set restrictive file permissions on the config: sudo chmod 600 /etc/satgate/hybrid-gateway.yaml

5. Set Up TLS (Caddy or nginx)

AI tools require HTTPS for custom API base URLs. Choose Caddy (automatic certificates) or nginx (manual certificate management).

# Install Caddy
sudo apt update
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | \
  sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
echo 'deb [signed-by=/usr/share/keyrings/caddy-stable-archive-keyring.gpg] \
  https://dl.cloudsmith.io/public/caddy/stable/deb/debian any-version main' | \
  sudo tee /etc/apt/sources.list.d/caddy-stable.list
sudo apt update
sudo apt install caddy

Configure Caddyfile

# /etc/caddy/Caddyfile
gw.yourdomain.com { reverse_proxy localhost:8080 { # REQUIRED for MCP SSE (Server-Sent Events) flush_interval -1 transport http { read_timeout 0 write_timeout 0 } } log { output file /var/log/caddy/satgate.log format json } header { Strict-Transport-Security "max-age=31536000; includeSubdomains" X-Frame-Options "DENY" X-Content-Type-Options "nosniff" Referrer-Policy "strict-origin-when-cross-origin" } }

🚨 CRITICAL: SSE Timeout Settings Required

The flush_interval and transport timeout settings are REQUIRED. Without them, Caddy kills MCP SSE connections after ~30 seconds. Cursor, Claude Desktop, and other MCP clients will connect, discover tools, then silently disconnect.

nginx Alternative

# /etc/nginx/sites-available/satgate
server { listen 443 ssl http2; server_name gw.yourdomain.com; ssl_certificate /etc/letsencrypt/live/gw.yourdomain.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/gw.yourdomain.com/privkey.pem; location / { proxy_pass http://127.0.0.1:8080; proxy_http_version 1.1; # REQUIRED for MCP SSE proxy_set_header Connection ''; proxy_buffering off; proxy_cache off; proxy_read_timeout 0; proxy_send_timeout 0; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } }
# Start and enable Caddy
sudo systemctl reload caddy
sudo systemctl enable caddy
sudo systemctl status caddy

✅ Why Caddy?

• Automatic Let's Encrypt certificates (no manual renewal)

• HTTP → HTTPS redirects automatically

• Zero-config HTTPS for most setups

• AI tools (Cursor, Claude Code) require HTTPS for custom API endpoints

6. Create systemd Service

Set up the gateway as a system service for automatic startup and restart on failure.

# /etc/systemd/system/satgate-gateway.service
[Unit] Description=SatGate Gateway (Enterprise Hybrid) After=network.target redis.service Wants=redis.service [Service] Type=simple User=root # Cloud connection Environment=ADMIN_TOKEN=your-admin-token-here # MCP configuration Environment=SATGATE_MCP_CONFIG=/etc/satgate/mcp-embedded.yaml Environment=GITHUB_TOKEN=ghp_your_github_token Environment=BRAVE_API_KEY=your_brave_api_key # Redis for budget enforcement Environment=REDIS_URL=redis://127.0.0.1:6379 ExecStart=/usr/local/bin/satgate-gateway \ -config /etc/satgate/hybrid-gateway.yaml \ --mode=hybrid \ --control-plane-url=wss://api.satgate.io/cloud/gateway/v1 \ --deployment-token=YOUR_DEPLOYMENT_TOKEN \ --gateway-name=my-gateway \ --gateway-region=us-east \ --gateway-listen=:8080 Restart=always RestartSec=5 StandardOutput=journal StandardError=journal [Install] WantedBy=multi-user.target

💡 Deployment Token

Get your --deployment-token from Settings → Hybrid Gateway in your dashboard.

# Create log directory and start service
sudo mkdir -p /var/log/satgate
sudo chmod 755 /var/log/satgate
sudo systemctl daemon-reload
sudo systemctl enable satgate-gateway
sudo systemctl start satgate-gateway
sudo systemctl status satgate-gateway

7. Configure MCP Tool Servers

The gateway loads MCP tool configuration from a separate YAML file pointed to by the SATGATE_MCP_CONFIG environment variable. This is how you expose actual MCP tools to connected agents.

Add to systemd Service

# In [Service] section of satgate-gateway.service:
Environment=SATGATE_MCP_CONFIG=/etc/satgate/mcp-embedded.yaml

Create MCP Configuration

# /etc/satgate/mcp-embedded.yaml
enabled: true path: /mcp upstreams: github: transport: stdio command: ["npx", "-y", "@modelcontextprotocol/server-github"] env: GITHUB_PERSONAL_ACCESS_TOKEN: "${GITHUB_TOKEN}" brave-search: transport: stdio command: ["npx", "-y", "@modelcontextprotocol/server-brave-search"] env: BRAVE_API_KEY: "${BRAVE_API_KEY}" budget: backend: redis limit: 10000 failMode: open tools: defaultCost: 5 costs: brave_web_search: 5 create_or_update_file: 20 search_repositories: 5 get_file_contents: 3 push_files: 25 create_issue: 10 create_pull_request: 25 enforcement: mode: observe

💡 Configuration Notes

• Environment variables (${VAR}) are expanded at load time — set them in the systemd service file

• Add API keys to the [Service] section: Environment=GITHUB_TOKEN=ghp_your_token_here

• Available transports: stdio (recommended for local tools), sse (for remote MCP servers)

enforcement: mode: observe logs tool calls without blocking — switch to control from the dashboard when ready

8. Connect to Cloud Dashboard

Verify the hybrid connection and enable real-time configuration management.

Gateway Side

  • Connects to cloud via WebSocket on startup
  • Authenticates with deployment token
  • Receives real-time config pushes
  • Sends audit events back to dashboard

Dashboard Side

  • Shows gateway status as "Connected"
  • Pushes routes, tokens, policies automatically
  • Displays real-time audit logs
  • Config changes take effect immediately

Verify Connection

  1. Go to Settings → Hybrid Gateway
  2. Check that status shows "Connected"
  3. Check gateway logs: sudo journalctl -u satgate-gateway -f
  4. Look for: "level":"info","msg":"cloud connection established"

✅ Hot Reload

Config changes in the dashboard take effect immediately — no gateway restart required. Routes, tokens, and policies are pushed in real-time.

9. Connect MCP Clients

Point your AI tools and MCP clients to the hybrid gateway. The gateway exposes MCP tools at the /mcp subpath.

⚠️ IMPORTANT: URL Must Include /mcp Subpath

When configuring MCP clients to connect to your hybrid gateway, the URL MUST include the /mcp subpath:

✅ Correct:https://gw.yourdomain.com/mcp
❌ Wrong:https://gw.yourdomain.com

The embedded MCP proxy is mounted at /mcp. Without the subpath, SSE connections will 404.

💡 Quick Setup

Visit /cloud/mcp/connect in your dashboard for tool-specific configuration guides with your exact endpoint URLs and tokens pre-filled.

Cursor

settings.json → mcpServers:

{ "mcpServers": { "satgate": { "url": "https://gw.yourdomain.com/mcp/sse", "headers": { "Authorization": "Bearer YOUR_SATGATE_TOKEN" } } } }

Claude Desktop

claude_desktop_config.json:

{ "mcpServers": { "satgate": { "command": "npx", "args": ["-y", "satgate-mcp-bridge"], "env": { "SATGATE_URL": "https://gw.yourdomain.com/mcp", "SATGATE_TOKEN": "YOUR_SATGATE_TOKEN" } } } }

OpenClaw

openclaw.json → mcp.servers:

{ "mcp": { "servers": { "satgate": { "command": "npx", "args": ["-y", "satgate-mcp-bridge"], "env": { "SATGATE_URL": "https://gw.yourdomain.com/mcp", "SATGATE_TOKEN": "YOUR_SATGATE_TOKEN" } } } } }

Claude Code

Environment (HTTP proxy mode):

ANTHROPIC_BASE_URL=https://gw.yourdomain.com ANTHROPIC_AUTH_TOKEN=<your-token>

10. Verify & Troubleshoot

Test the complete flow: token creation → AI tool configuration → request → audit verification.

1
Mint a Test Token

Go to Tokens and create a new token with a small budget ($1-5)

2
Configure an AI Tool

Set ANTHROPIC_AUTH_TOKEN to your test token and ANTHROPIC_BASE_URL to https://gw.yourdomain.com

3
Make a Test Request

Ask the AI tool to do something simple: "What's the capital of France?" or run a code generation task

4
Check Audit Log

Go to Audit and verify the request appears with cost attribution

5
Verify Budget Tracking

Check that the token's remaining budget decreased by the request cost

Quick curl Test

# Test the HTTP proxy directly
curl -X POST https://gw.yourdomain.com/anthropic/v1/messages \ -H "Authorization: Bearer <your-token>" \ -H "Content-Type: application/json" \ -H "anthropic-version: 2023-06-01" \ -d '{ "model": "claude-3-5-sonnet-20241022", "max_tokens": 50, "messages": [{"role": "user", "content": "Hello"}] }'

Common Issues

Common issues and solutions based on real deployment experience.

❌ "cannot execute binary file"

Cause: Wrong architecture — building on Mac creates arm64, but server is x86_64

Solution: Use GOOS=linux GOARCH=amd64 when cross-compiling

❌ "invalid signature" / "authentication failed"

Cause: Wrong deployment token or admin token in service file

Solution: Verify --deployment-token is copied exactly from Settings → Hybrid Gateway

❌ MCP tools return 404 / SSE disconnects after 30s

Cause: Either missing /mcp subpath in client URL, or Caddy/nginx missing SSE timeout settings

Solution: (1) Ensure client URL ends in /mcp, (2) Add flush_interval -1 and transport timeouts to Caddyfile

❌ Claude Code rejects HTTP

Cause: AI tools require HTTPS for custom API base URLs

Solution: Set up Caddy or nginx for TLS — HTTP is not sufficient for production

⚠️ Token doesn't work immediately

Cause: Config push from cloud takes ~5 seconds on first connect

Solution: Wait 5-10 seconds after creating a token before testing

⚠️ Gateway shows "Disconnected"

Cause: Network/firewall blocking WebSocket to api.satgate.io

Solution: Check firewall rules, ensure outbound HTTPS/WSS allowed on port 443

Log Analysis

Key log patterns to watch for:

✅ Successful startup:

"level":"info","msg":"gateway starting","version":"0.5.1"

✅ Cloud connected:

"level":"info","msg":"cloud connection established","tenant":"..."

⚠️ Config received:

"level":"info","msg":"config updated","routes":3,"tokens":5

❌ Auth failure:

"level":"error","msg":"authentication failed","error":"invalid signature"

Production Hardening

Additional security measures for production deployments.

🔒 Security

  • Use a dedicated service user (not root)
  • Set restrictive file permissions on config
  • Enable firewall (ufw/iptables)
  • Regular security updates

📊 Monitoring

  • Set up log rotation for gateway logs
  • Monitor disk space and Redis memory
  • Alert on service failures
  • Dashboard audit logs show request patterns

🔒 Enterprise: Network Policy Enforcement

For complete governance guarantee, block direct outbound access to LLM providers. All AI traffic must flow through SatGate.

Firewall Rules Example (iptables)

# Block direct access to LLM providers from agent subnet
iptables -A OUTPUT -d api.openai.com -j REJECT
iptables -A OUTPUT -d api.anthropic.com -j REJECT
iptables -A OUTPUT -d generativelanguage.googleapis.com -j REJECT
# Allow only SatGate gateway to reach upstreams
iptables -I OUTPUT -m owner --uid-owner satgate -j ACCEPT

See the Enterprise Deployment Guide for complete network policy patterns including Kubernetes and cloud-specific configurations.

🎯 Deployment Complete

🏗️
Infrastructure

Gateway deployed on your servers

🔗
Hybrid Connection

Real-time sync with cloud dashboard

🛡️
Governance

AI tools protected and audited

Your hybrid gateway is ready. Configure AI tools → mint tokens → monitor usage in the dashboard.