No, you don't need a Mac Mini or fancy hardware setup to run your own AI agent 24/7. All you need is a cloud virtual machine or VPS (Virtual Private Server).
I know what you're thinking: "What about security?" And you should be thinking about it. That's exactly why I'm going to walk you through the step-by-step process to securely set up an AI agent running as a Docker container.
Imagine having your own private AI assistant running 24/7 on a cloud server you control-accessible from anywhere, yet completely shielded from the public internet. That's exactly what we're building today.
In this guide, we'll deploy OpenClaw (also known as Moltbot/Clawdbot) on an AWS EC2 instance using Docker containers. But we're not just going to spin up a container and call it a day. We'll harden our server, lock down SSH access, and use Tailscale to create a secure private network that only you can access.
What You'll Have by the End
- A hardened Ubuntu server with non-standard SSH configuration
- Docker running OpenClaw in an isolated container
- Secure private access via Tailscale (no public ports exposed)
- A fully functional AI assistant accessible from your browser Let's get started.
If you prefer video tutorial, you can watch the below end-to-end video (else, keep reading the blog)
Prerequisites
Before we dive in, make sure you have the following ready:
Cloud Infrastructure
- AWS Account with EC2 access
- A fresh Ubuntu 24.04 LTS instance (Recommended specs: 2 vCPU, 4GB RAM, 15GB storage)
-
Key Pair: Your
.pemfile from AWS (e.g.,moltbot.pem) saved on your local computer -
Current Access: Ability to SSH into the instance as the default
ubuntuuser
API Keys
- Anthropic API Key (for Claude Sonnet/Opus - recommended for best performance)
- OpenAI API Key (Optional, as a backup)
Networking
- Tailscale Account: Free tier is sufficient (this is how we'll securely access our bot)
Pro Tip: If you're new to AWS, providers like Hetzner, DigitalOcean, or Vultr also work perfectly with this guide.
Phase 1: VM Hardening (Do This FIRST)
Before we install anything fun, we need to secure our server. Think of this as locking the doors and windows before you move your valuables inside.
Step 1: Create a New User
First, SSH into your server as the default ubuntu user:
ssh -i "moltbot.pem" ubuntu@<YOUR-EC2-PUBLIC-IP>
Once connected, let's update the system and create a dedicated user for OpenClaw:
# Update system
sudo apt update && sudo apt upgrade -y
# Create a new user (replace 'openclaw' if you want a different name)
sudo adduser openclaw
# (Enter a strong password when prompted)
# Grant sudo rights
sudo usermod -aG sudo openclaw
Why a new user? Running applications as a dedicated user follows the principle of least privilege. If something goes wrong, the blast radius is contained.
Step 2: Set Up SSH Keys for the New User
Here's where many tutorials fail you. The AWS key (.pem file) only works for the ubuntu user by default. We need to copy the authorized keys to our new user, or we'll be locked out.
Run these commands while still logged in as ubuntu:
# 1. Create the SSH directory for the new user
sudo mkdir -p /home/openclaw/.ssh
# 2. Copy the authorized keys from 'ubuntu' to 'openclaw'
sudo cp /home/ubuntu/.ssh/authorized_keys /home/openclaw/.ssh/
# 3. Fix permissions (CRITICAL: If this is wrong, login will fail)
sudo chown -R openclaw:openclaw /home/openclaw/.ssh
sudo chmod 700 /home/openclaw/.ssh
sudo chmod 600 /home/openclaw/.ssh/authorized_keys
The Permission Trinity: Directory at
700, keys file at600, owned by the user. Get any of these wrong, and SSH will silently reject your login.
Step 3: Configure AWS Security Group (External Firewall)
Time to switch to your web browser. We need to tell AWS to allow traffic on our new SSH port.
- Go to EC2 Dashboard → Security Groups
- Select your instance's security group → Edit inbound rules
-
Add Rule:
- Type:
Custom TCP - Port:
2222 - Source:
0.0.0.0/0(or "My IP" for extra security)
- Type:
- DO NOT delete the rule for Port 22 yet - this is your safety net
- Save rules
Step 4: Configure UFW (Internal Firewall)
Back in your terminal, let's set up the host-level firewall:
# Set default policies
sudo ufw default deny incoming
sudo ufw default allow outgoing
# Allow the CURRENT port (Safety Net)
sudo ufw allow 22/tcp
# Allow the FUTURE port
sudo ufw allow 2222/tcp
# Enable the firewall
sudo ufw enable
When prompted, type y to confirm. You now have two layers of firewall protection.
Step 5: The Golden Test
This is the moment of truth. Before we disable password authentication or change ports, we need to prove that our new user can log in with the SSH key.
Keep your current terminal window open (this is your lifeline).
Open a NEW terminal window on your local computer and run:
ssh -i "moltbot.pem" openclaw@<YOUR-IP-ADDRESS>
| Result | Action |
|---|---|
| Success: You log in without being prompted for a password | Proceed to Step 6 |
| Failure: "Permission denied" | Go back and re-check Step 2. Do not proceed. |
Step 6: Lock Down SSH Configuration
Now that we've verified key-based login works, it's time to harden SSH. This is where Ubuntu 24.04 throws a curveball that catches many admins off guard.
Edit the SSH config file:
sudo vi /etc/ssh/sshd_config
Make the following changes:
Port 2222
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
Save and close the file (:wq in vi).
Disable Systemd Socket Activation (CRITICAL)
Here's the gotcha: Ubuntu 24.04 uses "socket activation" which holds Port 22 open regardless of what you put in sshd_config. You must disable this:
# Stop the socket listener
sudo systemctl stop ssh.socket
sudo systemctl disable ssh.socket
# Restart the SSH service to apply your new config
sudo systemctl restart ssh
Verify the Port Change:
sudo ss -tulpn | grep ssh
| Output | Status |
|---|---|
0.0.0.0:2222 |
Success! |
0.0.0.0:22 |
Something went wrong. Do NOT disconnect. |
Step 7: Final Verification & Cleanup
Open a NEW terminal window and test the new port:
ssh -p 2222 -i "moltbot.pem" openclaw@<YOUR-IP-ADDRESS>
Only if that works, go back to your server terminal and lock down Port 22:
sudo ufw delete allow 22/tcp
Then go to AWS Security Groups and delete the inbound rule for Port 22.
Important: From this point forward, you can no longer use "EC2 Instance Connect" (the browser console). You must always use the SSH command above.
Phase 2: Environment Setup
With our server hardened, it's time to install the software stack. We'll set up Docker to run OpenClaw in isolation and Tailscale to create our private access tunnel.
1. Install Docker & Docker Compose
Docker ensures OpenClaw's dependencies don't interfere with your host OS. Here's the official installation method:
# Install Docker dependencies
sudo apt install apt-transport-https ca-certificates curl software-properties-common -y
# Add Docker GPG key & Repository
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# Install Docker
sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io docker-compose-plugin -y
# Allow 'openclaw' user to run Docker without sudo
sudo usermod -aG docker ${USER}
Now log out and log back in for the group change to take effect:
exit
Then reconnect via SSH:
ssh -p 2222 -i "moltbot.pem" openclaw@<YOUR-IP-ADDRESS>
Verify Docker works without sudo:
docker run hello-world
2. Install Tailscale (The Secure Access Layer)
Here's where the magic happens. Instead of exposing OpenClaw's web port (18789) to the public internet, we'll use Tailscale to create a private mesh network. Only devices on your Tailnet can access the bot.
On your EC2 server:
curl -fsSL https://tailscale.com/install.sh | sh
After installation, authenticate with your Tailscale account:
sudo tailscale up
Follow the link provided to authorize your server.
On your local machine:
Install Tailscale from tailscale.com/download and sign in with the same account.
Once both devices are on your Tailnet, they can communicate securely without any public ports.
Phase 3: OpenClaw Installation
The infrastructure is ready. Let's deploy the bot.
1. Clone the Repository
git clone https://github.com/openclaw/openclaw.git
cd openclaw
2. Clean Up Old Configurations
If you've experimented with OpenClaw before, nuke any old config folders to prevent conflicts:
sudo rm -rf ~/.openclaw
3. Pre-Create the Configuration Folder
This step prevents the dreaded "Permission Denied" errors. We create the folder manually and set permissions so both you AND Docker can write to it:
# Create the folder structure
mkdir -p /home/openclaw/.openclaw/workspace
# Give full read/write access (fixes the "Permission Denied" error)
sudo chmod -R 777 /home/openclaw/.openclaw
sudo chown -R openclaw:openclaw ~/openclaw
sudo chmod -R 775 ~/openclaw
4. Run the Setup Script
Now we're ready for the main event:
cd ~/openclaw
./docker-setup.sh
A series of prompts will appear. Select EXACTLY these options to avoid crashes:
| Prompt | Selection |
|---|---|
| Onboarding mode | Manual |
| Setup | Local gateway (this machine) |
| Workspace directory | (Press Enter to accept default) |
| Model/auth Provider | Anthropic |
| Anthropic API Key | (Enter your key) |
| Gateway port | 18789 |
| Gateway bind | Tailnet |
| Gateway auth | Token |
| Tailscale exposure | Off |
| Gateway Token | (Create a secure token) |
| Configure chat channel | (Whatsapp/Telegram - your choice) |
| Configure Skills | No |
| Hooks | Skip for Now |
Critical Warning: Do NOT select "Serve" for Tailscale exposure. This bypasses complex proxy logic that causes crashes. Select "Off" - Tailscale already handles secure access.
Wait for completion. The container will start, but DO NOT LOGIN YET.
5. The "Insecure Auth" Injection
Here's a quirk with OpenClaw: At this stage, the bot is running but will block your browser because you're connecting over HTTP (not HTTPS). Since Tailscale already encrypts our traffic end-to-end, we can safely enable HTTP authentication.
First, install jq inside the container:
docker compose exec -u root openclaw-gateway bash -c "apt update && apt install -y jq"
Then inject the setting:
docker compose exec -T openclaw-gateway bash -c '
jq ".gateway.controlUi.allowInsecureAuth = true" \
/home/node/.openclaw/openclaw.json > /home/node/.openclaw/tmp.json && \
mv /home/node/.openclaw/tmp.json /home/node/.openclaw/openclaw.json'
Restart the bot to apply changes:
docker compose restart
Why is this safe? We're not exposing any ports to the public internet. Traffic flows exclusively through your encrypted Tailscale tunnel. The "insecure" part only refers to HTTP vs HTTPS - and Tailscale already provides encryption.
Phase 4: Login & Verify
The moment of truth. Your bot is running, security is configured, and Tailscale is connecting your devices. Let's access the interface.
1. Check Container Status
Make sure the containers are healthy and staying up:
docker compose ps
Watch it for a few seconds. If the status stays "Up" for more than 10 seconds, you're good.
2. Get Your Tailscale IP
tailscale ip -4
This returns something like 100.x.x.x - your private Tailscale IP address.
3. Access the Web Interface
On your local machine (which must also be connected to Tailscale), open your browser and navigate to:
http://<YOUR_TAILSCALE_IP>:18789
For example: http://100.64.0.1:18789
Enter the Gateway Token you created during setup and click Connect.
Congratulations! You now have a private AI assistant running on your own infrastructure, accessible only through your secure Tailscale network.
Phase 5: Best Practices & Maintenance
Your bot is running, but a few housekeeping practices will keep it healthy and your wallet safe.
Set API Spend Limits
Agentic AI can sometimes get stuck in loops and burn through API credits rapidly. Protect yourself:
- Go to your Anthropic Console
- Navigate to Settings → Limits
- Set a hard monthly budget (e.g., $20)
Do the same for OpenAI if you configured it as a backup.
Enable Sandbox Mode
In the OpenClaw configuration, ensure Sandbox Mode is enabled if available. This restricts the bot's ability to execute unrestricted shell commands on the host system.
Back Up Your Bot's Memory
OpenClaw stores its "long-term memory" in Markdown files. If you lose this directory, the bot forgets everything it knows about you.
Create regular backups:
# Simple backup command
tar -czvf memory_backup_$(date +%F).tar.gz ./openclaw/memory
Consider automating this with a cron job for daily backups.
Monitor Logs
When things go sideways (and they sometimes do), logs are your best friend:
docker compose logs -f
The -f flag follows the log output in real-time. Press Ctrl+C to exit.
Conclusion
You've successfully deployed OpenClaw on a hardened EC2 instance with:
- Non-standard SSH port (2222) with key-only authentication
- Dual-layer firewall protection (AWS Security Groups + UFW)
- Docker containerization for clean isolation
- Tailscale private networking for secure, zero-trust access
- No public ports exposed for the application itself
Your AI assistant is now running on infrastructure you control, accessible only to devices on your private Tailnet. No VPN configurations, no exposed ports, no attack surface for the public internet to probe.
Happy building!
Top comments (0)