Run as a background service
Install and manage Revka as an OS service across launchd, systemd, OpenRC, and Windows.
revka service runs revka daemon as a persistent, OS-managed background service so it starts automatically on login or boot and is restarted on failure. One command set — install, start, stop, restart, status, logs, uninstall — drives the right native mechanism for your platform: a launchd agent on macOS, a systemd user unit or OpenRC init script on Linux, and a Windows Task Scheduler task on Windows.
Reach for this page once you want Revka to survive reboots and crashes without a terminal open. For the command-level reference (flags, subcommands, pairing) see revka gateway, daemon & service; for the daemon itself and its component supervisor see the same page.
How the init system is chosen
Section titled “How the init system is chosen”revka service auto-detects the platform and, on Linux, the init system:
| Platform | Mechanism | Artifact |
|---|---|---|
| macOS | launchd agent | ~/Library/LaunchAgents/com.revka.daemon.plist |
| Linux (systemd) | systemd user unit | ~/.config/systemd/user/revka.service |
| Linux (OpenRC / Alpine) | OpenRC init script | /etc/init.d/revka |
| Windows | Scheduled Task | task named Revka Daemon |
Linux detection is deny-by-default: it picks systemd if /run/systemd/system exists, otherwise OpenRC if /run/openrc exists and an OpenRC binary (/sbin/openrc-run or rc-service) is present, and errors out if it can find neither. Force a choice with --service-init:
revka service --service-init systemd installrevka service --service-init openrc install| Flag | Values | Default | Meaning |
|---|---|---|---|
--service-init | auto, systemd, openrc | auto | Force a specific Linux init system. Pass it before the subcommand. |
Commands
Section titled “Commands”The same subcommands work on every OS:
revka service install # generate and register the unit / plist / taskrevka service start # start the service (rotates logs first)revka service stop # stop the running servicerevka service restart # stop then startrevka service status # report whether the daemon is runningrevka service logs # tail the daemon logs (default: last 50 lines)revka service logs -n 100 --followrevka service uninstall # remove the unit / plist / task| Subcommand | Purpose |
|---|---|
install | Generate the platform artifact, register it, and (systemd) enable it for login start. |
start | Start the service. Rotates daemon logs first if they exceed 20 MB. |
stop | Stop the running service. |
restart | Stop then start. |
status | Report service state. Also checks the 45-second-fresh daemon state file as a fallback. |
logs | Tail daemon logs. -n / --lines <N> sets the line count (default 50); -f / --follow streams new output like tail -f. |
uninstall | Remove the platform artifact. |
Quick start
Section titled “Quick start”-
Install the service. The platform and init system are auto-detected.
Terminal window revka service install -
Start it.
Terminal window revka service start -
Confirm it is healthy. Check the service state and the public health endpoint.
Terminal window revka service statuscurl http://127.0.0.1:42617/health
Per-platform setup
Section titled “Per-platform setup”launchd agent
Section titled “launchd agent”revka service install writes a launchd agent plist to ~/Library/LaunchAgents/com.revka.daemon.plist and loads it with launchctl load -w followed by launchctl start com.revka.daemon. The agent runs revka daemon with RunAtLoad and KeepAlive both true, so it starts at login and is relaunched if it exits.
The generated plist looks like this:
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"><plist version="1.0"><dict> <key>Label</key> <string>com.revka.daemon</string> <key>ProgramArguments</key> <array> <string>/usr/local/bin/revka</string> <string>daemon</string> </array> <key>RunAtLoad</key> <true/> <key>KeepAlive</key> <true/> <key>SoftResourceLimits</key> <dict> <key>NumberOfFiles</key> <integer>4096</integer> </dict> <key>HardResourceLimits</key> <dict> <key>NumberOfFiles</key> <integer>8192</integer> </dict> <key>EnvironmentVariables</key> <dict> <key>PATH</key> <string>/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:...</string> </dict> <key>StandardOutPath</key> <string>/Users/you/.revka/logs/daemon.stdout.log</string> <key>StandardErrorPath</key> <string>/Users/you/.revka/logs/daemon.stderr.log</string></dict></plist>| Key | Value | Why |
|---|---|---|
RunAtLoad / KeepAlive | true | Start at login and relaunch on exit. |
SoftResourceLimits → NumberOfFiles | 4096 | File-descriptor soft cap. launchd defaults to 256, which an agent spawning MCP sidecars exhausts. |
HardResourceLimits → NumberOfFiles | 8192 | Hard ceiling. Operators can ulimit -n up to this at runtime without reinstalling. |
EnvironmentVariables → PATH | curated | An explicit PATH so the daemon can spawn subprocess tools. |
revka service installrevka service startrevka service logs --followHomebrew installs
Section titled “Homebrew installs”If Revka was installed via Homebrew, revka service install detects it automatically and adapts the plist:
- Logs go to
<brew_prefix>/var/revka/logs/instead of~/.revka/logs/. - The plist adds a
REVKA_CONFIG_DIRenvironment key and aWorkingDirectorypointing at the Homebrewvar/revkadirectory, so your config and workspace survivebrew upgrade.
brew services start revka uses the same plist:
brew services start revkaSee macOS update & uninstall for the full Homebrew lifecycle.
systemd user unit
Section titled “systemd user unit”On a systemd host, revka service install writes a user unit to ~/.config/systemd/user/revka.service, then runs systemctl --user daemon-reload and systemctl --user enable revka.service. No root is required.
The generated unit:
[Unit]Description=Revka daemonAfter=network.target
[Service]Type=simpleExecStart=/usr/local/bin/revka daemonRestart=alwaysRestartSec=3Environment=HOME=%hLimitNOFILE=4096:8192Environment="PATH=/home/you/.cargo/bin:/home/you/.local/bin:/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:..."PassEnvironment=DISPLAY XDG_RUNTIME_DIR
[Install]WantedBy=default.target| Directive | Value | Why |
|---|---|---|
Restart / RestartSec | always / 3 | Relaunch the daemon 3 seconds after any exit. |
LimitNOFILE | 4096:8192 | File-descriptor soft:hard limits. systemd user units often default to a 1024 soft cap, which MCP sidecars exhaust. |
Environment="PATH=..." | curated | systemd user services start with a minimal PATH that excludes ~/.cargo/bin and ~/.local/bin; without this, subprocess tool spawns fail with “No such file or directory”. |
PassEnvironment | DISPLAY XDG_RUNTIME_DIR | Inherited from the session so headless browsers work. |
Environment=HOME=%h | user home | So headless browsers can create profile/cache directories. |
revka service installrevka service startrevka service statusrevka service logs -n 100 --followBehind the scenes these map to systemctl --user start|stop|restart|is-active revka.service, and logs runs journalctl --user -u revka.service.
OpenRC init script
Section titled “OpenRC init script”OpenRC is system-wide and root-only. Run the service commands with sudo:
sudo revka service install # auto-detects OpenRC on Alpinesudo rc-update add revka default # enable at bootsudo rc-service revka startinstall writes /etc/init.d/revka, creates a revka:revka system user (Alpine: addgroup -S / adduser -S -s /sbin/nologin; other distros: useradd -r -s /sbin/nologin), sets ownership on /etc/revka/, /var/lib/revka/, and /var/log/revka/, and migrates an existing ~/.revka config into /etc/revka on first install (resolved from $SUDO_USER).
The generated init script:
#!/sbin/openrc-run
name="revka"description="Revka daemon"
command="/usr/local/bin/revka"command_args="--config-dir /etc/revka daemon"command_background="yes"command_user="revka:revka"pidfile="/run/${RC_SVCNAME}.pid"umask 027output_log="/var/log/revka/access.log"error_log="/var/log/revka/error.log"
export HOME="/var/lib/revka"rc_ulimit="-n 4096"export PATH="/usr/local/bin:/usr/bin:/bin:..."
depend() { need net after firewall}
start_pre() { checkpath --directory --owner revka:revka --mode 0750 /var/lib/revka}| Setting | Value | Why |
|---|---|---|
command_user | revka:revka | The daemon runs as an unprivileged system user (UID < 1000, shell /sbin/nologin). |
rc_ulimit | -n 4096 | OpenRC calls ulimit -n before launch so MCP sidecars don’t exhaust the FD cap. Single value — no separate hard cap. |
command_background | yes | OpenRC supervises the backgrounded process via pidfile. |
umask | 027 | Restrictive default permissions on files the daemon writes. |
revka service status / start / stop / restart map to rc-service revka <action>; revka service logs tails /var/log/revka/error.log (falling back to access.log).
Scheduled Task
Section titled “Scheduled Task”On Windows, revka service install registers a Scheduled Task named Revka Daemon via schtasks /SC ONLOGON, so the daemon launches at user logon — no elevation required. A .cmd wrapper script with a snapshotted PATH is placed in the config logs directory and is what the task actually runs.
revka service installrevka service startrevka service statusrevka service logs --followrevka service uninstall| Item | Value |
|---|---|
| Task name | Revka Daemon |
| Trigger | /SC ONLOGON (at user logon) |
| stdout log | <config_dir>\logs\daemon.stdout.log |
| stderr log | <config_dir>\logs\daemon.stderr.log |
| Follow logs | PowerShell Get-Content -Wait |
If the Task Scheduler is unavailable, revka service start falls back to a direct background spawn of revka daemon (detached, no console window) and prints instructions to run revka service install later to enable logon auto-start.
Log rotation
Section titled “Log rotation”Daemon logs (daemon.stdout.log and daemon.stderr.log) are rotated before each revka service start:
- Rotation triggers only when a log file exceeds 20 MB.
- Up to 5 rotated copies are kept, named
daemon.stdout.log.1throughdaemon.stdout.log.5(and likewise for stderr). - The oldest copy is deleted, the rest shift up by one, and the current file becomes
.1.
Logs live in the Homebrew var/revka/logs/ directory when Revka is installed via Homebrew, otherwise in <config_dir>/logs/.
| Constant | Value | Meaning |
|---|---|---|
| Rotation threshold | 20 MB | A log file smaller than this is left untouched. |
| Retained files | 5 | Maximum number of rotated copies kept per stream. |
Verifying and troubleshooting
Section titled “Verifying and troubleshooting”- Liveness.
GET http://127.0.0.1:42617/healthreturns200with pairing status and a component snapshot and needs no auth.revka status --format exit-codeexits0when healthy and1otherwise. Runrevka doctorfor structured diagnostics. - Service won’t start (Windows).
revka service statusconsults the 45-second-fresh daemon state file; if the scheduled task is unavailable, Revka falls back to a direct spawn — re-runrevka service installlater to restore logon auto-start. - systemd service stops after logout. A user unit needs lingering to survive logout:
loginctl enable-linger $USER. - OpenRC install fails on the user check. A pre-existing
revkauser with UID ≥ 1000 or a non-nologinshell is rejected; recreate it with the commands printed in the error. - Daemon can’t find subprocess tools. The launchd plist, systemd unit, and OpenRC script all inject a curated
PATHfor exactly this reason. If you installed Revka or its tools to a non-standard location, reinstall the service after the tools are onPATH. - Restart loops in the logs. A component keeps failing and the daemon supervisor keeps restarting it with growing backoff — see the component supervisor reference.