In Part 1 of this series, we provisioned two Hetzner Cloud VPS from scratch — covering account creation, firewall rules, SSH keys, the works. The result were two Ubuntu 24.04 machines sitting idle at €14.49/month each.
This post walks through installing and running OpenClaw and NanoClaw on each server, using Telegram as each agent's messaging channel. If you expected installation to be the boring part — just follow the docs and you're done — the reality is more revealing than that. How each framework handles its setup process tells you a lot about its documentation quality, security philosophy, dependency chain, and what you'll be paying to keep it running. This is where the comparison starts.
Shared setup — creating a non-root user and locking down SSH
Neither framework strictly requires this, but I chose to create a dedicated non-root user and lock down SSH on both servers before installing anything. You'll repeat these steps on each server with only the username changed (openclaw or nanoclaw), so I'll walk through them once.
After SSH-ing in as root, create the user, grant sudo access, and copy your SSH keys over:
ssh root@<your-server-ip-address>
adduser openclaw
usermod -aG sudo openclaw
mkdir -p /home/openclaw/.ssh
cp /root/.ssh/authorized_keys /home/openclaw/.ssh/
chown -R openclaw:openclaw /home/openclaw/.ssh
chmod 700 /home/openclaw/.ssh
chmod 600 /home/openclaw/.ssh/authorized_keysThen disable root login and password authentication:
echo "PermitRootLogin no" >> /etc/ssh/sshd_config
echo "PasswordAuthentication no" >> /etc/ssh/sshd_config
systemctl restart sshVerify you can SSH in as the new user before closing your root session.
ssh openclaw@<your-server-ip-address>If you lock yourself out, Hetzner's web console (accessible from the Cloud Console) is your emergency fallback.
This isn't just good hygiene — for agent frameworks that get shell access to your server, it's a deliberate and important security decision. That's especially true for OpenClaw. Since January 2026, security researchers have disclosed over 150 advisories for the platform, including CVE-2026-25253, a CVSS 8.8 vulnerability that allowed one-click remote code execution through WebSocket hijacking. Command injection flaws, sandbox escapes, and hundreds of malicious plugins in the ClawHub marketplace have followed. Running OpenClaw as root on a machine with anything else on it would be reckless. A dedicated VPS with a non-root user won't protect you from every vulnerability, but it meaningfully limits the blast radius — which is exactly why we set this up in Part 1.
Installing OpenClaw
The documentation problem
Before the first command, a warning: OpenClaw's installation documentation is fragmented in a way that will cost you time if you're not prepared for it.
There's an official Hetzner-specific Docker guide that walks through a multi-step Docker Compose setup with custom image builds, environment variables, and volume mounts. There are community guides on Reddit that take a different approach with overlapping but not identical steps. And there's a generic installer script that bypasses most of that complexity entirely.
These guides don't fully agree with each other. I tried the Docker-based approaches first — rebuilding the VPS from a clean state each time so that leftover artifacts from one approach couldn't silently affect another. Both attempts hit errors: a gateway startup failure related to controlUi.allowedOrigins configuration on the first try, and conflicting docker-compose.yml configurations between sources on the second.
The generic installer was the third attempt, and it worked. That's the approach I'll walk through here. If you go searching for alternatives, you'll find them — just know that the more manual Docker paths have rough edges that aren't well-documented.
Prerequisites — a model provider account
SSH in as your openclaw user and make sure the system is up to date:
sudo apt-get update && sudo apt-get upgrade -y
sudo apt-get install -y git curl ca-certificatesYou'll need a model provider. The OpenClaw installer gives you a choice of providers — you can use a model family-specific API key directly, or go through an aggregator like OpenRouter. I chose OpenRouter because it's a convenient abstraction: you can switch between proprietary models, experiment with local models, and conveniently track usage without managing multiple API keys. I selected Claude Sonnet 4.6 through OpenRouter to keep the comparison fair with NanoClaw.
Running the installer
With your model provider API key ready, run the generic installer:
curl -fsSL https://openclaw.ai/install.sh | bashThis launches an interactive setup wizard. Here are the key decisions and what I chose:
Setup mode: Manual. There's an automatic option, but I wanted to see every decision being made. Given OpenClaw's security track record, I wasn't comfortable letting the installer make choices about gateway binding, authentication, and network exposure without my input.
Gateway bind: Loopback (127.0.0.1). This means the gateway only listens on localhost — you can't reach it from the internet, only through an SSH tunnel. Given the WebSocket hijacking vulnerabilities that have plagued OpenClaw, loopback is a safer default.
Gateway auth: Token. The installer generates a token for you and stores it locally.
Model configuration: OpenRouter, with Claude Sonnet 4.6 as the default model.
I skipped web search, skills, and hooks — all of which can be configured later. The goal was a minimal working setup to establish an apples-to-apples baseline with NanoClaw.
Connecting Telegram
The installer walks you through Telegram integration directly. You'll open Telegram, chat with @BotFather, create a new bot with /newbot, and paste the token back into the installer.
One thing OpenClaw does well here: it explicitly warns you about DM access policy. By default, any Telegram user who discovers your bot can send pairing requests. The installer surfaces this and tells you how to configure an allowlist if you want to restrict access to specific user IDs. It's a small touch, but it's the kind of security transparency you want from a framework with OpenClaw's history.
After the installer finishes, send a message to your bot on Telegram. You'll receive a pairing request — approve it from the server with openclaw pairing approve, and you're connected. To access the browser-based Control UI, set up an SSH tunnel from your local machine:
ssh -N -L 18789:127.0.0.1:18789 openclaw@YOUR_VPS_IPThen open http://127.0.0.1:18789/ in your browser and authenticate with your gateway token.
The Heartbeat — and what it costs
The first thing OpenClaw did after connecting wasn't wait for my message. It automatically read a HEARTBEAT.md file from its workspace and reported back — consuming roughly 11,000 tokens in the process. This heartbeat runs every 30 minutes by default.
The Heartbeat is one of OpenClaw's most distinctive features and a big part of why it's been seen as innovative relative to other AI agents. It's what enables truly autonomous behavior: you can give the agent standing instructions — track my competitor's pricing, monitor my email inbox, check for new pull requests — and the Heartbeat is the mechanism that picks those tasks up on a recurring schedule without you needing to prompt it each time.
That autonomy comes with a cost. At Sonnet 4.6 pricing through OpenRouter (which adds a 5.5% platform fee), the default heartbeat costs approximately $2 per day in model costs — around $60/month on top of your VPS bill. That's worth knowing upfront so you can tune the interval and the instructions in HEARTBEAT.md to match what you're actually using it for.
One more rough edge: OpenClaw has a bootstrap process that's supposed to trigger on first run. According to the docs, the agent initiates a conversation to collaboratively establish its identity (name, vibe, emoji), learn about the user, and then populate workspace files like IDENTITY.md, USER.md, and SOUL.md — the latter being a set of behavioral guidelines the agent follows across sessions. That bootstrap never triggered for me. When I asked the agent about it afterward, it acknowledged the step should have happened and offered to walk through it retroactively. Not a dealbreaker, but it's another sign that the setup flow has gaps.
Installing NanoClaw
Prerequisites — Claude Code, a Claude account, and API credits
NanoClaw's dependency chain looks different from OpenClaw's. Where OpenClaw needs a model provider API key and not much else, NanoClaw pulls in the Claude ecosystem at multiple levels.
Claude Code is required to run NanoClaw's setup process. There's no traditional installer wizard — NanoClaw describes itself as AI-native, meaning Claude Code guides you through each step conversationally. At runtime, agents are powered by the Claude Agent SDK, not Claude Code itself, but you need Claude Code to get there. To install it on the server:
curl -fsSL https://claude.ai/install.sh | bashSince there's no browser on the VPS, Claude Code gives you a URL to open on your local machine. That page generates an authentication code you paste back into the terminal. It works, but it's not obvious the first time.
To use Claude Code, you need either a Claude subscription (e.g., $20/month for Pro) or an Anthropic API key. Either one works. To run NanoClaw, you also need either a Claude subscription or an Anthropic API key. I purchased both a subscription ($20/month) and $20 in API credits — using the subscription for Claude Code during setup and the API key for NanoClaw. This let me track NanoClaw's per-message token usage through the API console, making it easier to compare directly with OpenClaw. But you don't necessarily need both: if you only used a subscription for Claude Code and NanoClaw, the upfront cost would be lower.
Running /setup
With Claude Code authenticated, install Docker (NanoClaw uses it as its container runtime), then clone the NanoClaw repository and launch Claude Code:
curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker nanoclawLog out and back in for the Docker group membership to take effect, then:
git clone https://github.com/<you>/nanoclaw.git
cd nanoclaw
claudeInside Claude Code, run /setup. From here, Claude takes over. It installs Node.js dependencies, sets up the container runtime, builds the agent container image, installs OneCLI (NanoClaw's credential management vault) automatically, and walks you through channel configuration — all conversationally, with Claude asking for your input when needed.
For Telegram, Claude guides you through the BotFather flow and asks for your bot token and chat ID. The setup is similar to OpenClaw's but less explicit about access controls. NanoClaw uses registered chats rather than an allowlist or pairing system: only chats you've explicitly registered during setup can reach the bot. A stranger who discovers your bot and DMs it gets silently dropped. That's a reasonable default, but unlike OpenClaw, the installer doesn't draw your attention to it or explain your options.
First contact
After setup, I sent "Hi!" to the NanoClaw Telegram bot. Nothing happened. I asked Claude Code for help — I just sent 'Hi' to the Telegram bot but it didn't respond, can you help me figure out what's going on? — and it diagnosed the issue and ran the fix:
systemctl --user restart nanoclaw && sleep 3 && tail -20 logs/nanoclaw.logAfter the restart, it worked. A simple "Hi" and response cost approximately $0.03 and consumed roughly 12,800 tokens.
A few things I noticed immediately. NanoClaw doesn't surface which model it's using anywhere obvious. I had to check the Anthropic API console to confirm it was running Sonnet 4.6. When I asked the bot directly — which model are you using? — it confidently reported Sonnet 4.5, which was incorrect according to the API console. That question-and-answer exchange also consumed about 14,000 tokens, so it was an expensive wrong answer.
There's no default personality configuration, no equivalent to OpenClaw's SOUL.md, and no background tasks running. NanoClaw sits idle until you message it. That simplicity is both a strength (lower default maintenance costs) and a limitation (no proactive behavior out of the box).
Side-by-side: first impressions
After going through both installs, clear differences emerge — not just in the mechanics, but in what each framework prioritizes.
Documentation and setup experience. OpenClaw's fragmented documentation is its biggest barrier to entry. Multiple conflicting guides, a Docker-specific Hetzner path that's harder than it needs to be, and a setup flow that doesn't reliably complete all its own steps (the missing SOUL.md bootstrap). The generic installer works, but finding your way to it may take a couple of false starts. NanoClaw's Claude Code-driven setup is more streamlined — a single path, conversationally guided, with fewer manual decisions. The trade-off is opacity: Claude is doing a lot under the hood, and it's not always clear what it's configured or why.
Security posture. OpenClaw has an extensive and well-documented history of critical vulnerabilities, but its installer is at least transparent about security-relevant decisions — gateway binding, authentication mode, Telegram DM policy. You see the choices and make them yourself. NanoClaw has a smaller attack surface by design (containerized agents, a compact codebase), but it's less explicit about access controls during setup. Neither framework is set-it-and-forget-it from a security perspective; both need ongoing attention.
Dependencies and ongoing costs. OpenClaw's generic installer handles its own runtime dependencies — you just need a model provider API key (OpenRouter, Anthropic, or others). NanoClaw requires Docker and Claude Code (which itself requires either a Claude subscription or API key). In my setup, both frameworks consumed 11,000–13,000 tokens for a simple greeting. OpenClaw adds a 5.5% surcharge when using OpenRouter; NanoClaw has no equivalent fee but effectively locks you into Anthropic's model family, with virtually no support for alternatives.
Running costs to watch. During initial setup, the most notable cost difference was background usage: OpenClaw's default Heartbeat consumes ~11,000 tokens every 30 minutes, adding up to roughly $2/day ($60/month) in model costs. NanoClaw has no background token consumption by default. How per-message costs compare over time will depend on factors like session history, memory context, and how each framework loads its configuration files — something we'll explore in future posts. On the resource side, both frameworks sit comfortably under 10% RAM on a CPX32.
| OpenClaw | NanoClaw | |
|---|---|---|
| Setup experience | Multiple guides, manual decisions, two failed attempts before success | Single Claude-guided flow, mostly automated |
| Prerequisites | Model provider API key (OpenRouter, Anthropic, etc.) | Docker, Claude Code, Claude subscription and/or API key |
| Model provider | Flexible (OpenRouter, Anthropic, local models, others) | Anthropic API (locked to Claude family) |
| Telegram access control | Pairing system with explicit allowlist option | Registered chats only, not surfaced during setup |
| Background token usage | ~11K tokens every 30 min (Heartbeat) — ~$2/day | None by default |
| Personality config | Bootstrap + SOUL.md (supposed to trigger during setup) | None |
| RAM on CPX32 | ~6–7% | ~10% |
What's next
Both agents are running and responding to Telegram messages on their respective Hetzner servers. That's the foundation. But right now, they're both essentially blank slates — no personality, no web search, no skills or plugins, no scheduled tasks.
In the next post, we'll go deeper into configuration: setting up personality and memory, enabling web search, exploring the skills and plugin ecosystems, and comparing how the two frameworks handle day-to-day interactions. If this post was about getting through the front door, the next one is about making yourself at home.
If you haven't set up your Hetzner VPS yet, start with Part 1 — everything in this guide assumes you're starting from a provisioned, firewalled server with SSH access.