Skip to content

Instantly share code, notes, and snippets.

@oEdyb
Last active February 11, 2026 20:58
Show Gist options
  • Select an option

  • Save oEdyb/e0b4a2a65555e48834695c712c49693f to your computer and use it in GitHub Desktop.

Select an option

Save oEdyb/e0b4a2a65555e48834695c712c49693f to your computer and use it in GitHub Desktop.
OpenClaw Full Setup Guide

OpenClaw Setup Guide

Setup documentation for deploying OpenClaw on a VPS. Potential video content.


Prerequisites

  • Fresh Ubuntu server (tested on Ubuntu 24.04)
  • SSH access with key authentication
  • Anthropic API key
  • Dedicated VPS β€” never run on your daily driver machine

⚠️ SECURITY ALERT (Feb 2026): A high-severity vulnerability was disclosed enabling one-click RCE via cross-site WebSocket hijacking. Always run npm install -g openclaw@latest to get the patched version. If you have an existing install, update immediately.


1. SSH Key Setup (On Your Local Machine)

πŸ’‘ What are SSH keys? Instead of typing a password every time you connect, SSH keys let your computer prove its identity using cryptography. You have a "private key" (stays on YOUR computer, never share) and a "public key" (goes on servers you want to access). It's like a house key that only works with your specific lock.

# Generate SSH key (skip if you already have one)
# -t ed25519: Use the ed25519 algorithm (modern, secure, fast)
# -C "comment": A label to help you remember what this key is for
ssh-keygen -t ed25519 -C "openclaw-server"

# This creates two files in ~/.ssh/:
#   id_ed25519       = your PRIVATE key (NEVER share this!)
#   id_ed25519.pub   = your PUBLIC key (safe to share, goes on servers)

# Display your public key (copy this entire line including "ssh-ed25519...")
cat ~/.ssh/id_ed25519.pub

In Hetzner Cloud Console β†’ Create Server β†’ SSH Keys β†’ Add your public key.

# Connect to server using SSH
# "root" = username, YOUR_SERVER_IP = the IP address Hetzner gave you
# Your private key is used automatically to prove your identity
ssh root@YOUR_SERVER_IP

2. Server Security & Essentials

πŸ’‘ Why all this security stuff? A server on the internet gets attacked constantly β€” bots scan for weak passwords, open ports, and vulnerable software 24/7. These steps create layers of defense so even if one thing fails, attackers can't get in.

# Update package list and upgrade all installed packages to latest versions
# "apt update" = refresh the list of available software
# "apt upgrade" = install newer versions of what you have
# "-y" = answer "yes" automatically to prompts
sudo apt update && sudo apt upgrade -y

# Install essential security and utility tools:
# - ufw: "Uncomplicated Firewall" β€” blocks unwanted network traffic
# - fail2ban: Automatically bans IPs that try too many failed logins
# - git, curl, wget: Tools for downloading code and files
# - build-essential: Compilers needed to install some software
# - zsh: A nicer shell (optional but recommended)
sudo apt install -y ufw fail2ban git curl wget build-essential zsh

πŸ’‘ What does fail2ban do? It watches your login logs. If someone tries to guess your password and fails too many times (e.g., 5 failed attempts), fail2ban automatically blocks their IP address for a period of time. It runs in the background β€” you installed it, it's already protecting you, no extra config needed for basic protection.

# Ensure fail2ban starts on boot and is running
sudo systemctl enable fail2ban
sudo systemctl start fail2ban

# Verify it's active (should show "active (running)" in green)
sudo systemctl status fail2ban

Firewall Setup

πŸ’‘ What's a firewall? Think of it as a bouncer for your server. It blocks ALL incoming connections except the ones you explicitly allow. Without it, any service running on your server could be accessed by anyone on the internet.

# Allow SSH connections (port 22) β€” this is how YOU connect to the server
# If you block this, you'll lock yourself out!
sudo ufw allow ssh

# Turn on the firewall
# IMPORTANT: Make sure you allowed SSH first, or you'll be locked out
sudo ufw enable

# That's it! Only SSH is allowed now. OpenClaw's port (18789) stays blocked,
# which is exactly what we want β€” we'll access it securely via SSH tunnel later.

Disable Password Login

πŸ’‘ Why disable passwords? Passwords can be guessed. Bots try thousands of common passwords every day. SSH keys are virtually impossible to guess (they're like a 3000-character random password). Once your key is working, disable passwords to eliminate that attack vector entirely.

# Modify SSH config to disable password authentication
# "sed -i" = edit file in place
# 's/old/new/' = replace "old" with "new"
# We run it twice to catch both commented (#) and uncommented versions
sudo sed -i 's/#PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config
sudo sed -i 's/PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config

# Restart SSH service to apply changes
sudo systemctl restart ssh

# Verify the change worked (should show "PasswordAuthentication no")
grep PasswordAuthentication /etc/ssh/sshd_config

# Check firewall status (should only show SSH/22 allowed)
sudo ufw status

⚠️ Never expose port 18789 to the internet. Use SSH tunnel to access remotely (see Section 8).


(Optional) Better Shell with Zsh

Nicer terminal with autocomplete, syntax highlighting (shows valid commands in green, invalid in red), and quick directory jumping.

# Install Oh My Zsh (will prompt to set zsh as default)
sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"

# Install plugins
git clone https://github.com/zsh-users/zsh-autosuggestions.git ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-autosuggestions
git clone https://github.com/zsh-users/zsh-syntax-highlighting.git ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-syntax-highlighting

# Enable plugins (edit ~/.zshrc, find plugins= line)
nano ~/.zshrc
# Change to: plugins=(git z zsh-autosuggestions zsh-syntax-highlighting)
# Right click to paste, ctrl+o to save, enter, ctrl+x

# Apply
source ~/.zshrc

What you get:

  • z β€” jump to directories by partial name (e.g., z proj β†’ /home/user/projects)
  • Autosuggestions β€” gray text shows command history as you type, press β†’ to accept
  • Syntax highlighting β€” valid commands green, invalid red, paths underlined

3. Node.js 24 LTS

# Download and run the NodeSource setup script
# This adds their package repository so we can install a modern Node.js version
# (Ubuntu's default repos often have outdated versions)
# curl -fsSL = download silently, follow redirects, show errors
# | sudo -E bash - = pipe it to bash running as sudo
curl -fsSL https://deb.nodesource.com/setup_24.x | sudo -E bash -

# Now install Node.js from the repository we just added
sudo apt install -y nodejs

# Verify it worked (should show v24.x.x)
node --version

4. OpenClaw Install & Onboard

πŸ’‘ Why run as root? On a dedicated single-purpose VPS, running as root is simpler and avoids issues with systemd user services. The real security comes from network isolation (Tailscale + UFW), not user separation. This is also what most popular OpenClaw setup guides recommend.

# Install OpenClaw globally using npm
# "-g" = global install, so you can run "openclaw" from anywhere
# "@latest" = get the newest version
npm install -g openclaw@latest

# Run the setup wizard
# "--install-daemon" = also install it as a background service that starts on boot
openclaw onboard --install-daemon

During onboard:

  • Enabled hooks: boot-md, session-memory
  • Skipped skills (configure later)
  • Set up Anthropic auth (Claude token)

5. Security Audit

# Run OpenClaw's built-in security check and auto-fix issues
openclaw security audit --fix

# For a deeper scan (checks exposed ports, auth issues, permissions)
openclaw security audit --deep

# Verify the gateway is binding to localhost only
# netstat shows network connections; -tlnp = TCP, listening, numeric, process info
# We grep for the OpenClaw port to see what address it's bound to
netstat -tlnp | grep 18789

πŸ’‘ 127.0.0.1 vs 0.0.0.0 β€” why it matters:

  • 127.0.0.1:18789 = βœ… GOOD β€” only accepts connections from this machine itself (localhost)
  • 0.0.0.0:18789 = ❌ BAD β€” accepts connections from ANYWHERE on the internet

If you see 0.0.0.0, anyone who finds your server's IP could potentially access OpenClaw. With 127.0.0.1, the only way in is through an SSH tunnel (which requires your SSH key).


6. Discord Configuration

Done via TUI (not CLI commands):

  • Give it the Discord bot token
  • Add server (guild) ID
  • Add specific text channel IDs
  • Add your user ID to allowlist ← CRITICAL: never leave empty

πŸ’‘ Why is the allowlist critical? The allowlist controls WHO can give commands to your OpenClaw instance through Discord. If you leave it empty or set it wrong, random people in your Discord server could potentially make your AI agent do things. Always add your Discord user ID to the allowlist so only YOU can control it.


7. Auth Fix

If you get a 401 error, re-run onboarding:

openclaw onboard

Confirm existing config, re-authenticate with Anthropic.


8. Remote Access (From Your Local Machine)

Don't expose port 18789 to the internet. Use SSH tunnel instead.

πŸ’‘ What's an SSH tunnel? It's like a secret passage. Your computer connects to the server via SSH (which is allowed through the firewall), and then "forwards" traffic through that secure connection. So when you visit localhost:18789 on YOUR computer, it secretly travels through the SSH connection to reach the server's localhost:18789. The port never needs to be opened to the public internet.

# Run this on YOUR computer (not the server)
# -L = "Local port forwarding"
# 18789:localhost:18789 means:
#   "When I connect to port 18789 on my machine,
#    forward it to localhost:18789 on the remote server"
# root@YOUR_HETZNER_IP = connect as the root user
ssh -L 18789:localhost:18789 root@YOUR_HETZNER_IP

# While this SSH session is running, you can open your browser and go to:
#   http://localhost:18789
# It will actually show the OpenClaw interface from your server!
# When you close the SSH session, the tunnel closes too.

Alternative: Tailscale (Always-On Access)

πŸ’‘ What's Tailscale? It creates a private network between your devices using WireGuard VPN. Your server gets a private IP (like 100.x.x.x) that only YOUR devices can access. No port forwarding, no SSH tunnel needed β€” just connect directly using the Tailscale IP. It's like your server and laptop are on the same home network, even though one is in a data center.

# On the Hetzner server β€” install Tailscale
curl -fsSL https://tailscale.com/install.sh | sh

# Start Tailscale and authenticate (opens a browser link)
sudo tailscale up

# Check your Tailscale IP
tailscale ip -4
# Should show something like 100.64.0.1

Basic access (Tailscale IP):

# Install Tailscale on your laptop too, then access via the Tailscale IP:
#   http://100.64.0.1:18789
# Works from anywhere, no SSH tunnel needed, still secure

Better: Tailscale Serve (HTTPS with ts.net URL):

πŸ’‘ What's Tailscale Serve? Instead of using a raw IP + port, Tailscale Serve exposes your service at a clean HTTPS URL like https://srv1234567.ts.net. This adds TLS encryption and is easier to bookmark. Your service becomes completely invisible to the public internet β€” only devices on your Tailnet can access it.

# Set up Tailscale Serve (replace 18789 with your actual port if different)
# --bg = run in background
sudo tailscale serve --bg http://localhost:18789

# Check what URL you got
tailscale serve status
# Output shows something like: https://srv1234567.tail8328fe.ts.net

# Now you can access OpenClaw from any device on your Tailnet at that URL
# No port number needed, HTTPS included

Extra: Block the port explicitly in UFW:

# Even though the port isn't exposed by default, explicitly deny it
# This provides defense-in-depth in case something changes
sudo ufw deny 18789

Verify your setup is actually secure:

  1. βœ… Should work: Access your ts.net URL from a device with Tailscale connected
  2. ❌ Should NOT work: Access http://YOUR_VPS_PUBLIC_IP:18789 from any browser

If the public IP loads, your firewall isn't configured correctly.


9. Start Gateway

# Start the gateway (if not using daemon mode)
openclaw gateway

# Useful gateway commands:
openclaw gateway status    # Check if gateway is running
openclaw gateway restart   # Restart the gateway
openclaw logs              # View gateway logs
openclaw doctor            # Diagnose issues
openclaw channels status --probe  # Test Discord/channel connectivity

Access the dashboard:

# Get the correct tokenized URL
openclaw dashboard

# If accessing remotely, open SSH tunnel first (on your LOCAL machine):
ssh -N -L 18789:127.0.0.1:18789 root@YOUR_SERVER_IP

# Then open the URL in your browser

10. Gateway Token Auth

πŸ’‘ What's this? Even with Tailscale, you want a password on your dashboard. The gateway token acts as a shared secret β€” anyone with the token can access your OpenClaw instance. Without it, anyone on your Tailnet could control your agent.

Easiest method β€” get the correct tokenized URL:

openclaw dashboard

This outputs the full URL with token. Copy and paste it into your browser.

For Docker installs (Hostinger one-click, etc.):

# Find your gateway token in the container environment
docker inspect $(docker ps -q) | grep -i OPENCLAW_GATEWAY_TOKEN
# Output: "OPENCLAW_GATEWAY_TOKEN=abc123def456ghi789jkl"

# Your tokenized URL becomes:
# https://YOUR_TAILSCALE_URL?token=abc123def456ghi789jkl
# Example: https://srv1234567.ts.net?token=abc123def456ghi789jkl

For native npm installs:

# Check if token is configured (token is auto-generated during onboard)
cat ~/.openclaw/openclaw.json | grep gateway_token

# The onboard wizard generates a token automatically.
# Your tokenized URL is shown at the end of onboarding.
# If you need to regenerate, edit the config or run:
openssl rand -hex 32

Bookmark your tokenized URL. No token = no access.


11. Auto Security Updates

πŸ’‘ Why? Security patches drop constantly. Unattended-upgrades keeps your server patched automatically β€” one less thing to remember. Critical for a server that runs 24/7.

# Install unattended-upgrades
sudo apt install unattended-upgrades -y

# Enable automatic security updates
sudo dpkg-reconfigure -plow unattended-upgrades
# Select "Yes" when prompted

# Verify it's configured
cat /etc/apt/apt.conf.d/20auto-upgrades
# Should show: APT::Periodic::Unattended-Upgrade "1";

Your server now patches itself. Sleep better.


Troubleshooting

"unauthorized: gateway token mismatch"

This is the most common issue when accessing the dashboard. The token in your URL doesn't match what the gateway expects.

Fix it in one command:

openclaw dashboard

This outputs the correct tokenized URL. Copy and paste it into your browser.

If accessing remotely (SSH tunnel):

# On your LOCAL machine, open the tunnel:
ssh -N -L 18789:127.0.0.1:18789 root@YOUR_SERVER_IP

# Then open the URL from `openclaw dashboard` in your browser:
# http://localhost:18789/?token=YOUR_TOKEN_HERE

If you have OpenClaw running locally too:

If port 18789 is already in use on your local machine (e.g., you're running OpenClaw locally), use a different local port:

# Use port 18790 locally instead
ssh -N -L 18790:127.0.0.1:18789 root@YOUR_SERVER_IP

# Then access via the different port:
# http://localhost:18790/?token=YOUR_TOKEN_HERE

If the gateway isn't running:

# Check if it's running
netstat -tlnp | grep 18789

# Start it if needed
openclaw gateway

Gateway won't start / crashes

# Run diagnostics
openclaw doctor

# Check logs
openclaw logs

# Kill any zombie processes and restart
pkill -f openclaw-gate
openclaw gateway

Discord bot not responding

# Check channel connectivity
openclaw channels status --probe

# Make sure you configured the channel allowlist
openclaw configure --section discord

πŸ’‘ Pro tip: If you left the Discord channel allowlist empty during onboarding, the bot won't respond to any channels. You must add specific channel IDs.


Security Checklist

πŸ’‘ Why each item matters β€” if any of these fail, you're exposed:

Before going live:

  • Port 18789 NOT in UFW rules (sudo ufw status) β€” the port shouldn't appear in the list; it should be blocked from the internet
  • Gateway shows 127.0.0.1:18789 (not 0.0.0.0) β€” ensures OpenClaw only accepts local connections, not internet traffic
  • Discord user allowlist configured β€” prevents random Discord users from controlling your AI agent
  • Accessing via SSH tunnel or Tailscale β€” you have a secure way to reach the gateway without exposing it to the internet
  • Gateway token configured β€” dashboard requires password to access
  • Unattended-upgrades enabled β€” server patches itself automatically
  • Public IP access fails β€” test that http://YOUR_IP:18789 does NOT load from external browser
  • Dedicated VPS only β€” never run on your daily driver machine

Quick Reference Commands

# --- Status Checks ---
tailscale ip -4                    # Check Tailscale IP
tailscale serve status             # Check serve URL
sudo ufw status                    # Check firewall rules
netstat -tlnp | grep 18789         # Check what's listening on the port

# --- OpenClaw ---
openclaw dashboard                 # Get correct tokenized dashboard URL
openclaw gateway                   # Start the gateway
openclaw gateway status            # Check gateway running
openclaw logs                      # View logs
openclaw doctor                    # Diagnose issues
openclaw channels status --probe   # Test Discord connectivity

# --- Docker (if using) ---
docker ps                          # List running containers
docker logs $(docker ps -q)        # View container logs
docker inspect $(docker ps -q) | grep -i OPENCLAW_GATEWAY_TOKEN  # Get token

# --- Security ---
sudo systemctl status fail2ban     # Check fail2ban running
cat /etc/apt/apt.conf.d/20auto-upgrades  # Check auto-updates configured

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment