#How do I set up tailscale?
1 messages ¡ Page 1 of 1 (latest)
For what you want, think of it as two separate things:
- âCommand line for my bot machineâ = SSH (Tailscale helps you reach it privately)
- âOpenClaw dashboardâ = the Gateway Control UI (Tailscale Serve can publish it over HTTPS to your tailnet)
1) Remote command line access to the bot machine (SSH over Tailscale)
Tailscale doesnât magically give you a shell by itself â you still use SSH, just targeting the botâs Tailscale name/IP.
Option A (easiest): Tailscale SSH
On the bot machine, enable SSH in Tailscale:
- Either in the Tailscale admin console (recommended), or via CLI with
tailscale up --ssh(depending on your setup)
Then from your laptop:
tailscale ssh <bot-machine-name>
Option B: normal SSH to the Tailscale IP / MagicDNS name
- Make sure OpenSSH is enabled/running on the bot machine.
- Find the botâs tailnet address/name:
tailscale status
# or
tailscale ip -4
- From laptop:
ssh <user>@<bot-machine-magicdns-or-tailscale-ip>
2) Reaching the OpenClaw dashboard from your other computer
OpenClawâs Tailscale integration is documented here (worth skimming):
https://docs.openclaw.ai/gateway/tailscale
If you used Tailscale = Serve
This typically means: Gateway stays local, and Tailscale Serve publishes it.
From your laptop, open:
https://<magicdns>/(as the docs say), which is often also reachable as:https://<machine>.<tailnet>.ts.net/
If you see a âconnect/authâ prompt in the UI, youâll need to authenticate:
- either paste your Gateway Token (common), or
- configure the âTailscale identity headersâ flow (
gateway.auth.allowTailscale: true) if you want tokenless Control UI auth over Serve (docs explain the tradeoffs).
If you instead want direct Tailnet-IP access (no Serve)
Then the URL is:
http://<tailscale-ip>:18789/(Control UI)
(Thatâs gateway.bind: "tailnet" in the docs.)
Quick sanity checks (when it doesnât work)
On both machines:
tailscale status
tailscale ping <other-machine-name>
On the bot machine (for Serve mode):
tailscale serve status
If you tell me what URL youâre trying for the dashboard (MagicDNS vs ts.net vs IP:18789) and what error you see, I can point to the exact fix.
I don't see where to enable ssh in the Tailscale admin console. When I put "tailscale up --ssh" into the CLI I get a "bash:tailscale: command not found"
bash: tailscale: command not found means the Tailscale CLI isnât installed (or youâre in an environment that doesnât have it, like a container/WSL shell) on the machine where you ran the command.
A couple important clarifications + the fastest path:
1) You donât need âTailscale SSHâ to get a remote shell
You can just use normal SSH over the Tailscale network. Thatâs usually simpler.
But you do need Tailscale installed + logged in on the bot machine host OS (not inside a Docker container).
2) Install Tailscale CLI on the bot machine (host OS)
First: what OS is the bot machine (Ubuntu/Debian/macOS/Windows/WSL)?
In the meantime, the official install page is here:
- https://tailscale.com/download
Linux install guide: - https://tailscale.com/kb/1031/install-linux
After install, on the bot machine run:
tailscale status
(or tailscale up if itâs not connected yet)
3) Remote command line (recommended approach)
Once Tailscale is up, from your laptop just do:
ssh <user>@<bot-machine-tailscale-ip-or-magicdns>
To find the botâs Tailscale IP/name:
tailscale ip -4
tailscale status
4) OpenClaw dashboard from your other computer
Two cases:
-
Same LAN (works regardless of Tailscale):
http://<bot-lan-ip>:18789/ -
Via Tailscale Serve (what you selected): once Tailscale CLI is installed and Serve is set up, open:
https://<magicdns>/
(docs: https://docs.openclaw.ai/gateway/tailscale)
If you tell me the bot machine OS + whether youâre running OpenClaw in Docker, Iâll give you the exact install steps and the exact URL you should use.
tailscale status Same response
If tailscale status gives the same âcommand not foundâ, then the Tailscale CLI/daemon is not installed in that shell environment (or youâre not on the host OS).
Two quick questions so I donât send you down the wrong path:
- What OS is the bot machine? (paste output of
uname -aandcat /etc/os-releaseif itâs Linux) - Are you running OpenClaw inside Docker / a container? (If yes, youâre probably inside a container shell that wonât have
tailscale.)
If the bot machine is Ubuntu/Debian (most common)
On the bot machine host OS:
curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up
tailscale status
(Official guide: https://tailscale.com/kb/1031/install-linux)
If itâs macOS
Install the Tailscale app (or Brew), then in Terminal:
tailscale status
If that still isnât found, tell me whether you installed from the App Store or the direct download.
Once tailscale status works, we can do the next step:
- remote shell: normal
ssh user@<tailscale-ip> - dashboard via Serve:
https://<magicdns>/(https://docs.openclaw.ai/gateway/tailscale)
Reply with your OS info + whether Docker is involved and Iâll give the exact next commands.
Host machine is a MacOS
On macOS this is usually just a PATH/name thing: the Tailscale app bundles a CLI binary called Tailscale (capital T), but OpenClaw (and most docs) expect a lowercase tailscale command.
1) Confirm the bundled CLI works
On the bot Mac, run:
/Applications/Tailscale.app/Contents/MacOS/Tailscale status
If that prints something, youâre good.
2) Make tailscale available (so OpenClaw + your shell can find it)
For OpenClaw + launchd services, an alias wonât help â you want a real executable in PATH. The common fix is a symlink:
sudo ln -s /Applications/Tailscale.app/Contents/MacOS/Tailscale /usr/local/bin/tailscale
Then test:
tailscale status
tailscale ip -4
(If /usr/local/bin doesnât exist on your machine, tell me and Iâll give the right path for Apple Silicon setups.)
Remote command line access (from your laptop â bot Mac)
This is regular SSH (no âTailscale SSHâ feature needed):
- On the bot Mac: System Settings â General â Sharing â Remote Login â ON
- From your laptop:
ssh <mac_username>@<bot_tailscale_ip>
You can get <bot_tailscale_ip> from:
tailscale ip -4
OpenClaw dashboard from your laptop
Once Serve is set up and Tailscale is running, open:
https://<bot-magicdns-name>/
You can find the MagicDNS name in the Tailscale admin console under Machines (itâll look like your-mac.tailnet-xxxx.ts.net or similar).
If you paste the output of:
tailscale status
(after the symlink), I can tell you the exact hostname/IP to use.
I just got the SSH Cli installed on the host machine successfully
How do I connect to it with my remote machine now?
Nice â once the Tailscale CLI works on the bot Mac, the rest is straightforward.
A) Remote command line (SSH into the bot Mac)
-
On the bot Mac: enable SSH server
System Settings â General â Sharing â Remote Login â ON -
On the bot Mac, grab its Tailscale IP:
tailscale ip -4
- From your laptop:
ssh <mac_username>@<that_tailscale_ip>
(You can also use the MagicDNS name shown in tailscale status instead of the IP.)
B) OpenClaw dashboard from your laptop (via Tailscale Serve)
Now that tailscale exists, you typically need to restart the OpenClaw gateway so it can actually set up Serve:
openclaw gateway restart
Then on the bot Mac:
tailscale serve status
From your laptop, open the Serve URL (usually):
https://<bot-magicdns>/
Docs reference: https://docs.openclaw.ai/gateway/tailscale
If you paste the output of tailscale status (just the device names/lines; redact anything you want), I can tell you the exact hostname to use for ssh + the exact dashboard URL.
Tailscale is basically a private network: once both machines are logged into the same tailnet, you connect to the bot Mac exactly like you would on a LAN â just using its Tailscale IP / MagicDNS name.
1) On your remote machine (laptop)
Make sure Tailscale is:
- installed
- signed into the same Tailscale account
Then run:
tailscale status
You should see your bot Mac listed, along with a 100.x.y.z IP and a name.
(Optional sanity check)
tailscale ping <bot-name-or-100.x.ip>
2) SSH into the bot Mac
On the bot Mac, make sure you enabled:
System Settings â General â Sharing â Remote Login â ON
Then from the laptop:
ssh <mac_username>@<bot_tailscale_ip>
<mac_username>= the username on the bot Mac (you can check on the bot Mac withwhoami)<bot_tailscale_ip>= the 100.x IP you saw intailscale status
Example:
ssh wade@100.101.102.103
3) OpenClaw dashboard from the laptop
Open in a browser (Serve mode):
https://<bot-magicdns-name>/
If you paste the botâs line from tailscale status (device name + IP), Iâll tell you the exact ssh ... command + the exact dashboard URL to use.
When I tried to connect to the host using ssh it says "ssh: connect to host * port 22: Operation timed out"
A timeout usually means either (a) youâre not actually reaching the Mac over Tailscale, or (b) the Mac isnât listening/allowing SSH on port 22.
Do these checks in order:
1) Make sure youâre SSHâing to the Tailscale IP (100.x), not the LAN IP/hostname
On your laptop:
tailscale status
tailscale ping <bot-machine-name>
If tailscale ping canât reach it, SSH wonât work either (the Mac might be offline/asleep, or not logged into the same tailnet).
2) Confirm the bot Mac is awake + connected to Tailscale
On the bot Mac:
tailscale status
Make sure it shows your laptop as well (same tailnet).
3) Confirm SSH is actually enabled on the bot Mac
In macOS: System Settings â General â Sharing â Remote Login â ON
Or via terminal on the bot Mac:
sudo systemsetup -getremotelogin
(Should say Remote Login: On)
4) Check macOS Firewall isnât dropping SSH
If Remote Login is ON but you still get timeouts, check:
System Settings â Network â Firewall
Temporarily toggle it off to test, or ensure SSH/Remote Login is allowed.
If you paste one line from your laptopâs tailscale status for the bot Mac (the line showing its name + 100.x IP + âonline/offlineâ), I can tell you exactly what to try next.
Remote login is off
Yep â thatâll do it. If Remote Login is off, macOS isnât running an SSH server, so ssh ... will just hang/timeout.
Turn on SSH on the bot Mac
UI way (recommended)
System Settings â General â Sharing â Remote Login â ON
Then set âAllow access for:â to Only these users and add your Mac user (safer than âAll usersâ).
Terminal way (same effect)
On the bot Mac:
sudo systemsetup -setremotelogin on
sudo systemsetup -getremotelogin
Then connect from your laptop
Use the bot Macâs Tailscale IP (100.x):
ssh <mac_username>@<bot_tailscale_ip>
If it still times out after enabling Remote Login, the next thing to check is macOS Firewall allowing incoming SSH â but 90% of the time flipping Remote Login on fixes it.
If this gets you in, please mark the solution (rightâclick the solution message â Apps â â Mark Solution) so Answer Overflow indexes it.
I can now connect via SSH. It did give me this message:
The authenticity of host '... (...)' can't be established.
ED25519 key fingerprint is: *******
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '...' (*) to the list of known hosts.
That SSH prompt is totally normal the first time you connect to a machine (or the first time you connect to that IP/hostname).
Whatâs happening:
- SSH is telling you: âIâve never seen this host before â here is its host key fingerprint. Do you trust it?â
- When you typed
yes, it saved that host key into your~/.ssh/known_hosts. - Next time, SSH will silently verify the host key matches and wonât prompt.
When you should worry
If later you connect and SSH says the host key changed (a loud warning about possible MITM), that can mean:
- the machine was reinstalled / SSH host keys regenerated (common), or
- youâre being intercepted (rare, but possible), or
- you connected to a different machine that reused the same IP/name.
If you want to verify the fingerprint (optional)
On the bot Mac, you can print the SSH host key fingerprint and compare it to what your laptop showed:
ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub
If SSH is working now, youâre good.
If you still need help reaching the OpenClaw dashboard over Tailscale Serve, tell me whether youâre using the https://<magicdns>/ URL or the direct http://<tailscale-ip>:18789/ URL and what you see.
What is magicdns? The direct url didn't work
MagicDNS is Tailscaleâs built-in DNS that lets you reach machines by name instead of by the 100.x IP.
- Without MagicDNS: you generally connect via the 100.x IP.
- With MagicDNS enabled: your bot machine gets a stable name like
my-bot(and usually a full HTTPS name likemy-bot.<your-tailnet>.ts.net).
You enable it in the Tailscale admin console here:
- https://login.tailscale.com/admin/dns â toggle MagicDNS on
(Also make sure âHTTPSâ / certificates are enabled if you want the nicehttps://...ts.netURLs.)
Why the âdirect URLâ might not work
In OpenClaw Tailscale Serve mode, the Gateway often stays bound to 127.0.0.1, so this will not work:
http://<tailscale-ip>:18789/â âdirect URLâ (often fails in Serve mode)
Instead, you use the Serve HTTPS URL:
https://<magicdns>/(orhttps://<machine>.<tailnet>.ts.net/)
To see what (if anything) is currently being served, run on the bot machine:
tailscale serve status
If you tell me exactly which URL you tried (the form is enough: http://100.x:18789 vs https://name.ts.net) and what error you got (timeout vs refused vs 404), I can point you to the right fix/config.
no serve config
no serve config from tailscale serve status means Tailscale Serve isnât actually set up yet (so thereâs no https://... URL to hit).
Youâve got two good options:
Option 1 (works immediately): SSH tunnel the dashboard
On your laptop, run (leave it running):
ssh -N -L 18789:127.0.0.1:18789 <mac_username>@<bot_tailscale_ip>
Then open on your laptop:
http://127.0.0.1:18789/
This is the simplest âremote dashboardâ setup and doesnât require Serve at all. (Itâs also in the FAQ.)
Option 2 (what you originally picked): actually enable Tailscale Serve
Now that the tailscale CLI is installed, you usually just need the Gateway to configure it.
On the bot Mac:
openclaw gateway restart
tailscale serve status
If it still says âno serve configâ, check what OpenClaw thinks your settings are:
openclaw config get gateway.tailscale.mode
openclaw config get gateway.bind
For Serve to work as designed, it should be bind=loopback + tailscale.mode=serve (docs: https://docs.openclaw.ai/gateway/tailscale).
If you paste those two openclaw config get ... outputs here, Iâll tell you the exact next command(s) to flip it into a working Serve setup.
Connection refused is actually a good clue: it means your laptop can reach 100.84.127.107, but nothing is listening on port 22 on that machine/IP.
99% of the time on macOS that means Remote Login (sshd) is off or youâre SSHâing to the wrong device.
1) First: make sure 100.84.127.107 is really the bot Mac
On your laptop, run:
tailscale status
Find the bot Mac line and confirm the IP matches 100.84.127.107.
2) On the bot Mac: confirm SSH is enabled + listening
Run on the bot Mac:
sudo systemsetup -getremotelogin
sudo lsof -nP -iTCP:22 -sTCP:LISTEN
- If Remote Login is Off:
sudo systemsetup -setremotelogin on
- If Remote Login is On but nothing is listening on
:22, something is stopping sshd (less common) and weâll look at that next.
3) Then retry from laptop
ssh <mac_username>@100.84.127.107
Paste the outputs of those two bot-Mac commands (-getremotelogin + the lsof ...:22 line). Thatâll tell us immediately whatâs wrong.
When you say "your laptop" are you talking about the bot machine, or my other computer?
Good catch â I mean:
- Bot machine / host = the Mac thatâs running OpenClaw (the one you want to reach)
- Remote machine / client = your other computer (the one youâre sitting at when you try to SSH in)
So:
On your other computer (client)
Run this to confirm the bot Macâs Tailscale IP/name:
tailscale status
On the bot Mac (host)
Run these to confirm SSH is enabled + listening:
sudo systemsetup -getremotelogin
sudo lsof -nP -iTCP:22 -sTCP:LISTEN
Then from the other computer, you SSH into the bot Mac:
ssh <mac_username>@<bot_tailscale_ip>
If you tell me which machine youâre currently typing commands on (bot Mac vs other computer), I can keep the steps unambiguous.
Laptop says: -bash: tailscale: command not found
Bot machine says: Remote Login: On
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
launchd 1 root 34u IPv6 0xd02dda75fa2cbb32 0t0 TCP *:22 (LISTEN)
launchd 1 root 41u IPv4 0x1e72833e223ee61c 0t0 TCP *:22 (LISTEN)
launchd 1 root 42u IPv6 0xd02dda75fa2cbb32 0t0 TCP *:22 (LISTEN)
launchd 1 root 43u IPv4 0x1e72833e223ee61c 0t0 TCP *:22 (LISTEN)
That means the Tailscale CLI isnât available on your laptop in that Bash shell.
Two key points:
1) You donât actually need tailscale CLI on the laptop to connect
You only need the Tailscale app running + connected on the laptop.
You can get the bot Macâs Tailscale IP from the bot Mac itself:
tailscale ip -4
Then on the laptop you can just do:
ssh <mac_username>@<bot_tailscale_ip>
(no tailscale command needed on the laptop for that)
2) Why tailscale is missing on the laptop (most common causes)
Tell me what OS the laptop is:
- Laptop is macOS: same situation as the bot Mac earlier â the app bundles a
Tailscalebinary. You can run:
/Applications/Tailscale.app/Contents/MacOS/Tailscale status
and (optional) symlink it to tailscale like we did on the host.
- Laptop is Windows + youâre in WSL/Git Bash:
tailscalewonât exist inside WSL by default because Tailscale runs on Windows. Use PowerShell:
tailscale status
or just check the Tailscale GUI for âConnectedâ and the IP.
Reply with: what OS is the laptop? (macOS vs Windows/WSL vs Linux) and Iâll give the exact âtailscale statusâ equivalent for it.
Perfect â that output shows the bot Mac is definitely listening on SSH (*:22 (LISTEN)), so the problem is now 100% on the client side / which network/IP youâre using.
Next steps:
1) Confirm the bot Macâs actual Tailscale IP
On the bot Mac, run:
tailscale ip -4
Make sure it matches the IP youâre trying (you mentioned 100.84.127.107 earlier).
2) Your laptop saying tailscale: command not found is fine â but what OS is the laptop?
This matters because:
- If the laptop is Windows and youâre in WSL/Git Bash: you wonât have
tailscalein that shell. Do the test from PowerShell instead:
tailscale status
ssh <mac_username>@100.84.127.107
(You can have Tailscale connected on Windows while WSL doesnât have the CLI.)
- If the laptop is macOS: you likely need the same CLI path/symlink fix as on the bot Mac (or just donât use the CLI and connect via SSH directly).
3) Once SSH works, the dashboard is easiest via an SSH tunnel
From the laptop:
ssh -N -L 18789:127.0.0.1:18789 <mac_username>@<bot_tailscale_ip>
Then open:
Reply with: laptop OS (Windows/WSL vs macOS vs Linux) + the output of tailscale ip -4 from the bot Mac, and Iâll give you the exact ârun this here, not thereâ commands.
the laptop is a macos
Cool â since the laptop is macOS too, itâs the same situation as your bot Mac earlier: you probably have the Tailscale app, but the tailscale CLI isnât on your PATH.
1) Make sure Tailscale is actually connected on the laptop
Check the Tailscale menu bar icon on the laptop â it should say Connected (and logged into the same account/tailnet as the bot Mac).
2) Get the Tailscale CLI working on the laptop (optional but helpful)
On the laptop:
/Applications/Tailscale.app/Contents/MacOS/Tailscale status
If that works and you want the normal tailscale ... command:
sudo ln -s /Applications/Tailscale.app/Contents/MacOS/Tailscale /usr/local/bin/tailscale
Then:
tailscale status
3) Now SSH from laptop â bot Mac
First, on the bot Mac confirm its tailnet IP:
tailscale ip -4
Then from the laptop:
ssh <mac_username>@<bot_tailscale_ip>
If you still see âconnection refusedâ, it usually means youâre SSHâing to the wrong 100.x IP â so the âtailscale ip -4 on the bot Macâ step is the source of truth.
4) Dashboard (since Serve isnât configured yet)
Once SSH works, use the tunnel approach:
ssh -N -L 18789:127.0.0.1:18789 <mac_username>@<bot_tailscale_ip>
Open:
If you paste the output of tailscale ip -4 from the bot Mac, Iâll tell you the exact SSH command to run.
That worked. The dashboard is now asking me for the gateway token
Yep â thatâs expected. Your Gateway is in token auth mode, so the Control UI needs the token to connect.
On the bot machine (host), run:
openclaw config get gateway.auth.token
Then in the dashboard, paste it into the Gateway Token field and connect.
A couple notes:
- Donât paste the token into Discord (treat it like a password).
- If that command prints nothing /
null, generate one on the bot machine:
openclaw doctor --generate-gateway-token
then re-run openclaw config get gateway.auth.token.
If this got you fully in, please mark the solution (rightâclick the solution message â Apps â â Mark Solution) so it gets indexed.
That worked. I'm in the dashboard
Nice â then youâre fully set:
- Remote terminal: SSH to the bot Mac over Tailscale
- Remote dashboard: SSH tunnel â
http://127.0.0.1:18789/+ gateway token
If you want, the next upgrade is getting Tailscale Serve working so you donât need the SSH tunnel (docs: https://docs.openclaw.ai/gateway/tailscale).
If this solved it, please rightâclick the solution message â Apps â â Mark Solution so Answer Overflow indexes it.
If I were to reboot both machines. What steps would I need to do to reconnect now, and what steps can I take to streamline it?
After a reboot, nothing âspecialâ needs to be re-paired â you just need the same 3 things back up: Tailscale, the Gateway, and (if youâre using it) the SSH tunnel.
Reconnect checklist after reboot
On both machines
- Make sure Tailscale is running and Connected (menu bar icon).
If it isnât, open Tailscale and connect/login.
On the bot machine (host Mac)
- Make sure OpenClaw Gateway is running:
openclaw gateway status
If needed:
openclaw gateway start
- Make sure Remote Login stayed enabled (usually persists):
sudo systemsetup -getremotelogin
On your laptop (client Mac)
- Re-create the dashboard tunnel:
ssh -N -L 18789:127.0.0.1:18789 <mac_username>@<bot_tailscale_ip>
Then open:
http://127.0.0.1:18789/
The dashboard will usually remember the gateway token in the browser, so you shouldnât have to paste it again unless you switch browsers/profiles.
How to streamline it (recommended)
A) Put the tunnel in ~/.ssh/config (one-time setup)
On the laptop, add something like:
Host openclaw-bot
HostName 100.84.127.107
User <mac_username>
LocalForward 18789 127.0.0.1:18789
Then you can do:
ssh -N openclaw-bot
(And regular shell access is just ssh openclaw-bot.)
B) Make sure services auto-start
- Tailscale: set it to launch at login on both Macs.
- OpenClaw Gateway: if you installed it as a service, it should come up automatically; otherwise
openclaw gateway installis the âset and forgetâ route.
C) Optional: eliminate the tunnel entirely with Tailscale Serve
Once Serve is configured, you can open the dashboard via an HTTPS URL on your tailnet (docs: https://docs.openclaw.ai/gateway/tailscale). This is the cleanest long-term flow.
If you tell me whether you installed the gateway as a service (launchd) or you run it manually in a terminal, Iâll tailor the âauto-startâ steps exactly.
I'd love to get Talescale serve working. I don't completely understand how it works.
Tailscale Serve is basically a reverse proxy that runs inside Tailscale.
Mental model (why itâs nice)
- Your Gateway can stay bound to localhost (
127.0.0.1:18789) so itâs not exposed on your LAN or the internet. - Tailscale then gives you an HTTPS URL thatâs only reachable by devices in your tailnet, and it forwards traffic to that local port.
So instead of âopen port 18789 on the networkâ, you get:
https://<your-device>.<your-tailnet>.ts.net/â forwards to âhttp://127.0.0.1:18789/
OpenClaw can automate this: https://docs.openclaw.ai/gateway/tailscale
Getting Serve working (recommended steps)
1) Enable MagicDNS + HTTPS in Tailscale
In the Tailscale admin console:
- DNS page â turn on MagicDNS
- also enable HTTPS (Serve uses Tailscale certs)
2) Make sure the Gateway is loopback-bound
Serve works best when the Gateway is loopback-only.
On the bot Mac:
openclaw config get gateway.bind
openclaw config get gateway.tailscale.mode
You want:
gateway.bind = "loopback"gateway.tailscale.mode = "serve"
If not, set them:
openclaw config set gateway.bind loopback
openclaw config set gateway.tailscale.mode serve
openclaw gateway restart
3) Confirm Serve is configured
On the bot Mac:
tailscale serve status
You should see a URL + a mapping to 127.0.0.1:18789.
4) Open the dashboard from the laptop
Open:
https://<magicdns>/
Auth: will it still ask for a token?
By default, yes (token auth). You can paste the same gateway token once and the browser usually remembers it.
There is an optional tokenless flow for the Control UI via Tailscale identity headers (gateway.auth.allowTailscale: true), but it has tradeoffs and Iâd only enable it if you trust everything running on the gateway host. (Docs explain it.)
If you paste the outputs of:
openclaw config get gateway.bind
openclaw config get gateway.tailscale.mode
Iâll tell you exactly what to change (or confirm itâs already right).
Does enabling HTTPS and having my machine name in the public ledger pose any security risks?
For Tailscale Serve (tailnet-only): enabling HTTPS is mostly a privacy consideration, not âthis makes my dashboard publicâ.
What changes when you enable HTTPS
- Tailscale will serve your dashboard at an HTTPS name like:
https://<machine>.<tailnet>.ts.net/ - To do that, Tailscale issues a TLS certificate for that name.
The âpublic ledgerâ part (real but limited)
Those certificates are typically logged in Certificate Transparency (CT) logs (public, searchable). So your *.ts.net hostname can become publicly visible.
What that reveals:
- the hostname exists (machine + tailnet name)
What it does NOT do (for Serve):
- it does not make the service reachable from the public internet by default
- it does not bypass your Tailscale access controls or OpenClaw auth
Actual security risks to think about
- Name leakage: donât put sensitive info in the tailnet name / machine name (company, address, full name, etc.). Rename to something boring.
- Account/device compromise: if someone gets into your tailnet (stolen login, compromised device), they could reach Serve endpoints. Mitigation: enable 2FA, keep devices approved, remove old devices.
- Donât use Funnel unless you mean it: Funnel is the one that can expose publicly; OpenClaw forces password auth there for a reason.
If you tell me whether youâre using Serve or Funnel (sounds like Serve), I can give a âsafe defaultâ setup recommendation (names + auth mode) for OpenClaw.
Serve
Got it â for Serve the âsafe defaultâ setup I recommend is:
Safe default (Serve)
- Use Serve + keep the Gateway on loopback
gateway.bind: "loopback"gateway.tailscale.mode: "serve"
This keeps the Gateway off your LAN/public interfaces; Tailscale does the access.
- Keep token auth on
- leave
gateway.auth.modeastoken - use a strong token (and donât share it)
The dashboard will remember it in your browser once you paste it.
-
Enable MagicDNS + HTTPS, but use boring names
Because the*.ts.nethostname can show up in public CT logs, avoid personally identifying tailnet/device names. Renaming the device in the Tailscale admin console is enough. -
Donât use Funnel
Serve is tailnet-only. Funnel is public internet exposure (higher risk).
Convenience option (only if you trust the gateway host)
You can set gateway.auth.allowTailscale: true to allow tokenless Control UI auth via Tailscale identity headers â but Iâd only do that if you trust everything running on the gateway machine.
If you want, paste:
openclaw config get gateway.bind
openclaw config get gateway.tailscale.mode
openclaw config get gateway.auth.mode
openclaw config get gateway.auth.allowTailscale
and Iâll sanity-check your current settings against the âsafe defaultâ.
Got all that
Awesome â then youâre in the best place: Serve + loopback bind + token auth is the sweet spot for âremote but not publicly exposedâ.
If this thread is solved now, please rightâclick the solution message â Apps â â Mark Solution so Answer Overflow indexes it for the next person.
tailscale serve status results in "No serve config"
tailscale serve status â âNo serve configâ means: Tailscale itself is currently not serving anything. (Itâs state inside the Tailscale daemon, separate from âI selected Serve in the OpenClaw wizardâ.)
Most common cause in your case: when you first onboarded, the Gateway couldnât run tailscale serve (because the CLI wasnât installed yet), so it never got configured.
Fix (OpenClaw-driven, recommended)
On the bot machine, check what OpenClaw thinks the settings are:
openclaw config get gateway.bind
openclaw config get gateway.tailscale.mode
For Serve, you want:
gateway.bind=loopbackgateway.tailscale.mode=serve
Then restart the gateway so it can apply the Serve config:
openclaw gateway restart
tailscale serve status
If it still says âNo serve configâ
Run the explicit one-time setup command (from the docs/FAQ):
openclaw gateway --tailscale serve
Then in another terminal:
tailscale serve status
One more thing to sanity-check
If gateway.tailscale.resetOnExit is enabled, it can wipe Serve config when the gateway stops:
openclaw config get gateway.tailscale.resetOnExit
If you paste the two lines from openclaw config get gateway.bind and ...tailscale.mode, Iâll tell you exactly which knob is currently âwrongâ and what to set.
they are on loopback and serve
If OpenClaw is set to loopback + serve but tailscale serve status still says âNo serve configâ, it means one of these is true:
- the Gateway hasnât restarted since you changed the config, or
- the Gateway tried to run
tailscale serve âŚbut couldnât (most often because of PATH/permissions when running as a background service on macOS), or - HTTPS/MagicDNS isnât enabled yet so
tailscale serverefuses to configure.
Hereâs the quickest way to make it deterministic:
1) Ensure HTTPS + MagicDNS are enabled (admin console)
Tailscale Admin â DNS:
- MagicDNS: ON
- HTTPS: ON
2) Restart the Gateway (so it applies the Serve automation)
On the bot machine:
openclaw gateway restart
tailscale serve status
3) If it still says âNo serve configâ, run the Serve setup in a Terminal (not as a service)
On macOS, launchd services sometimes donât see /usr/local/bin PATH, so the Gateway canât find tailscale.
On the bot machine, in the same Terminal where tailscale status works:
openclaw gateway stop
openclaw gateway --tailscale serve
Leave that running for a moment, then in another Terminal:
22:51:17 Gateway failed to start: gateway already running (pid 18270); lock timeout after 5000ms
If the gateway is supervised, stop it with: openclaw gateway stop
22:51:18 Port 18789 is already in use.
22:51:18 - pid 18270 *: openclaw-gateway (127.0.0.1:18789)
22:51:18 - Gateway already running locally. Stop it (openclaw gateway stop) or use a different port.
22:51:18 Gateway service appears loaded. Stop it first.
22:51:18 Tip: openclaw gateway stop
22:51:18 Or: launchctl bootout gui/$UID/ai.openclaw.gateway
tailscale serve status
If you paste the output of:
tailscale status
tailscale serve status
openclaw gateway status
(from the bot machine), I can tell you which of the 3 cases youâre hitting and the cleanest âone-time fixâ so Serve stays configured.
Yep â that output is exactly what happens if you run openclaw gateway --tailscale serve while the Gateway service is already running. Itâs trying to start a second gateway on 127.0.0.1:18789 and canât.
Do this on the bot machine:
1) Stop the supervised/daemon gateway
openclaw gateway stop
2) Start it with Serve enabled (foreground)
openclaw gateway --tailscale serve
3) In another terminal, confirm Serve config exists now
tailscale serve status
Once tailscale serve status shows a URL/mapping, you have two choices:
- Keep the foreground gateway running (simplest for now), or
- Switch back to the service:
- stop the foreground gateway (Ctrl+C)
- start the service again:
openclaw gateway start
One important check: if gateway.tailscale.resetOnExit is true, stopping the gateway will wipe the Serve config. You can verify with:
openclaw config get gateway.tailscale.resetOnExit
Now I get "Gateway service not loaded.
Start with: openclaw gateway install
Start with: openclaw gateway
Start with: launchctl bootstrap gui/$UID ~/Library/LaunchAgents/ai.openclaw.gateway.plist"
tailscale serve status gave me the url/mapping. So I hit Ctrl+c. Then I typed in openclaw gateway start and it gave me that message
That message just means the launchd service isnât installed/loaded right now, so openclaw gateway start/stop/restart has nothing to control.
On the bot Mac, do:
openclaw gateway install
openclaw gateway start
openclaw gateway status
If youâve changed Node/OpenClaw installs recently (or the plist got out of sync), use the ârewrite everythingâ variant:
openclaw gateway install --force
openclaw gateway start
After itâs running again, re-check Serve:
tailscale serve status
If that still shows âNo serve configâ, weâll focus on why the running gateway isnât applying the Serve config (most commonly: the service environment canât find the tailscale CLI, even though it works in your interactive Terminal).
Makes sense â when you ran:
openclaw gateway --tailscale serve
âŚthe Gateway was running in the foreground in that terminal. Hitting Ctrl+C stopped the Gateway, so now thereâs nothing listening on 127.0.0.1:18789 anymore.
And the reason openclaw gateway start now complains is simply: the gateway service isnât installed/loaded, so thereâs nothing to âstartâ.
What to do next (pick one)
Option A: Keep running in a terminal (no service)
Just re-run and leave it running:
openclaw gateway --tailscale serve
Option B (recommended): Install the service so it survives reboots
On the bot Mac:
openclaw gateway install --force
openclaw gateway start
openclaw gateway status
Then confirm Serve + Gateway are both good:
tailscale serve status
If you want, paste the exact âGateway service not loaded âŚâ message again after running install --force and Iâll tell you what it means (usually it fixes it immediately).
That seems to have worked. Now i get the url/routing
Awesome â thatâs the finish line.
At this point:
- Keep the Gateway running via the service (
openclaw gateway statusshould show itâs up) - Use the Serve URL from
tailscale serve statuson your laptop (HTTPS) - If the dashboard asks for auth, paste the gateway token once (it usually remembers)
If this thread is fully solved now, please rightâclick the solution message â Apps â â Mark Solution so itâs indexed for others.
The dashboard login came back up. It has a different WebsocketURL autofilled, and the token is not working. It's giving me this message: origin not allowed (open the Control UI from the gateway host or allow it in gateway.controlUi.allowedOrigins)
That error is the Gateway doing an Origin allowlist check (itâs a safety feature so random web pages canât open a WebSocket to your gateway).
What changed: youâre now opening the Control UI from the Tailscale Serve HTTPS URL, so the browser âpage originâ is something like:
https://<machine>.<tailnet>.ts.net
âŚbut your gateway is still only allowing the old/local origin(s), so it rejects the WebSocket with:
origin not allowed ⌠allow it in
gateway.controlUi.allowedOrigins
Fix: allow the Serve URL origin
On the bot machine, set gateway.controlUi.allowedOrigins to include the exact origin youâre opening the UI from:
openclaw config set gateway.controlUi.allowedOrigins '["https://<your-serve-hostname>"]' --strict-json
openclaw gateway restart
Replace <your-serve-hostname> with the host from your tailscale serve status URL (no path, just the origin).
You can also include localhost if you still want local access too, e.g.
["http://127.0.0.1:18789", "https://<your-serve-hostname>"].
Docs: https://docs.openclaw.ai/gateway/tailscale (and Control UI notes mention allowedOrigins)
About the âdifferent WebsocketURL autofilledâ + token not working
Thatâs almost certainly old saved settings from when you used the SSH tunnel. Easiest fix:
- open the Serve dashboard URL in a Private/Incognito window (fresh localStorage), then paste the token again.
If you paste the Serve URL youâre using (just the hostname part is fine) I can tell you the exact allowedOrigins value to set.
now it says "pairing required" on the dashboard
Thatâs normal for the Control UI when you connect from a new remote browser/device (Serve counts as remote). The Gateway requires a one-time device pairing approval.
On the bot machine (gateway host), run:
openclaw devices list
You should see a pending pairing request. Approve it with:
openclaw devices approve <requestId>
Then reload the dashboard page.
Notes:
- Localhost (
http://127.0.0.1:18789) is auto-approved, but Tailnet/Serve access requires this one-time approval. - Each browser profile (and Incognito) looks like a different device, so it may ask again if you switch/clear browser data.
If devices list shows nothing pending, keep the dashboard tab open on the âpairing requiredâ screen and re-run openclaw devices list.
So in theory all I need to do now after rebooting each computer is connect tailscale on my laptop and I should be able to brose the dashboard?
Mostly yes â with two small âgotchasâ:
After reboot, you need:
- Tailscale connected on both machines (bot Mac + laptop)
- Gateway running on the bot Mac (service or manually)
- Then you can open the Serve URL in the laptop browser
If you installed the Gateway as a service (openclaw gateway install), it should come back automatically after reboot. You can sanity-check on the bot Mac with:
openclaw gateway status
And Serve should still be configured (unless you explicitly reset it or set resetOnExit):
tailscale serve status
What you shouldnât have to repeat
allowedOriginsconfig (persists)- the one-time device pairing (persists per browser profile)
- the gateway token (usually remembered by the dashboard in that browser profile)
So: connect Tailscale â open the Serve dashboard URL is the normal day-to-day flow, as long as the bot Mac is online and the gateway service is running.
I don't see anything in openclaw gateway status that says serve
Thatâs expected â openclaw gateway status is basically âis the gateway service running + can I probe it?â. It doesnât report Tailscale Serve state.
To confirm Serve, check it on the bot machine with:
tailscale serve status
And to confirm OpenClaw is configured to manage it:
openclaw config get gateway.tailscale.mode
openclaw config get gateway.bind
If tailscale serve status shows the URL/mapping, Serve is active regardless of what openclaw gateway status prints.
That all looks good
Perfect â then youâre set.
After any reboot, the âhappy pathâ is:
- Tailscale connected on both machines
- Gateway service running on the bot Mac (
openclaw gateway status) - Serve mapping present (
tailscale serve status) - Open the Serve URL â dashboard (token/pairing only if you changed browser/profile)
If this thread is solved, please rightâclick the solution message â Apps â â Mark Solution so it gets indexed for others.
Unrelated, I am also getting this message from the Doctor:
Doctor warnings âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââŽ
â â
â - channels.telegram.groupPolicy is "allowlist" but groupAllowFrom (and allowFrom) is â
â empty â all group messages will be silently dropped. Add sender IDs to â
â channels.telegram.groupAllowFrom or channels.telegram.allowFrom, or set groupPolicy to â
â "open".
That Doctor warning is saying:
You have Telegram group sender policy = allowlist, but you havenât actually allowed any senders (groupAllowFrom is empty, and it falls back to allowFrom which is also empty) â so all group messages will be dropped.
There are two separate controls for Telegram groups:
- Which groups are allowed â
channels.telegram.groups(these are negative chat IDs like-100âŚ) - Which people inside groups are allowed to trigger the bot â
channels.telegram.groupAllowFrom(these are numeric user IDs, not chat IDs)
Common fixes (pick one)
A) Allow only you in groups (safer)
{
channels: {
telegram: {
groupPolicy: "allowlist",
groupAllowFrom: ["<your_numeric_user_id>"],
},
},
}
B) Allow anyone in allowed groups (more open)
{
channels: {
telegram: {
groupPolicy: "allowlist",
groupAllowFrom: ["*"],
},
},
}
And donât forget you may also need to add the group itself under channels.telegram.groups if youâre running a group allowlist.
How to find your Telegram user ID
Safest method (no third-party bot):
- DM your bot
- run
openclaw logs --followon the gateway host - look for
from.id
If you paste your current channels.telegram block (redact tokens), I can tell you exactly what to add for your intended setup (DM-only vs one specific group vs any group).
I don't see anything that says From in the logs
Yeah â at the default log level you often wonât see the raw Telegram update payload, so thereâs nothing obvious like from.id in the output.
Youâve got 3 ways to get your Telegram user ID:
Option A (quick + safe): temporarily increase log level
On the gateway host (bot machine):
- Turn on more detailed file logs:
openclaw config set logging.level debug
openclaw gateway restart
- Then run:
openclaw logs --follow --json
- DM your bot in Telegram (âtestâ), and look for a log entry that includes something like
from/from.id(your numeric user id).
When youâve got it, turn logs back down:
openclaw config set logging.level info
openclaw gateway restart
Option B (official Telegram method): Bot API getUpdates
This works too, but donât paste your bot token here. Run it locally and look for from.id:
curl "https://api.telegram.org/bot<bot_token>/getUpdates"
Option C (easiest but less private): @userinfobot
It will tell you your numeric Telegram ID.
If you tell me which route you prefer (A/B/C), I can give you the exact âwhat to look forâ snippet so you donât have to eyeball the whole log stream.
For channels.telegram.groups, you enter the Telegram group chat ID (a negative number), not the group name.
It typically looks like:
-1001234567890(supergroups are usually-100âŚ)- older/basic groups can be a shorter negative number
How to get the group chat ID
Pick one:
- Easiest: forward any message from that group to
@getidsbot(or@userinfobot) and itâll tell you the groupâschat.id - Bot API:
getUpdateswill includechat: { id: ... }when the bot sees a group message - OpenClaw logs: look for
chat.id(same idea asfrom.id, but you may needlogging.level=debug)
Example
Allow one specific group:
channels: {
telegram: {
groups: {
"-1001234567890": { requireMention: true },
},
},
}
And separately (different setting) you control who inside groups can trigger it via groupAllowFrom (numeric user IDs).
If you tell me whether you want âanyone in the group can talk to the botâ vs âonly me canâ, Iâll give you the exact minimal config snippet.
The value under channels.telegram.groups is just a per-group settings object. It can be empty.
So the minimal âjust allow this group (defaults apply)â looks like:
channels: {
telegram: {
groups: {
"-1001234567890": {},
},
},
}
Common things you might put in the value:
- Allow messages without mentioning the bot:
"-1001234567890": { requireMention: false }
- Only allow specific users inside that group (user IDs, not chat IDs):
"-1001234567890": { allowFrom: ["8734062810"] }
- Override the group policy just for that one group:
"-1001234567890": { groupPolicy: "open" }
If you tell me âshould anyone in the group be able to talk to the bot, or only you?â, Iâll give you the exact smallest config block to paste.
@getisbot did not tell me the group id
Small thing first: itâs usually @getidsbot (with a d), not âgetisbotâ.
To get the group chat id, you have a couple reliable options:
Option A (fastest): forward a group message to an ID bot
- In your Telegram group, pick any message
- Forward it to
@getidsbot(or@userinfobot) in a DM - It should reply with the chat id (the group id), usually a negative
-100...number
If it replies with only your user id, try forwarding a message that was posted in the group (not a DM), or add the bot to the group first.
Option B (official, no third-party): use your botâs getUpdates
Make sure your bot is in the group, then send a test message in the group, then on your gateway host run (donât share the token here):
curl "https://api.telegram.org/bot<bot_token>/getUpdates"
Look for:
"chat": { "id": -1001234567890, ... }
That chat.id is what you put under channels.telegram.groups.
If you tell me which method you prefer (A or B), Iâll walk you through the exact clicks/what to look for.
bot_token is your Telegram bot token â the secret string you got from @BotFather when you created the bot (it looks like 123456789:AA...).
In OpenClaw itâs stored as:
channels.telegram.botTokenin~/.openclaw/openclaw.json, or- env var
TELEGRAM_BOT_TOKEN(default account)
So for the getUpdates call, you literally replace <bot_token> with that BotFather token on your own machine (donât paste it into Discord).
Example format:
curl "https://api.telegram.org/bot123456789:AA.../getUpdates"
If you canât find it, tell me whether you set Telegram up via the onboarding wizard or by editing openclaw.json, and Iâll point you to the exact place itâs saved.
Cool â Option B (Bot API getUpdates) will give you both the group chat id and your user id.
1) Make sure the bot actually receives a group message
In the Telegram group, send a message that Telegram will definitely deliver to the bot, e.g.:
/ping@YourBotUsername(any command works, it doesnât have to be real)
(If you just post normal text and the bot has BotFather privacy on, it might not receive it.)
2) On your gateway host, call getUpdates
Donât paste the token here â run locally:
TOKEN="123456789:AA..." # your BotFather token
curl -s "https://api.telegram.org/bot${TOKEN}/getUpdates" | python3 -m json.tool
3) What to look for in the output
Find the update that corresponds to your group message and look for:
- Group ID (this is what goes under
channels.telegram.groups):
"chat": { "id": -1001234567890, "title": "Your Group", ... }
- Your user ID (this is what goes under
groupAllowFromorallowFrom):
"from": { "id": 8734062810, ... }
If result is empty
Send another /ping@YourBotUsername in the group and run the curl again â getUpdates only shows messages the bot has actually received.
If you want, paste (redacting the token) just the small chat + from JSON block you see, and Iâll tell you exactly what to copy into openclaw.json.
zsh: command not found: #
{
"ok": false,
"error_code": 404,
"description": "Not Found"
}
Two separate things happened there:
-
zsh: command not found: #
You pasted the comment line (starting with#) as if it were a command. Just ignore that â donât paste the comment. -
Telegram returned
404 Not Found
For Telegramâs Bot API, 404 almost always means the bot token is wrong (or you used the placeholder).
Do this instead (copy/paste exactly)
Replace PASTE_YOUR_BOTFATHER_TOKEN_HERE with the real BotFather token (the one in channels.telegram.botToken):
TOKEN="PASTE_YOUR_BOTFATHER_TOKEN_HERE"
# sanity check the token:
curl -s "https://api.telegram.org/bot${TOKEN}/getMe"
If that returns "ok": true, then the token is correct. Then:
curl -s "https://api.telegram.org/bot${TOKEN}/getUpdates" | python3 -m json.tool
If getMe is still 404, youâre not using the Telegram BotFather token (easy to mix up with the OpenClaw gateway token). Make sure youâre using the value from:
channels.telegram.botToken(notgateway.auth.token)
Donât paste the token here; just tell me whether getMe returns ok: true or still 404.
{
"ok": false,
"error_code": 404,
"description": "Not Found"
}
If getMe is returning 404, the token youâre using is not a valid Telegram Bot API token (or itâs being pasted with extra characters).
A real BotFather token always looks like:
123456789:AA...(note the colon)
Most common mistakes
- Using the OpenClaw gateway token (usually hex) instead of the Telegram bot token
- Copying it with quotes/extra text, e.g. including
botToken:or surrounding quotes inside the value
Fix
- Get the correct token from @BotFather:
/mybotsâ pick your bot â API Token (or regenerate/revoke if needed)
- Set it in OpenClaw config (on the gateway host) â donât paste the token here:
openclaw config set channels.telegram.botToken "<PASTE_BOTFATHER_TOKEN>"
openclaw gateway restart
- Re-test:
TOKEN="<PASTE_BOTFATHER_TOKEN>"
curl -s "https://api.telegram.org/bot${TOKEN}/getMe"
If you tell me what format your token has (does it include a colon : or is it hex-looking?), I can immediately tell if youâre holding the right kind of token.
This thread is getting very long and answers may not be accurate due to the large context. Please start a new thread for any different problems/topics. @remote hatch please sum up the answer to the initial message and the conversation briefly.
When I remove the $ then I get {
"ok": true,
"result": []
}
{ "ok": true, "result": [] } is good news â it means youâre now hitting the Telegram API correctly, but your bot currently has no pending updates to show you.
Two clarifications:
1) The $ is only needed when you use a shell variable
- If you paste the token directly into the URL, thereâs no
$. - If you want to use the
TOKENvariable, you do need$TOKEN(or${TOKEN}).
2) Empty result just means: âbot hasnât received a new message since the last pollâ
To generate an update that includes the group chat id, do this:
- In the Telegram group, send something the bot will definitely receive:
/ping@YourBotUsername(any command is fine)
- Then immediately run:
curl -s "https://api.telegram.org/bot<PASTE_TOKEN_HERE>/getUpdates" | python3 -m json.tool
Now you should see an entry with:
"chat": { "id": -100..., "title": ... }â this is the group id"from": { "id": ... }â your user id
If itâs still empty after sending /ping@YourBotUsername, run:
curl -s "https://api.telegram.org/bot<PASTE_TOKEN_HERE>/getMe"
and confirm the username matches the bot you added to the group (itâs easy to be using a different bot token).
Still nothing
In telegram, i received a message from the bot saying "This group is not allowed"
If your OpenClaw Gateway is running with Telegram enabled (default longâpolling), itâs already calling getUpdates constantly â so when you run curl .../getUpdates manually, youâll usually see:
{ "ok": true, "result": [] }
because OpenClaw already âconsumedâ the updates.
Easiest way (donât fight getUpdates): use OpenClaw logs (with debug)
On the gateway host:
- Temporarily bump log level:
openclaw config set logging.level debug
openclaw gateway restart
- Tail logs:
openclaw logs --follow --json
- Send a message in the Telegram group (mention the bot or use a
/command@BotUsername)
In the log line for that inbound message, look for chat.id (thatâs the group id, usually -100...) and from.id (your user id).
After youâve got the IDs, set logs back:
openclaw config set logging.level info
openclaw gateway restart
Alternative (if you really want Bot API getUpdates)
Stop the gateway for a minute so itâs not polling:
openclaw gateway stop
Send the group message, run curl .../getUpdates, then start the gateway again.
If you paste one Telegram-related log line youâre seeing (redact tokens), I can point at the exact field names for chat.id / from.id in your output.
Nice â that tells us Telegram is wired up correctly. Now itâs just your access controls doing their job:
âThis group is not allowedâ = the groupâs chat id is not in
channels.telegram.groups(and youâre in the default failâclosed mode).
Fix: add this groupâs chat id to channels.telegram.groups
You need the group chat id (a negative number like -100âŚ). Since OpenClaw is already polling Telegram, the easiest way to get it is from the Gateway logs:
- On the gateway host:
openclaw logs --follow --json
-
Send another message in that Telegram group (mention the bot)
-
In the log entry for that inbound message, look for
chat.id(or similar) â thatâs the value to add underchannels.telegram.groups.
Then add it, e.g.:
channels: {
telegram: {
groups: {
"-1001234567890": {}, // your group id
},
},
}
Restart the gateway after changing config.
Quick temporary âjust let groups workâ option
If you donât care which group (yet), you can allow any group:
channels: {
telegram: {
groups: { "*": {} },
},
}
(You can still restrict who can talk in groups via groupAllowFrom later.)
If you paste one Telegram log line you see when it blocks (redact tokens), Iâll point out exactly where the chat.id is in your output.
Found the ID
Nice â once you have the group ID, the fix is just adding it to channels.telegram.groups and restarting the gateway.
Minimal example (allow that one group)
Add this to your config (ID as a string key is fine):
channels: {
telegram: {
groups: {
"-1001234567890": {}, // <- replace with the ID you found
},
},
}
Then:
openclaw gateway restart
Donât forget the sender allowlist (your earlier Doctor warning)
Right now you probably also need one of these, otherwise group messages will still be dropped:
- allow only you in groups:
groupAllowFrom: ["<your_user_id>"]
- or allow anyone in allowed groups:
groupAllowFrom: ["*"]
If you tell me which you want (only you vs anyone), Iâll give you the exact final combined block to paste.
Now when I /ping @ /help to my bot in telegram, it responds with a list of help commands. However, it doesn't respond to me if I just talk to it
Thatâs normal Telegram group behavior â youâre hitting two separate âgatesâ:
1) Telegram may not even deliver normal group messages to the bot
By default (BotFather privacy mode ON), bots in groups often only receive:
/commands(like/help)- messages that explicitly mention the bot (or replies, depending)
If you want the bot to see all group chat text:
- In @BotFather run
/setprivacyâ pick your bot â Disable - And/or make the bot an admin in the group (admin bots receive all messages)
2) OpenClaw also defaults to âmention requiredâ in groups
Even if Telegram delivers the message, OpenClaw will ignore non-mentions unless you turn it off.
In your config, set for that group:
channels: {
telegram: {
groups: {
"-1001234567890": {
requireMention: false,
},
},
},
}
Then openclaw gateway restart.
Quick test without changing anything
Try sending in the group:
@YourBotUsername hello
If it responds to that, Telegram delivery is fine and you just need requireMention: false if you want it always-on.
If it still doesnât respond even with an @mention, then itâs almost certainly BotFather privacy / admin status.
It didn't respond
If it didnât respond even to an @botusername message, then Telegram likely isnât delivering non-command messages to the bot (or the âmentionâ wasnât a real mention).
Do this in order:
1) Confirm the botâs actual username
On the gateway host:
curl -s "https://api.telegram.org/bot<YOUR_TOKEN>/getMe"
Look for "username": "YourBotUsername" â thatâs the only mention that counts.
2) Make sure Telegram will deliver normal group messages
In @BotFather:
/setprivacyâ pick your bot â Disable
In the Telegram group:
- Promote the bot to admin (recommended; admin bots receive all messages)
3) Ensure OpenClaw doesnât require mentions
In your OpenClaw config for that group:
channels: {
telegram: {
groups: {
"-100...": { requireMention: false },
},
},
}
Then:
openclaw gateway restart
4) Test in the group (this one should definitely reach the bot)
Send:
/help@YourBotUsername
If /help@YourBotUsername works but a real @YourBotUsername hello still doesnât, paste your channels.telegram.groups["-100..."] config block (no tokens) and weâll check the activation/allowlist settings.
{"ok":true,"result":[]}%
That output is getUpdates (result: []), not getMe.
To get the botâs username, you want getMe, which returns a single result object (not an array):
curl -s "https://api.telegram.org/bot<YOUR_TOKEN>/getMe"
Expected shape:
{"ok":true,"result":{"username":"YourBotUsername", ...}}
If youâre still seeing result: [], youâre hitting the wrong endpoint (or you pasted getUpdates again).
Also: donât worry if getUpdates is empty while OpenClaw is running â OpenClaw is polling Telegram, so getUpdates will usually show nothing when you call it manually.
{"ok":true,"result":{"id":,"is_bot":true,"first_name":"","username":"*","can_join_groups":true,"can_read_all_group_messages":false,"supports_inline_queries":false,"can_connect_to_business":false,"has_main_web_app":false,"has_topics_enabled":false,"allows_users_to_create_topics":false}}%
Perfect â that getMe output explains exactly why you only get /help-style behavior:
"can_read_all_group_messages": false
That means your bot is in privacy mode, so Telegram will not deliver ânormalâ group chat messages to it (itâll mostly get commands / explicit mentions).
Fix (recommended)
1) Disable privacy mode in BotFather
In Telegram, open @BotFather:
/setprivacy- choose your bot
- set to Disable
After that, re-run:
curl -s "https://api.telegram.org/bot<YOUR_TOKEN>/getMe"
and you should see "can_read_all_group_messages": true.
2) (Optional but good) Make the bot an admin in the group
Your own docs note: admin bots receive all group messages, which helps with âalways-onâ group behavior.
3) Make sure OpenClaw doesnât require mentions
Keep:
requireMention: false
for that group, then openclaw gateway restart.
Once privacy is disabled (or the bot is admin), the bot should start responding to normal group messages.
Is there any negative security implications to doing that?
Yes â the main ânegative securityâ implication is privacy/data exposure, not âit lets strangers hack youâ.
When you disable BotFather privacy (or make the bot an admin), Telegram will start delivering a lot more group content to your bot. That means:
What changes / risks
- The bot can now see all messages in that group (not just commands/mentions).
- Depending on your OpenClaw settings, those messages may end up:
- in your local logs
- in your session history
- potentially sent to a cloud model if the bot is configured to respond automatically (thatâs the big privacy/cost footgun)
How to keep it safe
If you want âalways-onâ delivery but still want to be cautious:
- Keep the group private, and restrict who can trigger the bot:
groupAllowFrom: ["<your_user_id>"](safest)- Consider leaving
requireMention: true(so it receives all messages but only acts when invoked) - If you make it an admin, give it the minimum admin permissions (donât grant delete/ban/etc unless you actually need it)
So: disabling privacy is fine for a personal group, but donât do it in a big/unknown group unless youâve locked down groupAllowFrom / mention behavior.
Do I actually need the bot in a group?
You only need the bot in a Telegram group if you actually want group chat behavior (multiple people talking to it, shared context, âbot in the roomâ, etc.).
Telegram bots can only receive messages from chats theyâre part of, so:
-
DM-only use case (most common for personal bots):
No, you donât need it in any group. Just DM the bot. -
Group use case:
Yes â it must be added to that group to see/respond there.
If you donât want group support, the cleanest setup is:
- keep using DMs
- set Telegram group handling to disabled (so Doctor stops warning and you donât accidentally ingest group chats)
In config thatâs:
channels: {
telegram: {
groupPolicy: "disabled",
},
}
(You can always re-enable later if you decide you want group mode.)
how do I put logs back to normal?
To put logs back to the default ânormalâ level, set logging.level back to info and restart the gateway:
openclaw config set logging.level info
openclaw gateway restart
(That controls the file logs that openclaw logs --follow tails.)
If you also cranked up console verbosity with --verbose, just stop/restart the gateway without --verbose.
@remote hatch can you generate a succinct markdown readme documentation of this chat? Leave out superfluous chat language, just commented commands structured and ordered to repeat complete setup
# OpenClaw Remote Access (macOS) via Tailscale Serve + SSH â Setup Playbook
This is a concise, repeatable checklist distilled from the thread. Replace placeholders like
`<BOT_MAC>`, `<TAILNET_HOSTNAME>`, `<GATEWAY_TOKEN>`, `<TELEGRAM_BOT_TOKEN>`.
---
## 0) Prereqs
- Two machines on the same Tailscale tailnet:
- **Bot Mac (Gateway host)**: runs OpenClaw Gateway
- **Laptop Mac (client)**: used to SSH + open dashboard
- OpenClaw installed on the Bot Mac.
- Tailscale app installed on both Macs and logged in.
---
## 1) Make the Tailscale CLI available on macOS (both Macs)
The macOS app bundles a CLI binary named `Tailscale` (capital T). OpenClaw expects `tailscale`.
On each Mac:
```bash
# Verify the bundled CLI works
/Applications/Tailscale.app/Contents/MacOS/Tailscale status
# Put it on PATH as `tailscale` (recommended for OpenClaw + scripts)
sudo ln -s /Applications/Tailscale.app/Contents/MacOS/Tailscale /usr/local/bin/tailscale
# Confirm
tailscale status
---
## 2) Enable SSH access to the Bot Mac (for remote command line)
On the **Bot Mac**:
```bash
# Enable Remote Login (SSH)
sudo systemsetup -setremotelogin on
sudo systemsetup -getremotelogin
# Confirm sshd is listening
sudo lsof -nP -iTCP:22 -sTCP:LISTEN
From the **Laptop Mac**:
```bash
# Find the Bot Mac tailnet IP/name (either works)
# (run on Bot Mac)
tailscale ip -4
tailscale status
# SSH in (run on Laptop Mac)
ssh <mac_username>@<bot_tailscale_ip>
Notes:
- First SSH connect will prompt to trust the host key â thatâs normal.
- If you see timeouts/refused, re-check âRemote Login: Onâ and youâre using the Bot Macâs **100.x** Tailscale IP.
---
## 3) Configure Tailscale Serve prerequisites (tailnet-only HTTPS)
In the Tailscale admin console:
- Enable **MagicDNS**
- Enable **HTTPS**
Privacy note: the `*.ts.net` hostname may appear in public certificate transparency logs (name leakage only; Serve is still tailnet-only).
---
## 4) Configure OpenClaw Gateway for Serve (recommended secure defaults)
On the **Bot Mac**:
```bash
# Keep gateway bound to loopback; Tailscale Serve provides remote access
openclaw config set gateway.bind loopback
# Tell OpenClaw to manage Tailscale Serve
openclaw config set gateway.tailscale.mode serve
4a) Allow Control UI origin when using Serve
When you open the dashboard at https://<TAILNET_HOSTNAME>/, the Gateway will enforce an origin allowlist.
Set it explicitly (full origin string):
```bash
# Example: allow both localhost + your Serve origin
openclaw config set gateway.controlUi.allowedOrigins '[
"http://127.0.0.1:18789",
"https://<TAILNET_HOSTNAME>"
]' --strict-json
5) Install/start the Gateway service (auto-start on reboot)
On the Bot Mac:
Install (or rewrite) the launchd service
openclaw gateway install --force
Start it
openclaw gateway start
Confirm service + probe
openclaw gateway status
---
## 6) Apply Serve config (and verify)
If `tailscale serve status` shows **No serve config**, apply Serve once:
```bash
Stop supervised gateway to avoid port/lock conflicts
openclaw gateway stop
Start gateway in "tailscale serve" mode (foreground)
openclaw gateway --tailscale serve
In another terminal on the **Bot Mac**:
```bash
# Confirm Serve URL + mapping now exist
tailscale serve status
Then switch back to the service:
Stop the foreground gateway (Ctrl+C), then:
openclaw gateway start
openclaw gateway status
---
## 7) Open the dashboard from the Laptop Mac
1) From the **Laptop Mac**, open the Serve URL shown in:
```bash
# run on Bot Mac
tailscale serve status
2) If the dashboard asks for the gateway token:
```bash
# run on Bot Mac (DO NOT share this token publicly)
openclaw config get gateway.auth.token
Paste into the dashboard âGateway Tokenâ field.
- If you see pairing required on the dashboard (remote connections require one-time approval):
# List pending device pairing requests
openclaw devices list
# Approve the request
openclaw devices approve <requestId>
4) If you see **origin not allowed**:
- Confirm you added the Serve origin to `gateway.controlUi.allowedOrigins`
- Restart the gateway:
```bash
openclaw gateway restart
- If the UI auto-filled a stale WebSocket URL (from old tunnel usage), use a private/incognito window to clear saved
gatewayUrl.
8) Alternative: Dashboard via SSH tunnel (no Serve required)
From the Laptop Mac:
```bash
# Keep this running; then browse http://127.0.0.1:18789/
ssh -N -L 18789:127.0.0.1:18789 <mac_username>@<bot_tailscale_ip>
9) After reboot: minimal reconnect checklist
- On both Macs: ensure Tailscale shows Connected
- On Bot Mac:
openclaw gateway status tailscale serve status
- On Laptop Mac: open `https://<TAILNET_HOSTNAME>/`
---
## 10) Reset logs back to normal (if set to debug)
```bash
openclaw config set logging.level info
openclaw gateway restart
Telegram (optional) â Fix Doctor warning + group behavior
## A) Doctor warning: `groupPolicy="allowlist"` but allowlists empty
If you want group messages to work, configure:
- `channels.telegram.botToken` (from BotFather)
- `channels.telegram.groups` (negative group chat IDs, e.g. `-100...`)
- `channels.telegram.groupAllowFrom` (numeric user IDs) OR set open behavior
Minimal âallow one group, allow only meâ example:
```json5
{
channels: {
telegram: {
enabled: true,
botToken: "<TELEGRAM_BOT_TOKEN>",
// Allow this specific group
groups: {
"-1001234567890": { requireMention: false },
},
// Allow only you to trigger the bot in groups
groupAllowFrom: ["<YOUR_TELEGRAM_USER_ID>"],
},
},
}
Restart after changes:
```bash
openclaw gateway restart
## B) âThis group is not allowedâ
Your group chat ID is missing from `channels.telegram.groups`. Add it (negative `-100...`).
## C) Bot only responds to `/help` but not normal group chat
From Telegram `getMe`, if you see:
- `"can_read_all_group_messages": false`
Then Telegram privacy mode is on. Fix:
- In **@BotFather**: `/setprivacy` â choose bot â **Disable**
- Optionally make the bot **admin** in the group
- In OpenClaw config: set per-group `requireMention: false` (if you want always-on)
---
## Quick âsanity probesâ
```bash
# Check gateway is up
openclaw gateway status
# Check serve mapping exists
tailscale serve status
Please remove the group number from that for privacy.
# OpenClaw Remote Access (macOS) via Tailscale Serve + SSH â Setup Playbook
This is a concise, repeatable checklist distilled from the thread. Replace placeholders like
`<BOT_MAC>`, `<TAILNET_HOSTNAME>`, `<GATEWAY_TOKEN>`, `<TELEGRAM_BOT_TOKEN>`.
---
## 0) Prereqs
- Two machines on the same Tailscale tailnet:
- **Bot Mac (Gateway host)**: runs OpenClaw Gateway
- **Laptop Mac (client)**: used to SSH + open dashboard
- OpenClaw installed on the Bot Mac.
- Tailscale app installed on both Macs and logged in.
---
## 1) Make the Tailscale CLI available on macOS (both Macs)
The macOS app bundles a CLI binary named `Tailscale` (capital T). OpenClaw expects `tailscale`.
On each Mac:
```bash
# Verify the bundled CLI works
/Applications/Tailscale.app/Contents/MacOS/Tailscale status
# Put it on PATH as `tailscale` (recommended for OpenClaw + scripts)
sudo ln -s /Applications/Tailscale.app/Contents/MacOS/Tailscale /usr/local/bin/tailscale
# Confirm
tailscale status
---
## 2) Enable SSH access to the Bot Mac (for remote command line)
On the **Bot Mac**:
```bash
# Enable Remote Login (SSH)
sudo systemsetup -setremotelogin on
sudo systemsetup -getremotelogin
# Confirm sshd is listening
sudo lsof -nP -iTCP:22 -sTCP:LISTEN
From the **Laptop Mac**:
```bash
# Find the Bot Mac tailnet IP/name (either works)
# (run on Bot Mac)
tailscale ip -4
tailscale status
# SSH in (run on Laptop Mac)
ssh <mac_username>@<bot_tailscale_ip>
Notes:
- First SSH connect will prompt to trust the host key â thatâs normal.
- If you see timeouts/refused, re-check âRemote Login: Onâ and youâre using the Bot Macâs **100.x** Tailscale IP.
---
## 3) Configure Tailscale Serve prerequisites (tailnet-only HTTPS)
In the Tailscale admin console:
- Enable **MagicDNS**
- Enable **HTTPS**
Privacy note: the `*.ts.net` hostname may appear in public certificate transparency logs (name leakage only; Serve is still tailnet-only).
---
## 4) Configure OpenClaw Gateway for Serve (recommended secure defaults)
On the **Bot Mac**:
```bash
# Keep gateway bound to loopback; Tailscale Serve provides remote access
openclaw config set gateway.bind loopback
# Tell OpenClaw to manage Tailscale Serve
openclaw config set gateway.tailscale.mode serve
4a) Allow Control UI origin when using Serve
When you open the dashboard at https://<TAILNET_HOSTNAME>/, the Gateway will enforce an origin allowlist.
Set it explicitly (full origin string):
```bash
# Example: allow both localhost + your Serve origin
openclaw config set gateway.controlUi.allowedOrigins '[
"http://127.0.0.1:18789",
"https://<TAILNET_HOSTNAME>"
]' --strict-json
5) Install/start the Gateway service (auto-start on reboot)
On the Bot Mac:
Install (or rewrite) the launchd service
openclaw gateway install --force
Start it
openclaw gateway start
Confirm service + probe
openclaw gateway status
---
## 6) Apply Serve config (and verify)
If `tailscale serve status` shows **No serve config**, apply Serve once:
```bash
Stop supervised gateway to avoid port/lock conflicts
openclaw gateway stop
Start gateway in "tailscale serve" mode (foreground)
openclaw gateway --tailscale serve
In another terminal on the **Bot Mac**:
```bash
# Confirm Serve URL + mapping now exist
tailscale serve status
Then switch back to the service:
Stop the foreground gateway (Ctrl+C), then:
openclaw gateway start
openclaw gateway status
---
## 7) Open the dashboard from the Laptop Mac
1) From the **Laptop Mac**, open the Serve URL shown in:
```bash
# run on Bot Mac
tailscale serve status
2) If the dashboard asks for the gateway token:
```bash
# run on Bot Mac (DO NOT share this token publicly)
openclaw config get gateway.auth.token
Paste into the dashboard âGateway Tokenâ field.
- If you see pairing required on the dashboard (remote connections require one-time approval):
# List pending device pairing requests
openclaw devices list
# Approve the request
openclaw devices approve <requestId>
4) If you see **origin not allowed**:
- Confirm you added the Serve origin to `gateway.controlUi.allowedOrigins`
- Restart the gateway:
```bash
openclaw gateway restart
- If the UI auto-filled a stale WebSocket URL (from old tunnel usage), use a private/incognito window to clear saved
gatewayUrl.
8) Alternative: Dashboard via SSH tunnel (no Serve required)
From the Laptop Mac:
```bash
# Keep this running; then browse http://127.0.0.1:18789/
ssh -N -L 18789:127.0.0.1:18789 <mac_username>@<bot_tailscale_ip>
9) After reboot: minimal reconnect checklist
- On both Macs: ensure Tailscale shows Connected
- On Bot Mac:
openclaw gateway status tailscale serve status
- On Laptop Mac: open `https://<TAILNET_HOSTNAME>/`
---
## 10) Reset logs back to normal (if set to debug)
```bash
openclaw config set logging.level info
openclaw gateway restart
Telegram (optional) â Fix Doctor warning + group behavior (sanitized)
## A) Doctor warning: `groupPolicy="allowlist"` but allowlists empty
If you want group messages to work, configure:
- `channels.telegram.botToken` (from BotFather)
- `channels.telegram.groups` (Telegram group chat IDs; use placeholders here)
- `channels.telegram.groupAllowFrom` (numeric user IDs) OR set open behavior
Minimal âallow one group, allow only meâ example:
```json5
{
channels: {
telegram: {
enabled: true,
botToken: "<TELEGRAM_BOT_TOKEN>",
// Allow this specific group
groups: {
"<TELEGRAM_GROUP_ID>": { requireMention: false },
},
// Allow only you to trigger the bot in groups
groupAllowFrom: ["<YOUR_TELEGRAM_USER_ID>"],
},
},
}
Restart after changes:
```bash
openclaw gateway restart
## B) âThis group is not allowedâ
Your group chat ID is missing from `channels.telegram.groups`. Add it (use `<TELEGRAM_GROUP_ID>` as the placeholder here).
## C) Bot only responds to `/help` but not normal group chat
From Telegram `getMe`, if you see:
- `"can_read_all_group_messages": false`
Then Telegram privacy mode is on. Fix:
- In **@BotFather**: `/setprivacy` â choose bot â **Disable**
- Optionally make the bot **admin** in the group
- In OpenClaw config: set per-group `requireMention: false` (if you want always-on)
---