Complete guide to installing and configuring OpenClaw as a root-privileged AI gateway with Telegram command execution on Ubuntu/Debian servers.
- Prerequisites
- Install Node.js via NVM
- Install OpenClaw
- Initial Setup (Interactive Wizard)
- Configure Telegram Bot
- Configure OpenClaw for Full Exec Access
- Set Up Exec Approvals
- Enable Passwordless Sudo
- Stop User-Level Services
- Create Root System-Level Services
- Fix Extension Ownership
- Enable and Start Services
- Verify Everything Works
- Post-Setup: Activate Exec in Telegram
- Maintenance and Troubleshooting
- Security Considerations
- Quick Reference
- OS: Ubuntu 24.04 LTS (or any systemd-based Linux)
- User: A non-root user with sudo access (referred to as
$USERthroughout) - Network: Internet access for downloading packages
- Telegram: A Telegram bot token (from @BotFather)
- AI Provider: API access to an LLM provider (e.g., OpenAI, Anthropic, or local Ollama)
# Update system
sudo apt update && sudo apt upgrade -y
# Install essential build tools
sudo apt install -y curl git build-essentialOpenClaw requires Node.js v24+.
# Install NVM
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.4/install.sh | bash
# Reload shell
source ~/.bashrc
# Install Node.js v24
nvm install 24
nvm use 24
nvm alias default 24
# Verify
node --version # Should show v24.x.x
npm --version# Install OpenClaw globally
npm install -g openclaw
# Verify installation
openclaw --versionRun the setup wizard to create the initial configuration:
openclaw doctorThis creates:
~/.openclaw/openclaw.json— main configuration~/.openclaw/workspace/— agent workspace directory~/.openclaw/extensions/— plugin extensions directory
The wizard will guide you through:
- Choosing an AI provider and model
- Setting up authentication
- Configuring basic gateway settings
After the wizard, OpenClaw typically installs user-level systemd services. We will replace these with root-level services later.
- Open Telegram and message @BotFather
- Send
/newbotand follow the prompts - Save the bot token (format:
123456789:AAG...) - Send
/setcommandsto BotFather and set the commands for your bot (optional)
- Message @userinfobot on Telegram
- It will reply with your user ID (a number like
6987875725)
Edit ~/.openclaw/openclaw.json with the full configuration. Replace the placeholder values with your own:
{
"agents": {
"defaults": {
"model": {
"primary": "YOUR_PROVIDER/YOUR_MODEL"
},
"models": {
"YOUR_PROVIDER/YOUR_MODEL": {}
},
"workspace": "/home/YOUR_USER/.openclaw/workspace",
"userTimezone": "YOUR_TIMEZONE"
}
},
"tools": {
"profile": "full",
"allow": [
"exec",
"process",
"read",
"write",
"edit",
"group:runtime",
"group:fs",
"group:sessions",
"group:memory"
],
"elevated": {
"enabled": true,
"allowFrom": {
"telegram": ["*"]
}
},
"web": {
"search": {
"enabled": false
}
},
"exec": {
"host": "gateway",
"security": "full",
"ask": "off",
"timeoutSec": 1800
}
},
"commands": {
"native": "auto",
"nativeSkills": "auto",
"restart": true,
"ownerDisplay": "raw"
},
"session": {
"dmScope": "per-channel-peer"
},
"channels": {
"telegram": {
"enabled": true,
"dmPolicy": "allowlist",
"botToken": "YOUR_BOT_TOKEN",
"allowFrom": [
"YOUR_TELEGRAM_USER_ID"
],
"groupPolicy": "allowlist",
"streaming": "off"
}
},
"gateway": {
"port": 18789,
"mode": "local",
"bind": "loopback",
"auth": {
"mode": "token",
"token": "GENERATE_A_RANDOM_TOKEN"
},
"tailscale": {
"mode": "off",
"resetOnExit": false
}
},
"plugins": {
"allow": [
"telegram"
],
"entries": {
"telegram": {
"enabled": true
}
}
}
}| Config Path | Value | Purpose |
|---|---|---|
tools.profile |
"full" |
Enable all tool categories |
tools.allow |
["exec", "process", ...] |
Explicitly allow exec and filesystem tools |
tools.elevated.enabled |
true |
Enable elevated (root) execution mode |
tools.elevated.allowFrom.telegram |
["*"] |
Allow all permitted Telegram users to use elevated exec |
tools.exec.host |
"gateway" |
Execute commands on the gateway host machine |
tools.exec.security |
"full" |
No command restrictions (allow everything) |
tools.exec.ask |
"off" |
Never prompt for approval before executing |
tools.exec.timeoutSec |
1800 |
30-minute command timeout |
channels.telegram.dmPolicy |
"allowlist" |
Only allow listed Telegram user IDs |
channels.telegram.allowFrom |
["YOUR_ID"] |
Your Telegram user ID |
openssl rand -base64 32 | tr -d '/+=' | head -c 44Create the exec approvals file with a wildcard pattern to auto-approve all commands:
cat > ~/.openclaw/exec-approvals.json << 'EOF'
{
"version": 1,
"socket": {},
"defaults": {},
"agents": {
"*": {
"allowlist": [
{
"pattern": "**"
}
]
}
}
}
EOFThe "pattern": "**" wildcard means all commands are pre-approved for all agents.
The service user needs passwordless sudo so systemd can manage root services:
sudo bash -c 'echo "YOUR_USERNAME ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/YOUR_USERNAME-nopasswd'
sudo chmod 440 /etc/sudoers.d/YOUR_USERNAME-nopasswd
# Verify
sudo -n whoami # Should print: rootIf OpenClaw's wizard already created user-level services, stop and disable them:
# Stop running services
systemctl --user stop openclaw-gateway.service openclaw-node.service 2>/dev/null
# Disable auto-start
systemctl --user disable openclaw-gateway.service openclaw-node.service 2>/dev/null
# Verify they're stopped
systemctl --user status openclaw-gateway.service 2>&1 | grep Active
systemctl --user status openclaw-node.service 2>&1 | grep ActiveFind your Node.js and OpenClaw paths:
# Node.js binary
NODE_BIN=$(which node)
echo "Node binary: $NODE_BIN"
# OpenClaw installation
OPENCLAW_DIR=$(npm root -g)/openclaw
echo "OpenClaw dir: $OPENCLAW_DIR"
# Your home directory
echo "Home: $HOME"# Replace paths below with your actual paths from step 10.1
sudo tee /etc/systemd/system/openclaw-gateway.service > /dev/null << 'EOF'
[Unit]
Description=OpenClaw Gateway - Root
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
ExecStart=/home/YOUR_USER/.nvm/versions/node/v24.14.0/bin/node /home/YOUR_USER/.nvm/versions/node/v24.14.0/lib/node_modules/openclaw/dist/entry.js gateway --port 18789
Restart=always
RestartSec=5
KillMode=process
User=root
Group=root
Environment=HOME=/home/YOUR_USER
Environment=TMPDIR=/tmp
Environment=PATH=/home/YOUR_USER/.nvm/versions/node/v24.14.0/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
Environment=OPENCLAW_GATEWAY_PORT=18789
Environment=OPENCLAW_GATEWAY_TOKEN=YOUR_GATEWAY_TOKEN
Environment=OPENCLAW_SYSTEMD_UNIT=openclaw-gateway.service
Environment=OPENCLAW_SERVICE_MARKER=openclaw
Environment=OPENCLAW_SERVICE_KIND=gateway
[Install]
WantedBy=multi-user.target
EOFsudo tee /etc/systemd/system/openclaw-node.service > /dev/null << 'EOF'
[Unit]
Description=OpenClaw Node Host - Root
After=network-online.target openclaw-gateway.service
Wants=network-online.target
Requires=openclaw-gateway.service
[Service]
Type=simple
ExecStart=/home/YOUR_USER/.nvm/versions/node/v24.14.0/bin/node /home/YOUR_USER/.nvm/versions/node/v24.14.0/lib/node_modules/openclaw/dist/index.js node run --host 127.0.0.1 --port 18789
Restart=always
RestartSec=5
KillMode=process
User=root
Group=root
Environment=HOME=/home/YOUR_USER
Environment=TMPDIR=/tmp
Environment=PATH=/home/YOUR_USER/.nvm/versions/node/v24.14.0/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
Environment=OPENCLAW_LAUNCHD_LABEL=ai.openclaw.node
Environment=OPENCLAW_SYSTEMD_UNIT=openclaw-node
Environment=OPENCLAW_LOG_PREFIX=node
Environment=OPENCLAW_SERVICE_MARKER=openclaw
Environment=OPENCLAW_SERVICE_KIND=node
[Install]
WantedBy=multi-user.target
EOFUser=rootandGroup=root— This is what gives OpenClaw root privilegesEnvironment=HOME=/home/YOUR_USER— Must point to the user home where~/.openclaw/config lives (NOT/root)Requires=openclaw-gateway.serviceon the node service ensures the gateway starts firstWantedBy=multi-user.targetensures services start on boot (system-level, not user-level)- PATH must include the nvm node binary directory so the service can find
node
When running as root, OpenClaw rejects extensions owned by non-root users ("suspicious ownership" security check). Fix this:
sudo chown -R root:root ~/.openclaw/extensions/If you install new extensions later, re-run this command.
# Reload systemd to pick up new service files
sudo systemctl daemon-reload
# Enable services to start on boot
sudo systemctl enable openclaw-gateway.service openclaw-node.service
# Start gateway first, wait for it to initialize
sudo systemctl start openclaw-gateway.service
sleep 5
# Then start node service
sudo systemctl start openclaw-node.service
sleep 3
# Check status
sudo systemctl status openclaw-gateway.service openclaw-node.serviceBoth services should show Active: active (running).
ps aux | grep openclaw | grep -v grepExpected output — all processes owned by root:
root 12345 ... openclaw
root 12346 ... openclaw-gateway
root 12347 ... openclaw-node
# Gateway logs
sudo journalctl -u openclaw-gateway.service --no-pager -n 30
# Node logs
sudo journalctl -u openclaw-node.service --no-pager -n 30Look for:
listening on ws://127.0.0.1:18789— gateway is accepting connections[telegram] [default] starting provider— Telegram bot is connected- No
Invalid configorConfig invaliderrors
openclaw config get toolsShould show "profile": "full", "security": "full", "ask": "off".
openclaw sandbox explainLook for:
execin the allow listElevated: enabled: true
Important: After making config changes, existing Telegram sessions use cached tool lists. You must start a fresh session:
- Open your Telegram bot chat
- Send
/resetor/newto start a new session - Test by asking the bot to run a command, e.g.: "Run
whoamiandidon the server"
The bot should now execute commands as root and return output.
sudo systemctl restart openclaw-gateway.service
sleep 5
sudo systemctl restart openclaw-node.service# Follow gateway logs
sudo journalctl -u openclaw-gateway.service -f
# Follow node logs
sudo journalctl -u openclaw-node.service -f| Error | Cause | Fix |
|---|---|---|
Config invalid |
Invalid JSON or unrecognized config key | Check openclaw.json syntax; run openclaw doctor --fix |
plugin not found: ... |
Plugin directory not owned by root | sudo chown -R root:root ~/.openclaw/extensions/ |
suspicious ownership |
Extension files owned by non-root user | Same as above |
connect ECONNREFUSED 127.0.0.1:18789 |
Node started before gateway was ready | Restart node: sudo systemctl restart openclaw-node.service |
agents.defaults: Unrecognized key: "tools" |
tools is not valid inside agents.defaults |
Move tools config to top-level tools section only |
| Bot says "no exec tool" | Stale Telegram session | Send /reset in Telegram to start fresh session |
# Update the package
npm update -g openclaw
# Fix extension ownership after update
sudo chown -R root:root ~/.openclaw/extensions/
# Update version in service files if needed, then restart
sudo systemctl daemon-reload
sudo systemctl restart openclaw-gateway.service
sleep 5
sudo systemctl restart openclaw-node.serviceThis setup gives the Telegram bot unrestricted root access to the server. Understand the risks:
- Any user in the
channels.telegram.allowFromlist can execute any command as root - This includes: installing/removing software, reading/writing any file, managing services, network configuration, etc.
-
Restrict Telegram users strictly — Only add your own Telegram user ID to
allowFrom. Never use"*"inchannels.telegram.allowFrom. -
Use allowlist DM policy — Keep
"dmPolicy": "allowlist"to reject messages from unknown users. -
Monitor logs — Regularly check
sudo journalctl -u openclaw-gateway.servicefor unexpected activity. -
Firewall the gateway port — The gateway binds to loopback (
127.0.0.1) by default, which is correct. Never expose port 18789 to the internet. -
Secure bot token — If your bot token is compromised, anyone could interact with the bot. Regenerate via BotFather if needed.
-
Consider per-sender restrictions for groups — If using group chats:
"channels": { "telegram": { "groups": { "GROUP_CHAT_ID": { "toolsBySender": { "id:YOUR_USER_ID": { "allow": ["exec", "process", "group:runtime"] } } } } } }
| File | Purpose |
|---|---|
~/.openclaw/openclaw.json |
Main configuration |
~/.openclaw/exec-approvals.json |
Command approval whitelist |
~/.openclaw/extensions/ |
Plugin extensions |
~/.openclaw/workspace/ |
Agent workspace |
/etc/systemd/system/openclaw-gateway.service |
Root gateway service |
/etc/systemd/system/openclaw-node.service |
Root node service |
/etc/sudoers.d/YOUR_USER-nopasswd |
Passwordless sudo config |
/tmp/openclaw-0/openclaw-*.log |
Runtime log files |
# Service management
sudo systemctl start openclaw-gateway.service
sudo systemctl start openclaw-node.service
sudo systemctl stop openclaw-gateway.service openclaw-node.service
sudo systemctl restart openclaw-gateway.service
sudo systemctl status openclaw-gateway.service openclaw-node.service
# Logs
sudo journalctl -u openclaw-gateway.service -f
sudo journalctl -u openclaw-node.service -f
# Config inspection
openclaw config get tools
openclaw sandbox explain
openclaw status --all
# Telegram session reset (send in chat)
/reset
/newThe absolute minimum config keys required for root exec via Telegram:
{
"tools": {
"profile": "full",
"elevated": {
"enabled": true,
"allowFrom": { "telegram": ["*"] }
},
"exec": {
"host": "gateway",
"security": "full",
"ask": "off"
}
},
"channels": {
"telegram": {
"enabled": true,
"dmPolicy": "allowlist",
"botToken": "YOUR_TOKEN",
"allowFrom": ["YOUR_USER_ID"]
}
}
}Combined with:
- System-level systemd services running as
User=root exec-approvals.jsonwith wildcard"pattern": "**"- Extension directories owned by root
Guide based on OpenClaw v2026.2.26 running on Ubuntu 24.04 LTS with Node.js v24.