>_ Install OpenClaw
from zero to automation

Hands-on workshop guide. Every command is ready to copy and paste into your terminal.

⏱ ~60 min πŸ–₯ Ubuntu 22.04+ VPS 🐳 Docker πŸ”’ Hardened πŸ€– Telegram + Email

// Netcup €5 Discount Voucher

Use this voucher when ordering your Netcup VPS to get €5 off your first order:

36nc17756369199

Click the code to copy it. Enter it at checkout on netcup.com.

// Before you start

Part I β€” VPS Setup & Server Hardening

Get a server, lock it down, install Docker

0

Create your VPS

~5 min (if account already verified)

We'll use Netcup β€” great performance, German hosting, and excellent value. The VPS 500 G12 gives you 2 vCPU, 4 GB RAM, and 128 GB NVMe for €4.69/month (minus €5 with the voucher above!).

Option A: Netcup (recommended)

Netcup account verification can take 15 minutes to 48 hours. If your account isn't verified yet, use the Hetzner fallback below and migrate later.

Option B: Hetzner Cloud (fallback)

If your Netcup account isn't ready, use Hetzner Cloud β€” no approval needed, servers deploy in seconds.

Generate an SSH key (if you don't have one)

local terminal
# Generate an Ed25519 SSH key pair (press Enter through all prompts)
ssh-keygen -t ed25519 -C "admin-workshop"

# Display your PUBLIC key β€” copy this into your VPS provider's dashboard
cat ~/.ssh/id_ed25519.pub
1

Connect via SSH

~1 min

Open your terminal and connect to the server. Replace the IP with your server's actual IP address.

local terminal
# Connect to your server as root
ssh root@YOUR_SERVER_IP

Type yes when asked about the host fingerprint. You should see a root shell prompt.

Netcup users: If you set a password (no SSH key), you'll be prompted for the root password you set in SCP.
2

Server hardening

~10 min

A fresh server on the internet gets brute-force SSH attempts within minutes. We'll lock it down in 6 steps.

2.1 β€” Update the system

First, bring all packages up to date. This patches known security vulnerabilities.

server (root)
# Update package lists and upgrade all installed packages
apt update && apt upgrade -y

2.2 β€” Create a non-root user

Running everything as root is dangerous β€” a single mistake or exploit has full system access. We'll create a dedicated user with sudo privileges instead.

server (root)
# Create a new user called "admin" with no password prompt
adduser --disabled-password --gecos "" admin

# Grant sudo (admin) privileges to this user
usermod -aG sudo admin

# Allow sudo without password prompt (convenience for workshop)
echo "admin ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/admin

# Copy your SSH key so you can log in as this user too
mkdir -p /home/admin/.ssh
cp ~/.ssh/authorized_keys /home/admin/.ssh/
chown -R admin:admin /home/admin/.ssh
chmod 700 /home/admin/.ssh
chmod 600 /home/admin/.ssh/authorized_keys

2.3 β€” Harden SSH configuration

We disable root login and password authentication entirely. Only SSH key login to the admin user will work after this.

server (root)
# Disable root login over SSH
sed -i 's/^#\?PermitRootLogin.*/PermitRootLogin no/' /etc/ssh/sshd_config

# Disable password-based login (SSH keys only)
sed -i 's/^#\?PasswordAuthentication.*/PasswordAuthentication no/' /etc/ssh/sshd_config

# Ensure public key authentication is enabled
sed -i 's/^#\?PubkeyAuthentication.*/PubkeyAuthentication yes/' /etc/ssh/sshd_config

# Restart the SSH daemon to apply changes
systemctl restart sshd
Don't close this terminal! Open a new tab and verify you can log in as the new user before closing the root session:
local terminal (new tab!)
# Test login with the new user β€” must work before closing root!
ssh admin@YOUR_SERVER_IP
Working? Great β€” from now on we use this admin user for everything. Close the root session.

2.4 β€” Set up the firewall (UFW)

UFW (Uncomplicated Firewall) blocks all incoming connections except the ones we explicitly allow. Right now we only need SSH.

server (admin user)
# Allow SSH connections through the firewall
sudo ufw allow OpenSSH

# Enable the firewall (--force skips the confirmation prompt)
sudo ufw --force enable

# Verify: should show SSH as ALLOW
sudo ufw status

2.5 β€” Install Fail2ban

Fail2ban monitors login attempts and automatically bans IP addresses that fail too many times. Essential protection against brute-force attacks.

server (admin user)
# Install fail2ban
sudo apt install fail2ban -y

# Create a local config (so updates don't overwrite your settings)
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local

# Start fail2ban and enable it on boot
sudo systemctl enable --now fail2ban

# Check the SSH jail status β€” shows banned IPs if any
sudo fail2ban-client status sshd

2.6 β€” Enable automatic security updates

Unattended-upgrades automatically installs security patches so your server stays protected even if you forget to update manually.

server (admin user)
# Install and configure automatic security updates
sudo apt install unattended-upgrades -y
sudo dpkg-reconfigure -plow unattended-upgrades
Server hardened. SSH key-only login, no root access, firewall active, brute-force protection on, auto-updates enabled.
3

Install Docker

~3 min

OpenClaw runs in Docker containers. This gives us isolation, easy updates, and consistent behavior across different servers.

server (admin user)
# Download and run Docker's official install script
curl -fsSL https://get.docker.com | sudo sh

# Add your user to the docker group so you don't need sudo for docker
sudo usermod -aG docker $USER

# Apply the new group membership without logging out
newgrp docker

# Verify both Docker and Docker Compose are installed
docker --version
docker compose version
Expected: Docker 27.x+ and Docker Compose v2.x+. If docker compose fails, try docker-compose (with hyphen β€” older syntax).

Part II β€” OpenClaw Installation & Hardening

Install OpenClaw, then lock down the application itself

4

Install OpenClaw

~8 min

4.1 β€” Clone and run setup

The setup script pulls the Docker image, generates auth tokens, and starts the gateway.

server (admin user)
# Clone the OpenClaw repository
git clone https://github.com/openclaw/openclaw.git
cd openclaw

# Run the interactive setup β€” it will ask for your LLM API keys
./scripts/docker/setup.sh
The setup prompts for: your LLM API key(s) (Anthropic, OpenAI, Google, etc.). It auto-generates a gateway token saved to .env and starts the containers.

4.2 β€” Open the web UI port

Allow access to the OpenClaw control panel through the firewall.

server (admin user)
# Allow the OpenClaw web UI port through the firewall
sudo ufw allow 18789/tcp

4.3 β€” Verify installation

server (admin user)
# Check the health endpoint β€” should return OK
curl -fsS http://127.0.0.1:18789/healthz

# See running containers
docker compose ps

Open your browser and navigate to the control panel:

browser address bar
http://YOUR_SERVER_IP:18789

You'll need your gateway token to access Settings. Find it with:

server (admin user)
# Display the gateway token from your .env file
grep GATEWAY_TOKEN .env
OpenClaw is live! You should see the Control UI in your browser. Now let's secure it.
5

OpenClaw security hardening

~10 min

The server is secure, but OpenClaw itself needs configuration to prevent misuse. We'll lock down API keys, restrict permissions, and control what the AI can execute.

5.1 β€” Secure the .env file

Your .env file contains API keys worth real money. Restrict its permissions so only your user can read it.

server (admin user)
# Set .env to be readable only by the owner (you)
chmod 600 ~/openclaw/.env

# Verify permissions β€” should show -rw------- 
ls -la ~/openclaw/.env

5.2 β€” Configure exec approvals (command allowlist)

By default, OpenClaw can execute shell commands. We'll set it to an allowlist-only mode so it can only run commands you've explicitly approved.

~/.config/openclaw/config.json5
{
  // Only allow explicitly approved commands
  "tools": {
    "exec": {
      "security": "allowlist",
      "allow": [
        "git pull",
        "npm install",
        "npm test",
        "python3",
        "pip install"
      ],
      "deny": [
        "rm -rf /",
        "git push --force",
        "chmod 777",
        "curl | sh",
        "wget | sh"
      ],
      "ask": "on-miss"
    }
  }
}

Create this config file:

server (admin user)
# Create the config directory
mkdir -p ~/.config/openclaw

# Create the config file with exec restrictions
cat > ~/.config/openclaw/config.json5 << 'CONF'
{
  "tools": {
    "exec": {
      "security": "allowlist",
      "allow": [
        "git pull",
        "npm install",
        "npm test",
        "python3",
        "pip install"
      ],
      "deny": [
        "rm -rf /",
        "git push --force",
        "chmod 777",
        "curl | sh",
        "wget | sh"
      ],
      "ask": "on-miss"
    }
  }
}
CONF
"ask": "on-miss" means if OpenClaw tries to run a command not in your allow/deny list, it will ask you for permission first instead of just running it.

5.3 β€” Set API spending limits

Prevent runaway costs by setting spending caps in your LLM provider dashboards.

Always set spending caps. An automation bug or a misconfigured loop could burn through your API credits. A $20/month cap is reasonable for personal use.

5.4 β€” Restrict Docker container capabilities

Harden the Docker container itself β€” drop all capabilities except what's needed and enforce read-only filesystems where possible.

server (admin user)
# Check that OpenClaw binds to localhost only (not 0.0.0.0)
# This ensures the web UI isn't exposed to the entire internet without auth
sudo ss -tlnp | grep 18789
Ideal output: 127.0.0.1:18789 means only accessible locally. If it shows 0.0.0.0:18789, the port is open to the world β€” that's fine for the workshop, but in production you'd put it behind a reverse proxy with HTTPS.

5.5 β€” Run a security audit

OpenClaw has a built-in security audit command that checks your configuration for common issues.

server (admin user)
# Run OpenClaw's security audit β€” reports misconfigurations
openclaw security audit

# Run the doctor command β€” checks for risky DM policies and other issues
openclaw doctor
OpenClaw hardened. API keys secured, exec commands restricted to an allowlist, spending caps set, container locked down, audit clean.

Part III β€” Skills, Telegram & Automation

Connect everything and build your first automation

6

Install skills

~5 min

Skills extend what OpenClaw can do. We'll install the ones needed for our morning briefing: email, web search, and weather.

server (admin user)
# Install the himalaya skill β€” gives OpenClaw email access via IMAP
openclaw skills install himalaya

# Install web search skill β€” for fetching news headlines
openclaw skills install web-search

# Install weather skill β€” for forecast data
openclaw skills install weather

# List all installed skills to verify
openclaw skills list
Browse all skills: clawhub.ai has the full skill registry. Always check a skill's page and source code before installing β€” just like you would with any software.

6.1 β€” Configure email (optional)

If you want the morning brief to include email summaries, configure himalaya with your email account:

server (admin user)
# Interactive wizard β€” walks you through IMAP/SMTP setup
himalaya account configure
Gmail users: You need an App Password, not your regular Google password. Go to Google Account β†’ Security β†’ App Passwords.

Or configure manually:

~/.config/himalaya/config.toml
[accounts.myemail]
email = "you@example.com"

[accounts.myemail.imap]
host = "imap.gmail.com"
port = 993
login = "you@example.com"
passwd.cmd = "echo 'your-app-password'"

[accounts.myemail.smtp]
host = "smtp.gmail.com"
port = 587
login = "you@example.com"
passwd.cmd = "echo 'your-app-password'"

Verify it works:

server (admin user)
# List your latest emails β€” should show subjects and senders
himalaya list
7

Connect Telegram

~8 min

7.1 β€” Create a bot via BotFather

On your phone or Telegram desktop:

7.2 β€” Connect the bot to OpenClaw

server (admin user)
cd ~/openclaw

# Register the Telegram channel with your bot token
docker compose run --rm openclaw-cli channels add \
  --channel telegram \
  --token "YOUR_BOT_TOKEN_FROM_BOTFATHER"

7.3 β€” Secure the bot (restrict who can use it)

By default, anyone who finds your bot can talk to it (and use your API credits). Let's restrict it to your Telegram account only.

First, send any message to your bot in Telegram, then find your user ID:

server (admin user)
# Watch logs β€” look for "from":{"id":123456789} in the output
openclaw logs --follow
Note your numeric user ID from the logs. Press Ctrl+C to stop watching logs once you have it.

Now restrict the bot to only accept messages from your Telegram ID:

server (admin user)
# Set DM policy to allowlist β€” only your user ID can talk to the bot
# Replace the number with YOUR Telegram user ID from the logs
cat >> ~/.config/openclaw/config.json5 << 'CONF'

// Telegram DM restrictions β€” only allow specific user IDs
// "channels": {
//   "telegram": {
//     "dmPolicy": "allowlist",
//     "allowFrom": [YOUR_TELEGRAM_USER_ID]
//   }
// }
CONF
Important: Without an allowlist, anyone who finds your bot's username can use it β€” racking up your API bill. Always restrict it in production.

7.4 β€” Test the connection

Send a message to your bot in Telegram β€” try "Hello, are you working?"

Telegram connected and secured! Your bot responds only to you. Now let's make it proactive.
8

Create the Morning Brief

~8 min

The grand finale β€” a scheduled automation that sends you a daily briefing at 9:00 AM via Telegram with news, weather, and email highlights.

8.1 β€” Create the cron job

server (admin user)
openclaw cron add \
  --name "Morning Brief" \
  --cron "0 9 * * *" \
  --tz "Europe/Berlin" \
  --session isolated \
  --announce \
  --channel telegram \
  --to "YOUR_TELEGRAM_CHAT_ID" \
  --message "Good morning! Please prepare my daily briefing:

1. **Top News**: Summarize the 3-5 most important world and tech news headlines from today.

2. **Weather**: What is the weather forecast for today and tomorrow in your city?

3. **Email Summary** (if himalaya is available): Check my recent emails from the last 12 hours. Summarize any important or action-required messages. Skip newsletters and spam.

Keep it concise and actionable. Under 500 words."
Timezone examples: Europe/Berlin, Europe/London, Europe/Kyiv, America/New_York, Asia/Tokyo. Use yours!

8.2 β€” Test it now

server (admin user)
# List your cron jobs β€” note the JOB_ID
openclaw cron list

# Trigger it immediately to test (don't wait until 9 AM!)
openclaw cron run JOB_ID

Check your Telegram β€” within a minute or two, your bot should send you a full morning briefing!

8.3 β€” Cron cheat sheet

reference
# Manage cron jobs
openclaw cron list                          # List all jobs
openclaw cron runs --id ID --limit 10       # See run history
openclaw cron edit ID                       # Edit a job
openclaw cron remove ID                     # Delete a job

# Common schedules
# "0 9 * * *"      β†’ 9:00 AM every day
# "0 9 * * 1-5"    β†’ 9:00 AM weekdays only
# "30 8,18 * * *"  β†’ 8:30 AM and 6:30 PM daily
# "0 */3 * * *"    β†’ every 3 hours
Done! You now have a personal AI assistant running 24/7 on your own server β€” secured, connected to Telegram, and sending you a proactive morning briefing every day. Explore ClawHub for hundreds more skills.