#19802: feat(daemon): support system-level systemd services via OPENCLAW_SYSTEMD_SYSTEM
gateway
commands
size: S
Cluster:
Gateway and System Fixes
## Summary
When running OpenClaw as a system-level systemd service (e.g. on NixOS with a dedicated `openclaw` user), the user D-Bus session is unavailable. This causes `openclaw status` to incorrectly report "systemd not installed" and breaks all daemon management commands.
This PR adds a `OPENCLAW_SYSTEMD_SYSTEM=1` environment variable that switches all `systemctl` calls from `--user` to system scope.
## Changes
- **`src/daemon/systemd.ts`**: Add `isSystemLevelService()` and `systemctlScope()` helpers. All 14 `--user` call sites now go through `systemctlScope()`. Availability checks handle exit code 3 (no units loaded) as success for system-level services. Unit path resolves to `/etc/systemd/system/` instead of `~/.config/systemd/user/`.
- **`src/commands/systemd-linger.ts`**: Skip linger management when running as system service (not applicable).
- **`src/daemon/systemd.test.ts`**: Add tests for `isSystemLevelService`, system-level availability, and system-level unit path resolution.
## Usage
```bash
# In your systemd service environment or shell profile:
export OPENCLAW_SYSTEMD_SYSTEM=1
export OPENCLAW_SYSTEMD_UNIT=openclaw # if unit name differs from default
openclaw status # now correctly detects system-level service
```
Works alongside the existing `OPENCLAW_SYSTEMD_UNIT` env var for custom unit names.
## AI assisted
Driven and tested by me, but AI assisted on finding all places that needed change. Changes were discussed and reviewed by me. Although this is not my primary coding language.
## Testing
- All 18 tests in src/daemon/systemd.test.ts pass
- TypeScript typecheck clean (no new errors)
- Tested on NixOS with system-level openclaw.service running as dedicated user
## Non related changes
I had to include:
- apps/shared/OpenClawKit/Sources/OpenClawProtocol/GatewayModels.swift
- apps/macos/Sources/OpenClawProtocol/GatewayModels.swift
So CI would pass, this seems like something is missing upstream and not part of my changes
Most Similar PRs
#21212: fix: detect and manage systemd system services (rebased)
by growthringsadvisory · 2026-02-19
78.3%
#18498: daemon: load systemd EnvironmentFile and drop-ins so gateway status...
by saurav470 · 2026-02-16
72.3%
#16185: fix: patch systemd unit version before service restart
by nozh · 2026-02-14
71.4%
#16016: fix: update systemd unit version on gateway restart
by jbold · 2026-02-14
71.1%
#22108: fix: prevent local DoS by fully clearing systemd services on uninstall
by berkeserce · 2026-02-20
69.2%
#11974: [FEATURE] feat: integrate systemd WatchdogSec for gateway hang dete...
by mcaxtr · 2026-02-08
66.5%
#20357: feat(gateway): make systemd KillMode configurable for gateway install
by Jackten · 2026-02-18
66.5%
#23666: fix(doctor): openclaw-browser.service falsely flagged as duplicate ...
by yinghaosang · 2026-02-22
64.5%
#8195: feat(migration): env fallbacks + legacy launchd cleanup
by shuv-amp · 2026-02-03
63.4%
#22313: fix: check plist existence before marking LaunchAgent missing
by MisterGuy420 · 2026-02-21
63.1%