A familiar service command that wraps runit.
Find a file
2026-03-28 00:30:22 +01:00
completions init 2026-03-27 11:13:36 +01:00
install.sh CLLF LF and sudo fix 2026-03-28 00:30:22 +01:00
LICENSE init 2026-03-27 11:13:36 +01:00
README.md init 2026-03-27 11:13:36 +01:00
service CLLF LF and sudo fix 2026-03-28 00:30:22 +01:00

service — runit wrapper for Void Linux

A familiar service command that wraps runit, giving you a systemd/sysvinit-style interface with automatic dependency resolution and boot-time ordering. No symlinks, no guesswork.

Install

git clone <repo> && cd runit-wrapper
sudo ./install.sh

This installs:

  • /usr/local/bin/service — the main command
  • /etc/service.d/ — dependency configuration (created empty)
  • /etc/sv.d/ — auto-generated boot wrappers (managed by the tool)
  • Bash tab completion

Quick start

service nginx start       # start nginx (and any dependencies)
service nginx stop        # stop nginx
service nginx restart     # restart nginx
service nginx enable      # enable at boot
service nginx disable     # disable at boot
service nginx status      # show status

That's it for 99% of use cases.

Dependency management

Some services need other services to be running first. Instead of figuring out runit's sv check dance, declare dependencies:

# nginx needs dbus running first
service nginx add-dep dbus

# Show the dependency tree
service nginx deps
#  nginx
#  └── dbus (running)

# Remove a dependency
service nginx remove-dep dbus

Dependencies are stored as plain text in /etc/service.d/<name>.dep (one dependency per line). You can edit these files directly if you prefer.

What happens at boot

When you enable a service that has dependencies, the tool generates a thin wrapper in /etc/sv.d/<name>/ that waits for each dependency to come up before starting the real service. The wrapper execs into the original run script so runit supervises the actual process, not the wrapper. Your original service files in /etc/sv/ are never modified.

Services without dependencies are linked directly to /etc/sv/ as usual.

What happens interactively

service <name> start resolves the full dependency tree (topological sort with cycle detection), starts everything in the right order, and waits for each service to be up before continuing.

Virtual targets

Some dependencies aren't runit services — they're system states. These are called virtual targets:

Target Description
network-online Waits until the network has a default route
service myapp add-dep network-online

Boot hooks (oneshot scripts)

Need to run a script once per boot after the network comes up? Create a hook:

service create-hook mysetup --after network-online --exec /root/setup.sh
service mysetup enable

The script runs exactly once per boot. If the machine reboots, it runs again. Hooks are regular runit services under the hood, so service mysetup status and service mysetup logs work as expected.

# Remove a hook (also disables it)
service remove-hook mysetup

List services

service list               # all services
service list --enabled     # only enabled
service list --disabled    # only disabled

Environment variables

Variable Default Description
SERVICE_TIMEOUT 30 Seconds to wait for dependencies

How it maps to runit

This tool What it does under the hood
service X start Resolve deps → sv start each in order
service X stop sv stop X
service X restart sv restart X
service X enable ln -s /etc/sv/X /var/service/X (or wrapper)
service X disable rm /var/service/X + cleanup wrapper
service X status sv status X + dep info
service X logs tail -f /var/log/X/current

File layout

/usr/local/bin/service          Main script
/etc/service.d/
  ├── nginx.dep                 Dependencies (one per line)
  ├── mysetup.dep               Hook dependency
  └── mysetup.hook              Marker file (identifies hooks)
/etc/sv.d/
  └── nginx/
      ├── run                   Generated wrapper (waits for deps, execs real run)
      └── log -> /etc/sv/nginx/log
/etc/sv/                        Original runit service definitions (untouched)
/var/service/                   Active services (symlinks managed by this tool)

Uninstall

sudo rm /usr/local/bin/service
sudo rm -rf /etc/sv.d /etc/service.d
# Bash completion (location may vary):
sudo rm /usr/share/bash-completion/completions/service