<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Caelum</title>
    <description>The latest articles on DEV Community by Caelum (@caelum7).</description>
    <link>https://dev.to/caelum7</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4202528%2F038911aa-dca2-4976-970e-c1c589ae67f4.png</url>
      <title>DEV Community: Caelum</title>
      <link>https://dev.to/caelum7</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/caelum7"/>
    <language>en</language>
    <item>
      <title>Deploy OpenClaw on a VPS with Telegram: A Step-by-Step Guide</title>
      <dc:creator>Caelum</dc:creator>
      <pubDate>Fri, 23 Oct 2026 11:57:59 +0000</pubDate>
      <link>https://dev.to/caelum7/deploy-openclaw-on-a-vps-with-telegram-a-step-by-step-guide-ibf</link>
      <guid>https://dev.to/caelum7/deploy-openclaw-on-a-vps-with-telegram-a-step-by-step-guide-ibf</guid>
      <description>&lt;p&gt;Cloud AI assistants are convenient, but they come with trade-offs: your conversations live on someone else's servers, the assistant forgets you between sessions, and it stops existing the moment you close the tab. &lt;strong&gt;OpenClaw&lt;/strong&gt; takes the opposite approach. It's an open-source AI assistant that runs on your own hardware, keeps its state and memory locally, and talks to you through chat apps you already use — including Telegram.&lt;/p&gt;

&lt;p&gt;Running it on your laptop works, but laptops sleep. A $5–10/month VPS keeps your assistant online around the clock. By the end of this guide you'll have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;OpenClaw installed on a fresh Ubuntu VPS, running as a background service&lt;/li&gt;
&lt;li&gt;A private Telegram bot connected to it&lt;/li&gt;
&lt;li&gt;Pairing-based access control, so only you can talk to it&lt;/li&gt;
&lt;li&gt;A Control UI you can reach securely — without exposing it to the internet&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's build it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A VPS running Ubuntu 22.04 or 24.04 (1–2 GB RAM is enough to start; the heavy lifting happens at the model provider, not on your server). Hetzner, DigitalOcean, Vultr, Linode — any of them works.&lt;/li&gt;
&lt;li&gt;Root SSH access to the server.&lt;/li&gt;
&lt;li&gt;A Telegram account.&lt;/li&gt;
&lt;li&gt;An API key from a model provider (Anthropic, OpenAI, etc.). OpenClaw is bring-your-own-key: you pay the provider directly for usage.&lt;/li&gt;
&lt;li&gt;About 30 minutes.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 1: Prepare the server
&lt;/h2&gt;

&lt;p&gt;SSH in as root, apply updates, and create a dedicated user. OpenClaw can execute commands and work with files, so it should not run as root — give it its own account:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh root@your-server-ip

apt update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt upgrade &lt;span class="nt"&gt;-y&lt;/span&gt;
adduser openclaw
usermod &lt;span class="nt"&gt;-aG&lt;/span&gt; &lt;span class="nb"&gt;sudo &lt;/span&gt;openclaw
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then enable the firewall, allowing only SSH. This matters later: OpenClaw's gateway port (18789) should &lt;strong&gt;never&lt;/strong&gt; be open to the public internet — we simply won't add a rule for it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ufw allow OpenSSH
ufw &lt;span class="nb"&gt;enable&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Log out and back in as the new user:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh openclaw@your-server-ip
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 2: Install OpenClaw
&lt;/h2&gt;

&lt;p&gt;The official installer detects your OS, provisions a supported Node.js runtime if needed, and installs the CLI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://openclaw.ai/install.sh | bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(If you'd rather read the script before piping it to bash — a reasonable instinct on a server — download it from &lt;code&gt;https://openclaw.ai/install.sh&lt;/code&gt;, inspect it, then run it with &lt;code&gt;bash install.sh&lt;/code&gt;.)&lt;/p&gt;

&lt;p&gt;Already managing Node.js yourself? Install the published package instead. Note the version requirement: the npm route needs Node 24.16+ or 26.1+, with Node 26 recommended:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; openclaw@latest &lt;span class="nt"&gt;--allow-scripts&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;openclaw
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;--allow-scripts=openclaw&lt;/code&gt; flag applies to npm 12 (or npm 11.16+). On npm 11.15 and earlier, omit it.&lt;/p&gt;

&lt;p&gt;Verify the install:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;openclaw doctor
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;openclaw doctor&lt;/code&gt; checks your environment and flags missing pieces before they turn into confusing errors later.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Run onboarding and install the daemon
&lt;/h2&gt;

&lt;p&gt;The onboarding wizard walks you through choosing a model provider and entering your API key, then sets up the local state directory (&lt;code&gt;~/.openclaw&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;openclaw onboard &lt;span class="nt"&gt;--install-daemon&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;--install-daemon&lt;/code&gt; flag registers OpenClaw as a background service (systemd on Linux), so the gateway starts on boot and restarts if it crashes. Follow the wizard prompts; when it asks about chat channels, you can skip for now — we'll add Telegram explicitly in Step 5 so you see exactly what gets configured.&lt;/p&gt;

&lt;p&gt;Confirm the gateway is healthy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;openclaw status
openclaw health
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 4: Create your Telegram bot
&lt;/h2&gt;

&lt;p&gt;OpenClaw doesn't use a shared public bot — you create your own, which means your bot's username and token are yours alone.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In Telegram, open a chat with &lt;strong&gt;&lt;a class="mentioned-user" href="https://dev.to/botfather"&gt;@botfather&lt;/a&gt;&lt;/strong&gt; (the official bot-management account — double-check the handle).&lt;/li&gt;
&lt;li&gt;Send &lt;code&gt;/newbot&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Pick a display name, then a username ending in &lt;code&gt;bot&lt;/code&gt; (e.g. &lt;code&gt;my_openclaw_assistant_bot&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;BotFather replies with a token that looks like &lt;code&gt;123456789:ABCdef...&lt;/code&gt;. Treat it like a password: anyone holding it controls your bot.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Step 5: Connect Telegram to OpenClaw
&lt;/h2&gt;

&lt;p&gt;The quickest path is the CLI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;openclaw channels add &lt;span class="nt"&gt;--channel&lt;/span&gt; telegram &lt;span class="nt"&gt;--token&lt;/span&gt; &amp;lt;bot-token&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This writes the Telegram channel into your config at &lt;code&gt;~/.openclaw/openclaw.json&lt;/code&gt;. The equivalent config block — useful if you prefer editing files — looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"channels"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"telegram"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"enabled"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"botToken"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;bot-token&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"dmPolicy"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"pairing"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"groups"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"*"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"requireMention"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two settings deserve attention:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;dmPolicy: "pairing"&lt;/code&gt;&lt;/strong&gt; is the default, and you should keep it. It means the bot ignores strangers: a new sender gets a pairing code, and nothing they send is processed until you approve it from the server.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;requireMention: true&lt;/code&gt;&lt;/strong&gt; for groups means that if you later add the bot to a group chat, it only responds when mentioned, instead of reacting to every message.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Prefer keeping the token out of the config file? Set it as an environment variable instead — &lt;code&gt;TELEGRAM_BOT_TOKEN&lt;/code&gt; — and omit &lt;code&gt;botToken&lt;/code&gt; from the config. (If both exist, the config value wins.)&lt;/p&gt;

&lt;p&gt;Restart the gateway to pick up the channel, then check that Telegram connected:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;openclaw gateway restart
openclaw channels status &lt;span class="nt"&gt;--probe&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see Telegram listed as connected, with your bot's username.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 6: Pair your account and say hello
&lt;/h2&gt;

&lt;p&gt;Now open Telegram, find your bot, and send it any message — "hi" is fine. Because of the pairing policy, it won't answer yet. Back on the server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;openclaw pairing list telegram
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You'll see your pending request with a code. Approve it (codes expire after one hour; if yours lapses, just message the bot again to generate a fresh one):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;openclaw pairing approve telegram &amp;lt;PAIRING-CODE&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Send the bot another message. This time it answers — and from now on, that answer comes from &lt;em&gt;your&lt;/em&gt; server, running &lt;em&gt;your&lt;/em&gt; assistant, reachable from any device where you're logged into Telegram.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 7: Reach the Control UI safely
&lt;/h2&gt;

&lt;p&gt;OpenClaw ships with a web Control UI served by the gateway on port 18789 — bound to localhost. Don't change that binding and don't open the port in your firewall. Instead, tunnel it through SSH from your own machine:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh &lt;span class="nt"&gt;-L&lt;/span&gt; 18789:127.0.0.1:18789 openclaw@your-server-ip
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then open &lt;code&gt;http://127.0.0.1:18789&lt;/code&gt; in your local browser. The UI is reachable only while the tunnel is up, and only by you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common errors
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The bot never replies.&lt;/strong&gt; Almost always pairing: you messaged it but never approved the request. Run &lt;code&gt;openclaw pairing list telegram&lt;/code&gt; and approve your code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;"Invalid token" on startup.&lt;/strong&gt; The BotFather token was copied incompletely or with stray whitespace. Re-copy the full token, or have BotFather revoke and reissue it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;"Telegram channel disabled."&lt;/strong&gt; The config is missing &lt;code&gt;"enabled": true&lt;/code&gt;, or the gateway wasn't restarted after your edit. Config changes only take effect after &lt;code&gt;openclaw gateway restart&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;npm install fails on &lt;code&gt;sharp&lt;/code&gt; / &lt;code&gt;libvips&lt;/code&gt;.&lt;/strong&gt; A global libvips is conflicting. Retry with &lt;code&gt;SHARP_IGNORE_GLOBAL_LIBVIPS=1 npm install -g openclaw@latest&lt;/code&gt;, or just use the installer script, which handles the runtime for you.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Node version errors on the npm route.&lt;/strong&gt; The package requires Node 24.16+ or 26.1+. Check with &lt;code&gt;node --version&lt;/code&gt;; again, the installer script sidesteps this by provisioning a supported runtime.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Install runs out of memory on a tiny VPS.&lt;/strong&gt; On 1 GB instances, add swap before installing: &lt;code&gt;sudo fallocate -l 2G /swapfile &amp;amp;&amp;amp; sudo chmod 600 /swapfile &amp;amp;&amp;amp; sudo mkswap /swapfile &amp;amp;&amp;amp; sudo swapon /swapfile&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pairing code expired.&lt;/strong&gt; Codes live for one hour. Message the bot again and approve the new code promptly.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What it costs
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;VPS:&lt;/strong&gt; roughly $5–10/month for a small instance at most providers. OpenClaw itself is free and open source (MIT).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Model usage:&lt;/strong&gt; pay-as-you-go to your API provider. Light personal use typically lands in the $2–10/month range, but it depends entirely on which model you pick and how chatty you are. Set a spending limit in your provider's console if you want a hard ceiling.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Security notes
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Keep secrets secret.&lt;/strong&gt; Bot tokens and API keys belong in environment variables or the protected config under &lt;code&gt;~/.openclaw&lt;/code&gt; — never in git repos, screenshots, or shared shell histories. If a token leaks, revoke it (BotFather can reissue bot tokens; your model provider can rotate API keys).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Run as a dedicated non-root user&lt;/strong&gt;, as in Step 1, and keep the OS patched.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Port 18789 stays closed.&lt;/strong&gt; Reach the Control UI through an SSH tunnel or a trusted private network, never the public internet.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keep &lt;code&gt;dmPolicy&lt;/code&gt; on &lt;code&gt;pairing&lt;/code&gt; or &lt;code&gt;allowlist&lt;/code&gt;.&lt;/strong&gt; Setting it to &lt;code&gt;open&lt;/code&gt; lets anyone who finds your bot's username send it commands — a bad idea for an assistant that can run tools.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Change defaults.&lt;/strong&gt; If your VPS provider gave you a default root password, replace it, use SSH keys, and disable password authentication once your key works.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  You're done
&lt;/h2&gt;

&lt;p&gt;You now have a personal AI assistant that lives on your server, remembers context between conversations, and answers you in Telegram from anywhere — no subscription, no third-party platform holding your data. From here, the natural next steps are adding skills, connecting a second channel (WhatsApp, Discord, and Slack are all supported), and tuning the assistant's workspace files to your projects.&lt;/p&gt;

&lt;p&gt;If you'd rather skip the setup, I offer this as a done-for-you service on Fiverr: &lt;a href="http://www.fiverr.com/s/NeeqRgp" rel="noopener noreferrer"&gt;http://www.fiverr.com/s/NeeqRgp&lt;/a&gt;&lt;/p&gt;

</description>
      <category>openclaw</category>
      <category>ai</category>
      <category>telegram</category>
      <category>selfhosted</category>
    </item>
  </channel>
</rss>
