Deploy an AI Agent to a VPS
Run a self-hosted AI assistant on a cloud VPS, accessible 24/7 via Telegram.
Introduction
30 Second Summary
AI assistants are incredibly useful, but only when they're actually available. Running one on your laptop means it goes offline whenever you close the lid, lose Wi-Fi, or simply walk away.
In this project, you will deploy OpenClaw (an AI assistant framework) to a cloud server so it stays online 24/7, accessible from Telegram on your phone at any time of day.
What You'll Build
A personal AI assistant powered by OpenClaw running on a Hetzner VPS that responds to your Telegram messages using Claude as its brain.
By the end of this project, you'll have:
- A provisioned and secured Hetzner CX22 VPS running Ubuntu 24.04 with firewall rules and SSH key-only access.
- OpenClaw installed as a persistent systemd service that auto-restarts on failure and survives reboots.
- A Telegram bot connected so you can message your AI assistant from your phone at any time.
- Secret Mission: Add a proactive daily briefing skill that sends you a morning summary via Telegram.
Are there any prerequisites?
You'll need a credit or debit card for Hetzner signup, an Anthropic API key (pay-as-you-go), and a Telegram account. The project uses a Mac terminal for local commands, but the server itself runs Linux.
Generate an SSH Key and Sign Up for Hetzner
Your AI assistant needs a home that never sleeps. A VPS (Virtual Private Server) gives you a dedicated machine in the cloud with its own IP address and 24/7 uptime.
To access that machine securely, you need an SSH key. Think of it as a digital lock-and-key pair that proves your identity without a password. In this step, you will generate that key, create a Hetzner Cloud account, and spin up the server your assistant will live on.
In this step, get ready to:
- Generate an SSH key pair for secure server access.
- Create a Hetzner Cloud account and project.
- Provision a CX22 server running Ubuntu 24.04.
Generate an SSH key pair on your Mac
An SSH key pair consists of a private key (stays on your Mac) and a public key (uploaded to your server). When you connect, the server checks that your private key matches the public key it has on file.
- Press Cmd+Space to open Spotlight Search.
- Type Terminal and press Enter to open it.
- Generate your SSH key by running this command:
ssh-keygen -t ed25519
What will this command ask you?
The ssh-keygen command will prompt you twice:
- "Enter a file in which to save the key" - press Enter to accept the default location (~/.ssh/id_ed25519).
- "Enter passphrase" - press Enter twice to skip setting a passphrase. For a personal VPS this keeps things simple.
- Press Enter for the file location prompt.
- Press Enter twice for the passphrase prompts (leaving it empty).
You should see output mentioning your key fingerprint and a randomart image. This confirms the key was created.
- Verify your new key exists by running:
ls ~/.ssh/id_ed25519.pub
You should see the file path printed back with no error.
Seeing "No such file or directory"?
- Make sure you ran ssh-keygen -t ed25519 exactly as shown above and pressed Enter at each prompt.
- If you accidentally chose a different filename, check what files exist with ls ~/.ssh/ and look for the .pub file.
Help me troubleshoot my SSH key generation.
- Copy your public key to the clipboard by running:
cat ~/.ssh/id_ed25519.pub | pbcopy
What does this command do?
The cat command prints the public key contents, and pbcopy copies that output directly to your clipboard. You will paste this key into Hetzner in the next substep.
Create a Hetzner Cloud account
Hetzner Cloud is a European hosting provider known for affordable, high-performance VPS plans. The CX22 plan gives you 2 vCPUs and 4GB RAM for about $4 per month.
- Open your browser and go to https://accounts.hetzner.com/login.
- Click Register now.
- Enter your email address, personal details, and billing address.
- Check your inbox for a verification email and click the link to verify your account.
- Log in to your new Hetzner account.
- Add a payment method (credit or debit card) when prompted.
Why Hetzner over other cloud providers?
Hetzner's CX22 plan offers 2 vCPU, 4GB RAM, and 40GB NVMe SSD for roughly $4/month. A comparable plan on other providers costs $6 or more for less hardware. Since OpenClaw needs 2 CPU cores and 4GB RAM as a production baseline, Hetzner gives you the exact specs at the lowest price.
Now upload the SSH key you copied earlier so Hetzner can attach it to your new server.
- In the Hetzner Cloud Console, click your profile icon in the top-right corner.
- Select Security from the dropdown menu.
- Click Add SSH Key.
- Paste your public key (it should still be on your clipboard from the pbcopy command).
- Give it a name like my-macbook so you can identify it later.
- Click Add SSH Key to save it.
You should see your key listed under the SSH Keys section.
Account verification taking a long time?
Hetzner occasionally requires identity verification for new accounts, which can take up to 24 hours. This is uncommon but can happen. If you are blocked, wait for the verification email or contact Hetzner support.
Help me figure out why my Hetzner account is stuck in verification.
Create a CX22 server
With your account ready and SSH key uploaded, you can now provision the actual server that will run your AI assistant around the clock.
- In the Hetzner Cloud Console, click + New Project.
- Name it openclaw and click Add Project.
- Click into your new project.
- Click Add Server.
You will see a server creation form with several options to configure. Set each one:
- Under Location, pick the datacenter closest to your physical location (this reduces latency when you SSH in).
- Under Image, select Ubuntu 24.04.
- Under Type, select Shared vCPU and choose the CX22 plan (2 vCPU, 4 GB RAM, 40 GB NVMe).
- Under Networking, keep the default public IPv4 and IPv6 options enabled.
- Under SSH Keys, check the box next to the key you uploaded (my-macbook).
- Leave all other settings at their defaults.
- Click Create & Buy now at the bottom.
Hetzner will provision your server in about 30 seconds. Once it is ready, you will see it listed in your project with a public IP address next to its name.
- Copy the public IP address shown next to your new server. You will use this to connect via SSH in the next step.
What is Ubuntu 24.04?
Ubuntu 24.04 is a Long Term Support (LTS) release of the Linux operating system. LTS means it receives security updates for 5 years, making it ideal for servers you want to set-and-forget.
Server creation failed?
- Make sure your payment method was accepted. Check for a billing notification in your Hetzner dashboard.
- If you hit a resource limit, new Hetzner accounts are limited to 5 servers by default. One server should be well within the limit.
Help me troubleshoot my Hetzner server creation.
Your VPS is live and waiting. Next up, you will SSH into it for the first time and install Node.js to prepare for OpenClaw.
Connect to Your VPS and Install Node.js
Your VPS is running, but right now it's just an empty Ubuntu machine sitting in a data center. To turn it into a home for your AI assistant, you need to get inside it, set it up securely, and install the runtime that OpenClaw needs.
In this step, you'll connect to your server over SSH, create a dedicated non-root user (a security best practice), and install Node.js 24 so OpenClaw has the runtime it requires.
In this step, get ready to:
- SSH into your VPS and update system packages.
- Create a non-root user with sudo privileges and SSH key access.
- Install Node.js 24 via the NodeSource repository.
SSH into your new server
SSH is how you remotely control a Linux server from your own terminal. Your VPS is waiting for a connection on port 22, and because you uploaded your public key to Hetzner in the previous step, you can log in without a password.
- Open Terminal on your Mac by pressing Cmd+Space and typing Terminal, then pressing Enter.
- Connect to your VPS as root by running this command:
ssh root@[[VPS_IP="your server's public IP address"]]
What does this command do?
The ssh command opens a secure, encrypted connection to your VPS.
- root is the default admin user on a fresh Ubuntu server.
- The IP address tells SSH which server to connect to. You can find this in your Hetzner Cloud Console under your server's details.
- If this is your first time connecting, you'll see a fingerprint confirmation prompt. Type yes and press Enter to continue.
You should see a welcome message and a root@your-server-name:~# prompt. You're now inside your VPS.
- Update all system packages by running these commands:
apt update && apt upgrade -y
What does this command do?
The apt update command refreshes the list of available packages from Ubuntu's repositories. The apt upgrade -y command installs the latest versions of all installed packages. The -y flag auto-confirms the upgrade so you don't have to type yes manually.
You'll see a stream of output as packages download and install. This may take a minute or two.
Connection refused or timed out?
- Double-check the IP address in your Hetzner Cloud Console matches what you typed.
- Make sure your VPS shows a green "Running" status in Hetzner.
- If you see "Permission denied (publickey)", your SSH key may not have been attached during server creation. Delete the server in Hetzner, re-create it, and ensure you select your uploaded SSH key.
Why can't I connect to my VPS via SSH?
Create a non-root user
Running services as the root user is a security risk. If an attacker compromises your service, they get full control of the entire server. You'll create a dedicated user that has sudo access for admin tasks but runs day-to-day services with limited privileges.
- Create a new user called openclaw by running this command:
adduser --disabled-password --gecos "" openclaw
What does this command do?
The adduser command creates a new Linux user account.
- --disabled-password means this user can't log in with a password. Only SSH key authentication works.
- --gecos "" skips the interactive prompts for full name, phone number, etc.
- Add the user to the sudo group by running:
usermod -aG sudo openclaw
- Copy your SSH key to the new user's home directory by running these commands:
mkdir -p /home/openclaw/.ssh
cp /root/.ssh/authorized_keys /home/openclaw/.ssh/authorized_keys
chown -R openclaw:openclaw /home/openclaw/.ssh
chmod 700 /home/openclaw/.ssh
chmod 600 /home/openclaw/.ssh/authorized_keys
What does this code do?
These commands copy the same SSH key that lets you log in as root over to the new user's account.
- mkdir -p creates the .ssh directory if it doesn't already exist.
- chown changes ownership so the openclaw user owns their own files.
- chmod sets strict permissions. SSH refuses to use keys if the permissions are too open.
- Test the new user by switching to it:
su - openclaw
- Verify sudo access by running:
sudo whoami
You'll be prompted to enter a password. Since this user has no password set, press Ctrl+D to exit back to root. You'll verify the full SSH login from your Mac in a moment.
Actually, sudo requires a password by default. Let's allow passwordless sudo for the openclaw user so it can run admin commands without getting blocked.
- Press Ctrl+D to exit back to the root shell if you haven't already.
- Grant passwordless sudo to the openclaw user by running:
echo "openclaw ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/openclaw
- Now test the full SSH login. Open a new Terminal tab on your Mac (Cmd+T) and run:
ssh openclaw@[[VPS_IP="your server's public IP address"]]
You should see a prompt like openclaw@your-server-name:~$. You're now logged in as the non-root user.
- Confirm sudo works by running:
sudo whoami
You should see root printed. This means your openclaw user can perform admin tasks when needed.
Permission denied when SSHing as openclaw?
- Check that /home/openclaw/.ssh/authorized_keys exists and contains your public key. Run cat /home/openclaw/.ssh/authorized_keys from the root session.
- Make sure permissions are correct: the .ssh folder should be 700 and authorized_keys should be 600.
- Make sure the file is owned by openclaw. Run ls -la /home/openclaw/.ssh/ from the root session to check.
Why can't I SSH in as my new user?
Install Node.js 24
OpenClaw requires Node.js 24 as its runtime. Ubuntu 24.04 ships with an older version of Node.js in its default repositories, so you'll install it from the NodeSource repository to get the correct version.
- Switch to your root session (the original Terminal tab where you're logged in as root).
- Download the NodeSource setup script for Node.js 24 by running:
curl -fsSL https://deb.nodesource.com/setup_24.x -o nodesource_setup.sh
- Run the setup script to configure the repository:
bash nodesource_setup.sh
- Install Node.js by running:
apt install -y nodejs
What did these commands do?
The NodeSource setup script adds a new package repository to your system that contains up-to-date Node.js builds. Without it, apt install nodejs would grab whatever outdated version Ubuntu bundles by default.
After the repository is configured, apt install -y nodejs pulls Node.js 24 from NodeSource's servers and installs it system-wide.
- Verify the installation by running:
node --version
You should see a version number starting with v24 (for example, v24.11.0 or similar). This confirms Node.js 24 is installed and ready.
Seeing an older version or command not found?
- If node --version shows something lower than v24, the NodeSource repository may not have configured properly. Re-run bash nodesource_setup.sh and check for errors in the output.
- If you see "command not found", try running apt install -y nodejs again. The install may have been interrupted.
- Make sure you ran the commands as root (not as the openclaw user without sudo).
Help me fix my Node.js installation on my VPS.
- Clean up the setup script since you no longer need it:
rm nodesource_setup.sh
Your server is updated, secured with a non-root user, and has Node.js 24 ready to go. Next up, you'll install OpenClaw itself and run the onboarding wizard to get your AI assistant's gateway running as a persistent service.
Install OpenClaw and Run Onboarding
Your VPS is connected, updated, and running Node.js 24 under a dedicated non-root user.
Now it is time to install OpenClaw itself and run its onboarding wizard. The wizard configures the gateway, connects your LLM provider, and installs a systemd service so the gateway survives reboots and SSH disconnections.
In this step, get ready to:
- Install OpenClaw globally via npm.
- Run the onboarding wizard to configure the gateway and install the daemon.
- Verify the gateway is running as a systemd user service.
Install OpenClaw globally
OpenClaw is distributed as an npm package. Since Node.js 24 is already installed, you can install it globally with a single command.
- Install OpenClaw by running this command:
npm install -g openclaw@latest
The installation takes a minute or two depending on your server's connection speed.
- Confirm the installation succeeded by running:
openclaw --version
You should see a version number printed in the output.
Why install globally?
The -g flag installs OpenClaw system-wide so the openclaw command is available from any directory. This is important because the systemd service needs to find the binary on startup without relying on a project-local node_modules folder.
Command not found after install?
If openclaw --version returns an error, the npm global bin directory may not be in your PATH. Try logging out and back in (exit then SSH again), or run export PATH=$PATH:$(npm config get prefix)/bin to add it temporarily.
help me fix the openclaw command not found error after npm install -g
Run the onboarding wizard with daemon installation
The onboarding wizard handles three things at once: it configures the gateway, connects your LLM model, and installs a systemd service that keeps the gateway running permanently.
Without the --install-daemon flag, the gateway would stop the moment you close your SSH session. The flag tells OpenClaw to create a systemd user service that auto-starts on boot.
- Start the onboarding wizard by running this command:
openclaw onboard --install-daemon
The wizard asks you several configuration questions interactively.
- When asked for the gateway port, press Enter to accept the default (18789).
- When asked for the bind address, keep the default 127.0.0.1 (localhost only).
- When asked for your LLM provider, select Anthropic.
- Paste your Anthropic API key when prompted.
- When asked about daemon installation, confirm yes.
Why bind to 127.0.0.1?
Binding to 127.0.0.1 means the gateway only accepts connections from the server itself. No one on the internet can reach it directly.
You will access the Control UI securely through an SSH tunnel in a later step. Messaging channels like Telegram connect outbound from the gateway, so they work fine on localhost.
The wizard finishes by starting the gateway and printing a success message. You should see confirmation that the systemd service was installed and started.
Wizard fails with a permission error?
If the daemon installation step fails, your user session may not have lingering enabled. Run loginctl enable-linger openclaw (you may need to prefix with sudo) and then re-run the onboarding command.
help me fix a permission error when running openclaw onboard --install-daemon
Verify the gateway is running
The onboarding wizard should have started the gateway automatically. Let's confirm it is active and listening on the correct port.
- Check the systemd service status by running:
systemctl --user status openclaw-gateway.service
You should see the service listed as active and running, with a green dot indicator. The output also shows the process ID and recent log lines from the gateway.
- Confirm the gateway is listening on port 18789 by running:
ss -tlnp | grep 18789
You should see a line showing the gateway listening on 127.0.0.1:18789.
What is systemctl --user?
The --user flag tells systemctl to manage services in your user session rather than system-wide services. OpenClaw installs itself as a user service so it runs with your user's permissions instead of root.
The Restart=always policy in the service file means systemd will automatically restart the gateway if it ever crashes.
Service not active?
If the status shows inactive or failed, try starting it manually with systemctl --user start openclaw-gateway.service. Check the logs with journalctl --user -u openclaw-gateway.service for error details.
help me troubleshoot why my openclaw-gateway systemd user service is not running
Your OpenClaw gateway is installed, configured, and running as a persistent service. Next up, you will connect Telegram so you can message your AI assistant from your phone.
Connect Telegram as a Messaging Channel
Your gateway is running and listening on localhost, but right now you have no way to talk to it outside of SSH. Telegram solves this by giving your assistant a phone-friendly chat interface you can message from anywhere.
In this step, you'll create a Telegram bot, connect it to OpenClaw, and send your first message. Once it replies, your always-on assistant is officially live.
In this step, get ready to:
- Create a Telegram bot via @BotFather and save the bot token.
- Add the Telegram channel to OpenClaw using the CLI.
- Send a test message from your phone and get a Claude-powered response.
Create a Telegram bot
Telegram bots are special accounts that act as an interface for external services. You create one by chatting with @BotFather, Telegram's official bot-management tool.
- Open Telegram on your phone or desktop app.
- In the search bar, type @BotFather and open the chat with the verified BotFather account (look for the blue checkmark).
- Send the /newbot command.
- BotFather will ask for a display name for your bot. Type whatever you like (e.g. My OpenClaw Assistant).
- Next it will ask for a username. This must end in bot (e.g. my_openclaw_bot). Usernames are unique across all of Telegram, so you may need to try a few variations.
- BotFather replies with your bot token. It looks like 110201543:AAHdqTcvCH1vGWJxfSeofSAs0K5PALDsaw. Copy this token and save it somewhere safe.
What is a bot token?
The token is a unique string that authenticates your bot on the Telegram Bot API. Anyone with this token has full control over the bot, so treat it like a password.
Keep the token handy
You'll paste this token into OpenClaw in the next substep. If you lose it, you can always generate a new one by sending /token to @BotFather and selecting your bot.
Add Telegram to OpenClaw
OpenClaw's CLI has a dedicated command for connecting channels. It writes the bot token into your gateway configuration and hot-reloads the gateway automatically.
- Switch back to your SSH session on the VPS.
- Add the Telegram channel by running this command (replace the placeholder with your actual bot token):
openclaw channels add --channel telegram --token your-bot-token-here
What does this command do?
This writes channels.telegram.enabled: true and channels.telegram.botToken into your ~/.openclaw/openclaw.json config file. The gateway watches this file and picks up the change without a restart.
The default DM policy is pairing. This means the first time you message the bot, it generates a pairing code you must approve before the conversation can begin.
- Verify the channel is connected by running:
openclaw channels status --probe
You should see Telegram listed as enabled with a status indicating it is polling for messages.
Telegram showing as not configured?
Make sure you pasted the full token (including the colon and everything after it). An incomplete token will cause the gateway to reject the channel.
Check that no empty TELEGRAM_BOT_TOKEN environment variable is set, as it can override your config value. Run echo $TELEGRAM_BOT_TOKEN to confirm it's empty.
help me troubleshoot why my Telegram channel is showing as not configured in OpenClaw
Test the connection
Your gateway is now polling the Telegram Bot API for incoming messages. Time to prove it works end-to-end.
- Open Telegram on your phone.
- Search for your bot's username (the one you chose in BotFather) and open the chat.
- Tap Start (or send any message like Hello).
What happens with the pairing code?
Because the default DM policy is pairing, your first message triggers a pairing request. You need to approve it from the VPS before the bot will respond.
The bot may reply with a pairing code in Telegram. You then approve it on the server side so the gateway knows to accept future messages from your Telegram account.
- Back in your SSH session, list pending pairing requests by running:
openclaw pairing list telegram
- Approve your pairing request by running (replace the placeholder with the code shown):
openclaw pairing approve telegram your-pairing-code-here
- Go back to Telegram and send another message (e.g. What is the capital of France?).
You should receive a response powered by Claude within a few seconds. Your always-on AI assistant is live.
Not getting a response?
Check the gateway logs to see if messages are arriving. Run journalctl --user -u openclaw-gateway.service -f to watch live output.
Make sure you approved the pairing code. Pairing codes expire after 1 hour, so if you waited too long, send another message to trigger a new code.
help me debug why my OpenClaw Telegram bot is not responding to messages
Your assistant now lives on the VPS and responds to you from anywhere via Telegram. Next up, you'll lock down the server so nobody else can reach the gateway.
Harden Security and Set Up Remote Access
Your AI assistant is live on Telegram. Anyone with internet access can reach it through Telegram's bot API. But the VPS itself is also on the internet, and right now it has no firewall and still accepts password logins.
In this step, you'll lock down the server so only SSH key holders can connect, block all unnecessary ports with a firewall, and set up a secure tunnel to access the OpenClaw Control UI from your browser.
In this step, get ready to:
- Configure UFW to allow only SSH traffic and block everything else.
- Disable password authentication so only SSH keys work.
- Access the OpenClaw Control UI securely through an SSH tunnel.
Configure the firewall
Your VPS currently accepts connections on every port. A firewall lets you explicitly whitelist only the traffic you want. Port 22 (SSH) is the only port that needs to be reachable from the public internet.
- Allow SSH traffic through the firewall by running this command:
sudo ufw allow OpenSSH
- Enable the firewall by running:
sudo ufw enable
What does this prompt mean?
UFW will ask: "Command may disrupt existing ssh connections. Proceed with operation (y|n)?" Type y and press Enter. Since you already allowed OpenSSH in the previous command, your current connection is safe.
- Verify the firewall is active by running:
sudo ufw status
You should see output showing that the firewall is active, with port 22 listed as allowed from anywhere.
Why not open port 18789?
The OpenClaw gateway is bound to 127.0.0.1 (localhost only). This means no outside traffic can reach it directly. Opening port 18789 in the firewall would serve no purpose and would weaken your security posture if you ever rebind to 0.0.0.0 by accident.
You'll access the Control UI through a secure SSH tunnel instead.
Lost your SSH connection?
If you ran sudo ufw enable before allowing SSH, your connection may drop. Use the Hetzner Cloud Console's browser-based terminal to reconnect and run sudo ufw allow OpenSSH.
Help me fix my UFW firewall so I can SSH back into my Hetzner VPS.
Secure SSH by disabling password authentication
You're already connecting with an SSH key. Disabling password authentication closes the door on brute-force password attacks entirely.
Do not proceed if your SSH key is not working
If you logged in using a password at any point (instead of your SSH key), disabling password authentication will lock you out permanently. Confirm you can connect with your key before continuing.
- Disable password authentication in the SSH config by running:
sudo sed -i 's/^#PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config
What does this command do?
The sed -i command edits the file in place. It finds the line #PasswordAuthentication yes (commented out by default on Ubuntu) and replaces it with PasswordAuthentication no (uncommented and set to no).
- On Ubuntu 24.04, a cloud-init config file can override your change. Check if it exists and remove it by running:
sudo rm -f /etc/ssh/sshd_config.d/50-cloud-init.conf
Why delete this file?
Hetzner's Ubuntu images include /etc/ssh/sshd_config.d/50-cloud-init.conf which sets PasswordAuthentication yes. Config files in the .d/ directory are loaded after the main config and can override your settings. Removing it ensures your PasswordAuthentication no sticks.
- Verify the setting took effect by running:
grep "^PasswordAuthentication" /etc/ssh/sshd_config
You should see PasswordAuthentication no in the output.
- Restart the SSH service to apply your changes by running:
sudo systemctl restart ssh
Your existing SSH session stays connected. The new rules apply to future login attempts only.
Still seeing PasswordAuthentication yes?
Check for other override files in /etc/ssh/sshd_config.d/ by running ls /etc/ssh/sshd_config.d/. Any file there with PasswordAuthentication yes will override your main config.
Help me disable password authentication on Ubuntu 24.04 SSH.
Access the Control UI via SSH tunnel
The OpenClaw Control UI is a web dashboard running on port 18789. Since the gateway is bound to localhost, it's only reachable from the VPS itself. An SSH tunnel forwards that remote port to your Mac so you can open it in your local browser.
- Open a new Terminal window on your Mac (keep your existing SSH session open).
- Create the SSH tunnel by running this command:
ssh -N -L 18789:127.0.0.1:18789 [[VPS_IP="openclaw@your-server-ip"]]
What does this command do?
The -N flag tells SSH not to run a remote command (tunnel only). The -L 18789:127.0.0.1:18789 flag forwards your Mac's port 18789 to the VPS's localhost port 18789. The terminal will appear to hang with no output. That's normal.
- Open your browser on your Mac and go to http://localhost:18789.
You should see the OpenClaw Control UI dashboard. This is where you can manage your gateway, view connected channels, and monitor activity.
Close the tunnel when you're done
Press Ctrl+C in the tunnel terminal window to close the connection. You can re-open it any time you need the Control UI.
Can't load localhost:18789?
Make sure the tunnel terminal is still running (it should show no output and appear frozen). If you see "Connection refused," verify the OpenClaw gateway is still active on the VPS by running systemctl --user status openclaw-gateway.service in your other SSH session.
Help me troubleshoot my SSH tunnel to the OpenClaw Control UI.
Your VPS is now hardened. The firewall blocks everything except SSH, passwords are disabled, and the Control UI is only reachable through your encrypted tunnel. Next up, you'll verify that your setup survives reboots and create a backup of your OpenClaw state.
Verify Always-On Behavior and Create a Backup
Your VPS is secured, your firewall is locked down, and your Telegram bot is chatting away. But what happens when the server reboots after a kernel update or a hardware migration?
In this step, you'll prove that your systemd service survives a full reboot and set up a backup script to protect your OpenClaw configuration data.
In this step, get ready to:
- Test that the OpenClaw gateway auto-restarts after a reboot.
- Review systemd logs for clean startup behavior.
- Create a backup script for your OpenClaw data.
Test auto-restart after a reboot
The whole point of a VPS is that your assistant stays online even when you're not watching. A reboot is the ultimate test of your systemd configuration.
- Reboot your VPS by running this command:
sudo reboot
Your SSH connection will immediately drop. This is expected.
- Wait about 30 seconds for the server to come back online.
- SSH back into your VPS by running this command:
ssh [[VPS_USER="openclaw"]]@[[VPS_IP="your-server-ip"]]
- Check that the OpenClaw gateway restarted automatically by running:
systemctl --user status openclaw-gateway.service
What should I see?
You should see Active: active (running) in the output. This confirms the systemd service started itself after the reboot without any manual intervention.
- Open Telegram on your phone and send your bot a message.
You should receive a response powered by Claude. This proves end-to-end functionality survived the reboot.
Bot not responding after reboot?
If systemctl --user status openclaw-gateway.service shows inactive or failed, check that lingering is enabled for your user. Without lingering, user services only run while the user has an active session.
Run sudo loginctl enable-linger openclaw and then start the service manually with systemctl --user start openclaw-gateway.service.
Why isn't my service auto-starting after reboot?
Check systemd service health
Knowing the service is running is good. Knowing it started cleanly is better. The journal logs tell you whether the gateway had any issues during startup.
- Review the gateway logs by running:
journalctl --user -u openclaw-gateway.service
What does this command do?
This filters the systemd journal to show only entries from your openclaw-gateway.service user unit. You're looking for clean startup messages with no error lines.
The --user flag tells journalctl to look at your user-level journal (since OpenClaw runs as a user service, not a system service). The -u flag filters to a specific unit name.
- Look for a line indicating the gateway started and connected to Telegram successfully.
- Verify the Restart=always policy is active by running:
systemctl --user show openclaw-gateway.service | grep Restart=
You should see Restart=always in the output. This confirms your service will automatically restart if it ever crashes.
Seeing 'No journal files were found'?
If journalctl returns no entries, persistent logging may not be enabled. Run sudo nano /etc/systemd/journald.conf and set Storage=persistent under the [Journal] section. Then reboot to apply the change.
Help me troubleshoot journal access on my VPS
Create a backup script
Your OpenClaw configuration, Telegram channel settings, and conversation history all live in ~/.openclaw/. If this directory gets corrupted or accidentally deleted, you'd need to redo the entire onboarding process. A backup script protects you.
- Create the backup script file by running:
nano ~/backup-openclaw.sh
- Define the backup logic by pasting this into the file:
#!/bin/bash
# Backup script for OpenClaw configuration and data
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
BACKUP_DIR=~/openclaw-backups
# Create backup directory if it doesn't exist
mkdir -p "$BACKUP_DIR"
# Archive the entire OpenClaw data directory
tar -czf "$BACKUP_DIR/openclaw-backup-$TIMESTAMP.tar.gz" -C ~ .openclaw/
echo "Backup created: $BACKUP_DIR/openclaw-backup-$TIMESTAMP.tar.gz"
What does this script do?
- TIMESTAMP generates a unique date-time string so each backup has a distinct filename.
- mkdir -p creates the backup directory if it doesn't already exist.
- tar -czf compresses your entire ~/.openclaw/ directory into a single .tar.gz archive.
- Save the file by pressing Ctrl+O, then Enter, then Ctrl+X to exit nano.
- Make the script executable by running:
chmod +x ~/backup-openclaw.sh
- Test the backup script by running:
~/backup-openclaw.sh
- Verify the backup was created by running:
ls ~/openclaw-backups/
You should see a file named something like openclaw-backup-20260520_143022.tar.gz in the output.
Schedule daily backups with cron
To run this script automatically every day at 3 AM, add it to your crontab. Run crontab -e and add this line at the bottom:
0 3 * * * /home/openclaw/backup-openclaw.sh
This is optional but recommended for long-term use. Your backups will accumulate over time, so you may want to add a cleanup step later that removes backups older than 7 days.
Backup file is empty or missing?
Make sure ~/.openclaw/ exists and contains files. Run ls -la ~/.openclaw/ to check. If the directory is empty, your OpenClaw gateway may not have written its state yet. Send a Telegram message first to generate some data, then re-run the backup script.
Help me debug my backup script
Secret mission
Add a Daily Briefing Cron Skill
Your assistant is running 24/7, but right now it only responds when you message it. What if it could reach out to you first? In this secret mission, you'll make your assistant proactive by creating a scheduled skill that sends you a personalized daily briefing every morning via Telegram.
Clean Up Your Resources
Clean Up Your Resources
This project provisions a Hetzner VPS that incurs ongoing charges of approximately $4/month while running, plus Anthropic API costs based on usage.
Decide whether to keep your resources running, pause them to come back later, or delete them entirely.
Cost warning
Your Hetzner CX22 VPS is billed hourly while running (approximately $4/month total). Anthropic API charges accumulate with every message your assistant processes. If you leave everything running and actively use the assistant, expect $4/month for hosting plus $10-30/month in API tokens depending on usage.
If you are not actively using your assistant, choose Pause or Delete below to stop charges.
Resources you used:
- Hetzner CX22 VPS running Ubuntu 24.04 (~$4/month while active).
- Anthropic API key (pay-per-token charges with each assistant interaction).
- Telegram bot (free, created via @BotFather).
- SSH key pair stored in ~/.ssh/ on your Mac.
Keep everything running
No action needed. Choose this if your always-on assistant is working well and you want to keep messaging it from Telegram at any time.
- Your VPS continues running 24/7 at approximately $4/month.
- Anthropic API charges continue with each message your assistant processes.
- Your daily briefing skill continues firing at your scheduled time each morning.
- Run your backup script (~/backup-openclaw.sh) periodically to protect your OpenClaw state.
Pause - I'll come back to this later
Shut down your VPS to stop compute charges. Your server and data remain intact, but the assistant will stop responding until you power it back on.
- Log in to the Hetzner Cloud Console at console.hetzner.cloud.
- Select your project, then click on your server name.
- Click the Power toggle or select Power Off to shut down the server.
- Compute charges stop while the server is off. Storage charges may still apply at a reduced rate.
- Your Telegram bot will stop responding to messages until you power the server back on.
- To resume, power the server back on from the same page. The openclaw-gateway.service will start automatically thanks to systemd.
Delete - I don't want to use this again
Remove all project resources to stop all charges immediately. Your OpenClaw state will be permanently lost unless you backed it up first.
- Run your backup script before deleting anything, if you want to preserve your OpenClaw configuration:
ssh openclaw@your-server-ip 'bash ~/backup-openclaw.sh'
Delete the Hetzner VPS:
- Log in to the Hetzner Cloud Console at console.hetzner.cloud.
- Select your project, then click on your server name.
- Click the ... menu or scroll to the bottom of the server details page.
- Click Delete and confirm the deletion. All compute and storage charges stop immediately.
Delete your Telegram bot:
- Open Telegram and message @BotFather.
- Send /deletebot and select your bot from the list.
- Confirm the deletion when prompted.
Revoke your Anthropic API key:
- Go to the Anthropic Console at console.anthropic.com.
- Navigate to API Keys in the settings.
- Find the key you created for this project and click Revoke. This ensures no further charges can accumulate on your account.
Remove the SSH key from your Mac:
- Remove the key pair you generated for this project by running:
rm ~/.ssh/id_ed25519 ~/.ssh/id_ed25519.pub
- If you used a custom key name during ssh-keygen, replace the filenames above with the ones you chose.
- Also remove the entry for your server from ~/.ssh/known_hosts if you want a fully clean state.
What about the Hetzner account itself?
Your Hetzner Cloud account is free to keep open with no servers running. You only pay for active resources. If you want to delete your account entirely, look for the account settings page in the Hetzner Cloud Console.
That's a Wrap!
That's a Wrap!
Your personal AI assistant is now truly always-on. You've deployed OpenClaw to a cloud VPS that stays online 24/7, accessible from your phone via Telegram whenever you need it.
You've learned how to:
- Provisioned and secured a Hetzner CX22 VPS running Ubuntu 24.04, installed Node.js 24, and deployed OpenClaw as a persistent systemd service that auto-restarts and survives reboots.
- Connected Telegram as a messaging channel so you can talk to your AI assistant from anywhere, at any time.
- Hardened your server with UFW firewall rules, SSH key-only authentication, a localhost-bound gateway, and secure SSH tunnel access to the Control UI.
- Added a proactive daily briefing skill with cron scheduling that sends you useful information every morning via Telegram.
Ready to quiz yourself?