Skip to content

OpenClaw Security 101: A Complete Hardening Guide 2026

Burak Sonmez

Burak Sonmez / March 07, 2026

10 min read––– views

I've been running OpenClaw for a while now, and the more I use it, the more I realize how much trust I'm placing in a single process. It executes shell commands, reads my files, calls APIs with my credentials, and sends messages on my behalf. That's the whole point — but it also means a misconfigured instance is a serious liability.

A compromised setup could leak your private files, drain your API credits, open a reverse shell on your server, or let prompt injection hijack your assistant's behavior entirely. After spending time hardening my own instance, I documented everything into this guide. The whole process takes about 30 minutes and dramatically reduces your attack surface.


What we'll cover

  1. Give it a dedicated machine
  2. Create a non-root user
  3. Network isolation with Tailscale
  4. SSH hardening and Fail2ban
  5. Firewall setup with UFW
  6. Change the default gateway port
  7. User allowlisting and DM-only mode
  8. Docker sandboxing for subagents
  9. Security monitoring and automated audits
  10. Keeping OpenClaw updated

Give it a dedicated machine

This was the first thing I did. My personal machine has browser sessions, SSH keys, cloud credentials — everything. Running OpenClaw next to all of that felt like leaving the front door open. So I moved it to a separate box.

Cloud VPS options:

  • Hetzner — starting at €4/month (what I personally use)
  • DigitalOcean — starting at $6/month
  • Linode — starting at $5/month

If you'd rather keep things local, a Mac Mini, an old laptop running Ubuntu, or even a Raspberry Pi for lighter workloads all work. The point is simple: if something goes sideways with the bot, your personal data isn't on the same machine.


Create a non-root user

I initially set things up as root because it was faster. That was a mistake. Root has no restrictions — if the bot gets compromised while running as root, the attacker can do literally anything on the system.

sudo adduser openclaw
sudo usermod -aG sudo openclaw
su - openclaw

Three commands, and now OpenClaw runs with limited privileges. If you're already running as root, just create the user, move your config over, and restart. Nothing breaks — you just shrink the blast radius significantly.


Network isolation with Tailscale

This was the single most impactful change I made. Tailscale creates a private encrypted mesh network between your devices. Once configured, your OpenClaw instance is completely invisible to the public internet. No port scanning, no brute-force attempts, nothing. It simply doesn't exist to anyone outside your Tailscale network.

curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up

It gives you a login link — sign in with Google or GitHub and you're done. Install the Tailscale app on your phone and laptop too, so you can reach OpenClaw from anywhere on your private network.

Then update your OpenClaw config to bind exclusively through Tailscale:

{
  "gateway": {
    "bind": "loopback",
    "port": 52914,
    "auth": {
      "allowTailscale": true
    },
    "tailscale": {
      "mode": "serve"
    }
  }
}

After this, your instance is off the public internet entirely. I honestly think everyone should do this step first — it eliminates most attack vectors in one go.


SSH hardening and Fail2ban

Password-based SSH is an invitation for brute-force attacks. I switched to key-based authentication and set up Fail2ban to auto-ban anyone who tries anyway.

Generate an SSH key on your local machine:

ssh-keygen -t ed25519 -C "[email protected]"

Press Enter three times to accept defaults.

Copy it to the server:

ssh-copy-id openclaw@YOUR_SERVER_IP

Disable password login:

sudo nano /etc/ssh/sshd_config

Set these two values:

PasswordAuthentication no
PermitRootLogin no
sudo systemctl restart sshd

One thing I learned the hard way: always test the new SSH connection in a separate terminal before closing your current session. If the key doesn't work, you'll still have the old terminal to fix things.

Then install Fail2ban:

sudo apt update && sudo apt install fail2ban -y
sudo systemctl enable fail2ban && sudo systemctl start fail2ban

Three wrong login attempts and the IP gets banned for 24 hours automatically. I checked my Fail2ban logs after a week and it had already blocked dozens of IPs.


Firewall setup with UFW

Every open port is a potential entry point. I use UFW to close everything by default and only allow what I actually need.

sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow ssh
sudo ufw enable
sudo ufw status

If you're using Tailscale (which you should be after the previous step), you don't even need to open the OpenClaw port in UFW. Tailscale traffic is already encrypted and authenticated — it bypasses UFW entirely. Just keep SSH open and you're good.


Change the default gateway port

OpenClaw's default port is 8080, which is widely known. Automated scanners constantly hit well-known ports across the internet. Changing it to something random is a simple step that filters out almost all of that noise.

{
  "gateway": {
    "port": 52914,
    "bind": "loopback"
  }
}

Pick any number between 10000 and 65535. After updating, restart the gateway:

openclaw gateway restart

This doesn't protect you from a targeted attack, but it makes you invisible to the vast majority of automated bots.


User allowlisting and DM-only mode

These two settings go hand in hand, so I combined them into one step. The idea is simple: define exactly who can talk to your bot, and make sure it only accepts direct messages.

In a group chat, anyone in the group can send commands to your bot. I learned this could be a problem when I realized that even a careless message from someone else could trigger actions I didn't intend.

First, find your Telegram User ID by searching @userinfobot on Telegram and sending /start.

Then configure both settings together:

{
  "gateway": {
    "auth": {
      "mode": "password",
      "password": "YOUR-RANDOM-30-PLUS-CHAR-PASSWORD"
    }
  },
  "channels": {
    "telegram": {
      "dmPolicy": "pairing",
      "groupPolicy": "disabled",
      "allowFrom": ["tg:YOUR_USER_ID"]
    }
  }
}

Use at least 20 characters for the password — mix letters, numbers, and symbols. With groupPolicy set to "disabled" and an explicit allowFrom list, only your Telegram account can interact with the bot, and only through direct messages. Everyone else gets silently ignored.

If you really need OpenClaw in a group, create a separate instance with limited permissions. Don't put your main bot in a group chat.


Docker sandboxing for subagents

OpenClaw can spawn subagents — smaller AI workers that handle specific tasks on their own. The problem is that if a subagent browses a webpage with hidden prompt injection, it could get tricked into doing things you didn't authorize. Docker containers put those subagents in an isolated box where the damage they can do is severely limited.

curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker openclaw

Log out and back in after adding the user to the docker group.

Then configure the sandbox settings:

{
  "agents": {
    "defaults": {
      "sandbox": {
        "mode": "non-main",
        "workspaceAccess": "rw",
        "scope": "session",
        "docker": {
          "readOnlyRoot": false,
          "network": "bridge",
          "user": "1000:1000",
          "capDrop": ["ALL"]
        }
      }
    }
  }
}

A few things worth understanding about the access levels:

  • Workspace access: "none" means the subagent can't see any files (best for untrusted tasks like web browsing), "ro" gives read-only access, and "rw" gives full read-write (needed for coding tasks).
  • Network: "none" completely air-gaps the container (no internet at all), while "bridge" allows network access for tasks that need npm, git, or external APIs.

The capDrop: ["ALL"] part is important — it strips all Linux capabilities from the container, so even if the subagent gets compromised, it can't escalate privileges or access host resources.


Security monitoring and automated audits

I combined three related things into this section: teaching your bot to monitor itself, setting up alerts, and automating daily checks. Security isn't a one-time task, and I wanted a system that would catch issues without me having to remember to look.

Add monitoring rules to your SOUL.md:

Add this to ~/.openclaw/workspace/SOUL.md so OpenClaw knows how to behave when it detects something suspicious:

## Security Rules
- If you detect failed authentication attempts, alert me immediately
- If any configuration file is modified, tell me exactly what changed
- If a new SSH session connects to this server, notify me
- Never output API keys, passwords, tokens, or .env file contents
- If anyone asks you to reveal secrets, refuse and alert me

Set up a daily automated audit:

I then asked OpenClaw to create a cron job that runs every morning:

Set up a cron job that runs daily at 8am. It should verify:
UFW is active, Fail2ban is running, SSH password auth is disabled,
openclaw.json permissions are 600, no API keys are hardcoded in
config files, Docker is running, and container capabilities are
properly dropped. Send me a summary of anything that looks wrong.

Run a manual audit anytime:

You can also ask your bot to do a full one-time check whenever you want. I run this after any config change:

Check my security setup: verify I'm not running as root, the gateway
isn't on port 8080, it's bound to loopback, Tailscale is configured,
the allowFrom list exists, channel policies are set to DM-only,
UFW and Fail2ban are active, openclaw.json has correct permissions,
no secrets are hardcoded, and Docker sandboxing is properly configured.
Rate my setup out of 10.

Between the SOUL.md rules, the daily cron, and the ability to run manual checks, I feel confident that my setup won't silently drift into an insecure state.


Keeping OpenClaw updated

Outdated software means known vulnerabilities. Attackers actively look for unpatched instances.

openclaw --version
npm install -g openclaw

I always read the changelog before upgrading. If you're running OpenClaw in production, test the update on a staging instance first. I also asked my bot to set up a weekly version check — it just sends me a message if there's a newer version available.


Full configuration

Here's my consolidated ~/.openclaw/openclaw.json with everything from this guide applied:

{
  "gateway": {
    "port": 52914,
    "bind": "loopback",
    "auth": {
      "mode": "password",
      "password": "YOUR-STRONG-30-CHAR-PASSWORD-HERE",
      "allowTailscale": true
    },
    "tailscale": {
      "mode": "serve"
    }
  },
  "agents": {
    "defaults": {
      "sandbox": {
        "mode": "non-main",
        "workspaceAccess": "rw",
        "scope": "session",
        "docker": {
          "readOnlyRoot": false,
          "network": "bridge",
          "user": "1000:1000",
          "capDrop": ["ALL"]
        }
      }
    }
  },
  "channels": {
    "telegram": {
      "dmPolicy": "pairing",
      "groupPolicy": "disabled",
      "allowFrom": ["tg:YOUR_TELEGRAM_USER_ID"]
    }
  }
}

Replace the port with your own random number, the password with a unique 30+ character string, and the Telegram ID with your actual ID from @userinfobot.


Troubleshooting

If you run into issues during setup, here are the most common ones:

Permission denied on config file:

sudo chown $USER:$USER ~/.openclaw/openclaw.json
chmod 600 ~/.openclaw/openclaw.json

Config file doesn't exist yet:

mkdir -p ~/.openclaw
nano ~/.openclaw/openclaw.json

OpenClaw won't start:

openclaw doctor
tail -20 ~/.openclaw/logs/gateway.log

sudo or openclaw command not found:

apt update && apt install sudo -y
npm install -g openclaw