# OpenClaw VPS Configuration Guide This is a step-by-step configuration guide for [[OpenClaw]] on a VPS ([[Ubuntu]]-based), using [[Tailscale]] for more secure access. ``` # Create your VPS # Get the IP & root account password # Login over SSH as root ssh root@<ip> # Change root password # Add your SSH pubkey to ~/ssh/authorized_keys # Update sudo apt update && sudo apt upgrade sudo apt dist-upgrade # Enabled automatic security updates sudo apt install unattended-upgrades -y sudo dpkg-reconfigure -plow unattended-upgrades ## Verify it's enabled: cat /etc/apt/apt.conf.d/20auto-upgrades # Change hostname sudo hostnamectl set-hostname <foo> # Create YOUR user account (sudoer) adduser <yourusername> # Add it to sudoers usermod -aG sudo <yourusername> # Switch user su <yourusername> # Add your SSH pubkey mkdir /home/<yourusername>/.ssh sudo chown -R <yourusername> /home/<yourusername>/.ssh sudo chgrp -R <yourusername> /home/<yourusername>/.ssh sudo chmod 0700 /home/<yourusername>/.ssh sudo chmod 0600 /home/<yourusername>/.ssh/authorized_keys # Validate that you can connect using your SSH key # Configure the SSH daemon sudo su # Switch back to root nano /etc/sshd/sshd_config PermitRootLogin no PasswordAuthentication no PermitEmptyPasswords no # Restart SSH daemon sudo sshd -t && sudo systemctl reload ssh # Brute-force protection → Auto-ban IPs after failed login attempts. sudo apt install fail2ban -y sudo systemctl enable --now fail2ban # Enable NTP Time Synchronization sudo apt install chrony -y sudo systemctl enable --now chrony ## Verify it's working chronyc tracking # Create a Swap file sudo fallocate -l 2G /swapfile sudo chmod 600 /swapfile sudo mkswap /swapfile sudo swapon /swapfile echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab ## Verify it's ok free -h # Install Tailscale # More secure connections to the VPS sudo curl -fsSL https://tailscale.com/install.sh | sh # Start Tailscale sudo tailscale up # Connect the VPS to Tailscale # Optional: Disable key expiry for it: https://login.tailscale.com/admin/machines # Verify Tailscale is running tailscale status # Get Tailscale IPv4 on your own computer (aka client host) tailscale ip -4 # Take note of it # Run the same command on your VPS to get its Tailscale IP # BLOCK Tailscale incoming traffic on your own computer # If your VPS is p0wned, you DO NOT want it to be able to reach your machine sudo tailscale set --shields-up=true # Change SSH configuration on your own client to use the Tailscale IP as HostName ## Go to ~/.ssh ## Edit the 'config' file ## Add an entry to use your SSH key and use the VPS' Tailscale IP ## Validate it works # Enable UFW sudo apt install ufw -y sudo ufw enable # Restrict traffic sudo ufw default deny incoming sudo ufw default allow outgoing sudo ufw status verbose # SSH only via Tailscale: No more public SSH exposure # Allow inbound Tailscale traffic sudo ufw allow in on tailscale0 sudo ufw status verbose # Reload UFW sudo ufw reload sudo service ssh restart # Enable 443 and 80 ports from your client host (i.e., your machine) sudo ufw allow from <your client host's Tailscale IP>/24 to any port 443 proto tcp sudo ufw allow from <your client host's Tailscale IP>/24 to any port 80 proto tcp sudo ufw status verbose sudo ufw reload # Create a user account for the AI Agent sudo adduser foo sudo usermod -aG sudo foo su - foo # Install OpenClaw curl -fsSL https://openclaw.ai/install.sh | bash exec bash # Reload bash profile source .profile # Configure the OpenClaw gateway to use Tailscale openclaw configure # Where will the Gateway run? Local (this machine) # Select sections to configure: Gateway # Gateway port: 18789 # Gateway bind mode: Tailnet (Tailscale IP) # Tailscale exposure: Serve (Private HTTPS for your tailnet (devices on Tailscale)) # Reset Tailscale serve/funnel on exit? No ## During the config, connect your WhatsApp or Telegram etc # Expose the Gateway via Tailscale sudo tailscale serve --bg 18789 sudo tailscale serve status # To disable it: sudo tailscale serve --https=443 off # Run audits and tighten security openclaw doctor openclaw security audit openclaw security audit --deep openclaw security audit --fix # Added trusteproxies (127.0.0.1) to ~/.openclaw/openclaw.json # Inside "gateway" object: # "trustedProxies": ["127.0.0.1"] # Start the gateway openclaw gateway --force # In another terminal ## List devices openclaw devices list ## Approve client Tailscale device openclaw devices approve <Request> # Connect with browser to Tailscale service URL # Install jq sudo apt install jq # Install nvm curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.4/install.sh | bash nvm install x.y.z nvm use x.y.z # Install Bun: https://bun.com/docs/installation sudo apt install unzip curl -fsSL https://bun.com/install | bash source /home/foo/.bashrc ## Install pnpm: https://pnpm.io/installation curl -fsSL https://get.pnpm.io/install.sh | sh - ## Install Homebrew /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" echo >> /home/foo/.bashrc echo 'eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv bash)"' >> /home/foo/.bashrc # Install gh CLI curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg | sudo dd of=/usr/share/keyrings/githubcli-archive-keyring.gpg sudo chmod go+r /usr/share/keyrings/githubcli-archive-keyring.gpg echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null sudo apt update && sudo apt install gh -y # Configure Web client openclaw configure --section web ## Get a Brave API key and enable web fetch: https://api-dashboard.search.brave.com/app/keys # Configure systemctl service sudo cp ~/.openclaw/openclaw-gateway.service /etc/systemd/system/ sudo systemctl daemon-reload sudo systemctl enable --now openclaw-gateway sudo systemctl status openclaw-gateway # Setup the systemd daemon # Reference: https://docs.openclaw.ai/platforms/linux#system-control-systemd-user-unit Create ~/.config/systemd/user/openclaw-gateway.service Add this to it: --- [Unit] Description=OpenClaw Gateway After=network-online.target Wants=network-online.target [Service] Type=simple ExecStart=/home/foo/.npm-global/bin/openclaw gateway --port 18789 Restart=always RestartSec=5 Environment=HOME=/home/foo Environment=PATH=/usr/local/bin:/usr/bin:/bin:/home/foo/.npm-global/bin Environment=NODE_ENV=production [Install] WantedBy=default.target --- # Enable the systemd service systemctl --user enable --now openclaw-gateway.service # Verify it is running correctly systemctl --user status openclaw journalctl --user -u openclaw -f # Once started, you should be able to connect to the Web UI # TIP: You can find your Tailscale DNS name here: https://login.tailscale.com/admin/dns # Run a deep check and fix any raised issues: openclaw security audit --deep openclaw security audit --fix # Install browser agent + Chromium: https://github.com/vercel-labs/agent-browser npm install -g agent-browser agent-browser install --with-deps # Install a real Web browser wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb sudo dpkg -i google-chrome-stable_current_amd64.deb sudo apt --fix-broken install -y # if there are dependency errors ## Configure the browser to run as a service touch ~/.config/systemd/user/openclaw-browser.service && nano ~/.config/systemd/user/openclaw-browser.service --- [Unit] Description=OpenClaw Browser (Chrome CDP) After=network.target [Service] ExecStart=/usr/bin/google-chrome --headless --no-sandbox --disable-gpu --remote-debugging-port=18800 --user-data-dir=%h/.openclaw/browser/openclaw/user-data about:blank Restart=on-failure RestartSec=5 [Install] WantedBy=default.target --- ## Then enable the browser service systemctl --user enable --now openclaw-browser.service ## Test it curl -s http://127.0.0.1:18791/ | jq '{running, pid, chosenBrowser}' curl -s -X POST http://127.0.0.1:18791/start curl -s http://127.0.0.1:18791/tabs ## Configure OpenClaw to use it nano ~/.openclaw/openclaw.json --- "browser": { "enabled": true, "executablePath": "/usr/bin/google-chrome-stable", "headless": true, "noSandbox": true }, --- ``` # Back everything up ``` tar czf - ~/.openclaw > openclaw-backup-$(date +%Y%m%d).tar.gz ``` After this your VPS should be secure-enough and good to go! ## More "protections" Although this won't save you from everything, these skills can help: ``` npx clawhub install skillguard npx clawhub install prompt-guard ``` Also, make 100% sure you BLOCK the incoming traffic to machines on your [[Tailscale]] network by default using: `` ## Heartbeat Play with your agent for a while before enabling the heartbeat (i.e., what makes the agent come alive every X). Once you're more confident, check out: https://docs.openclaw.ai/gateway/heartbeat When you configure that, make sure to adapt HEARTBEAT.md in the workspace. That's where you can configure the instructions/prompt: https://docs.openclaw.ai/gateway/heartbeat#what-the-heartbeat-prompt-is-for ## Staying up to date See here: https://docs.openclaw.ai/install/updating ## Bonuses ### Git for the OpenClaw workspace You may also want to create a repository for [[OpenClaw]]'s workspace (~/.openclaw/workspace). This is a good thing to do because that way you have a backup and can restore if/when needed. If you do that, also make sure to give a hard rule to your agent about always doing a git commit/push when it changes its workspace. ### Disable mDNS Broadcasting You should also probably disable mDNS broadcasting. Your whole network doesn't need to know you're running OpenClaw: ``` echo 'export OPENCLAW_DISABLE_BONJOUR=1' >> ~/.bashrc source ~/.bashrc sudo systemctl restart openclaw ``` ### Install and Configure Skills - Run `openclaw configure` - Go to the skills configuration - Select those you want using space, then hit enter - Recommended - summarize - video-frames - ... ### Create a Discord Bot - Go to https://discord.com/developers/applications - Click "New Application" → name it - Go to *Bot* section → "Add Bot" - Copy the *Bot Token* (keep it secret!) - Enable required intents - In Bot settings, enable: - ✅ Message Content Intent - ✅ Server Members Intent (optional) - Invite the bot to your server - Go to *OAuth2 → URL Generator* - Select scopes: bot - Select permissions: Send Messages, Read Message History, Add Reactions, ... (or Administrator, depending on what you want/need your agent to do) - Open the generated URL to add the bot to your server - Give the bot token to your assistant and let it handle the configuration on its side - Once configured, send a Discord DM to your bot. It will reply with a pairing code - Go to your server and run `openclaw pairing list discord` - Copy the code - Run `openclaw pairing approve discord <code>` - You're good to go DO NOT open this up. Lock down access to your server id only, enforce approvals, etc: - Set `groupPolicy` to `allowlist` - Add your server id to `guilds` ### Give Control Over Chrome running on your Computer Although this MUST be considered HIGHLY risky, it's possible to expose a Chrome browser launched in debug mode on your computer to the OpenClaw agent running on your VPS. This can be useful when the agent can't work around [[Cloudflare]] and the like, or you need to be able to see the browser to intervene. **WARNING**: As I said, this is REALLY dangerous. If you do want that nevertheless, then you SHOULD REALLY use a temporary/dedicated chrome profile and NOT your own. Also, ONLY expose your computer for the minimum amount of time. Don't allow incoming connections all the time. And EVEN if you do that, you'll be at risk, because the [[Lethal Trifecta for AI Agents|Lethal Trifecta]] may p0wn your AI... The idea is to start Chrome on your computer with the [[Chrome Debug Mode]] enabled, and to connect to its [[Chrome DevTools]] via the [[Chrome DevTools Protocol (CDP)]]. First, get your computer's IPv4 [[Tailscale]]: `tailscale ip -4`. One the OpenClaw server, edit the `openclaw.json` configuration. You need to add a profile for your browser. Give it a useful name, and make it point to port `9223` on your computer's Tailscale IP: ``` ... "browser": { "enabled": true, ... "profiles": { "your-browser": { "cdpUrl": "http://<your computer tailscale ip:9223" ... }, ... } } ... ``` Second, install the prerequisites on your computer: - [[socat]], a powerful tool created by [[Gerhard Rieger]]. This will expose the traffic from the chrome instance (normally limited to your local host) to [[OpenClaw]] - And of course Chrome ;-) Then, you can use the following [[Bash]] function on your computer to: - Temporarily disable the [[Tailscale]] shield (i.e., let your machine accept incoming traffic through Tailscale) - Start Chrome in debug mode with a temporary profile (use the path to your actual Chrome profile instead if you're nuts) - Start [[socat]] - (OpenClaw can connect after this) - Finally, it re-enables the [[Tailscale]] shield once done Once that's started, you can ask your [[OpenClaw]] server to connect and use your browser, and you'll get to see all the fun things it does for you. ``` chrome-openclaw() { local TS_IP=$(tailscale ip -4) echo "🔓 Lowering Tailscale shields..." sudo tailscale set --shields-up=false echo "🚀 Starting Chrome + socat on $TS_IP:9223..." google-chrome-stable --remote-debugging-port=9222 \ --user-data-dir=/tmp/openclaw-chrome & local CHROME_PID=$! sleep 2 socat TCP-LISTEN:9223,bind=$TS_IP,reuseaddr,fork TCP:127.0.0.1:9222 & local SOCAT_PID=$! echo "✅ Ready! OpenClaw can connect. Press Ctrl+C to stop." cleanup() { echo "🧹 Cleaning up..." kill $CHROME_PID $SOCAT_PID 2>/dev/null echo "🛡️ Raising Tailscale shields..." sudo tailscale set --shields-up=true echo "✅ Done" } trap cleanup INT TERM EXIT wait $CHROME_PID 2>/dev/null } ``` **TIP**: Just for additional safety, run `killall socat` when you're done. Oh and explain your agent that it should let you know when it needs access to your Web browser. ## Additional recommendations This stuff is fun AND powerful, but VERY dangerous. A few pieces of advice: - DO NOT install this on your own computer - Apply the least privilege principle - Don't give it all the keys to your kingdom - Don't make it read whatever on the Web (prompt injection risks are REAL); only let it consume trusted sources - Use short-lived API keys - You can install skills using `openclaw skills install <foo>`, but be VERY careful. That's a perfect vector for prompt injection. Only install stuff from people you really trust - Same with everything else - Don't let your bot partipate in Moltbook. Probably not a great idea from a security pov - Use the "CRITICAL" keyword in SOUL.MD - ... ## References - https://docs.openclaw.ai - https://docs.openclaw.ai/gateway/heartbeat ## Related - [[OpenClaw]] - [[Tailscale]] - [[Secure Shell (SSH)]]