This guide provides an Ansible playbook to deploy Nanobot with Docker Compose on Debian 10+, Ubuntu 20.04+, and RHEL 9+ compatible hosts. Nanobot is an ultra-lightweight Python AI agent (~4,000 lines of code) supporting 10+ messaging platforms.
Important: Nanobot does not provide an official Docker image. This playbook builds from the official repository using Docker Compose.
Official Resources:
---
- name: Deploy Nanobot with Docker
hosts: nanobot
become: true
vars:
app_root: /opt/nanobot
app_name: nanobot
app_port: 18790
nanobot_repo: "https://github.com/HKUDS/nanobot"
nanobot_version: "main"
# LLM Configuration
llm_provider: "openrouter"
openrouter_api_key: "{{ vault_nanobot_openrouter_api_key }}"
default_model: "anthropic/claude-opus-4-5"
tasks:
- name: Install Docker on Debian/Ubuntu
apt:
name:
- docker.io
- docker-compose-plugin
- git
state: present
update_cache: true
when: ansible_os_family == "Debian"
- name: Install Docker on RHEL family
dnf:
name:
- docker
- docker-compose-plugin
- git
state: present
when: ansible_os_family == "RedHat"
- name: Enable and start Docker
service:
name: docker
state: started
enabled: true
- name: Add user to docker group
user:
name: "{{ ansible_user }}"
groups: docker
append: true
- name: Clone Nanobot repository
git:
repo: "{{ nanobot_repo }}"
dest: "{{ app_root }}"
version: "{{ nanobot_version }}"
force: true
- name: Create configuration directory on host
file:
path: "{{ ansible_user_dir }}/.nanobot"
state: directory
mode: "0755"
owner: "{{ ansible_user }}"
- name: Write Nanobot configuration
copy:
dest: "{{ ansible_user_dir }}/.nanobot/config.json"
mode: "0640"
owner: "{{ ansible_user }}"
content: |
{
"providers": {
"{{ llm_provider }}": {
"apiKey": "{{ openrouter_api_key }}"
}
},
"agents": {
"defaults": {
"model": "{{ default_model }}",
"provider": "{{ llm_provider }}"
}
},
"channels": {}
}
- name: Write Docker Compose override file
copy:
dest: "{{ app_root }}/docker-compose.override.yml"
mode: "0644"
content: |
services:
nanobot-gateway:
restart: unless-stopped
ports:
- "{{ app_port }}:18790"
deploy:
resources:
limits:
cpus: '1'
memory: 1G
reservations:
cpus: '0.25'
memory: 256M
- name: Run onboarding (first time setup)
shell: |
docker compose run --rm nanobot-cli onboard
args:
chdir: "{{ app_root }}"
register: onboarding_result
ignore_errors: true
when: onboarding_run | default(true)
- name: Build and start Nanobot
shell: |
docker compose build
docker compose up -d nanobot-gateway
args:
chdir: "{{ app_root }}"
- name: Wait for gateway to be ready
wait_for:
port: "{{ app_port }}"
delay: 5
timeout: 60
Save the playbook as deploy-nanobot-docker.yml.
Create an inventory file (inventory.ini):
[nanobot]
server1.example.com
server2.example.com
[nanobot:vars]
ansible_user=deploy
ansible_ssh_private_key_file=~/.ssh/id_ed25519
Use Ansible Vault to store sensitive values:
# Create vault file
ansible-vault create group_vars/nanobot/vault.yml
Add your API keys:
vault_nanobot_openrouter_api_key: "sk-or-v1-your-actual-api-key"
vault_nanobot_telegram_token: "YOUR_TELEGRAM_BOT_TOKEN"
# Basic run
ansible-playbook -i inventory.ini deploy-nanobot-docker.yml
# With vault
ansible-playbook -i inventory.ini deploy-nanobot-docker.yml --ask-vault-pass
# Skip onboarding (if already configured)
ansible-playbook -i inventory.ini deploy-nanobot-docker.yml -e "onboarding_run=false"
---
- name: Deploy Nanobot with Telegram
hosts: nanobot
become: true
vars:
app_root: /opt/nanobot
app_port: 18790
openrouter_api_key: "{{ vault_nanobot_openrouter_api_key }}"
telegram_bot_token: "{{ vault_nanobot_telegram_token }}"
allowed_user_ids:
- "YOUR_USER_ID"
tasks:
- name: Install Docker and dependencies
apt:
name:
- docker.io
- docker-compose-plugin
- git
state: present
update_cache: true
when: ansible_os_family == "Debian"
- name: Enable and start Docker
service:
name: docker
state: started
enabled: true
- name: Add user to docker group
user:
name: "{{ ansible_user }}"
groups: docker
append: true
- name: Clone Nanobot repository
git:
repo: "https://github.com/HKUDS/nanobot"
dest: "{{ app_root }}"
version: "main"
force: true
- name: Create config directory
file:
path: "{{ ansible_user_dir }}/.nanobot"
state: directory
mode: "0750"
owner: "{{ ansible_user }}"
- name: Write Nanobot configuration
copy:
dest: "{{ ansible_user_dir }}/.nanobot/config.json"
mode: "0640"
owner: "{{ ansible_user }}"
content: |
{
"providers": {
"openrouter": {
"apiKey": "{{ openrouter_api_key }}"
}
},
"agents": {
"defaults": {
"model": "anthropic/claude-opus-4-5",
"provider": "openrouter"
}
},
"channels": {
"telegram": {
"enabled": true,
"token": "{{ telegram_bot_token }}",
"allowFrom": {{ allowed_user_ids | to_json }}
}
}
}
- name: Build and start Nanobot
shell: |
docker compose build
docker compose up -d nanobot-gateway
args:
chdir: "{{ app_root }}"
---
- name: Deploy Nanobot with Multiple Channels
hosts: nanobot
become: true
vars:
app_root: /opt/nanobot
app_port: 18790
openrouter_api_key: "{{ vault_nanobot_openrouter_api_key }}"
telegram_token: "{{ vault_nanobot_telegram_token }}"
discord_token: "{{ vault_nanobot_discord_token }}"
tasks:
- name: Install Docker
apt:
name:
- docker.io
- docker-compose-plugin
- git
state: present
update_cache: true
when: ansible_os_family == "Debian"
- name: Enable and start Docker
service:
name: docker
state: started
enabled: true
- name: Clone Nanobot repository
git:
repo: "https://github.com/HKUDS/nanobot"
dest: "{{ app_root }}"
force: true
- name: Write Nanobot configuration (multi-channel)
copy:
dest: "{{ ansible_user_dir }}/.nanobot/config.json"
mode: "0640"
content: |
{
"providers": {
"openrouter": {
"apiKey": "{{ openrouter_api_key }}"
}
},
"agents": {
"defaults": {
"model": "anthropic/claude-opus-4-5",
"provider": "openrouter"
}
},
"channels": {
"telegram": {
"enabled": true,
"token": "{{ telegram_token }}",
"allowFrom": ["YOUR_USER_ID"]
},
"discord": {
"enabled": true,
"token": "{{ discord_token }}"
}
}
}
- name: Build and start Nanobot
shell: |
docker compose build
docker compose up -d
args:
chdir: "{{ app_root }}"
---
- name: Deploy Nanobot with Nginx
hosts: nanobot
become: true
vars:
app_root: /opt/nanobot
app_port: 18790
nginx_port: 80
domain_name: "nanobot.example.com"
openrouter_api_key: "{{ vault_nanobot_openrouter_api_key }}"
tasks:
- name: Install Docker
apt:
name:
- docker.io
- docker-compose-plugin
- git
state: present
update_cache: true
when: ansible_os_family == "Debian"
- name: Enable and start Docker
service:
name: docker
state: started
enabled: true
- name: Clone Nanobot repository
git:
repo: "https://github.com/HKUDS/nanobot"
dest: "{{ app_root }}"
force: true
- name: Write Docker Compose override (with Nginx)
copy:
dest: "{{ app_root }}/docker-compose.override.yml"
mode: "0644"
content: |
services:
nanobot-gateway:
restart: unless-stopped
expose:
- "18790"
nginx:
image: nginx:alpine
container_name: nanobot-nginx
restart: unless-stopped
ports:
- "{{ nginx_port }}:80"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
depends_on:
- nanobot-gateway
- name: Write Nginx configuration
copy:
dest: "{{ app_root }}/nginx.conf"
mode: "0644"
content: |
events {
worker_connections 1024;
}
http {
upstream nanobot {
server nanobot-gateway:18790;
}
server {
listen 80;
server_name {{ domain_name }};
location / {
proxy_pass http://nanobot;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
}
- name: Start application stack
command: docker compose up -d
args:
chdir: "{{ app_root }}"
~/.nanobot/config.json| Variable | Default | Description |
|---|---|---|
app_root |
/opt/nanobot |
Application installation directory |
app_name |
nanobot |
Container name |
app_port |
18790 |
Port to expose Nanobot gateway |
nanobot_repo |
https://github.com/HKUDS/nanobot |
Git repository URL |
nanobot_version |
main |
Git branch or tag to deploy |
llm_provider |
openrouter |
LLM provider key |
openrouter_api_key |
- |
OpenRouter API key (use Ansible Vault) |
default_model |
anthropic/claude-opus-4-5 |
Default model to use |
| Provider | Config Key | Notes |
|---|---|---|
| OpenRouter | openrouter |
Multi-provider aggregator (recommended) |
| Anthropic | anthropic |
Claude models |
| OpenAI | openai |
GPT-4, GPT-3.5-turbo |
| DeepSeek | deepseek |
DeepSeek models |
| Groq | groq |
Fast inference |
| Google Gemini | gemini |
Google AI models |
| Zhipu | zhipu |
Chinese LLM provider |
| Platform | Config Key | Notes |
|---|---|---|
| Telegram | telegram |
Bot token from @BotFather |
| Discord | discord |
Bot token, requires Message Content intent |
whatsapp |
QR scan, requires Node.js 18+ | |
| Slack | slack |
Bot token + App token (Socket Mode) |
| Feishu | feishu |
App ID + App Secret |
| DingTalk | dingtalk |
App Key + App Secret |
qq |
Bot credentials | |
email |
IMAP/SMTP configuration | |
| Matrix | matrix |
Homeserver + access token, E2EE support |
| Mochat | mochat |
Enterprise messaging |
| Wecom | wecom |
Bot ID + Bot Secret (Enterprise WeChat) |
# SSH to server
ssh user@server
# Check container status
docker compose ps -f /opt/nanobot
# View logs
docker compose logs -f nanobot-gateway
# SSH to server and test
ssh user@server
curl http://127.0.0.1:18790
# SSH to server
ssh user@server
# Edit config
nano ~/.nanobot/config.json
# Restart container
docker compose -f /opt/nanobot/docker-compose.yml restart
---
- name: Backup Nanobot configuration
hosts: nanobot
become: true
vars:
app_root: /opt/nanobot
tasks:
- name: Create backup directory
file:
path: "{{ app_root }}/backups"
state: directory
- name: Backup configuration
archive:
path: "{{ ansible_user_dir }}/.nanobot"
dest: "{{ app_root }}/backups/config-{{ ansible_date_time.date }}.tar.gz"
---
- name: Update Nanobot
hosts: nanobot
become: true
vars:
app_root: /opt/nanobot
tasks:
- name: Pull latest code
git:
repo: "{{ nanobot_repo }}"
dest: "{{ app_root }}"
force: true
- name: Rebuild and restart
shell: |
docker compose build
docker compose up -d
args:
chdir: "{{ app_root }}"
# SSH to server
ssh user@server
# Check container status
docker compose ps -f /opt/nanobot
# View logs
docker compose logs -f nanobot-gateway
docker compose -f /opt/nanobot/docker-compose.yml restart
cd /opt/nanobot
git pull
docker compose build
docker compose up -d
Docker permission errors:
# Add user to docker group
sudo usermod -aG docker $USER
# Log out and back in
Configuration not loading:
# Check config file
cat ~/.nanobot/config.json
# Verify JSON syntax
python3 -m json.tool ~/.nanobot/config.json
For detailed security guidance, see Nanobot Security.
Any questions?
Feel free to contact us. Find all contact information on our contact page.