DigitalOcean Droplet (Manual)

Full control deployment on a DigitalOcean droplet with Docker, systemd, security hardening, and monitoring

Platform: DigitalOcean
Cost: $6-24/month
Time: 45 minutes
Difficulty: Intermediate

Deploy OpenClaw on a DigitalOcean Droplet

A production-ready deployment guide covering server provisioning, security hardening, process management, and monitoring. By the end of this guide, you will have OpenClaw running as a persistent systemd service on an Ubuntu droplet with automatic restarts, firewall protection, and log rotation.

Estimated time: 45 minutes | Cost: $6-24/month | Difficulty: Intermediate


Prerequisites

Before you begin, make sure you have:

  • A DigitalOcean account with a valid payment method (sign up here)
  • An SSH key pair on your local machine (generate one with ssh-keygen -t ed25519 if you do not have one)
  • Your SSH public key added to your DigitalOcean account under Settings > Security > SSH Keys
  • An API key for your chosen LLM provider (e.g., Anthropic, OpenAI) -- OpenClaw needs this to run agents
  • (Optional) A domain name if you want to expose OpenClaw behind a custom URL with SSL

Step 1: Create the Droplet

Log in to the DigitalOcean control panel and click Create > Droplets.

Recommended configuration:

SettingValue
RegionChoose the region closest to you or your users (e.g., nyc1, sfo3, fra1)
ImageUbuntu 24.04 LTS (or 22.04 LTS)
Droplet TypeBasic (Shared CPU)
Plan$6/mo (1 vCPU, 1 GB RAM) for light use; $12/mo (1 vCPU, 2 GB RAM) recommended for production
AuthenticationSSH Key (select the key you added)
Hostnameopenclaw-prod or similar

Click Create Droplet and wait roughly 60 seconds for provisioning to finish. Copy the droplet's public IP address from the dashboard.

Tip: The $6/mo plan works fine for a single agent with light traffic. If you are running multiple concurrent agents or handling webhook-heavy workloads, start with the $12/mo plan so you have 2 GB of RAM and room to breathe.


Step 2: Initial Server Setup

SSH into your new droplet as root:

ssh root@YOUR_DROPLET_IP

Create a non-root user

Running everything as root is a security risk. Create a dedicated user:

# Create user and grant sudo privileges
adduser openclaw
usermod -aG sudo openclaw

# Copy your SSH key to the new user
rsync --archive --chown=openclaw:openclaw ~/.ssh /home/openclaw

Switch to the new user for the rest of the setup:

su - openclaw

Configure the firewall

Ubuntu ships with ufw (Uncomplicated Firewall). Enable it with sensible defaults:

# Allow SSH connections so you don't lock yourself out
sudo ufw allow OpenSSH

# Allow HTTP and HTTPS for the OpenClaw dashboard (port 18789) behind a reverse proxy
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp

# Enable the firewall
sudo ufw enable

# Verify the rules
sudo ufw status verbose

You should see OpenSSH, 80/tcp, and 443/tcp listed as ALLOW.


Step 3: Install Dependencies

Install Node.js 20 LTS via nvm

nvm (Node Version Manager) lets you install and switch between Node.js versions without conflicting with system packages:

# Install nvm
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash

# Load nvm into the current shell
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"

# Install Node.js 20 LTS
nvm install 20

# Verify the installation
node --version   # Should print v20.x.x
npm --version    # Should print 10.x.x

Install Docker and Docker Compose

Docker is optional but useful if you want to run OpenClaw in a container or add services like Redis or PostgreSQL alongside it:

# Remove any old Docker packages
sudo apt-get remove docker docker-engine docker.io containerd runc 2>/dev/null

# Install prerequisites
sudo apt-get update
sudo apt-get install -y ca-certificates curl gnupg

# Add Docker's official GPG key
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg

# Add the Docker repository
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
  $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# Install Docker Engine and Docker Compose plugin
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

# Add your user to the docker group (avoids needing sudo for docker commands)
sudo usermod -aG docker $USER

# Apply group changes (or log out and back in)
newgrp docker

# Verify Docker is running
docker --version
docker compose version

Step 4: Install OpenClaw

Install the CLI globally

npm install -g openclaw

Verify the installation:

openclaw --version

Configure environment variables

Create a dedicated directory for your OpenClaw configuration:

mkdir -p ~/.openclaw

Create the environment file with your API keys and settings:

cat > ~/.openclaw/.env << 'EOF'
# LLM Provider API Keys
# Uncomment and fill in the provider(s) you use
ANTHROPIC_API_KEY=your-anthropic-api-key-here
# OPENAI_API_KEY=your-openai-api-key-here

# OpenClaw Configuration
OPENCLAW_PORT=3111
OPENCLAW_HOST=0.0.0.0
OPENCLAW_LOG_LEVEL=info

# Optional: Webhook URL for notifications
# OPENCLAW_WEBHOOK_URL=https://your-webhook-endpoint.com/hook
EOF

Lock down permissions on the env file so only your user can read it:

chmod 600 ~/.openclaw/.env

Verify OpenClaw starts correctly

Run a quick test to make sure everything is wired up:

cd ~/.openclaw
openclaw start --dry-run

If the dry run succeeds, OpenClaw can read your configuration and connect to your LLM provider.


Step 5: Run as a Service

Running OpenClaw in a terminal session means it dies when you disconnect. A systemd service keeps it running permanently, starts it on boot, and restarts it automatically if it crashes.

Create the service file:

sudo tee /etc/systemd/system/openclaw.service > /dev/null << 'EOF'
[Unit]
Description=OpenClaw AI Agent Framework
Documentation=https://docs.openclaw.dev
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=openclaw
Group=openclaw
WorkingDirectory=/home/openclaw/.openclaw

# Load nvm and use the correct Node.js version
Environment=HOME=/home/openclaw
Environment=NVM_DIR=/home/openclaw/.nvm
ExecStart=/bin/bash -c 'source $NVM_DIR/nvm.sh && exec openclaw start'

# Load environment variables from the .env file
EnvironmentFile=/home/openclaw/.openclaw/.env

# Restart policy: always restart, wait 5 seconds between attempts
Restart=always
RestartSec=5
StartLimitIntervalSec=60
StartLimitBurst=5

# Security: restrict what the service can do
NoNewPrivileges=true
ProtectSystem=strict
ReadWritePaths=/home/openclaw/.openclaw

# Logging
StandardOutput=journal
StandardError=journal
SyslogIdentifier=openclaw

[Install]
WantedBy=multi-user.target
EOF

Enable and start the service:

# Reload systemd to pick up the new service file
sudo systemctl daemon-reload

# Enable the service to start on boot
sudo systemctl enable openclaw

# Start the service now
sudo systemctl start openclaw

# Check the status
sudo systemctl status openclaw

You should see active (running) in green. To view live logs:

journalctl -u openclaw -f

Useful service management commands:

sudo systemctl restart openclaw   # Restart after config changes
sudo systemctl stop openclaw      # Stop the service
sudo systemctl status openclaw    # Check health
journalctl -u openclaw --since "1 hour ago"  # Recent logs

Step 6: Security Hardening

Your droplet is exposed to the public internet. These steps significantly reduce your attack surface.

Disable root SSH login

sudo sed -i 's/^PermitRootLogin yes/PermitRootLogin no/' /etc/ssh/sshd_config
sudo sed -i 's/^#PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config
sudo systemctl restart sshd

Warning: Before doing this, verify you can SSH in as the openclaw user from another terminal window. If you lock yourself out, you will need to use the DigitalOcean console to regain access.

Install and configure fail2ban

fail2ban watches log files and bans IPs that show malicious behavior (like brute-force SSH attempts):

sudo apt-get install -y fail2ban

# Create a local configuration override
sudo tee /etc/fail2ban/jail.local > /dev/null << 'EOF'
[DEFAULT]
bantime = 3600
findtime = 600
maxretry = 3

[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
EOF

sudo systemctl enable fail2ban
sudo systemctl start fail2ban

Check banned IPs at any time:

sudo fail2ban-client status sshd

Enable unattended security upgrades

Keep your server patched automatically:

sudo apt-get install -y unattended-upgrades
sudo dpkg-reconfigure -plow unattended-upgrades

Select Yes when prompted. Ubuntu will now automatically install security patches overnight without requiring manual intervention.

Review firewall rules

Double-check that only the ports you need are open:

sudo ufw status numbered

If you do not need HTTP/HTTPS (e.g., OpenClaw only communicates outbound to APIs), remove those rules:

sudo ufw delete allow 80/tcp
sudo ufw delete allow 443/tcp

Step 7: Monitoring

Basic health check with a cron job

Create a script that checks whether OpenClaw is responding and restarts it if not:

sudo tee /usr/local/bin/openclaw-healthcheck.sh > /dev/null << 'SCRIPT'
#!/bin/bash
# Simple health check: verify the openclaw service is active
if ! systemctl is-active --quiet openclaw; then
    echo "$(date): OpenClaw is down, restarting..." >> /var/log/openclaw-healthcheck.log
    systemctl restart openclaw
fi
SCRIPT

sudo chmod +x /usr/local/bin/openclaw-healthcheck.sh

Schedule it to run every 5 minutes:

echo "*/5 * * * * root /usr/local/bin/openclaw-healthcheck.sh" | sudo tee /etc/cron.d/openclaw-healthcheck

Configure log rotation

Prevent log files from consuming all your disk space:

sudo tee /etc/logrotate.d/openclaw > /dev/null << 'EOF'
/home/openclaw/.openclaw/logs/*.log {
    daily
    rotate 7
    compress
    delaycompress
    missingok
    notifempty
    create 640 openclaw openclaw
    postrotate
        systemctl restart openclaw > /dev/null 2>&1 || true
    endscript
}
EOF

Journald (which captures systemd service logs) has its own rotation. Cap it at 500 MB:

sudo sed -i 's/#SystemMaxUse=/SystemMaxUse=500M/' /etc/systemd/journald.conf
sudo systemctl restart systemd-journald

Optional: External monitoring

For production deployments, consider adding an external monitoring agent:

Datadog (full observability):

DD_API_KEY=your-datadog-api-key bash -c \
  "$(curl -L https://install.datadoghq.com/scripts/install_script_agent7.sh)"

Grafana Cloud (free tier available): Install the Grafana Agent to push metrics and logs to Grafana Cloud. This gives you dashboards, alerting, and log search without running your own Grafana instance.

Uptime Kuma (self-hosted, free): If you want a lightweight status page, run Uptime Kuma as a Docker container on the same droplet:

docker run -d --restart=always -p 3001:3001 \
  -v uptime-kuma:/app/data \
  --name uptime-kuma \
  louislam/uptime-kuma:1

Cost Breakdown

PlanvCPUsRAMDiskTransferMonthly CostBest For
Basic11 GB25 GB SSD1 TB$6Single agent, light usage, testing
Basic12 GB50 GB SSD2 TB$12Production single agent, moderate traffic
Basic22 GB60 GB SSD3 TB$18Multiple agents, webhook-heavy workloads
Basic24 GB80 GB SSD4 TB$24High-traffic production, concurrent agents

Additional costs to consider:

  • LLM API usage: This is typically your largest cost. Budget $10-100+/month depending on agent activity and model choice.
  • Domain name: ~$10-15/year if you want a custom domain.
  • Backups: DigitalOcean automated backups add 20% to the droplet cost ($1.20-$4.80/mo).
  • Monitoring: Datadog starts at ~$15/host/month. Grafana Cloud has a generous free tier. Uptime Kuma is free.

Recommendation: Start with the $6/mo plan. DigitalOcean lets you resize droplets with a few clicks and minimal downtime. Scale up only when you actually need it.


Troubleshooting

OpenClaw fails to start

Check the service logs:

journalctl -u openclaw -n 50 --no-pager

Common causes:

  • Missing or invalid API key in ~/.openclaw/.env. Verify the key works by running openclaw start --dry-run.
  • Node.js not found. The systemd service needs nvm loaded. Make sure the NVM_DIR environment variable in the service file points to the correct path.
  • Port already in use. Check with sudo ss -tlnp | grep 3111 and kill the conflicting process.

Cannot SSH into the server

  • Verify your SSH key is added to ~/.ssh/authorized_keys for the openclaw user.
  • If you disabled root login and cannot get in, use the DigitalOcean Console from the droplet dashboard (Access > Launch Droplet Console).
  • Check that UFW has not blocked SSH: use the DigitalOcean console to run sudo ufw allow OpenSSH.

High memory usage

  • The $6 droplet only has 1 GB of RAM. Add swap space as a safety net:
sudo fallocate -l 1G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
  • If memory is still a problem, resize to the $12/mo plan from the DigitalOcean dashboard.

Service keeps restarting

Check for crash loops:

journalctl -u openclaw --since "10 minutes ago" | grep -i error

If the service hits the restart limit (5 restarts in 60 seconds), systemd will stop trying. Reset the counter and investigate:

sudo systemctl reset-failed openclaw
sudo systemctl start openclaw

Docker permission denied

If you see permission denied when running Docker commands, your user is not in the docker group:

sudo usermod -aG docker $USER
newgrp docker

Firewall blocking connections

If external services cannot reach OpenClaw, verify the port is open:

sudo ufw allow 3111/tcp
sudo ufw reload

Next Steps

Once OpenClaw is running on your droplet, consider these improvements:

  • Set up a reverse proxy: Use Nginx or Caddy to serve OpenClaw behind a domain with automatic SSL via Let's Encrypt.
  • Enable backups: Turn on DigitalOcean automated backups from the droplet settings.
  • Add a domain: Point an A record to your droplet IP and configure SSL.
  • Set up CI/CD: Automate deployments with GitHub Actions that SSH into your droplet and update OpenClaw on push.
  • Join the community: Share your deployment setup and custom skills at openclaw.dev/community.