Skip to content

Security Hardening

ScenarioRecommended config
Local only (single machine)Default — no changes needed
LAN access (home/office)Bind to LAN IP, firewall to local subnet
Internet-facingReverse proxy with HTTPS, firewall, IP allowlist

Never expose the Snippbot port directly to the internet. Use nginx or Caddy to terminate TLS:

Terminal window
# Snippbot listens on localhost only
snippbot start --host 127.0.0.1 --port 18781

Your reverse proxy handles HTTPS and forwards to localhost:18781. See Reverse Proxy.

Allow only trusted IPs to reach the proxy:

Terminal window
# Ubuntu — ufw
ufw allow from YOUR_IP_HERE to any port 443
ufw deny 443
# Block direct access to Snippbot ports
ufw deny 18781
ufw deny 18790

The channel adapter (port 18790) needs to accept webhook traffic from specific platform IPs:

  • Slack: see Slack IP ranges
  • Discord: no fixed IP ranges — accept from anywhere, verify signatures
  • Telegram: 149.154.160.0/20 and 91.108.4.0/22

Always use HTTPS for internet-facing deployments:

Terminal window
# With Caddy (automatic Let's Encrypt)
caddy run --config Caddyfile
# With nginx + certbot
certbot --nginx -d snippbot.yourdomain.com

Redirect all HTTP to HTTPS — never serve on plain HTTP in production.

  1. Use strong API keys — the auto-generated snip_ keys are cryptographically random (256 bits). Don’t create short or guessable keys.

  2. Rotate keys regularly — revoke old keys and issue new ones:

    Terminal window
    # Revoke via UI: Settings → API Keys → Revoke
    # Or via API:
    curl -X DELETE http://localhost:18781/api/auth/keys/key_abc123 \
    -H "Authorization: Bearer $CURRENT_KEY"
  3. Use one key per client — don’t share keys between scripts, CI/CD, and users. This way you can revoke one without disrupting others.

  4. Store keys securely — use environment variables or a secrets manager. Never commit keys to version control.

Add rate limiting at the reverse proxy layer:

# nginx — limit to 30 requests/second per IP
limit_req_zone $binary_remote_addr zone=snippbot:10m rate=30r/s;
server {
location /api/ {
limit_req zone=snippbot burst=60 nodelay;
proxy_pass http://localhost:18781;
}
}
~/.snippbot/config.toml
# Require auth for all endpoints (default: true)
api_key_required = true
# Shorter session expiry for shared machines
session_expiry = 3600 # 1 hour
# Shorter inactivity timeout
inactivity_timeout = 900 # 15 minutes

The code-execution sandbox is not configured with environment variables. It is managed at runtime through the Sandbox settings page (or the PUT /api/sandbox/config API) and persisted to ~/.snippbot/sandbox_config.json.

To harden it, set the Isolation Profile to Strict, which containerizes all commands, mounts the workspace read-only, and disables the container network (zero outbound egress). Equivalently, via the API:

Terminal window
curl -X PUT http://127.0.0.1:18781/api/sandbox/config \
-H "Authorization: Bearer $SNIPPBOT_API_KEY" \
-H "Content-Type: application/json" \
-d '{"mode": "all", "workspace_access": "ro", "network": {"enabled": false}}'

Cap per-container memory with the Resources fields on that page (or the resources.memory_mb config field). Ensure a real container runtime is present (Docker or Podman) rather than the process fallback — set runtime_preference to prefer docker/podman, and consider block_when_no_runtime: true so a missing runtime fails closed (blocks) instead of falling back to the host.

Enable debug logging for the auth subsystem:

Terminal window
SNIPPBOT_LOG_LEVEL=debug snippbot start 2>&1 | grep -i 'auth\|unauthorized\|failed'

Review the access log periodically:

Terminal window
grep '401\|403' ~/.snippbot/logs/daemon.log | tail -50