Hi! First time posting, total beginner. Just migrated my agent (Pip) from my Mac to a Hetzner server.
Setup: Hetzner CPX32, Ubuntu 24.04, Claude CLI as provider, Telegram channel.
What’s working: Server up, OpenClaw running, Telegram pairing approved, status shows everything green.
What’s broken: Every time I message Pip on Telegram, the agent errors out. Logs show this repeating:
--dangerously-skip-permissions cannot be used with root/sudo privileges for security reasons
So Pip is running as root and Claude CLI refuses to run that way.
ls /home shows there’s already an openclaw user. systemctl list-unit-files | grep openclaw shows openclaw.service enabled at the system level. There’s also a user-level systemd service that was reported as installed/enabled/running in openclaw status.
What’s the canonical way to switch over so Pip runs as the openclaw user instead of root? I’ve already run systemctl stop openclaw so it’s stopped right now.
Thanks 🦞
#mac to hetzner
1 messages · Page 1 of 1 (latest)
Welcome! You diagnosed the important bit correctly: if Claude CLI is the provider, don’t run the Gateway/agent as root. Canonical Linux install is a systemd user service under the account that owns the OpenClaw state.
First, quick version check because service behavior has changed over time:
openclaw --version
Likely path from where you are:
# 1) Make sure the root/system service is not the one coming back
sudo systemctl disable --now openclaw.service
sudo systemctl disable --now openclaw-gateway.service 2>/dev/null || true
# 2) Keep the openclaw user's systemd --user service alive after logout
sudo loginctl enable-linger openclaw
# 3) Check the CLI is available and auth works as the openclaw user
sudo -iu openclaw openclaw --version
sudo -iu openclaw claude --version
# 4) Install/reinstall the Gateway user service as openclaw
sudo -iu openclaw openclaw gateway install --force
# 5) Start it as the openclaw user's user service
sudo -iu openclaw systemctl --user daemon-reload
sudo -iu openclaw systemctl --user enable --now openclaw-gateway.service
# 6) Verify from the same user
sudo -iu openclaw openclaw gateway status
sudo -iu openclaw openclaw status --all
If systemctl --user complains about the bus/session, use this variant for the systemctl lines:
sudo XDG_RUNTIME_DIR=/run/user/$(id -u openclaw) -u openclaw systemctl --user enable --now openclaw-gateway.service
One big gotcha: if you originally configured/pairing while running as root, the working config may be in /root/.openclaw, not /home/openclaw/.openclaw. In that case, stop services first, back it up, then copy/chown the state to the service account:
sudo systemctl disable --now openclaw.service
sudo -iu openclaw systemctl --user stop openclaw-gateway.service 2>/dev/null || true
sudo rsync -a /root/.openclaw/ /home/openclaw/.openclaw/
sudo chown -R openclaw:openclaw /home/openclaw/.openclaw
Then rerun the install/start/status steps as openclaw.
Docs refs: Linux service notes https://docs.openclaw.ai/platforms/linux and setup FAQ https://docs.openclaw.ai/help/faq. 🦞
Thanks Krill! Quick check before I run these — is there a single command or script that handles the full migration (disable root → backup → copy state → chown → reinstall as openclaw user → restart)? I’m not super comfortable in terminal and want to minimize the chance of breaking the state. Also — does openclaw onboard have a “rehome” or “fix permissions” mode?
Good instinct to ask before running a bunch of service commands.
Short answer: I don’t know of an official openclaw onboard --rehome / “fix ownership and migrate from root” mode. openclaw doctor --fix can repair some config/state issues, and openclaw gateway install --force rewrites the service launcher, but neither is a full root→user state migration. Docs point to systemd user services as the normal Linux path: https://docs.openclaw.ai/platforms/linux
If you want a single paste, I’d use a conservative script like this. It makes backups first, stops/disables the system/root service, copies /root/.openclaw to /home/openclaw/.openclaw, fixes ownership, enables linger, reinstalls the user service, and starts it.
cat >/tmp/openclaw-rehome-to-openclaw-user.sh <<'SCRIPT'
#!/usr/bin/env bash
set -euo pipefail
TARGET_USER="openclaw"
SRC="/root/.openclaw"
DST="/home/${TARGET_USER}/.openclaw"
TS="$(date +%Y%m%d-%H%M%S)"
if [ "$(id -u)" -ne 0 ]; then
echo "Run this with sudo: sudo bash /tmp/openclaw-rehome-to-openclaw-user.sh"
exit 1
fi
id "$TARGET_USER" >/dev/null
if [ ! -d "$SRC" ]; then
echo "Expected root state at $SRC, but it does not exist. Aborting."
exit 1
fi
echo "== Stopping root/system OpenClaw services =="
systemctl disable --now openclaw.service 2>/dev/null || true
systemctl disable --now openclaw-gateway.service 2>/dev/null || true
echo "== Stopping existing openclaw user service, if any =="
USER_UID="$(id -u "$TARGET_USER")"
XDG_RUNTIME_DIR="/run/user/${USER_UID}" sudo -u "$TARGET_USER" systemctl --user stop openclaw-gateway.service 2>/dev/null || true
echo "== Backing up state =="
tar -C /root -czf "/root/openclaw-root-state-before-rehome-${TS}.tgz" .openclaw
if [ -d "$DST" ]; then
tar -C "/home/${TARGET_USER}" -czf "/root/openclaw-user-state-before-rehome-${TS}.tgz" .openclaw
fi
echo "== Copying root state to ${DST} =="
mkdir -p "$DST"
if command -v rsync >/dev/null 2>&1; then
rsync -a "$SRC/" "$DST/"
else
cp -a "$SRC/." "$DST/"
fi
chown -R "${TARGET_USER}:${TARGET_USER}" "$DST"
chmod 700 "$DST"
echo "== Enabling linger for always-on user service =="
loginctl enable-linger "$TARGET_USER"
echo "== Reinstalling and starting Gateway as ${TARGET_USER} =="
sudo -iu "$TARGET_USER" openclaw gateway install --force
XDG_RUNTIME_DIR="/run/user/${USER_UID}" sudo -u "$TARGET_USER" systemctl --user daemon-reload
XDG_RUNTIME_DIR="/run/user/${USER_UID}" sudo -u "$TARGET_USER" systemctl --user enable --now openclaw-gateway.service
echo "== Status =="
sudo -iu "$TARGET_USER" openclaw gateway status || true
sudo -iu "$TARGET_USER" openclaw status --all || true
echo "Done. Backups are in /root/openclaw-*-before-rehome-${TS}.tgz"
SCRIPT
sudo bash /tmp/openclaw-rehome-to-openclaw-user.sh
Important: this does not delete /root/.openclaw, so rollback is possible. Once it’s green, test Telegram. If Pip still errors, grab:
sudo -iu openclaw openclaw --version
sudo -iu openclaw claude --version
sudo -iu openclaw openclaw logs --tail 120
And yep, if this fixes it, please mark the solution so Answer Overflow indexes it for the next Hetzner lobster wrangler 🦞
One more dumb question — running this from the Hetzner web console where I can’t paste. Any way to fetch this script as a file (gist link, curl from a URL) so I can run it without retyping? Or is there a recommended way to get it onto the server safely?
Not dumb at all — the Hetzner web console is exactly the place where long scripts go to die 😅
I would not curl a random gist for this. Safest path is: use SSH from your Mac, then copy the script over with scp/ssh.
On your Mac, save the script as openclaw-rehome-to-openclaw-user.sh, then run:
scp openclaw-rehome-to-openclaw-user.sh root@YOUR_SERVER_IP:/tmp/
ssh root@YOUR_SERVER_IP 'bash /tmp/openclaw-rehome-to-openclaw-user.sh'
If you normally SSH as a non-root user:
scp openclaw-rehome-to-openclaw-user.sh YOUR_USER@YOUR_SERVER_IP:/tmp/
ssh YOUR_USER@YOUR_SERVER_IP 'sudo bash /tmp/openclaw-rehome-to-openclaw-user.sh'
Even better, if you can SSH at all, you can avoid the web console entirely.
If SSH isn’t set up yet, use the Hetzner console only for the tiny bit needed to enable it / add your key, then do the migration over SSH. Typing a long root-state migration script into a browser console is too easy to botch.
Update — ran the script. Most of it worked (stop, backup, copy, ownership, linger all green). Got stuck at the last step:
Gateway install failed: Error: systemctl --user unavailable: Failed to connect to bus: No medium found
The script printed these tips:
• sudo loginctl enable-linger $(whoami)
• export XDG_RUNTIME_DIR=/run/user/$(id -u), then retry
• or run gateway in the foreground
What’s the recommended next step? Headless Hetzner Ubuntu 24.04.
Recommended next step: fix the systemd user bus, don’t switch to foreground as the long-term setup.
On headless Ubuntu this usually happens when linger was enabled, but the command is running in a shell that doesn’t have the user runtime dir/bus yet — often after su/sudo or before reconnecting.
Try this as the same non-root user that owns ~/.openclaw:
openclaw --version
sudo loginctl enable-linger "$(whoami)"
loginctl show-user "$(whoami)" -p Linger -p RuntimePath
ls -ld /run/user/$(id -u)
export XDG_RUNTIME_DIR=/run/user/$(id -u)
systemctl --user status
openclaw gateway install
openclaw gateway status
If /run/user/$(id -u) does not exist or systemctl --user status still says no bus, fully log out of SSH and reconnect directly as that user, then retry the last 3 commands. If you created a dedicated openclaw user, SSH as openclaw directly rather than staying in a root shell and su-ing.
Foreground mode is fine as a temporary smoke test (openclaw gateway run), but for a Hetzner box I’d want the systemd service working so it survives logout/reboot.
Docs: https://docs.openclaw.ai/gateway and https://docs.openclaw.ai/start/setup
Update: openclaw user can now run openclaw gateway install cleanly, systemd user session works, linger is on. Problem: there's still a root-owned gateway process auto-respawning on port 18789, blocking the openclaw one.
Killed PID 49997, but a new root-owned gateway with PID 63599 came back ~3 minutes later. So something is auto-restarting it.
What's the canonical way to find and stop the root-level supervisor? (Suspect a leftover systemd unit from before the rehome, but the migration script ran systemctl disable --now openclaw.service and openclaw-gateway.service.)
Yep — don’t keep killing PIDs. Find the parent supervisor/cgroup, then disable that unit.
First, please grab openclaw --version too, just so we know what installer/service logic you’re on.
Canonical systemd hunt:
# 1) Identify what owns the live root process
sudo ps -fp 63599
sudo pstree -asp 63599
sudo cat /proc/63599/cgroup
sudo systemctl status 63599 --no-pager
# 2) List root/system units that look OpenClaw-ish
sudo systemctl list-units --type=service --all | grep -Ei 'openclaw|clawdbot|moltbot|gateway'
sudo systemctl list-unit-files | grep -Ei 'openclaw|clawdbot|moltbot|gateway'
# 3) Also check timers in case something restarts it every few minutes
sudo systemctl list-timers --all | grep -Ei 'openclaw|clawdbot|moltbot|gateway'
sudo crontab -l
crontab -l
If systemctl status 63599 or /proc/63599/cgroup shows a unit name, stop it by exact name, for example:
sudo systemctl disable --now openclaw-gateway.service
sudo systemctl mask openclaw-gateway.service
sudo systemctl daemon-reload
sudo systemctl reset-failed
Also check whether there are old aliases/names — historical installs may be clawdbot, moltbot, openclaw, or openclaw-gateway.
If the unit file still exists, inspect/remove only after confirming it’s the stale root one:
sudo systemctl cat <unit-name>
sudo systemctl show <unit-name> -p FragmentPath -p DropInPaths -p ExecStart
Then verify the port is free and start the intended user service:
sudo ss -ltnp 'sport = :18789'
sudo -iu openclaw systemctl --user restart openclaw-gateway.service
sudo -iu openclaw systemctl --user status openclaw-gateway.service --no-pager
OpenClaw’s built-in scan may also point directly at the stale service:
sudo -iu openclaw openclaw gateway status --deep
sudo -iu openclaw openclaw doctor --deep
Docs: https://docs.openclaw.ai/gateway / https://docs.openclaw.ai/gateway/troubleshooting
Update: openclaw user service is running cleanly, root service is stopped/disabled/linger-off. Telegram messages get to the agent but error out with:
[boot] failed to read BOOT.md: EACCES: permission denied, open '/root/.openclaw/workspace/BOOT.md'
Error: EACCES: permission denied, mkdir '/root/.openclaw/workspace'
Looks like a path is still pointing at /root/.openclaw/ after the rehome. What's the canonical place to fix the workspace path so it uses /home/openclaw/.openclaw/workspace?
Yep — canonical fix is agent config, not chmodding /root.
The workspace path is agents.defaults.workspace in the active OpenClaw config, and per-agent overrides can also exist under agents.list[].workspace. Since ~ expands based on the service user’s HOME, /root/.openclaw/... usually means either an explicit stale config value, a stale service env, or a per-agent override.
Run these as the openclaw user:
sudo -iu openclaw openclaw --version
sudo -iu openclaw openclaw config get agents.defaults.workspace
sudo -iu openclaw openclaw config get agents.list
sudo -iu openclaw openclaw gateway status --json
Then set the default workspace explicitly:
sudo -iu openclaw openclaw config set agents.defaults.workspace /home/openclaw/.openclaw/workspace
sudo -iu openclaw mkdir -p /home/openclaw/.openclaw/workspace
sudo -iu openclaw openclaw gateway restart
If agents.list shows a Telegram-routed/default agent with workspace: /root/.openclaw/workspace, fix that specific agent entry too. Don’t leave both a default and an override disagreeing.
Also inspect the user unit for stale root env/path:
sudo -iu openclaw systemctl --user cat openclaw-gateway.service
sudo -iu openclaw systemctl --user show openclaw-gateway.service -p Environment -p ExecStart
If the config looks right but it still tries /root, search the OpenClaw state for stale references:
sudo grep -R "/root/.openclaw" -n /home/openclaw/.openclaw /etc/systemd/system /root/.config/systemd 2>/dev/null
Most likely hit: /home/openclaw/.openclaw/openclaw.json or an agent entry. Less likely: a persisted session record from the old root install; if so, start a fresh Telegram thread/session after the workspace config is fixed.
Docs: https://docs.openclaw.ai/gateway/configuration and https://docs.openclaw.ai/gateway/config-agents
Final batch of questions before I move on — want to make sure this migration leaves Pip in a clean, durable state, not a held-together-with-tape state:
- Workspace transfer. Pip's responding cleanly on the new openclaw user setup, but the workspace at /home/openclaw/.openclaw/workspace is empty because we redirected agents.defaults.workspace. The old workspace at /root/.openclaw/workspace has several days of real memory/files/projects I want to keep. Safe to cp -a /root/.openclaw/workspace/. /home/openclaw/.openclaw/workspace/ then sudo chown -R openclaw:openclaw, then restart? Or are there session/state files I should leave behind?
- Session continuity. sessions.json and trajectory files still reference /root/.openclaw/agents/main/sessions/... paths. Do those need to be rewritten, or will Pip just start fresh sessions and the old ones become unreachable history? Will /new in Telegram help?
- Memory/identity. Does Pip's "who am I, what's my name, what have we been working on" live in the workspace folder, in a separate memory plugin store, or both? Want to know what I'm actually preserving.
- Cleanup. Once the rehome is verified working, is it safe to delete /root/.openclaw/ entirely (after keeping the .tgz backup), or does anything still read from there?
- Verification. Is there an openclaw doctor or openclaw status --deep output I should send you to confirm the install is fully clean before I close this out?
Trying to land this so the next time my laptop closes, Pip just keeps going — not held together with workarounds.
Good instincts. I’d land it like this — clean rehome, no duct tape.
- Workspace transfer
Yes, copy the old workspace. The workspace is where Pip’s identity/memory/project files live; it is not the session store.
I’d do it with the gateway stopped so nothing writes mid-copy:
sudo -iu openclaw systemctl --user stop openclaw-gateway.service
sudo rsync -aH --numeric-ids /root/.openclaw/workspace/ /home/openclaw/.openclaw/workspace/
sudo chown -R openclaw:openclaw /home/openclaw/.openclaw/workspace
sudo -iu openclaw openclaw config set agents.defaults.workspace /home/openclaw/.openclaw/workspace
sudo -iu openclaw systemctl --user start openclaw-gateway.service
cp -a /root/.openclaw/workspace/. ... is basically fine too; I prefer rsync -aH for migrations. Watch for symlinks in the old workspace that point back into /root — those are the main gotcha.
- Session continuity
Don’t hand-rewrite sessions.json unless you’re doing deliberate surgery. Session state lives under:
~/.openclaw/agents/<agentId>/sessions/sessions.json
~/.openclaw/agents/<agentId>/sessions/*.jsonl
If those entries still point at /root/..., they’re stale from the old state dir. Pip can start fresh sessions; old root sessions become historical unless you migrate that session directory too. /new in Telegram is a good way to force a clean fresh conversation after the workspace copy.
If you really want old transcript history available, copy /root/.openclaw/agents/main/sessions/ to /home/openclaw/.openclaw/agents/main/sessions/ and chown it, but I’d avoid path-rewriting unless there’s a specific session you need to resume.
- Memory / identity
Mostly workspace. Pip’s “who am I / what’s my name / what have we been working on” should be in files like:
/home/openclaw/.openclaw/workspace/IDENTITY.md
/home/openclaw/.openclaw/workspace/USER.md
/home/openclaw/.openclaw/workspace/SOUL.md
/home/openclaw/.openclaw/workspace/MEMORY.md
/home/openclaw/.openclaw/workspace/memory/*.md
The memory plugin may also keep an index/cache, but the canonical human-readable memory is Markdown in the workspace. Preserve the workspace first.
- Cleanup
After verification, yes: nothing in the new openclaw user service should need /root/.openclaw. But don’t delete immediately. I’d keep the .tgz backup, then move it aside first:
sudo mv /root/.openclaw /root/.openclaw.migrated-backup
Run for a day/reboot. If nothing tries to read it, then delete later. Moving catches hidden stale references without destroying the fallback.
- Verification to send
Best bundle:
sudo -iu openclaw openclaw --version
sudo -iu openclaw openclaw status --all
sudo -iu openclaw openclaw gateway status --deep
sudo -iu openclaw openclaw doctor --deep
sudo -iu openclaw openclaw config get agents.defaults.workspace
sudo -iu openclaw openclaw config get agents.list
sudo ss -ltnp 'sport = :18789'
sudo grep -R "/root/.openclaw" -n /home/openclaw/.openclaw /etc/systemd/system 2>/dev/null