This guide explains how to secure your OpenClaw installation with various authentication methods to protect your AI agent and its capabilities from unauthorized access.
OpenClaw uses token-based authentication for the Web UI and API. This guide covers various approaches to secure your OpenClaw instance including gateway tokens, API keys, and reverse proxy authentication.
Generate a strong random token for gateway authentication:
# Generate a 64-character hex token
openssl rand -hex 32
# Or generate a base64 token
openssl rand -base64 32
Store this token securely (password manager or secrets vault).
cat > .env << EOF
# Gateway access token (required)
OPENCLAW_GATEWAY_TOKEN=your-secure-random-token-here
# Gateway port
OPENCLAW_GATEWAY_PORT=18789
OPENCLAW_BRIDGE_PORT=18790
# Bind address: "lan" for all interfaces, "loopback" for localhost only
OPENCLAW_GATEWAY_BIND=loopback
# Volume paths
OPENCLAW_CONFIG_DIR=/opt/openclaw/config
OPENCLAW_WORKSPACE_DIR=/opt/openclaw/workspace
# Docker image
OPENCLAW_IMAGE=ghcr.io/openclaw/openclaw:main
EOF
In your configuration file (~/.openclaw/openclaw.json or mounted config volume):
{
"gateway": {
"mode": "local",
"port": 18789,
"bind": "loopback",
"auth": {
"mode": "token",
"token": "your-secure-random-token-here"
}
},
"security": {
"pairingRequired": true,
"autoApprove": false,
"rateLimit": {
"enabled": true,
"requests": 100,
"windowMs": 3600000
}
}
}
version: '3.8'
services:
openclaw-gateway:
image: ${OPENCLAW_IMAGE:-openclaw:local}
container_name: openclaw-gateway
restart: unless-stopped
ports:
- "${OPENCLAW_GATEWAY_PORT:-18789}:18789"
volumes:
- ${OPENCLAW_CONFIG_DIR}:/home/node/.openclaw
- ${OPENCLAW_WORKSPACE_DIR}:/home/node/.openclaw/workspace
environment:
- HOME=/home/node
- OPENCLAW_GATEWAY_TOKEN=${OPENCLAW_GATEWAY_TOKEN}
# Security: Read-only root filesystem
read_only: true
tmpfs:
- /tmp
- /run
# Security: Drop capabilities
security_opt:
- no-new-privileges:true
cap_drop:
- ALL
cap_add:
- CHOWN
- SETUID
- SETGID
networks:
- openclaw-net
openclaw-cli:
image: ${OPENCLAW_IMAGE:-openclaw:local}
container_name: openclaw-cli
restart: unless-stopped
volumes:
- ${OPENCLAW_CONFIG_DIR}:/home/node/.openclaw
- ${OPENCLAW_WORKSPACE_DIR}:/home/node/.openclaw/workspace
environment:
- HOME=/home/node
- OPENCLAW_GATEWAY_TOKEN=${OPENCLAW_GATEWAY_TOKEN}
- BROWSER=echo
entrypoint: ["node", "dist/index.js"]
stdin_open: true
tty: true
# Security: Drop capabilities
security_opt:
- no-new-privileges:true
cap_drop:
- ALL
networks:
- openclaw-net
networks:
openclaw-net:
driver: bridge
Create an Nginx configuration with basic authentication:
cat > nginx-auth.conf << 'EOF'
events {
worker_connections 1024;
}
http {
# Upstream
upstream openclaw_backend {
server openclaw-gateway:18789;
}
# HTTP to HTTPS redirect
server {
listen 80;
server_name openclaw.yourdomain.com;
return 301 https://$server_name$request_uri;
}
# HTTPS server with authentication
server {
listen 443 ssl http2;
server_name openclaw.yourdomain.com;
ssl_certificate /etc/nginx/ssl/cert.pem;
ssl_certificate_key /etc/nginx/ssl/key.pem;
# Security headers
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
# Basic authentication
auth_basic "OpenClaw Authentication";
auth_basic_user_file /etc/nginx/.htpasswd;
# Rate limiting
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
limit_req zone=api burst=20 nodelay;
location / {
proxy_pass http://openclaw_backend;
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;
# Timeout settings
proxy_connect_timeout 60s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
}
# Health check without authentication
location /health {
access_log off;
return 200 "healthy\n";
add_header Content-Type text/plain;
}
}
}
EOF
# Install apache2-utils (for htpasswd command)
# Debian/Ubuntu:
apt-get install apache2-utils
# Create htpasswd file
htpasswd -c /etc/nginx/.htpasswd openclaw-user
# Add additional users
htpasswd /etc/nginx/.htpasswd another-user
Create an API key configuration file:
mkdir -p config/auth
cat > config/auth/api_keys.json << 'EOF'
{
"keys": [
{
"id": "prod-key-1",
"key": "sk-prod-abcdefghijklmnopqrstuvwxyz1234567890",
"name": "Production Application",
"permissions": ["read", "write", "execute-actions"],
"created_at": "2026-02-13T00:00:00.000Z",
"expires_at": null,
"rate_limit": 1000
},
{
"id": "dev-key-1",
"key": "sk-dev-abcdefghijklmnopqrstuvwxyz0987654321",
"name": "Development Access",
"permissions": ["read"],
"created_at": "2026-02-13T00:00:00.000Z",
"expires_at": "2026-03-13T00:00:00.000Z",
"rate_limit": 100
}
]
}
EOF
Reference this in your openclaw.json:
{
"security": {
"apiKeys": {
"enabled": true,
"file": "~/.openclaw/auth/api_keys.json"
}
}
}
OpenClaw requires device pairing for new channels. Configure pairing settings:
{
"security": {
"pairingRequired": true,
"autoApprove": false,
"pairingTimeout": 300,
"maxPendingPairings": 5
}
}
# List pending pairings
openclaw devices list
# Approve a pairing
openclaw devices approve <REQUEST_ID>
# Reject a pairing
openclaw devices reject <REQUEST_ID>
Configure rate limiting in openclaw.json:
{
"security": {
"rateLimit": {
"enabled": true,
"requests": 100,
"windowMs": 3600000,
"perIp": true,
"perUser": true
}
}
}
In Nginx:
# Rate limiting zones
limit_req_zone $binary_remote_addr zone=user_rate_limit:10m rate=10r/s;
limit_req_zone $server_zone zone=server_rate_limit:10m rate=100r/s;
# Apply rate limiting
location / {
limit_req zone=user_rate_limit burst=20 nodelay;
limit_req zone=server_rate_limit burst=200 nodelay;
# ... proxy configuration ...
}
Configure session settings:
{
"security": {
"session": {
"timeout": 7200,
"maxConcurrent": 10,
"secure": true,
"sameSite": "strict"
}
}
}
Store API keys in environment variables or a secrets manager:
# Using environment variables
export ANTHROPIC_API_KEY=sk-ant-your-key-here
export OPENAI_API_KEY=sk-your-key-here
# Or use a secrets file
cat > .secrets << EOF
ANTHROPIC_API_KEY=sk-ant-your-key-here
OPENAI_API_KEY=sk-your-key-here
EOF
# Load secrets
source .secrets
For additional security, encrypt sensitive configuration:
# Install age (modern encryption tool)
# macOS: brew install age
# Linux: apt install age
# Encrypt secrets
age -o .secrets.age -R recipients.txt .secrets
# Decrypt when needed
age -d -i key.txt .secrets.age
OPENCLAW_GATEWAY_BIND=loopback)# Verify token is set
echo $OPENCLAW_GATEWAY_TOKEN
# Check configuration
cat ~/.openclaw/openclaw.json | grep -A5 auth
# View logs for auth errors
docker compose logs openclaw-gateway | grep -i auth
# Generate new token
openssl rand -hex 32
# Update .env file
# Update openclaw.json
# Restart gateway
docker compose restart openclaw-gateway
# List pending pairings
openclaw devices list
# Clear all pending pairings
openclaw devices clear
# Check channel status
openclaw channels status
Any questions?
Feel free to contact us. Find all contact information on our contact page.