Skip to content

feat(service): add OpenRC support for Alpine Linux#716

Merged
chumyin merged 12 commits intozeroclaw-labs:mainfrom
Baz00k:feat/service/openrc-alpine-support
Feb 20, 2026
Merged

feat(service): add OpenRC support for Alpine Linux#716
chumyin merged 12 commits intozeroclaw-labs:mainfrom
Baz00k:feat/service/openrc-alpine-support

Conversation

@Baz00k
Copy link
Copy Markdown
Contributor

@Baz00k Baz00k commented Feb 17, 2026

Summary

Describe this PR in 2-5 bullets:

  • Problem: ZeroClaw service management only supported systemd (user-level) on Linux, so Alpine/OpenRC deployments could not use zeroclaw service end-to-end.
  • Why it matters: Alpine is common for minimal systems and containers; lacking OpenRC support blocks service lifecycle management on those hosts.
  • What changed: Added OpenRC support with init auto-detection, --service-init flag, OpenRC install/start/stop/status/uninstall flow, and docs updates for Alpine service usage.
  • What did not change (scope boundary): No macOS/Windows service changes; no unrelated channel/provider behavior changes.

Label Snapshot (required)

  • Risk label (risk: low|medium|high): risk: medium
  • Size label (size: XS|S|M|L|XL, auto-managed/read-only): auto-managed
  • Scope labels (core|agent|channel|config|cron|daemon|doctor|gateway|health|heartbeat|integration|memory|observability|onboard|provider|runtime|security|service|skillforge|skills|tool|tunnel|docs|dependencies|ci|tests|scripts|dev, comma-separated): service,docs
  • Module labels (<module>:<component>, for example channel:telegram, provider:kimi, tool:shell): service:openrc
  • Contributor tier label (trusted contributor|experienced contributor|principal contributor|distinguished contributor, auto-managed/read-only; author merged PRs >=5/10/20/50): auto-managed
  • If any auto-label is incorrect, note requested correction: none

Change Metadata

  • Change type (bug|feature|refactor|docs|security|chore): feature
  • Primary scope (runtime|provider|channel|memory|security|ci|docs|multi): multi

Linked Issue

Supersede Attribution (required when Supersedes # is used)

  • Superseded PRs + authors (#<pr> by @<author>, one per line): N/A
  • Integrated scope by source PR (what was materially carried forward): N/A
  • Co-authored-by trailers added for materially incorporated contributors? (Yes/No): N/A
  • If No, explain why (for example: inspiration-only, no direct code/design carry-over): N/A
  • Trailer format check (separate lines, no escaped \n): (Pass/Fail): N/A

Validation Evidence (required)

Commands and result summary:

./scripts/ci/rust_quality_gate.sh
./scripts/ci/rust_strict_delta_gate.sh
./scripts/ci/docs_quality_gate.sh
  • ./scripts/ci/rust_quality_gate.sh -> FAIL (full-repo fmt check currently reports upstream formatting drift outside this PR delta)
  • ./scripts/ci/rust_strict_delta_gate.sh -> PASS (no blocking issues on changed Rust lines)
  • ./scripts/ci/docs_quality_gate.sh -> PASS (no blocking markdown issues on changed lines)
  • Evidence provided (test/log/trace/screenshot/perf): CLI logs from local gate runs posted in PR comments.
  • If any command is intentionally skipped, explain why: none

Security Impact (required)

  • New permissions/capabilities? (Yes/No): Yes (OpenRC system service management on Alpine)
  • New external network calls? (Yes/No): No
  • Secrets/tokens handling changed? (Yes/No): No
  • File system access scope changed? (Yes/No): Yes (/etc/init.d/zeroclaw, /etc/conf.d/zeroclaw, /etc/zeroclaw, /var/log/zeroclaw on OpenRC path)
  • If any Yes, describe risk and mitigation: Risk is broader service/filesystem scope under root on OpenRC systems. Mitigations include explicit root requirement checks, restrictive ownership/mode setup for runtime dirs, and init-system-specific command paths.

Privacy and Data Hygiene (required)

  • Data-hygiene status (pass|needs-follow-up): pass
  • Redaction/anonymization notes: No personal/sensitive payloads added.
  • Neutral wording confirmation (use ZeroClaw/project-native labels if identity-like wording is needed): confirmed

Compatibility / Migration

  • Backward compatible? (Yes/No): Yes
  • Config/env changes? (Yes/No): No (optional CLI flag)
  • Migration needed? (Yes/No): No
  • If yes, exact upgrade steps: N/A

Human Verification (required)

What was personally validated beyond CI:

  • Verified scenarios: Installed zeroclaw service on a fresh Alpine LXC
  • What was not verified: Backwards compatibility with systemd

Side Effects / Blast Radius (required)

  • Affected subsystems/workflows: src/service/mod.rs, src/main.rs, src/channels/mod.rs, Cargo.toml/Cargo.lock, README.md, docs/network-deployment.md
  • Potential unintended effects: Service management behavior differences across Linux init systems.
  • Guardrails/monitoring for early detection: strict delta gate + docs gate + CI checks on PR.

Agent Collaboration Notes (recommended)

  • Agent tools used (if any): opencode
  • Verification focus: rebase correctness, no unrelated file changes, local gate results.
  • Confirmation: naming + architecture boundaries followed (AGENTS.md + CONTRIBUTING.md): Yes

Rollback Plan (required)

  • Fast rollback command/path: git revert <openrc-commit-range>
  • Feature flags or config toggles (if any): --service-init can explicitly select init system.
  • Observable failure symptoms: OpenRC install/start failures, missing service status output, daemon restart not triggered as expected.

Risks and Mitigations

List real risks in this PR (or write None).

  • Risk: OpenRC-specific behavior may differ across Alpine/OpenRC versions.
    • Mitigation: explicit init selection and deterministic script paths/ownership checks.
  • Risk: Full-repo rust quality gate currently fails due non-delta formatting drift on base.
    • Mitigation: strict delta gate passes for changed lines; continue tracking upstream quality gate status in CI.

@github-actions github-actions Bot added docs Auto scope: docs/markdown/template files changed. dependencies Auto scope: dependency manifest/lock/policy changed. core Auto scope: root src/*.rs files changed. channel Auto scope: src/channels/** changed. service Auto scope: src/service/** changed. size: L Auto size: 501-1000 non-doc changed lines. risk: medium Auto risk: src/** or dependency/config changes. service: core Auto module: service core files changed. channel: cli Auto module: channel/cli changed. and removed channel Auto scope: src/channels/** changed. service Auto scope: src/service/** changed. labels Feb 17, 2026
@Baz00k Baz00k marked this pull request as draft February 18, 2026 00:00
@github-actions github-actions Bot added channel Auto scope: src/channels/** changed. service Auto scope: src/service/** changed. and removed channel Auto scope: src/channels/** changed. service Auto scope: src/service/** changed. labels Feb 18, 2026
@github-actions github-actions Bot added channel Auto scope: src/channels/** changed. config Auto scope: src/config/** changed. service Auto scope: src/service/** changed. and removed channel Auto scope: src/channels/** changed. config Auto scope: src/config/** changed. service Auto scope: src/service/** changed. labels Feb 18, 2026
@github-actions
Copy link
Copy Markdown

Hi @Baz00k, friendly automation nudge from PR hygiene.

This PR has had no new commits for 21h and still needs an update before merge:

  • No CI Required Gate run was found for the current head commit.

Recommended next steps

  1. Rebase your branch on main.
  2. Push the updated branch and re-run checks (or use Re-run failed jobs).
  3. Post fresh validation output in this PR thread.

Maintainers: apply no-stale to opt out for accepted-but-blocked work.
Head SHA: 160d59701a11

Baz00k and others added 12 commits February 20, 2026 21:41
- Add InitSystem enum with auto-detection (systemd/OpenRC)
- Add --service-init CLI flag to override init system detection
- Generate OpenRC init script with security hardening:
  - Runs as zeroclaw:zeroclaw user
  - umask 027 for file permissions
  - Logs to /var/log/zeroclaw/
  - Depends on net and firewall
- Require root for OpenRC install with clear error message
- Warn if binary is in home directory
- Add OpenRC auto-restart support in channels module
- Document OpenRC setup in README and network-deployment.md

Non-goals:
- No changes to systemd behavior
- No user-level OpenRC services
- No other init systems (SysV, runit, s6)

Security: OpenRC install requires root, validates user, creates
directories with proper permissions
- Add chown_to_zeroclaw() helper to change directory ownership
- Log directory /var/log/zeroclaw now owned by zeroclaw:zeroclaw
- Fix docs: config file should be owned by zeroclaw:zeroclaw
  (service runs as zeroclaw user, needs read access)

Fixes permission denied error when service tries to write logs.
- Detect Alpine Linux via /etc/alpine-release
- Use adduser/deluser on Alpine instead of useradd/userdel
- Auto-create zeroclaw system user during install
- Provide correct commands in error messages

Alpine uses BusyBox which has different user management commands:
- adduser -S -s /sbin/nologin -H -D zeroclaw (Alpine)
- useradd -r -s /sbin/nologin zeroclaw (Debian/RHEL)
- Alpine adduser -S doesn't create a group automatically
- Explicitly create group with addgroup -S zeroclaw first
- Then add user with -G zeroclaw to join the group
- Update error message commands to include group handling

OpenRC service runs as zeroclaw:zeroclaw, so group must exist.
- Move chown_to_zeroclaw outside the if block
- Fixes permission denied when directory already exists
- Ensures correct ownership even on reinstall
- Add global --config-dir CLI flag that sets ZEROCLAW_CONFIG_DIR env
- Add ZEROCLAW_CONFIG_DIR override in config resolution (takes precedence)
- Update OpenRC script to use --config-dir and set env vars for config/workspace
- Prefer /usr/local/bin/zeroclaw for OpenRC executable
- Create /etc/zeroclaw/workspace directory with correct ownership on install
- Update docs to reflect --service-init flag order (service-level before subcommand)
Add automatic runtime-state migration to /etc/zeroclaw with secure ownership/permissions. Implement env-based config resolution for service startup, eliminating the need for manual --service-init flags in the happy path.
Switch OpenRC service generation from env exports
(ZEROCLAW_CONFIG_DIR/WORKSPACE) to explicit command_args with
--config-dir flag. Fixes startup crash with 'Permission denied (os error
13)' under OpenRC init system.
- Linux managed daemon now falls back to systemd when OpenRC restart probe fails, instead of returning early with no action.

- OpenRC uninstall no longer fails hard if rc-update del fails; it warns and continues to remove the init script.
@chumyin
Copy link
Copy Markdown
Contributor

chumyin commented Feb 20, 2026

Thanks @Baz00k for the OpenRC support contribution, and congratulations on getting this over the line.\n\nI performed a deep maintainer pass and applied a focused follow-up commit to keep the scope tight and stable:\n- removed unrelated schema drift ( on )\n- made the root-detection test deterministic on non-Unix targets\n- tightened OpenRC docs wording to avoid over-promising automatic migration behavior\n\nI also rebased the branch on current , resolved conflicts, and re-ran local validation on the service/OpenRC paths with a clean worktree setup.\n\nWe are currently conducting ZeroClaw automated testing. This is an automated comment from ZeroClaw. If you have any questions, please contact @chumyin.

@chumyin
Copy link
Copy Markdown
Contributor

chumyin commented Feb 20, 2026

Correction to my previous comment (shell stripped inline code formatting):

Thanks @Baz00k for the OpenRC support contribution, and congratulations on getting this over the line.

I performed a deep maintainer pass and applied a focused follow-up commit to keep the scope tight and stable:

  • removed unrelated schema drift (serde alias = "on" on StreamMode::Partial)
  • made the root-detection test deterministic on non-Unix targets
  • tightened OpenRC docs wording to avoid over-promising automatic migration behavior

I also rebased the branch on current main, resolved conflicts, and re-ran local validation on the service/OpenRC paths with a clean worktree setup.

We are currently conducting ZeroClaw automated testing. This is an automated comment from ZeroClaw. If you have any questions, please contact @chumyin.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

channel Auto scope: src/channels/** changed. config: core Auto module: config core files changed. core Auto scope: root src/*.rs files changed. dependencies Auto scope: dependency manifest/lock/policy changed. docs Auto scope: docs/markdown/template files changed. provider Auto scope: src/providers/** changed. risk: medium Auto risk: src/** or dependency/config changes. service: core Auto module: service core files changed. size: XL Auto size: >1000 non-doc changed lines.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants