How to Install and Secure Nanoclaw on a Self-Managed VPS and VDS via SSH

Before you start: NanoClaw runs agents inside isolated Docker containers, but the host machine itself is still a real server exposed to the internet. Harden SSH access and the firewall first, the same as you would for any VPS or VDS — this guide walks through that before touching NanoClaw itself.

This guide installs NanoClaw manually on a blank Self-Managed VPS or VDS over SSH. NanoClaw is an AI agent that connects to messaging platforms (Telegram, Discord, WhatsApp, Slack, and others) and runs each conversation's agent inside its own disposable Docker container — nothing an agent does touches the host filesystem unless you explicitly allow it.

System Requirements

Resource Minimum Specification Recommended Specification
Processor (CPU) 1 vCPU (64-bit architecture) 2 vCPUs or higher
Memory (RAM) 4 GB — the installer specifically warns below ~3.7 GB 4 GB or higher
Disk Space 10 GB available SSD storage 25 GB or higher (agent container images add up if you run several groups)
Operating System Ubuntu 22.04 LTS (amd64) Ubuntu 24.04 LTS (amd64)

These specs apply whether you're running on Self-Managed VPS or VDS.

Prerequisites

  1. A Self-Managed VPS or VDS meeting the specs above, freshly provisioned with no Application pre-selected.
  2. Root SSH access: the server's IP address and the initial root password (or key) provided at provisioning.
  3. A credential for your AI provider: by default this is Claude — a Pro/Max subscription, an OAuth token, or an Anthropic API key. You don't need this in hand before you start; the setup wizard asks for it partway through and you can also skip it and connect later.

Connect to Your VPS or VDS via SSH

ssh root@your_server_ip

Example Output:

Welcome to Ubuntu 24.04 LTS (GNU/Linux 6.8.0-generic x86_64) root@server-123456:~#

1. Baseline Linux Host Hardening

Do this before installing NanoClaw, not after — a fresh VPS or VDS is exposed to automated scanning the moment it's on the internet.

Create an Unprivileged Deployment User

adduser nanoclawadmin

The prompts after this (Full Name, Room Number, Phone, etc.) are just optional Linux account metadata — press Enter through all of them.

usermod -aG sudo nanoclawadmin

Install a Text Editor (If Not Present)

apt update && apt install nano -y

Set Up Key-Based Login — Do This Before Disabling Passwords

This step is not optional, and the order matters. The next section disables password login entirely. If you disable it before confirming a key works, you will lock yourself out with no way back in except your hosting provider's recovery console.

If you don't already have SSH key-based access set up for this server, generate a key pair on your own computer and copy it over:

ssh-keygen -t ed25519 -C "nanoclaw-vps" ssh-copy-id nanoclawadmin@your_server_ip

Already have a working key for this server? Skip straight to confirming it below.

In a new, separate terminal window — keeping your current root session open — confirm it works without a password prompt:

ssh nanoclawadmin@your_server_ip sudo whoami

You should land at a prompt with no password asked for SSH, and sudo whoami should print root (it will ask for nanoclawadmin's own password — that's normal and separate from SSH login). Only continue once this works.

Disable Password and Root SSH Login

nano /etc/ssh/sshd_config

Ubuntu's default file already has these three lines, commented out, in the "Authentication:" section — find and uncomment each, setting the values below:

PermitRootLogin no PasswordAuthentication no PubkeyAuthentication yes
systemctl restart ssh

Immediately test a fresh login in yet another new terminal before closing anything:

ssh nanoclawadmin@your_server_ip

Configure the Firewall

ufw isn't installed by default on a minimal Ubuntu image:

apt install ufw -y

Allow SSH before enabling the firewall, or you'll lock yourself out the same way as the password change above:

ufw allow OpenSSH ufw default deny incoming ufw default allow outgoing ufw enable

Example Output:

Command may disrupt existing ssh connections. Proceed with operation (y|n)? y Firewall is active and enabled on system startup
NanoClaw doesn't need any inbound ports opened beyond SSH. It doesn't run a web dashboard, and its channel adapters (Telegram, Discord, WhatsApp) connect outbound to those platforms' APIs rather than listening for inbound traffic. The one exception is Slack, which pushes events in via a webhook — if you connect Slack later, that's the only case where you'd need to open an additional port, and the /add-slack skill will tell you if so at setup time.

Deploy Fail2Ban

apt install fail2ban -y systemctl enable --now fail2ban

From here on, do everything as your unprivileged user:

su - nanoclawadmin

2. Install NanoClaw

NanoClaw's installer checks for Node.js, pnpm, and Docker, and installs whatever's missing on its own — you don't need to install Docker yourself first. Make sure git is available, then run the installer:

sudo apt install git -y git clone https://github.com/nanocoai/nanoclaw.git cd nanoclaw bash nanoclaw.sh

This launches an interactive setup wizard — it takes roughly 15 minutes on a fresh machine (most of that is the first container image build). It will ask you, in order: Standard or Advanced setup, whether to reuse or install a OneCLI credential vault, how you want to connect your AI provider (subscription sign-in, OAuth token, API key, or skip), a display name for your assistant, your timezone, and whether to connect a messaging channel now or later.

Confirmed by direct testing — this is the single most common thing to trip up a manual install: partway through, the installer silently runs the equivalent of usermod -aG docker nanoclawadmin to let your user talk to Docker. That group change does not take effect in the SSH session you're already in — only in a session that starts after the change. If you complete the whole wizard in one sitting, the background service will crash-loop with an error like:
permission denied while trying to connect to the docker API at unix:///var/run/docker.sock
The fix, without needing to fully log out:
newgrp docker docker info
Once docker info returns real output instead of a permission error, restart the service:
systemctl --user restart 'nanoclaw-v2-*'

3. Verify the Install

Confirm the background service is actually running:

systemctl --user list-units 'nanoclaw-v2-*' systemctl --user status 'nanoclaw-v2-*' --no-pager -l

Confirm the socket the CLI and chat script talk to actually exists:

ls -la data/cli.sock

Then test it directly from the terminal:

pnpm run chat hi

If you skipped provider sign-in during setup, this will fail with something like 401 No credentials configured... in OneCLI — that's expected, not a bug; finish sign-in with bash nanoclaw.sh or inside a claude session to resolve it.

4. Agent Groups, Not "Profiles"

Each isolated agent identity in NanoClaw is called a group (found under groups/<folder>/ in your checkout) — not a "profile." The underlying advice still holds: keep unrelated jobs in separate groups rather than combining them, so a compromised or misbehaving agent in one group can't reach another group's files, memory, or mounts. Groups are created and managed with the ncl CLI, covered in a separate article on managing your install day to day.

5. How You Actually Interact With It

There's no web dashboard. NanoClaw doesn't ship one, doesn't bind to any port for configuration, and there's no SYSTEM_USER/SYSTEM_PASS login to set up. All configuration happens over the SSH session you already have.

Three ways to work with your install once it's running:

  • Chat directly from the terminal: pnpm run chat hi
  • Open a full Claude Code session (for setup skills, debugging, adding channels): claude
  • Query or modify state directly (groups, channels, approvals) with the ncl CLI: pnpm ncl help
  • Talk to it for real once you've connected a channel — Telegram, Discord, WhatsApp, Slack, and others install on demand via /add-<channel> skills inside a claude session.

Channel Connection Safety

Most channel adapters (Telegram, Discord, WhatsApp) connect outbound to that platform's own API using a bot token or paired session — there's no inbound port or webhook to secure for these. Slack is the exception, since Slack delivers events via an outbound webhook call to your server; if you connect Slack, put it behind TLS (e.g. via Nginx or Caddy as a reverse proxy) rather than exposing it directly.

Summary

The security fundamentals for a NanoClaw Self-Managed VPS or VDS are the same as for any server: key-based SSH only, a firewall that only allows what you actually need open, and Fail2Ban watching for brute-force attempts. NanoClaw's own security model — container isolation per agent, mount allowlists, and an approval workflow for sensitive actions — is handled by the application itself once it's running; it doesn't require a manually maintained Docker Compose stack or an exposed web dashboard.