merox

Deploying OpenClaw on Proxmox

Deploy OpenClaw (formerly Moltbot/Clawdbot) on Proxmox in an unprivileged LXC — setup, security hardening, and post-breach recommendations.

OpenClaw was the agent I ran for inbox, calendar and tasks, driven entirely from Telegram. The difference from a chatbot is that it executes things instead of describing them, and that difference is also the whole security problem.

It lived in an Ubuntu 22.04 LXC on Proxmox — 4GB RAM, 2 cores, which is plenty for personal use. Running Ollama models through it locally wants 8GB or more.

Read this before you deploy it

This is software that holds your API keys, reads your email, and has a shell. In the four weeks around this post, all three of those turned into incidents.

Exposed dashboards. Bitdefender found hundreds of instances leaking API keys, OAuth tokens and chat histories, because their control panel was on the public internet. Never expose the dashboard. Tailscale or an SSH tunnel, nothing else.

Prompt injection. Researchers extracted cryptocurrency private keys in under five minutes through crafted emails. Recent releases harden this; none of them close it, because it isn’t closeable in general.

Shell access. An AI with a local shell belongs in an isolated LXC or VM, unprivileged, and nowhere else.

The breach is the visible half. The structural half is that Moltbook is a package registry with an agent attached: researchers found published skills containing live data exfiltration code, and a post can carry prompt-injection instructions aimed at other agents. Because agents have persistent memory, a payload can be split across several posts and assembled later — which means reviewing any single post tells you nothing.

What you’ll need

  • Proxmox, and an Ubuntu 22.04 LXC or VM
  • A model provider — OpenAI, Anthropic, or self-hosted Ollama. Ollama is the one that keeps your mail on your own hardware
  • Node.js 22+

The container

20GB disk, 2 cores, 4096 MB memory, static IP. Keep Unprivileged container ticked — it maps container root to an unprivileged host UID, and it’s the difference between a compromise being contained and not.

apt update && apt upgrade -y
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -
apt install -y nodejs
node -v   # should be v22.x
npm -v

Installing it

curl -fsSL https://openclaw.ai/install.sh | bash
curl -fsSL https://openclaw.ai/install-cli.sh | bash

The onboarding wizard starts on its own. If it doesn’t:

openclaw onboard

Docker, Ansible, Nix and several cloud platforms are also supported — the install docs cover those.

Onboarding

The wizard walks through the security acknowledgement, QuickStart mode, then the two decisions that matter:

Model provider. OpenAI opens a browser for OAuth, Anthropic wants an API key, Ollama wants a URL like http://your-ollama-server:11434.

Channel. For Telegram, message @BotFather, run /newbot, and paste the token — it looks like 123456:ABC.... WhatsApp pairs by QR code; Discord and Slack want bot tokens.

Skip skills and hooks for now. Then:

openclaw tui       # terminal UI (recommended)
openclaw dashboard # web UI
openclaw status    # check status

Config lands in ~/.openclaw/openclaw.json, logs in ~/.openclaw/logs/gateway.log.

Hardening

Not optional, given the section above.

Egress, not just ingress. The reason to lock outbound traffic is prompt injection: the attack needs somewhere to send what it stole. Put the container on its own VLAN, then:

# Loopback: the gateway and its dashboard talk over localhost
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT

# Replies to connections already allowed, both ways
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A OUTPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

# Out: DNS and HTTPS only
iptables -A OUTPUT -p udp --dport 53 -j ACCEPT
iptables -A OUTPUT -p tcp --dport 53 -j ACCEPT
iptables -A OUTPUT -p tcp --dport 443 -j ACCEPT
# Ollama on another host, if that's your provider
iptables -A OUTPUT -p tcp -d OLLAMA_IP --dport 11434 -j ACCEPT

# In: SSH from your admin network only
iptables -A INPUT -p tcp -s ADMIN_CIDR --dport 22 -j ACCEPT

iptables -P INPUT DROP
iptables -P OUTPUT DROP

The policies go last, so the session you’re typing in survives. The rules don’t survive a reboot on their own — apt install iptables-persistent saves them. Or set the same policy from outside the container, in the Proxmox firewall on the container’s network device, where a compromised container can’t edit it.

Be honest about what this buys: open port 443 is still a way out, and a determined injection can exfiltrate over HTTPS to any host. Closing that needs an outbound proxy that only allows your model provider’s and Telegram’s domains. The rules above stop everything else — raw TCP, odd ports, plain HTTP. That includes apt, which on Ubuntu still fetches over port 80: point its sources at an HTTPS mirror, or allow 80 while you update.

The dashboard stays private. It listens on localhost, on the gateway’s port (18789 by default). Reach it with Tailscale inside the container, or an SSH tunnel to the container — ssh -L 18789:localhost:18789 user@openclaw-lxc. Nginx with basic auth behind a firewall if you must, but the tunnel is less to get wrong.

Keys in the environment, not the config file:

export ANTHROPIC_API_KEY="your-key-here"
export OPENAI_API_KEY="your-key-here"
openclaw gateway start

Read the logs on purpose, because nothing here alerts you:

tail -f ~/.openclaw/logs/gateway.log
grep -i "error\|unauthorized\|injection" ~/.openclaw/logs/gateway.log

What it’s actually for

“Clear my inbox of newsletters.” “What needs my attention today.” “Schedule a meeting with X next Tuesday.” Tasks and calendar work the same way.

The value isn’t the model — it’s that this happens in an app I already have open. A dashboard I have to remember to check is a dashboard I stop checking.

Troubleshooting

Gateway won’t start:

cat ~/.openclaw/logs/gateway.log
openclaw status
openclaw gateway restart

Telegram bot silent. Check the token, send /start to the bot yourself — it won’t talk first — and confirm the gateway is up with openclaw status.

OpenAI OAuth fails. The callback goes to localhost:1455, which your browser has to be able to reach. If it can’t, paste the redirect URL by hand.

Container networking:

ping 8.8.8.8
curl http://your-ollama-server:11434/api/tags

systemd inside LXC. Nesting on, or move to a VM.

Suspected prompt injection:

grep -E "rm -rf|curl.*sh|wget.*sh" ~/.openclaw/logs/gateway.log
openclaw skills list

Rotate every API key it held before you re-onboard. A key that was readable is a key that’s gone.

Should you run this?

The costs are real and worth stating plainly: API usage adds up unless you’re on Ollama, external providers see your mail, uptime is your problem, and larger local models want 8GB+ of RAM you might rather spend elsewhere.

But the honest summary is the security one. This is useful software with a live attack surface, published by a project that renamed itself twice and had a 770,000-record database exposure in the same month. Run it unprivileged, on its own VLAN, with egress locked and keys you can rotate without regret — or don’t run it yet.

References