Skip to content

Setting Up Sudo for OpenClaw Safely (Without NOPASSWD: ALL)

Burak Sonmez

Burak Sonmez · Software engineer writing about security & ops

April 22, 2026 · Updated May 06, 2026

8 min read––– views

Setting Up Sudo for OpenClaw Safely

The right way to give OpenClaw sudo access isn't NOPASSWD: ALL — that hands the bot full root and undoes most of your hardening work. The production-safe pattern is a scoped sudoers fragment that lets OpenClaw run only the specific commands it actually needs (apt, systemctl, ufw, docker), with everything else still requiring a human at the keyboard.

This post is the deep-dive companion to the full hardening guide. The pillar covers the whole hardening checklist; this one focuses on getting sudo right, which is one of the easiest places to silently undo the rest of your work. Defaults and JSON paths come from the OpenClaw docs.

Why blanket NOPASSWD: ALL is the wrong answer

NOPASSWD: ALL is the line in /etc/sudoers (or a fragment in /etc/sudoers.d/) that says: "this user can run any command via sudo without ever entering a password." It's the path of least resistance when you hit a sudo prompt that breaks an automation, and it shows up in install scripts and tutorials more often than it should.

The problem is that it makes the user functionally equivalent to root. Anything the bot can be tricked into running, it runs with full root authority — no password gate, no command allowlist, no second chance. That includes:

  • Prompt injection. A web page the bot reads contains a hidden instruction. The bot decides to "investigate" by running a shell command. With NOPASSWD: ALL, that shell command can rm -rf your home directory, write a new SSH key for the attacker, or open a reverse shell.
  • Supply-chain compromise. A package OpenClaw installs is compromised upstream. The package's post-install script runs as root because sudo is wide open.
  • Accidental destructive command. The bot generates a one-liner with a typo. Without sudo prompts, there's no friction stopping it.

If you've already gone through the work of running OpenClaw as a non-root user, sandboxing subagents in Docker, and locking the gateway behind Tailscale, granting NOPASSWD: ALL quietly cancels most of that effort. The blast radius of a compromise becomes "everything on the host" again.

The right mental model: sudo is a capability you hand to the bot, and you should hand it the smallest one that still gets the job done.

The mental model: scoped commands via /etc/sudoers.d/openclaw

Linux gives you a clean way to scope sudo capabilities. Instead of editing /etc/sudoers directly (which is shared with the OS package manager and easy to mangle), drop a separate file into /etc/sudoers.d/. Each file in that directory is read as if it were appended to the main sudoers config.

This pattern has three big advantages:

  • Package-manager safe. Distro upgrades won't touch your fragment. /etc/sudoers itself sometimes gets overwritten on package updates; /etc/sudoers.d/openclaw does not.
  • Easy to revoke. Removing OpenClaw's sudo capabilities is one rm command.
  • Reviewable. A short file with five lines is much easier to audit than a 200-line /etc/sudoers with your changes mixed in.

The syntax for a scoped rule is:

<user> <host>=(<runas>) NOPASSWD: <command1>, <command2>, ...

For an OpenClaw fragment that's almost always:

openclaw ALL=(root) NOPASSWD: /usr/bin/apt-get update, /usr/bin/apt-get install -y *

<user>: the OS user OpenClaw runs as. <host>=ALL: applies regardless of which host the rule is on (fine for single-host deployments). (root): the target user — what OpenClaw becomes when it runs the command. NOPASSWD: lets the rule bypass the password prompt only for these specific commands. Then a comma-separated list of allowed commands.

Two non-negotiables when authoring the file:

  1. Always validate before activating. Run sudo visudo -cf /etc/sudoers.d/openclaw to check the syntax. A broken sudoers file can lock you out of sudo entirely. visudo -c parses the file without committing it.
  2. File permissions must be 440 (chmod 440 /etc/sudoers.d/openclaw) and owner must be root:root. sudo will refuse to read the file otherwise — a safety feature, not a bug.

The minimal sudoers fragment that covers OpenClaw's actual needs

Here's the fragment I run in production, with comments so you can adapt it to your environment:

# /etc/sudoers.d/openclaw — scoped sudo capabilities for the OpenClaw bot
# After editing: sudo visudo -cf /etc/sudoers.d/openclaw && sudo chmod 440 /etc/sudoers.d/openclaw

# Package management — apt only, no arbitrary scripts
openclaw ALL=(root) NOPASSWD: /usr/bin/apt-get update
openclaw ALL=(root) NOPASSWD: /usr/bin/apt-get install -y *
openclaw ALL=(root) NOPASSWD: /usr/bin/apt-get upgrade -y
openclaw ALL=(root) NOPASSWD: /usr/bin/apt list --upgradable

# Service control — only OpenClaw-related units
openclaw ALL=(root) NOPASSWD: /bin/systemctl restart openclaw
openclaw ALL=(root) NOPASSWD: /bin/systemctl status openclaw
openclaw ALL=(root) NOPASSWD: /bin/systemctl restart fail2ban
openclaw ALL=(root) NOPASSWD: /bin/systemctl status fail2ban

# Firewall — let the bot inspect, but require a password for changes
openclaw ALL=(root) NOPASSWD: /usr/sbin/ufw status verbose
# Note: no NOPASSWD for `ufw allow` / `ufw deny` — those still prompt

# Docker — only needed if openclaw is not in the docker group
# (preferred path: add openclaw to docker group, drop these lines)
openclaw ALL=(root) NOPASSWD: /usr/bin/docker ps
openclaw ALL=(root) NOPASSWD: /usr/bin/docker logs *

A few things worth understanding about this fragment:

  • Wildcards in command lists are sharp. /usr/bin/apt-get install -y * means "any package name." If your bot decides to install a malicious package, this rule allows it. Tighten to a specific package list (apt-get install -y htop, jq, nmap) if you can.
  • Absolute paths are required. Sudoers does not honor $PATH. Always write /usr/bin/apt-get, never just apt-get. Find a binary's absolute path with which apt-get.
  • Service control is per-unit. systemctl restart openclaw is allowed; systemctl restart sshd is not. Add specific units only as needed.
  • Read-only commands are safer than write commands. ufw status is read-only and fine to allow. ufw allow 2222 modifies firewall state and should still prompt.
  • Prefer group membership over sudo for Docker. If the user is in the docker group, no sudo is needed at all for docker commands. The sudo rules above are a fallback when group membership isn't available.

After saving the file, validate and lock it down:

sudo visudo -cf /etc/sudoers.d/openclaw
sudo chown root:root /etc/sudoers.d/openclaw
sudo chmod 440 /etc/sudoers.d/openclaw

Then test as the OpenClaw user:

sudo -u openclaw sudo -l

You'll see the list of NOPASSWD commands. If you see "user openclaw is not in the sudoers file," the fragment isn't being read — most likely a permissions or syntax issue.

Auditing what OpenClaw ran with sudo

A scoped sudoers file isn't a substitute for visibility. Sudo logs every invocation, and reviewing those logs is the only way to catch a misbehaving bot before it causes real damage.

On systems using systemd-journald (Ubuntu 16.04+, Debian 9+, Fedora, modern CentOS):

journalctl _COMM=sudo --grep " openclaw : " --since "1 hour ago"

On older systems or where /var/log/auth.log is still primary:

sudo grep " openclaw : " /var/log/auth.log | tail -50

Why the space-padded pattern: sudo's log format puts the calling user first (openclaw : TTY=... USER=root ; COMMAND=...), where USER= is actually the target user. Filtering on USER=openclaw would catch the wrong rows. Matching openclaw : (with surrounding spaces) reliably hits the calling-user position.

A typical entry looks like:

sudo:    openclaw : TTY=unknown ; PWD=/home/openclaw ; USER=root ; COMMAND=/usr/bin/apt-get update

What to look for:

  • Unexpected commands. Anything outside your sudoers fragment should not appear here. If it does, the fragment isn't enforcing what you think it is.
  • Repeated failures. A line ending in command not allowed means the bot tried something the fragment denied. One or two of these are normal during development; a sustained burst suggests the bot is confused or being prompted to escalate.
  • Out-of-window activity. If you only run commands during your working hours but logs show sudo invocations at 3am, that's a signal worth investigating.

For ongoing monitoring, I send a daily summary to my Telegram via the OpenClaw cron pattern from the pillar guide:

Each morning at 8am, summarize all sudo invocations by openclaw from
the last 24 hours. List any commands not in /etc/sudoers.d/openclaw,
any denied attempts, and any activity outside 8am-11pm local time.

That single rule has caught two real config drifts on my host — both benign in the end, but the visibility was the whole point.

Revoking sudo cleanly when you're done

When you decommission OpenClaw on a host, switch users, or suspect something is off, revoke sudo with three commands.

1. Remove from the sudo group:

sudo gpasswd -d openclaw sudo

This removes the user from the broad-sudo group. After this, only the rules in /etc/sudoers.d/openclaw apply.

2. Delete the scoped sudoers fragment:

sudo rm /etc/sudoers.d/openclaw

The fragment is gone — OpenClaw can no longer use any of the NOPASSWD rules.

3. Verify the revocation:

sudo -l -U openclaw

The output should be Sorry, user openclaw is not allowed to run sudo on <hostname>. If you still see rule entries, one of the previous steps didn't take — check that the fragment was actually deleted (ls /etc/sudoers.d/) and that the user isn't in any other sudo-granting group (groups openclaw).

If OpenClaw was actively running when you revoked, restart it to drop any cached sudo tokens:

sudo systemctl restart openclaw

That's the whole revocation. Three commands, fully reversible by re-adding the group membership and the fragment if you change your mind.