Installation and Security Hardening
From a fresh Ubuntu VPS to a running, hardened OpenClaw Gateway with Nginx SSL and systemd auto-restart.
⚠️ Security Warning
Do not skip the security steps. OpenClaw binds to 0.0.0.0 by default, which exposes the control API to the public internet on port 18789. In early 2026, Censys found over 21,000 exposed instances before CVE-2026-25253 (a one-click RCE via WebSocket hijacking) was patched. The fix is in current versions, but the exposure problem is architectural and yours to solve.
1Initial Server Configuration
Create a dedicated service user. Running the Gateway as root is unnecessary and significantly increases blast radius if a skill misbehaves.
# Update the system
apt update && apt upgrade -y
# Create a non-root user for OpenClaw
adduser openclawops
usermod -aG sudo openclawops
# Copy your SSH authorized_keys to the new user
mkdir -p /home/openclawops/.ssh
cp ~/.ssh/authorized_keys /home/openclawops/.ssh/
chown -R openclawops:openclawops /home/openclawops/.ssh
chmod 700 /home/openclawops/.ssh
chmod 600 /home/openclawops/.ssh/authorized_keysDisconnect and reconnect as openclawops before continuing. Do not run the rest of this guide as root.
2Firewall Configuration with UFW
# Set default policies
sudo ufw default deny incoming
sudo ufw default allow outgoing
# Allow SSH with rate limiting
sudo ufw allow 22/tcp
sudo ufw limit 22/tcp
# Allow HTTP and HTTPS for Nginx
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
# Explicitly block the OpenClaw Gateway port from public access
sudo ufw deny 18789/tcp
# Enable the firewall
sudo ufw enable
# Verify rules
sudo ufw status verboseThe Gateway will be accessible through Nginx on port 443 after SSL is configured. Port 18789 stays closed to the public.
3Install fail2ban
fail2ban monitors log files and bans IPs that show signs of brute-force activity. On a public VPS this is not optional.
sudo apt install fail2ban -y
# Create a local config that survives package updates
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.localEdit the [sshd] section in /etc/fail2ban/jail.local:
[sshd]
enabled = true
port = ssh
filter = sshd
logpath = %(sshd_log)s
maxretry = 5
bantime = 3600
findtime = 600sudo systemctl enable fail2ban
sudo systemctl start fail2ban4Install Node.js 24
The official OpenClaw documentation requires Node.js 22.16 at minimum and recommends Node.js 24. Older versions produce silent failures.
# Install NodeSource repository for Node.js 24
curl -fsSL https://deb.nodesource.com/setup_24.x | sudo -E bash -
sudo apt install nodejs -y
# Verify versions
node --version # Should output v24.x.x
npm --version5Install OpenClaw (Native Install)
The recommended first-install path uses the official onboard script with the --install-daemon flag to register a systemd service.
# Install OpenClaw globally
npm install -g openclaw@latest
# Verify the install
openclaw --version
# Run the interactive onboard wizard
openclaw onboard --install-daemonThe wizard will configure your model provider, workspace directory, gateway settings, and optional channels.
🔒 Critical Security Configuration
When asked about the gateway bind address, set it to loopback rather than the default. This restricts the Gateway to localhost only:
gateway.bind: "loopback"If you miss this during onboard:
openclaw config set gateway.bind loopback
openclaw gateway restart5Alternative: Docker-Based Install
If you prefer container isolation, Docker is a supported install path.
# Install Docker
curl -fsSL https://get.docker.com | sudo bash
sudo usermod -aG docker openclawops
# Log out and back in, then:
mkdir -p ~/openclaw
cd ~/openclaw
cat > docker-compose.yml <<'EOF'
services:
openclaw:
image: openclaw/openclaw:latest
container_name: openclaw
restart: unless-stopped
ports:
- "127.0.0.1:18789:18789"
volumes:
- openclaw_config:/root/.openclaw
- openclaw_workspace:/root/.openclaw/workspace
environment:
- OPENCLAW_GATEWAY_BIND=loopback
volumes:
openclaw_config:
openclaw_workspace:
EOF
docker compose up -d
docker compose logs -f openclawThe 127.0.0.1:18789:18789 port binding exposes the Gateway only on the loopback interface — not on the public IP.
6Verify the systemd Service (Native Install)
# Check service status
systemctl --user status openclaw
# Enable at boot
systemctl --user enable openclaw
# View logs
journalctl --user -u openclaw -f
# Enable lingering so service starts without login
sudo loginctl enable-linger openclawops7Nginx Reverse Proxy with SSL
Nginx terminates SSL and proxies to 127.0.0.1:18789. Port 18789 never needs to be open to the public.
sudo apt install nginx certbot python3-certbot-nginx -yCreate /etc/nginx/sites-available/openclaw:
server {
listen 80;
server_name agent.yourdomain.com;
location / {
proxy_pass http://127.0.0.1:18789;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
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;
proxy_read_timeout 86400;
}
}The Upgrade and Connection headers are required — OpenClaw uses WebSockets for real-time communication.
# Enable the site
sudo ln -s /etc/nginx/sites-available/openclaw /etc/nginx/sites-enabled/
# Test and reload Nginx
sudo nginx -t
sudo systemctl reload nginx
# Obtain SSL certificate
sudo certbot --nginx -d agent.yourdomain.com
# Verify auto-renewal
sudo certbot renew --dry-run8Set a Gateway Auth Token
Even behind Nginx with SSL, the Control UI should require authentication.
# Generate a strong token
openssl rand -hex 32
# Set it in OpenClaw
openclaw config set gateway.token "your-strong-random-token-here"
openclaw gateway restart9Harden Credential Storage
OpenClaw stores API keys and credentials in plaintext under ~/.openclaw/credentials/. This is a known target for infostealers.
chmod 700 ~/.openclaw/credentials/
chmod 600 ~/.openclaw/credentials/*
# Also restrict the main config directory
chmod 700 ~/.openclaw/10Verify the Deployment
openclaw doctorThis checks runtime status, channel connections, Gateway reachability, and common misconfigurations. Then open https://agent.yourdomain.com and send a test message.
Key File Locations
| Path | Purpose |
|---|---|
| ~/.openclaw/ | Main config directory |
| ~/.openclaw/credentials/ | API keys and channel secrets |
| ~/.openclaw/workspace/ | Agent memory, skills, notes |
| ~/.openclaw/openclaw.config.yaml | Main configuration file |
| /etc/nginx/sites-available/openclaw | Nginx server block |
