Splux Linux

source-based Linux using SPS

SPS · log · files · refs · tags · releases · people · languages · GitHub · commit

bf0ad20


Add SysV init and ship daemon scripts for every PID 1.

Date
Commitbf0ad207776a9a2fcdbe6a696bcc93a68272ebae
GitHubmirror

Parents

Stat

 DESIGN.md                                          |  10 +-
 PACKAGE-MAINTAINER.md                              |  30 +-
 README.md                                          |   3 +-
 bin/mkiso                                          |   4 +-
 bin/setup                                          |  56 ++--
 lib/setup/service.sh                               | 155 +++++++++-
 lib/setup/services                                 |  40 ++-
 lib/setup/sv/dinit/atd                             |   4 +
 lib/setup/sv/dinit/caddy                           |   4 +
 lib/setup/sv/dinit/chronyd                         |   4 +
 lib/setup/sv/dinit/crond                           |   4 +
 lib/setup/sv/dinit/haveged                         |   4 +
 lib/setup/sv/dinit/lxc-net                         |   5 +-
 lib/setup/sv/dinit/nftables                        |   3 +
 lib/setup/sv/dinit/nginx                           |   4 +
 lib/setup/sv/dinit/polkitd                         |   5 +
 lib/setup/sv/dinit/redis                           |   4 +
 lib/setup/sv/dinit/smartd                          |   4 +
 lib/setup/sv/dinit/syncthing                       |   4 +
 lib/setup/sv/dinit/tlp                             |   3 +
 lib/setup/sv/dinit/transmission-daemon             |   4 +
 lib/setup/sv/dinit/udevd                           |   4 +
 lib/setup/sv/dinit/upowerd                         |   5 +
 lib/setup/sv/dinit/wpa_supplicant                  |   5 +
 lib/setup/sv/openrc/NetworkManager                 |   5 +-
 lib/setup/sv/openrc/atd                            |  11 +
 lib/setup/sv/openrc/bluetooth                      |   5 +-
 lib/setup/sv/openrc/caddy                          |  11 +
 lib/setup/sv/openrc/chronyd                        |  11 +
 lib/setup/sv/openrc/crond                          |  11 +
 lib/setup/sv/openrc/cupsd                          |   4 +-
 lib/setup/sv/openrc/dbus                           |   3 +-
 lib/setup/sv/openrc/dhcpcd                         |   3 +-
 lib/setup/sv/openrc/elogind                        |   5 +-
 lib/setup/sv/openrc/haveged                        |  10 +
 lib/setup/sv/openrc/iwd                            |   6 +-
 lib/setup/sv/openrc/nftables                       |   9 +
 lib/setup/sv/openrc/nginx                          |  11 +
 lib/setup/sv/openrc/pipewire                       |   5 +-
 lib/setup/sv/openrc/polkitd                        |  11 +
 lib/setup/sv/openrc/power-profiles-daemon          |   5 +-
 lib/setup/sv/openrc/redis                          |  11 +
 lib/setup/sv/openrc/sddm                           |   5 +-
 lib/setup/sv/openrc/seatd                          |   5 +
 lib/setup/sv/openrc/smartd                         |  11 +
 lib/setup/sv/openrc/sshd                           |   9 +
 lib/setup/sv/openrc/syncthing                      |  15 +
 lib/setup/sv/openrc/tlp                            |  10 +
 lib/setup/sv/openrc/transmission-daemon            |  11 +
 lib/setup/sv/openrc/udevd                          |  10 +
 lib/setup/sv/openrc/upowerd                        |  11 +
 lib/setup/sv/openrc/wireplumber                    |   7 +-
 lib/setup/sv/openrc/wpa_supplicant                 |  11 +
 lib/setup/sv/runit/NetworkManager/run              |   5 -
 lib/setup/sv/runit/atd/run                         |   3 +
 lib/setup/sv/runit/bluetooth/run                   |   5 -
 lib/setup/sv/runit/caddy/run                       |   3 +
 lib/setup/sv/runit/chronyd/run                     |   3 +
 lib/setup/sv/runit/crond/run                       |   3 +
 lib/setup/sv/runit/cupsd/run                       |   5 -
 lib/setup/sv/runit/elogind/run                     |   5 -
 lib/setup/sv/runit/haveged/run                     |   3 +
 lib/setup/sv/runit/iwd/run                         |   5 -
 lib/setup/sv/runit/lxc-net/run                     |   3 +-
 lib/setup/sv/runit/nftables/run                    |   4 +
 lib/setup/sv/runit/nginx/run                       |   3 +
 lib/setup/sv/runit/pipewire/run                    |   5 -
 lib/setup/sv/runit/polkitd/run                     |   3 +
 lib/setup/sv/runit/power-profiles-daemon/run       |   5 -
 lib/setup/sv/runit/redis/run                       |   3 +
 lib/setup/sv/runit/sddm/run                        |   5 -
 lib/setup/sv/runit/smartd/run                      |   3 +
 lib/setup/sv/runit/sshd/run                        |   1 +
 lib/setup/sv/runit/syncthing/run                   |   4 +
 lib/setup/sv/runit/tlp/run                         |   4 +
 lib/setup/sv/runit/transmission-daemon/run         |   3 +
 lib/setup/sv/runit/udevd/run                       |   3 +
 lib/setup/sv/runit/upowerd/run                     |   3 +
 lib/setup/sv/runit/wireplumber/run                 |   5 -
 lib/setup/sv/runit/wpa_supplicant/run              |   3 +
 lib/setup/sv/s6/NetworkManager/run                 |   5 -
 lib/setup/sv/s6/atd/run                            |   3 +
 lib/setup/sv/s6/bluetooth/run                      |   5 -
 lib/setup/sv/s6/caddy/run                          |   3 +
 lib/setup/sv/s6/chronyd/run                        |   3 +
 lib/setup/sv/s6/crond/run                          |   3 +
 lib/setup/sv/s6/cupsd/run                          |   5 -
 lib/setup/sv/s6/elogind/run                        |   5 -
 lib/setup/sv/s6/haveged/run                        |   3 +
 lib/setup/sv/s6/iwd/run                            |   5 -
 lib/setup/sv/s6/lxc-net/run                        |   3 +-
 lib/setup/sv/s6/nftables/run                       |   4 +
 lib/setup/sv/s6/nginx/run                          |   3 +
 lib/setup/sv/s6/pipewire/run                       |   5 -
 lib/setup/sv/s6/polkitd/run                        |   3 +
 lib/setup/sv/s6/power-profiles-daemon/run          |   5 -
 lib/setup/sv/s6/redis/run                          |   3 +
 lib/setup/sv/s6/sddm/run                           |   5 -
 lib/setup/sv/s6/smartd/run                         |   3 +
 lib/setup/sv/s6/sshd/run                           |   1 +
 lib/setup/sv/s6/syncthing/run                      |   4 +
 lib/setup/sv/s6/tlp/run                            |   4 +
 lib/setup/sv/s6/transmission-daemon/run            |   3 +
 lib/setup/sv/s6/udevd/run                          |   3 +
 lib/setup/sv/s6/upowerd/run                        |   3 +
 lib/setup/sv/s6/wireplumber/run                    |   5 -
 lib/setup/sv/s6/wpa_supplicant/run                 |   3 +
 lib/setup/sv/shepherd/atd.scm                      |   9 +
 lib/setup/sv/shepherd/caddy.scm                    |   9 +
 lib/setup/sv/shepherd/chronyd.scm                  |   9 +
 lib/setup/sv/shepherd/crond.scm                    |   9 +
 lib/setup/sv/shepherd/haveged.scm                  |   9 +
 lib/setup/sv/shepherd/nftables.scm                 |   9 +
 lib/setup/sv/shepherd/nginx.scm                    |   9 +
 lib/setup/sv/shepherd/polkitd.scm                  |   9 +
 lib/setup/sv/shepherd/redis.scm                    |   9 +
 lib/setup/sv/shepherd/smartd.scm                   |   9 +
 lib/setup/sv/shepherd/syncthing.scm                |   9 +
 lib/setup/sv/shepherd/tlp.scm                      |   9 +
 lib/setup/sv/shepherd/transmission-daemon.scm      |   9 +
 lib/setup/sv/shepherd/udevd.scm                    |   9 +
 lib/setup/sv/shepherd/upowerd.scm                  |   9 +
 lib/setup/sv/shepherd/wireplumber.scm              |   2 +-
 lib/setup/sv/shepherd/wpa_supplicant.scm           |   9 +
 lib/setup/sv/systemd/NetworkManager.service        |   3 +-
 lib/setup/sv/systemd/atd.service                   |  10 +
 lib/setup/sv/systemd/bluetooth.service             |   3 +-
 lib/setup/sv/systemd/caddy.service                 |  10 +
 lib/setup/sv/systemd/chronyd.service               |  10 +
 lib/setup/sv/systemd/crond.service                 |  10 +
 lib/setup/sv/systemd/cups.service                  |   3 +-
 lib/setup/sv/systemd/dbus.service                  |   1 -
 lib/setup/sv/systemd/dhcpcd.service                |   1 +
 lib/setup/sv/systemd/elogind.service               |   1 -
 lib/setup/sv/systemd/haveged.service               |   9 +
 lib/setup/sv/systemd/iwd.service                   |   3 +-
 lib/setup/sv/systemd/nftables.service              |  10 +
 lib/setup/sv/systemd/nginx.service                 |  10 +
 lib/setup/sv/systemd/pipewire.service              |   3 +-
 lib/setup/sv/systemd/polkit.service                |  10 +
 lib/setup/sv/systemd/power-profiles-daemon.service |   3 +-
 lib/setup/sv/systemd/redis.service                 |  10 +
 lib/setup/sv/systemd/sddm.service                  |   3 +-
 lib/setup/sv/systemd/seatd.service                 |   1 +
 lib/setup/sv/systemd/smartd.service                |  10 +
 lib/setup/sv/systemd/sshd.service                  |   1 +
 lib/setup/sv/systemd/syncthing.service             |  10 +
 lib/setup/sv/systemd/tlp.service                   |  11 +
 lib/setup/sv/systemd/transmission-daemon.service   |  10 +
 lib/setup/sv/systemd/udevd.service                 |   9 +
 lib/setup/sv/systemd/upower.service                |  10 +
 lib/setup/sv/systemd/wireplumber.service           |   5 +-
 lib/setup/sv/systemd/wpa_supplicant.service        |  10 +
 lib/setup/sv/sysvinit/NetworkManager               |  41 +++
 lib/setup/sv/sysvinit/atd                          |  41 +++
 lib/setup/sv/sysvinit/avahi-daemon                 |  41 +++
 lib/setup/sv/sysvinit/bluetooth                    |  41 +++
 lib/setup/sv/sysvinit/caddy                        |  41 +++
 lib/setup/sv/sysvinit/chronyd                      |  41 +++
 lib/setup/sv/sysvinit/conntrackd                   |  41 +++
 lib/setup/sv/sysvinit/crond                        |  41 +++
 lib/setup/sv/sysvinit/cupsd                        |  41 +++
 lib/setup/sv/sysvinit/dbus                         |  42 +++
 lib/setup/sv/sysvinit/dhcpcd                       |  41 +++
 lib/setup/sv/sysvinit/distccd                      |  41 +++
 lib/setup/sv/sysvinit/dnsmasq                      |  41 +++
 lib/setup/sv/sysvinit/dropbear                     |  45 +++
 lib/setup/sv/sysvinit/elogind                      |  41 +++
 lib/setup/sv/sysvinit/fail2ban                     |  41 +++
 lib/setup/sv/sysvinit/haproxy                      |  41 +++
 lib/setup/sv/sysvinit/haveged                      |  41 +++
 lib/setup/sv/sysvinit/iwd                          |  41 +++
 lib/setup/sv/sysvinit/libvirtd                     |  41 +++
 lib/setup/sv/sysvinit/lighttpd                     |  41 +++
 lib/setup/sv/sysvinit/lxc-net                      |  42 +++
 lib/setup/sv/sysvinit/mariadbd                     |  42 +++
 lib/setup/sv/sysvinit/memcached                    |  41 +++
 lib/setup/sv/sysvinit/nfs-server                   |  44 +++
 lib/setup/sv/sysvinit/nftables                     |  42 +++
 lib/setup/sv/sysvinit/nginx                        |  41 +++
 lib/setup/sv/sysvinit/openvpn                      |  41 +++
 lib/setup/sv/sysvinit/pipewire                     |  41 +++
 lib/setup/sv/sysvinit/polkitd                      |  41 +++
 lib/setup/sv/sysvinit/postgresql                   |  42 +++
 lib/setup/sv/sysvinit/power-profiles-daemon        |  41 +++
 lib/setup/sv/sysvinit/redis                        |  41 +++
 lib/setup/sv/sysvinit/sddm                         |  41 +++
 lib/setup/sv/sysvinit/seatd                        |  41 +++
 lib/setup/sv/sysvinit/smartd                       |  41 +++
 lib/setup/sv/sysvinit/sshd                         |  42 +++
 lib/setup/sv/sysvinit/syncthing                    |  42 +++
 lib/setup/sv/sysvinit/tinyproxy                    |  41 +++
 lib/setup/sv/sysvinit/tlp                          |  42 +++
 lib/setup/sv/sysvinit/tor                          |  41 +++
 lib/setup/sv/sysvinit/transmission-daemon          |  41 +++
 lib/setup/sv/sysvinit/udevd                        |  41 +++
 lib/setup/sv/sysvinit/unbound                      |  41 +++
 lib/setup/sv/sysvinit/upowerd                      |  41 +++
 lib/setup/sv/sysvinit/usbmuxd                      |  41 +++
 lib/setup/sv/sysvinit/valkey                       |  41 +++
 lib/setup/sv/sysvinit/wireplumber                  |  41 +++
 lib/setup/sv/sysvinit/wpa_supplicant               |  41 +++
 man/mkiso.1                                        |  19 +-
 man/pkin.1                                         |   3 +-
 man/setup.1                                        |  15 +-
 tests/test_services.sh                             |  20 ++
 tests/test_setup.sh                                |  11 +
 tests/test_stock_services.sh                       |   1 +
 tools/write-stock-services.py                      | 328 ++++++++++++++++++---
 209 files changed, 3318 insertions(+), 249 deletions(-)

Diff

diff --git a/DESIGN.md b/DESIGN.md
index c6ffd14..58485b3 100644
--- a/DESIGN.md
+++ b/DESIGN.md
@@ -89,16 +89,18 @@ Hook entries must be regular files, not symlinks.
 
 `pkin` always attempts to enable a mapped service after a successful
 post-install. The map is `$SPS_LIBDIR/setup/services`. The init name is
-read from `$SPS_ROOT/etc/sps/init`. Supported names are `systemd`,
-`openrc`, `s6`, `runit`, `dinit`, and `shepherd`. When the package did
-not ship a file for that init, a stock script is copied from
+read from `$SPS_ROOT/etc/sps/init`, or inferred from the landed `init-*`
+package or target `/sbin/init`. Supported names are `systemd`,
+`openrc`, `s6`, `runit`, `dinit`, `shepherd`, and `sysvinit`. Daemon
+packages ship a file for every init into the directory that init
+expects. When a file is still missing, a stock script is copied from
 `$SPS_LIBDIR/setup/sv/<init>/` and then enabled. Unknown packages and
 `init` set to `none` are no-ops.
 
 `setup --init` installs the matching `init-*` metapackage, drops
 conflicting PID 1 packages from the plan, writes `/etc/sps/init` and
 `/etc/sps/sps.conf` before the first `sget`, and enables every mapped
-service that is present (or can be filled from stock scripts).
+service that is present (package-shipped scripts, then stock copies).
 
 ## Repository index
 
diff --git a/PACKAGE-MAINTAINER.md b/PACKAGE-MAINTAINER.md
index e451def..3f3f590 100644
--- a/PACKAGE-MAINTAINER.md
+++ b/PACKAGE-MAINTAINER.md
@@ -315,14 +315,25 @@ retained modified protected files and any state created by lifecycle hooks.
 ## Init scripts for daemons
 
 Mapped daemons live in `lib/setup/services`. After `pkin`, SPS enables the
-service for the init named in `/etc/sps/init`. Supported inits are `systemd`,
-`openrc`, `s6`, `runit`, `dinit`, and `shepherd`.
-
-A package should ship a systemd unit under `$PKG/usr/lib/systemd/system` and
-an OpenRC script under `$PKG/etc/init.d` (see `seatd`, `openssh`, and the
-database/network daemons in extra). When the chosen init has no file in the
-package, `pkin` copies a stock script from `lib/setup/sv/<init>/` and then
-enables it. Add a stock file for every supported init whenever you introduce a
+service for the init named in `/etc/sps/init` (or inferred from the
+landed `init-*` package). Supported inits are `systemd`, `openrc`,
+`s6`, `runit`, `dinit`, `shepherd`, and `sysvinit`.
+
+A daemon recipe ships a file for every init into that init's directory:
+
+```text
+$PKG/usr/lib/systemd/system/NAME.service
+$PKG/etc/init.d/NAME
+$PKG/etc/sv/NAME/run
+$PKG/etc/s6/sv/NAME/run
+$PKG/etc/dinit.d/NAME
+$PKG/etc/shepherd.d/NAME.scm
+$PKG/etc/rc.d/init.d/NAME
+```
+
+`pkin` enables only the detected target init. Stock copies in
+`lib/setup/sv/<init>/` fill a gap when an older package omitted a file.
+Add a stock file for every supported init whenever you introduce a
 new daemon:
 
 ```text
@@ -332,10 +343,11 @@ lib/setup/sv/runit/NAME/run
 lib/setup/sv/s6/NAME/run
 lib/setup/sv/dinit/NAME
 lib/setup/sv/shepherd/NAME.scm
+lib/setup/sv/sysvinit/NAME
 ```
 
 `tools/write-stock-services.py` regenerates those stock files from its service
-table and installs the systemd plus OpenRC copies next to extra recipes.
+table and installs copies next to core and extra recipes.
 
 ## Rolling upgrades (`tools/upgrade-recipes`)
 
diff --git a/README.md b/README.md
index 678ce22..d21fdcd 100644
--- a/README.md
+++ b/README.md
@@ -190,8 +190,7 @@ checklist (`--extra`) plus locale and login-shell screens.
 The installer writes hostname, timezone, keymap, and a first user into the
 target, then copies bundled live recipe trees (when present), runs
 `src update`, and `sget install`. Guided partitioning is optional and waits
-until the last confirmation. Choose systemd, OpenRC, s6, runit, dinit, or
-Shepherd as PID 1 (`--init`); those packages conflict. `grub-install` still needs
+until the last confirmation. Choose systemd, OpenRC, s6, runit, dinit, Shepherd, or SysV as PID 1 (`--init`); those packages conflict. `grub-install` still needs
 `--install-bootloader` and `--disk`.
 
 ## SPS Linux live ISO
diff --git a/bin/mkiso b/bin/mkiso
index 57f5c4d..b379a5b 100755
--- a/bin/mkiso
+++ b/bin/mkiso
@@ -185,8 +185,8 @@ case $mkiso_session in
 	*) sps_die "$SPS_EX_USAGE" "session must be tty or plasma" ;;
 esac
 case $mkiso_init in
-	systemd|openrc) ;;
-	*) sps_die "$SPS_EX_USAGE" "init must be systemd or openrc" ;;
+	systemd|openrc|s6|runit|dinit|shepherd|sysvinit) ;;
+	*) sps_die "$SPS_EX_USAGE" "init must be systemd, openrc, s6, runit, dinit, shepherd, or sysvinit" ;;
 esac
 
 mkiso_cleanup()
diff --git a/bin/setup b/bin/setup
index 3574b6e..27758ec 100755
--- a/bin/setup
+++ b/bin/setup
@@ -75,7 +75,7 @@ options:
   --kernel NAME             none, linux, linux-desktop, or custom
   --kernel-config FILE      .config for --kernel custom
   --drivers auto|none       map lspci/cpu to packages (microcode, nouveau, iwd)
-  --init systemd|openrc|s6|runit|dinit|shepherd|none
+  --init systemd|openrc|s6|runit|dinit|shepherd|sysvinit|none
                             PID 1 on the installed system (default: none in
                             scripts; live /etc/sps/init or systemd on the
                             interactive screen)
@@ -115,42 +115,49 @@ setup_pkg_conflicts_init()
 	case $setup_ci in
 		systemd)
 			case $setup_cp in
-				elogind|eudev|openrc|init-openrc|s6|s6-linux-init|init-s6|runit|init-runit|dinit|init-dinit|shepherd|init-shepherd)
+				elogind|eudev|openrc|init-openrc|s6|s6-linux-init|init-s6|runit|init-runit|dinit|init-dinit|shepherd|init-shepherd|sysvinit|init-sysvinit)
 					return 0
 					;;
 			esac
 			;;
 		openrc)
 			case $setup_cp in
-				systemd|init-systemd|s6|s6-linux-init|init-s6|runit|init-runit|dinit|init-dinit|shepherd|init-shepherd)
+				systemd|init-systemd|s6|s6-linux-init|init-s6|runit|init-runit|dinit|init-dinit|shepherd|init-shepherd|sysvinit|init-sysvinit)
 					return 0
 					;;
 			esac
 			;;
 		s6)
 			case $setup_cp in
-				systemd|init-systemd|openrc|init-openrc|runit|init-runit|dinit|init-dinit|shepherd|init-shepherd)
+				systemd|init-systemd|openrc|init-openrc|runit|init-runit|dinit|init-dinit|shepherd|init-shepherd|sysvinit|init-sysvinit)
 					return 0
 					;;
 			esac
 			;;
 		runit)
 			case $setup_cp in
-				systemd|init-systemd|openrc|init-openrc|s6|s6-linux-init|init-s6|dinit|init-dinit|shepherd|init-shepherd)
+				systemd|init-systemd|openrc|init-openrc|s6|s6-linux-init|init-s6|dinit|init-dinit|shepherd|init-shepherd|sysvinit|init-sysvinit)
 					return 0
 					;;
 			esac
 			;;
 		dinit)
 			case $setup_cp in
-				systemd|init-systemd|openrc|init-openrc|s6|s6-linux-init|init-s6|runit|init-runit|shepherd|init-shepherd)
+				systemd|init-systemd|openrc|init-openrc|s6|s6-linux-init|init-s6|runit|init-runit|shepherd|init-shepherd|sysvinit|init-sysvinit)
 					return 0
 					;;
 			esac
 			;;
 		shepherd)
 			case $setup_cp in
-				systemd|init-systemd|openrc|init-openrc|s6|s6-linux-init|init-s6|runit|init-runit|dinit|init-dinit)
+				systemd|init-systemd|openrc|init-openrc|s6|s6-linux-init|init-s6|runit|init-runit|dinit|init-dinit|sysvinit|init-sysvinit)
+					return 0
+					;;
+			esac
+			;;
+		sysvinit)
+			case $setup_cp in
+				systemd|init-systemd|openrc|init-openrc|s6|s6-linux-init|init-s6|runit|init-runit|dinit|init-dinit|shepherd|init-shepherd)
 					return 0
 					;;
 			esac
@@ -1022,20 +1029,21 @@ setup_ask_init()
 	if [ -f /etc/sps/init ]; then
 		setup_live_init=$(sed -n '1p' /etc/sps/init)
 		case $setup_live_init in
-			systemd|openrc|s6|runit|dinit|shepherd)
+			systemd|openrc|s6|runit|dinit|shepherd|sysvinit)
 				setup_init_default=$setup_live_init
 				;;
 		esac
 	fi
 	setup_init=$(setup_dialog --title "Init system" --default-item "$setup_init_default" \
-		--menu "PID 1 on the installed system. These packages conflict; sget will refuse more than one. Supervision inits (s6, runit, dinit, Shepherd) pull eudev and elogind the same way OpenRC does. setup copies stock service scripts for the chosen init when a package did not ship its own." \
-		20 76 8 \
+		--menu "PID 1 on the installed system. These packages conflict; sget will refuse more than one. Non-systemd inits pull eudev and elogind. Daemon packages ship scripts for every init into the right directories; setup enables the detected init." \
+		22 76 9 \
 		systemd "systemd (udev, logind, the default)" \
 		openrc "OpenRC plus eudev and elogind" \
 		s6 "s6 plus eudev and elogind" \
 		runit "runit plus eudev and elogind" \
 		dinit "dinit plus eudev and elogind" \
-		shepherd "GNU Shepherd plus eudev, elogind, and Guile") ||
+		shepherd "GNU Shepherd plus eudev, elogind, and Guile" \
+		sysvinit "SysV init plus eudev and elogind") ||
 		setup_fail "$SPS_EX_USAGE" "cancelled"
 }
 
@@ -1360,8 +1368,8 @@ case $setup_drivers in
 	*) setup_fail "$SPS_EX_USAGE" "drivers must be auto or none" ;;
 esac
 case $setup_init in
-	none|systemd|openrc|s6|runit|dinit|shepherd) ;;
-	*) setup_fail "$SPS_EX_USAGE" "init must be systemd, openrc, s6, runit, dinit, shepherd, or none" ;;
+	none|systemd|openrc|s6|runit|dinit|shepherd|sysvinit) ;;
+	*) setup_fail "$SPS_EX_USAGE" "init must be systemd, openrc, s6, runit, dinit, shepherd, sysvinit, or none" ;;
 esac
 case $setup_services in
 	yes|no) ;;
@@ -1556,6 +1564,7 @@ case $setup_init in
 	runit) setup_add_pkg init-runit ;;
 	dinit) setup_add_pkg init-dinit ;;
 	shepherd) setup_add_pkg init-shepherd ;;
+	sysvinit) setup_add_pkg init-sysvinit ;;
 esac
 
 if [ "$setup_drivers" = auto ]; then
@@ -1651,7 +1660,7 @@ setup_summary()
 	if [ "$setup_init" = none ] &&
 	   grep -Eq '^(sddm|plasma-desktop|plasma-full)$' "$setup_pkg_file"
 	then
-		printf '\nNote: init is none; SDDM/Plasma will not start at boot. Choose systemd, OpenRC, s6, runit, dinit, or Shepherd.\n'
+		printf '\nNote: init is none; SDDM/Plasma will not start at boot. Choose systemd, OpenRC, s6, runit, dinit, Shepherd, or SysV.\n'
 	fi
 	if [ "$setup_kernel" = none ]; then
 		case $setup_partition in
@@ -1853,13 +1862,17 @@ After the packages land:
             they do not collide with busybox.
   shepherd  PID 1 is GNU Shepherd. Services are Scheme files in
             /etc/shepherd.d. This pulls Guile and Fibers.
+  sysvinit  PID 1 is /sbin/init. Boot scripts live in /etc/rc.d.
+            Enable with a symlink in /etc/rc.d/rc3.d (and friends).
+            eudev and elogind come with init-sysvinit.
   none      no init package was requested. Busybox can still provide
             an init applet if you copy it to /sbin/init yourself.
 
-setup copies stock service scripts for the chosen init when a package
-did not ship one, then enables known services (SDDM, dbus, sshd,
-NetworkManager, ...). See /root/sps-services.txt. Pass --services no
-to skip that. Later sget install of a mapped package enables it too.
+setup enables known services for the init recorded in /etc/sps/init
+(and the landed init-* package). Daemon packages ship scripts for
+every init into the directories that init expects. Pass --services no
+to skip enablement. Later sget install of a mapped package enables
+it too.
 EOF
 
 	cat >"$setup_root/root/sps-network.txt" <<EOF
@@ -2094,7 +2107,7 @@ if [ "$setup_services" = yes ] &&
    command -v setup_service_enable_present >/dev/null 2>&1
 then
 	case $setup_init in
-		systemd|openrc|s6|runit|dinit|shepherd)
+		systemd|openrc|s6|runit|dinit|shepherd|sysvinit)
 			printf '%s: enabling services after user configuration, init %s\n' \
 				"$sps_prog" "$setup_init" >&2
 			setup_svc_list=$(setup_service_enable_present \
@@ -2103,7 +2116,8 @@ then
 				printf '%s\n' \
 					"Init: $setup_init" \
 					"setup enables known services that were installed." \
-					"Missing unit/script files are filled from stock copies" \
+					"Daemon packages already contain scripts for this init." \
+					"Missing files are filled from stock copies" \
 					"in $SPS_LIBDIR/setup/sv/$setup_init." \
 					"It does not start daemons inside a target chroot." \
 					""
@@ -2122,7 +2136,7 @@ then
 Init is ${setup_init:-none}. setup did not enable services.
 
 To have SDDM, sshd, NetworkManager, and similar start at boot, rerun
-setup with --init systemd, openrc, s6, runit, dinit, or shepherd, or
+setup with --init systemd, openrc, s6, runit, dinit, shepherd, or sysvinit, or
 enable them yourself.
 EOF
 			;;
diff --git a/lib/setup/service.sh b/lib/setup/service.sh
index 15d6210..86089e8 100644
--- a/lib/setup/service.sh
+++ b/lib/setup/service.sh
@@ -9,7 +9,15 @@
 
 setup_service_known_inits()
 {
-	printf '%s\n' systemd openrc s6 runit dinit shepherd
+	printf '%s\n' systemd openrc s6 runit dinit shepherd sysvinit
+}
+
+setup_service_is_known_init()
+{
+	case $1 in
+		systemd|openrc|s6|runit|dinit|shepherd|sysvinit) return 0 ;;
+	esac
+	return 1
 }
 
 setup_service_map_file()
@@ -87,16 +95,69 @@ setup_service_abs()
 	fi
 }
 
-setup_service_init_of()
+setup_service_set_init()
 {
+	# Init name from a landed init-* metapackage in the target.
 	setup_svc_root=$(setup_service_root "$1")
 	if [ -z "$setup_svc_root" ]; then
-		setup_svc_initf=/etc/sps/init
+		setup_svc_setdir=/usr/share/sps/sets
 	else
-		setup_svc_initf=$setup_svc_root/etc/sps/init
+		setup_svc_setdir=$setup_svc_root/usr/share/sps/sets
 	fi
+	[ -d "$setup_svc_setdir" ] || return 1
+	setup_svc_found=
+	setup_svc_n=0
+	for setup_svc_name in systemd openrc s6 runit dinit shepherd sysvinit
+	do
+		[ -f "$setup_svc_setdir/init-$setup_svc_name" ] || continue
+		setup_svc_n=$((setup_svc_n + 1))
+		setup_svc_found=$setup_svc_name
+	done
+	[ "$setup_svc_n" -eq 1 ] || return 1
+	printf '%s\n' "$setup_svc_found"
+}
+
+setup_service_init_from_sbin()
+{
+	# Target /sbin/init only. Busybox live PID 1 is not a choice.
+	setup_svc_initbin=$(setup_service_abs "$1" /sbin/init)
+	[ -e "$setup_svc_initbin" ] || return 1
+	setup_svc_real=$(readlink -f "$setup_svc_initbin" 2>/dev/null) ||
+		setup_svc_real=$setup_svc_initbin
+	case $setup_svc_real in
+		*systemd*) printf '%s\n' systemd; return 0 ;;
+		*openrc*) printf '%s\n' openrc; return 0 ;;
+		*runit*) printf '%s\n' runit; return 0 ;;
+		*s6*) printf '%s\n' s6; return 0 ;;
+		*dinit*) printf '%s\n' dinit; return 0 ;;
+		*shepherd*) printf '%s\n' shepherd; return 0 ;;
+		*busybox*) return 1 ;;
+	esac
+	printf '%s\n' sysvinit
+	return 0
+}
+
+setup_service_init_of()
+{
+	# Target init. Never use host PID 1 when SPS_ROOT is a disk.
+	setup_svc_pkg_init=$(setup_service_set_init "$1") || setup_svc_pkg_init=
+	if [ -n "$setup_svc_pkg_init" ]; then
+		printf '%s\n' "$setup_svc_pkg_init"
+		return 0
+	fi
+	setup_svc_initf=$(setup_service_abs "$1" /etc/sps/init)
+	setup_svc_file_init=
 	if [ -f "$setup_svc_initf" ]; then
-		sed -n '1p' "$setup_svc_initf"
+		setup_svc_file_init=$(sed -n '1p' "$setup_svc_initf")
+	fi
+	if setup_service_is_known_init "$setup_svc_file_init"; then
+		printf '%s\n' "$setup_svc_file_init"
+		return 0
+	fi
+	setup_svc_bin_init=$(setup_service_init_from_sbin "$1") ||
+		setup_svc_bin_init=
+	if [ -n "$setup_svc_bin_init" ]; then
+		printf '%s\n' "$setup_svc_bin_init"
 		return 0
 	fi
 	printf '%s\n' none
@@ -221,6 +282,12 @@ setup_service_ensure_scripts()
 					"/etc/shepherd.d/$setup_svc_name.scm")" \
 				644 "$setup_svc_stock/$setup_svc_name.scm" || :
 			;;
+		sysvinit)
+			setup_service_copy_file \
+				"$(setup_service_abs "$setup_svc_root" \
+					"/etc/rc.d/init.d/$setup_svc_name")" \
+				755 "$setup_svc_stock/$setup_svc_name" || :
+			;;
 	esac
 	return 0
 }
@@ -331,6 +398,45 @@ setup_service_enable_shepherd()
 	return 0
 }
 
+setup_service_enable_sysvinit()
+{
+	setup_svc_rc=$2
+	setup_svc_level=${3:-default}
+	[ -n "$setup_svc_rc" ] || return 1
+	setup_svc_script=$(setup_service_abs "$1" \
+		"/etc/rc.d/init.d/$setup_svc_rc")
+	setup_svc_rel=/etc/rc.d/init.d/$setup_svc_rc
+	if [ ! -f "$setup_svc_script" ]; then
+		setup_svc_script=$(setup_service_abs "$1" \
+			"/etc/init.d/$setup_svc_rc")
+		setup_svc_rel=/etc/init.d/$setup_svc_rc
+	fi
+	[ -f "$setup_svc_script" ] || return 1
+	setup_svc_prio=50
+	if [ "$setup_svc_rc" = sddm ]; then
+		setup_svc_prio=80
+	fi
+	if [ "$setup_svc_level" = sysinit ]; then
+		setup_svc_d=$(setup_service_abs "$1" /etc/rc.d/rcS.d)
+		mkdir -p "$setup_svc_d" || return 1
+		ln -sf "$setup_svc_rel" "$setup_svc_d/S20$setup_svc_rc"
+		return 0
+	fi
+	for setup_svc_rl in 2 3 4 5; do
+		setup_svc_d=$(setup_service_abs "$1" /etc/rc.d/rc${setup_svc_rl}.d)
+		mkdir -p "$setup_svc_d" || return 1
+		ln -sf "$setup_svc_rel" \
+			"$setup_svc_d/S${setup_svc_prio}$setup_svc_rc"
+	done
+	for setup_svc_rl in 0 1 6; do
+		setup_svc_d=$(setup_service_abs "$1" /etc/rc.d/rc${setup_svc_rl}.d)
+		mkdir -p "$setup_svc_d" || return 1
+		ln -sf "$setup_svc_rel" \
+			"$setup_svc_d/K${setup_svc_prio}$setup_svc_rc"
+	done
+	return 0
+}
+
 setup_service_is_live_root()
 {
 	setup_svc_root=$(setup_service_root "$1")
@@ -364,6 +470,23 @@ setup_service_pid1()
 		s6-svscan|s6-linux-init*) printf '%s\n' s6; return 0 ;;
 		dinit) printf '%s\n' dinit; return 0 ;;
 		shepherd) printf '%s\n' shepherd; return 0 ;;
+		init)
+			if [ -r /proc/1/exe ]; then
+				setup_svc_exe=$(readlink -f /proc/1/exe 2>/dev/null) ||
+					setup_svc_exe=
+				case $setup_svc_exe in
+					*systemd*) printf '%s\n' systemd; return 0 ;;
+					*busybox*) ;;
+					*)
+						if [ -e /run/initctl ] || [ -p /dev/initctl ]
+						then
+							printf '%s\n' sysvinit
+							return 0
+						fi
+						;;
+				esac
+			fi
+			;;
 	esac
 	case $setup_svc_cmd in
 		*systemd*) printf '%s\n' systemd; return 0 ;;
@@ -373,6 +496,10 @@ setup_service_pid1()
 		*dinit*) printf '%s\n' dinit; return 0 ;;
 		*shepherd*) printf '%s\n' shepherd; return 0 ;;
 	esac
+	if [ -e /run/initctl ] || [ -p /dev/initctl ]; then
+		printf '%s\n' sysvinit
+		return 0
+	fi
 	if [ -d /run/runit ]; then
 		printf '%s\n' runit
 		return 0
@@ -440,6 +567,14 @@ setup_service_maybe_start()
 				herd start "$setup_svc_rc" 2>/dev/null || :
 			fi
 			;;
+		sysvinit)
+			[ -n "$setup_svc_rc" ] || return 0
+			if [ -x /etc/rc.d/init.d/"$setup_svc_rc" ]; then
+				/etc/rc.d/init.d/"$setup_svc_rc" start 2>/dev/null || :
+			elif [ -x /etc/init.d/"$setup_svc_rc" ]; then
+				/etc/init.d/"$setup_svc_rc" start 2>/dev/null || :
+			fi
+			;;
 	esac
 	return 0
 }
@@ -512,6 +647,14 @@ setup_service_enable_one()
 				setup_svc_did=1
 			fi
 			;;
+		sysvinit)
+			if [ -n "$setup_svc_rc" ] &&
+			   setup_service_enable_sysvinit "$setup_svc_root" \
+				"$setup_svc_rc" "$setup_svc_level"
+			then
+				setup_svc_did=1
+			fi
+			;;
 		*)
 			return 1
 			;;
@@ -555,7 +698,7 @@ setup_service_hook_enable()
 	setup_svc_root=${SPS_ROOT:-/}
 	setup_svc_init=$(setup_service_init_of "$setup_svc_root")
 	case $setup_svc_init in
-		systemd|openrc|s6|runit|dinit|shepherd) ;;
+		systemd|openrc|s6|runit|dinit|shepherd|sysvinit) ;;
 		*) return 0 ;;
 	esac
 	setup_service_enable_one "$setup_svc_root" "$setup_svc_init" \
diff --git a/lib/setup/services b/lib/setup/services
index 019e8c1..bc86c41 100644
--- a/lib/setup/services
+++ b/lib/setup/services
@@ -1,22 +1,48 @@
-# package  systemd-unit  wanted-by  openrc-name  openrc-runlevel
-# "-" means this init has no file for that package.
+# package  systemd-unit  wanted-by  rc-name  runlevel
+# Scripts for every init live in lib/setup/sv and are also shipped
+# in the daemon recipe (systemd, OpenRC, runit, s6, dinit,
+# Shepherd, SysV). pkin enables the detected target init.
 dbus	dbus.service	multi-user.target	dbus	sysinit
+eudev	udevd.service	sysinit.target	udevd	sysinit
+udevd	udevd.service	sysinit.target	udevd	sysinit
+elogind	elogind.service	multi-user.target	elogind	sysinit
 sddm	sddm.service	graphical.target	sddm	default
 networkmanager	NetworkManager.service	multi-user.target	NetworkManager	default
+NetworkManager	NetworkManager.service	multi-user.target	NetworkManager	default
 openssh	sshd.service	multi-user.target	sshd	default
+sshd	sshd.service	multi-user.target	sshd	default
 cups	cups.service	multi-user.target	cupsd	default
+cupsd	cups.service	multi-user.target	cupsd	default
 bluez	bluetooth.service	multi-user.target	bluetooth	default
+bluetooth	bluetooth.service	multi-user.target	bluetooth	default
 iwd	iwd.service	multi-user.target	iwd	default
 dhcpcd	dhcpcd.service	multi-user.target	dhcpcd	default
 seatd	seatd.service	multi-user.target	seatd	default
-elogind	elogind.service	multi-user.target	elogind	sysinit
 power-profiles-daemon	power-profiles-daemon.service	multi-user.target	power-profiles-daemon	default
-bluetooth	bluetooth.service	multi-user.target	bluetooth	default
-sshd	sshd.service	multi-user.target	sshd	default
-cupsd	cups.service	multi-user.target	cupsd	default
-NetworkManager	NetworkManager.service	multi-user.target	NetworkManager	default
 pipewire	pipewire.service	default.target	pipewire	default
 wireplumber	wireplumber.service	default.target	wireplumber	default
+polkit	polkit.service	multi-user.target	polkitd	sysinit
+polkitd	polkit.service	multi-user.target	polkitd	sysinit
+cronie	crond.service	multi-user.target	crond	default
+crond	crond.service	multi-user.target	crond	default
+at	atd.service	multi-user.target	atd	default
+atd	atd.service	multi-user.target	atd	default
+chrony	chronyd.service	multi-user.target	chronyd	default
+chronyd	chronyd.service	multi-user.target	chronyd	default
+haveged	haveged.service	multi-user.target	haveged	sysinit
+nginx	nginx.service	multi-user.target	nginx	default
+caddy	caddy.service	multi-user.target	caddy	default
+redis	redis.service	multi-user.target	redis	default
+syncthing	syncthing.service	multi-user.target	syncthing	default
+wpa_supplicant	wpa_supplicant.service	multi-user.target	wpa_supplicant	default
+tlp	tlp.service	multi-user.target	tlp	default
+smartmontools	smartd.service	multi-user.target	smartd	default
+smartd	smartd.service	multi-user.target	smartd	default
+upower	upower.service	multi-user.target	upowerd	default
+upowerd	upower.service	multi-user.target	upowerd	default
+transmission	transmission-daemon.service	multi-user.target	transmission-daemon	default
+transmission-daemon	transmission-daemon.service	multi-user.target	transmission-daemon	default
+nftables	nftables.service	multi-user.target	nftables	sysinit
 fail2ban	fail2ban.service	multi-user.target	fail2ban	default
 unbound	unbound.service	multi-user.target	unbound	default
 dnsmasq	dnsmasq.service	multi-user.target	dnsmasq	default
diff --git a/lib/setup/sv/dinit/atd b/lib/setup/sv/dinit/atd
new file mode 100644
index 0000000..6d93753
--- /dev/null
+++ b/lib/setup/sv/dinit/atd
@@ -0,0 +1,4 @@
+type = process
+command = /usr/sbin/atd -f
+restart = true
+smooth-recovery = true
diff --git a/lib/setup/sv/dinit/caddy b/lib/setup/sv/dinit/caddy
new file mode 100644
index 0000000..8a3477d
--- /dev/null
+++ b/lib/setup/sv/dinit/caddy
@@ -0,0 +1,4 @@
+type = process
+command = /usr/bin/caddy run
+restart = true
+smooth-recovery = true
diff --git a/lib/setup/sv/dinit/chronyd b/lib/setup/sv/dinit/chronyd
new file mode 100644
index 0000000..682515a
--- /dev/null
+++ b/lib/setup/sv/dinit/chronyd
@@ -0,0 +1,4 @@
+type = process
+command = /usr/sbin/chronyd -d
+restart = true
+smooth-recovery = true
diff --git a/lib/setup/sv/dinit/crond b/lib/setup/sv/dinit/crond
new file mode 100644
index 0000000..6db86a0
--- /dev/null
+++ b/lib/setup/sv/dinit/crond
@@ -0,0 +1,4 @@
+type = process
+command = /usr/sbin/crond -n
+restart = true
+smooth-recovery = true
diff --git a/lib/setup/sv/dinit/haveged b/lib/setup/sv/dinit/haveged
new file mode 100644
index 0000000..105f1b2
--- /dev/null
+++ b/lib/setup/sv/dinit/haveged
@@ -0,0 +1,4 @@
+type = process
+command = /usr/sbin/haveged -w 1024 -F
+restart = true
+smooth-recovery = true
diff --git a/lib/setup/sv/dinit/lxc-net b/lib/setup/sv/dinit/lxc-net
index 828b4bb..0d49861 100644
--- a/lib/setup/sv/dinit/lxc-net
+++ b/lib/setup/sv/dinit/lxc-net
@@ -1,4 +1,3 @@
-type = process
+type = script
 command = /usr/libexec/lxc/lxc-net start
-restart = true
-smooth-recovery = true
+restart = false
diff --git a/lib/setup/sv/dinit/nftables b/lib/setup/sv/dinit/nftables
new file mode 100644
index 0000000..d7bfc04
--- /dev/null
+++ b/lib/setup/sv/dinit/nftables
@@ -0,0 +1,3 @@
+type = script
+command = /usr/sbin/nft -f /etc/nftables.conf
+restart = false
diff --git a/lib/setup/sv/dinit/nginx b/lib/setup/sv/dinit/nginx
new file mode 100644
index 0000000..df86469
--- /dev/null
+++ b/lib/setup/sv/dinit/nginx
@@ -0,0 +1,4 @@
+type = process
+command = /usr/bin/nginx -g 'daemon off;'
+restart = true
+smooth-recovery = true
diff --git a/lib/setup/sv/dinit/polkitd b/lib/setup/sv/dinit/polkitd
new file mode 100644
index 0000000..1522fdc
--- /dev/null
+++ b/lib/setup/sv/dinit/polkitd
@@ -0,0 +1,5 @@
+type = process
+command = /usr/libexec/polkitd --no-debug
+restart = true
+smooth-recovery = true
+depends-on = dbus
diff --git a/lib/setup/sv/dinit/redis b/lib/setup/sv/dinit/redis
new file mode 100644
index 0000000..e25456e
--- /dev/null
+++ b/lib/setup/sv/dinit/redis
@@ -0,0 +1,4 @@
+type = process
+command = /usr/bin/redis-server --daemonize no
+restart = true
+smooth-recovery = true
diff --git a/lib/setup/sv/dinit/smartd b/lib/setup/sv/dinit/smartd
new file mode 100644
index 0000000..8da7542
--- /dev/null
+++ b/lib/setup/sv/dinit/smartd
@@ -0,0 +1,4 @@
+type = process
+command = /usr/sbin/smartd -n
+restart = true
+smooth-recovery = true
diff --git a/lib/setup/sv/dinit/syncthing b/lib/setup/sv/dinit/syncthing
new file mode 100644
index 0000000..f11678b
--- /dev/null
+++ b/lib/setup/sv/dinit/syncthing
@@ -0,0 +1,4 @@
+type = process
+command = /usr/bin/syncthing serve --no-browser --home=/var/lib/syncthing
+restart = true
+smooth-recovery = true
diff --git a/lib/setup/sv/dinit/tlp b/lib/setup/sv/dinit/tlp
new file mode 100644
index 0000000..e21f26e
--- /dev/null
+++ b/lib/setup/sv/dinit/tlp
@@ -0,0 +1,3 @@
+type = script
+command = /usr/sbin/tlp init start
+restart = false
diff --git a/lib/setup/sv/dinit/transmission-daemon b/lib/setup/sv/dinit/transmission-daemon
new file mode 100644
index 0000000..d80b539
--- /dev/null
+++ b/lib/setup/sv/dinit/transmission-daemon
@@ -0,0 +1,4 @@
+type = process
+command = /usr/bin/transmission-daemon -f --log-level=error
+restart = true
+smooth-recovery = true
diff --git a/lib/setup/sv/dinit/udevd b/lib/setup/sv/dinit/udevd
new file mode 100644
index 0000000..df837e9
--- /dev/null
+++ b/lib/setup/sv/dinit/udevd
@@ -0,0 +1,4 @@
+type = process
+command = /usr/sbin/udevd
+restart = true
+smooth-recovery = true
diff --git a/lib/setup/sv/dinit/upowerd b/lib/setup/sv/dinit/upowerd
new file mode 100644
index 0000000..473d6e4
--- /dev/null
+++ b/lib/setup/sv/dinit/upowerd
@@ -0,0 +1,5 @@
+type = process
+command = /usr/libexec/upowerd
+restart = true
+smooth-recovery = true
+depends-on = dbus
diff --git a/lib/setup/sv/dinit/wpa_supplicant b/lib/setup/sv/dinit/wpa_supplicant
new file mode 100644
index 0000000..cd8aca6
--- /dev/null
+++ b/lib/setup/sv/dinit/wpa_supplicant
@@ -0,0 +1,5 @@
+type = process
+command = /usr/sbin/wpa_supplicant -u -s
+restart = true
+smooth-recovery = true
+depends-on = dbus
diff --git a/lib/setup/sv/openrc/NetworkManager b/lib/setup/sv/openrc/NetworkManager
index f0a0c00..caf5676 100755
--- a/lib/setup/sv/openrc/NetworkManager
+++ b/lib/setup/sv/openrc/NetworkManager
@@ -6,7 +6,6 @@ command_background="yes"
 pidfile="/run/NetworkManager.pid"
 
 depend() {
-	need dbus
-	after dbus
-	provide net
+    need dbus
+    after dbus
 }
diff --git a/lib/setup/sv/openrc/atd b/lib/setup/sv/openrc/atd
new file mode 100755
index 0000000..f51cc9e
--- /dev/null
+++ b/lib/setup/sv/openrc/atd
@@ -0,0 +1,11 @@
+#!/sbin/openrc-run
+description="at job scheduler"
+command="/usr/sbin/atd"
+command_args="-f"
+command_background="yes"
+pidfile="/run/atd.pid"
+
+depend() {
+    use net
+    after net
+}
diff --git a/lib/setup/sv/openrc/bluetooth b/lib/setup/sv/openrc/bluetooth
index 5c3c0d1..0bfaf1f 100755
--- a/lib/setup/sv/openrc/bluetooth
+++ b/lib/setup/sv/openrc/bluetooth
@@ -1,10 +1,11 @@
 #!/sbin/openrc-run
 description="Bluetooth daemon"
 command="/usr/libexec/bluetooth/bluetoothd"
+command_args=""
 command_background="yes"
 pidfile="/run/bluetooth.pid"
 
 depend() {
-	need dbus
-	after dbus
+    need dbus
+    after dbus
 }
diff --git a/lib/setup/sv/openrc/caddy b/lib/setup/sv/openrc/caddy
new file mode 100755
index 0000000..3950f0d
--- /dev/null
+++ b/lib/setup/sv/openrc/caddy
@@ -0,0 +1,11 @@
+#!/sbin/openrc-run
+description="Caddy HTTP server"
+command="/usr/bin/caddy"
+command_args="run"
+command_background="yes"
+pidfile="/run/caddy.pid"
+
+depend() {
+    use net
+    after net
+}
diff --git a/lib/setup/sv/openrc/chronyd b/lib/setup/sv/openrc/chronyd
new file mode 100755
index 0000000..2103908
--- /dev/null
+++ b/lib/setup/sv/openrc/chronyd
@@ -0,0 +1,11 @@
+#!/sbin/openrc-run
+description="chrony NTP daemon"
+command="/usr/sbin/chronyd"
+command_args="-d"
+command_background="yes"
+pidfile="/run/chronyd.pid"
+
+depend() {
+    use net
+    after net
+}
diff --git a/lib/setup/sv/openrc/crond b/lib/setup/sv/openrc/crond
new file mode 100755
index 0000000..318d069
--- /dev/null
+++ b/lib/setup/sv/openrc/crond
@@ -0,0 +1,11 @@
+#!/sbin/openrc-run
+description="cron daemon"
+command="/usr/sbin/crond"
+command_args="-n"
+command_background="yes"
+pidfile="/run/crond.pid"
+
+depend() {
+    use net
+    after net
+}
diff --git a/lib/setup/sv/openrc/cupsd b/lib/setup/sv/openrc/cupsd
index e2566df..d04e17c 100755
--- a/lib/setup/sv/openrc/cupsd
+++ b/lib/setup/sv/openrc/cupsd
@@ -6,6 +6,6 @@ command_background="yes"
 pidfile="/run/cupsd.pid"
 
 depend() {
-	need dbus
-	after dbus
+    need dbus
+    after dbus
 }
diff --git a/lib/setup/sv/openrc/dbus b/lib/setup/sv/openrc/dbus
index f67ebfe..8ef95c5 100755
--- a/lib/setup/sv/openrc/dbus
+++ b/lib/setup/sv/openrc/dbus
@@ -6,8 +6,7 @@ command_background="yes"
 pidfile="/run/dbus.pid"
 
 depend() {
-	need localmount
-	provide dbus
+    need localmount
 }
 
 start_pre() {
diff --git a/lib/setup/sv/openrc/dhcpcd b/lib/setup/sv/openrc/dhcpcd
index cec1604..04473c5 100755
--- a/lib/setup/sv/openrc/dhcpcd
+++ b/lib/setup/sv/openrc/dhcpcd
@@ -6,5 +6,6 @@ command_background="yes"
 pidfile="/run/dhcpcd.pid"
 
 depend() {
-	provide net
+    use net
+    after net
 }
diff --git a/lib/setup/sv/openrc/elogind b/lib/setup/sv/openrc/elogind
index 089d9c1..aaa6572 100755
--- a/lib/setup/sv/openrc/elogind
+++ b/lib/setup/sv/openrc/elogind
@@ -1,10 +1,11 @@
 #!/sbin/openrc-run
 description="elogind login manager"
 command="/usr/libexec/elogind"
+command_args=""
 command_background="yes"
 pidfile="/run/elogind.pid"
 
 depend() {
-	need dbus
-	after dbus
+    need dbus
+    after dbus
 }
diff --git a/lib/setup/sv/openrc/haveged b/lib/setup/sv/openrc/haveged
new file mode 100755
index 0000000..28b0126
--- /dev/null
+++ b/lib/setup/sv/openrc/haveged
@@ -0,0 +1,10 @@
+#!/sbin/openrc-run
+description="haveged entropy daemon"
+command="/usr/sbin/haveged"
+command_args="-w 1024 -F"
+command_background="yes"
+pidfile="/run/haveged.pid"
+
+depend() {
+    need localmount
+}
diff --git a/lib/setup/sv/openrc/iwd b/lib/setup/sv/openrc/iwd
index b7bb685..81ff150 100755
--- a/lib/setup/sv/openrc/iwd
+++ b/lib/setup/sv/openrc/iwd
@@ -1,11 +1,11 @@
 #!/sbin/openrc-run
 description="iNet wireless daemon"
 command="/usr/libexec/iwd"
+command_args=""
 command_background="yes"
 pidfile="/run/iwd.pid"
 
 depend() {
-	need dbus
-	after dbus
-	provide net
+    need dbus
+    after dbus
 }
diff --git a/lib/setup/sv/openrc/nftables b/lib/setup/sv/openrc/nftables
new file mode 100755
index 0000000..2e9ede4
--- /dev/null
+++ b/lib/setup/sv/openrc/nftables
@@ -0,0 +1,9 @@
+#!/sbin/openrc-run
+description="nftables packet filter"
+command="/usr/sbin/nft"
+command_args="-f /etc/nftables.conf"
+command_background="no"
+
+depend() {
+    need localmount
+}
diff --git a/lib/setup/sv/openrc/nginx b/lib/setup/sv/openrc/nginx
new file mode 100755
index 0000000..b590c18
--- /dev/null
+++ b/lib/setup/sv/openrc/nginx
@@ -0,0 +1,11 @@
+#!/sbin/openrc-run
+description="nginx HTTP server"
+command="/usr/bin/nginx"
+command_args="-g daemon off;"
+command_background="yes"
+pidfile="/run/nginx.pid"
+
+depend() {
+    use net
+    after net
+}
diff --git a/lib/setup/sv/openrc/pipewire b/lib/setup/sv/openrc/pipewire
index c99bf09..919841f 100755
--- a/lib/setup/sv/openrc/pipewire
+++ b/lib/setup/sv/openrc/pipewire
@@ -1,10 +1,11 @@
 #!/sbin/openrc-run
 description="PipeWire multimedia server"
 command="/usr/bin/pipewire"
+command_args=""
 command_background="yes"
 pidfile="/run/pipewire.pid"
 
 depend() {
-	need dbus
-	after dbus
+    need dbus
+    after dbus
 }
diff --git a/lib/setup/sv/openrc/polkitd b/lib/setup/sv/openrc/polkitd
new file mode 100755
index 0000000..88b0832
--- /dev/null
+++ b/lib/setup/sv/openrc/polkitd
@@ -0,0 +1,11 @@
+#!/sbin/openrc-run
+description="polkit authorization manager"
+command="/usr/libexec/polkitd"
+command_args="--no-debug"
+command_background="yes"
+pidfile="/run/polkitd.pid"
+
+depend() {
+    need dbus
+    after dbus
+}
diff --git a/lib/setup/sv/openrc/power-profiles-daemon b/lib/setup/sv/openrc/power-profiles-daemon
index eee4954..2e2016e 100755
--- a/lib/setup/sv/openrc/power-profiles-daemon
+++ b/lib/setup/sv/openrc/power-profiles-daemon
@@ -1,10 +1,11 @@
 #!/sbin/openrc-run
 description="Power profiles daemon"
 command="/usr/libexec/power-profiles-daemon"
+command_args=""
 command_background="yes"
 pidfile="/run/power-profiles-daemon.pid"
 
 depend() {
-	need dbus
-	after dbus
+    need dbus
+    after dbus
 }
diff --git a/lib/setup/sv/openrc/redis b/lib/setup/sv/openrc/redis
new file mode 100755
index 0000000..ac67a4c
--- /dev/null
+++ b/lib/setup/sv/openrc/redis
@@ -0,0 +1,11 @@
+#!/sbin/openrc-run
+description="Redis data store"
+command="/usr/bin/redis-server"
+command_args="--daemonize no"
+command_background="yes"
+pidfile="/run/redis.pid"
+
+depend() {
+    use net
+    after net
+}
diff --git a/lib/setup/sv/openrc/sddm b/lib/setup/sv/openrc/sddm
index 55afe20..a4d7acf 100755
--- a/lib/setup/sv/openrc/sddm
+++ b/lib/setup/sv/openrc/sddm
@@ -1,10 +1,11 @@
 #!/sbin/openrc-run
 description="Simple Desktop Display Manager"
 command="/usr/bin/sddm"
+command_args=""
 command_background="yes"
 pidfile="/run/sddm.pid"
 
 depend() {
-	need dbus
-	after dbus
+    need dbus
+    after dbus
 }
diff --git a/lib/setup/sv/openrc/seatd b/lib/setup/sv/openrc/seatd
index 2acc752..a4e4d48 100755
--- a/lib/setup/sv/openrc/seatd
+++ b/lib/setup/sv/openrc/seatd
@@ -4,3 +4,8 @@ command="/usr/bin/seatd"
 command_args="-g video"
 command_background="yes"
 pidfile="/run/seatd.pid"
+
+depend() {
+    use net
+    after net
+}
diff --git a/lib/setup/sv/openrc/smartd b/lib/setup/sv/openrc/smartd
new file mode 100755
index 0000000..fae3ea8
--- /dev/null
+++ b/lib/setup/sv/openrc/smartd
@@ -0,0 +1,11 @@
+#!/sbin/openrc-run
+description="S.M.A.R.T. disk monitoring"
+command="/usr/sbin/smartd"
+command_args="-n"
+command_background="yes"
+pidfile="/run/smartd.pid"
+
+depend() {
+    use net
+    after net
+}
diff --git a/lib/setup/sv/openrc/sshd b/lib/setup/sv/openrc/sshd
index e3f73c5..5c14569 100755
--- a/lib/setup/sv/openrc/sshd
+++ b/lib/setup/sv/openrc/sshd
@@ -4,3 +4,12 @@ command="/usr/sbin/sshd"
 command_args="-D"
 command_background="yes"
 pidfile="/run/sshd.pid"
+
+depend() {
+    use net
+    after net
+}
+
+start_pre() {
+	if command -v ssh-keygen >/dev/null 2>&1; then ssh-keygen -A >/dev/null 2>&1 || :; fi
+}
diff --git a/lib/setup/sv/openrc/syncthing b/lib/setup/sv/openrc/syncthing
new file mode 100755
index 0000000..1d2b34f
--- /dev/null
+++ b/lib/setup/sv/openrc/syncthing
@@ -0,0 +1,15 @@
+#!/sbin/openrc-run
+description="Syncthing file synchronization"
+command="/usr/bin/syncthing"
+command_args="serve --no-browser --home=/var/lib/syncthing"
+command_background="yes"
+pidfile="/run/syncthing.pid"
+
+depend() {
+    use net
+    after net
+}
+
+start_pre() {
+	install -d -m 0755 /var/lib/syncthing || :
+}
diff --git a/lib/setup/sv/openrc/tlp b/lib/setup/sv/openrc/tlp
new file mode 100755
index 0000000..11b5e32
--- /dev/null
+++ b/lib/setup/sv/openrc/tlp
@@ -0,0 +1,10 @@
+#!/sbin/openrc-run
+description="TLP laptop power management"
+command="/usr/sbin/tlp"
+command_args="init start"
+command_background="no"
+
+depend() {
+    use net
+    after net
+}
diff --git a/lib/setup/sv/openrc/transmission-daemon b/lib/setup/sv/openrc/transmission-daemon
new file mode 100755
index 0000000..2103e51
--- /dev/null
+++ b/lib/setup/sv/openrc/transmission-daemon
@@ -0,0 +1,11 @@
+#!/sbin/openrc-run
+description="Transmission BitTorrent daemon"
+command="/usr/bin/transmission-daemon"
+command_args="-f --log-level=error"
+command_background="yes"
+pidfile="/run/transmission-daemon.pid"
+
+depend() {
+    use net
+    after net
+}
diff --git a/lib/setup/sv/openrc/udevd b/lib/setup/sv/openrc/udevd
new file mode 100755
index 0000000..8f3292f
--- /dev/null
+++ b/lib/setup/sv/openrc/udevd
@@ -0,0 +1,10 @@
+#!/sbin/openrc-run
+description="eudev device manager"
+command="/usr/sbin/udevd"
+command_args=""
+command_background="yes"
+pidfile="/run/udevd.pid"
+
+depend() {
+    need localmount
+}
diff --git a/lib/setup/sv/openrc/upowerd b/lib/setup/sv/openrc/upowerd
new file mode 100755
index 0000000..5464aa3
--- /dev/null
+++ b/lib/setup/sv/openrc/upowerd
@@ -0,0 +1,11 @@
+#!/sbin/openrc-run
+description="UPower power management"
+command="/usr/libexec/upowerd"
+command_args=""
+command_background="yes"
+pidfile="/run/upowerd.pid"
+
+depend() {
+    need dbus
+    after dbus
+}
diff --git a/lib/setup/sv/openrc/wireplumber b/lib/setup/sv/openrc/wireplumber
index 7dbfb15..08a877f 100755
--- a/lib/setup/sv/openrc/wireplumber
+++ b/lib/setup/sv/openrc/wireplumber
@@ -1,10 +1,11 @@
 #!/sbin/openrc-run
-description="WirePlumber session manager"
+description="PipeWire session manager"
 command="/usr/bin/wireplumber"
+command_args=""
 command_background="yes"
 pidfile="/run/wireplumber.pid"
 
 depend() {
-	need dbus
-	after dbus
+    need dbus
+    after dbus
 }
diff --git a/lib/setup/sv/openrc/wpa_supplicant b/lib/setup/sv/openrc/wpa_supplicant
new file mode 100755
index 0000000..4c3d644
--- /dev/null
+++ b/lib/setup/sv/openrc/wpa_supplicant
@@ -0,0 +1,11 @@
+#!/sbin/openrc-run
+description="wpa_supplicant Wi-Fi client"
+command="/usr/sbin/wpa_supplicant"
+command_args="-u -s"
+command_background="yes"
+pidfile="/run/wpa_supplicant.pid"
+
+depend() {
+    need dbus
+    after dbus
+}
diff --git a/lib/setup/sv/runit/NetworkManager/run b/lib/setup/sv/runit/NetworkManager/run
index 8e226f1..133052a 100755
--- a/lib/setup/sv/runit/NetworkManager/run
+++ b/lib/setup/sv/runit/NetworkManager/run
@@ -1,8 +1,3 @@
 #!/bin/sh
 exec 2>&1
-if [ -x /usr/bin/sv ]; then
-	sv start dbus >/dev/null 2>&1 || :
-elif [ -x /usr/bin/s6-svwait ] && [ -d /run/service/dbus ]; then
-	s6-svwait /run/service/dbus >/dev/null 2>&1 || :
-fi
 exec /usr/sbin/NetworkManager --no-daemon
diff --git a/lib/setup/sv/runit/atd/run b/lib/setup/sv/runit/atd/run
new file mode 100755
index 0000000..085dff6
--- /dev/null
+++ b/lib/setup/sv/runit/atd/run
@@ -0,0 +1,3 @@
+#!/bin/sh
+exec 2>&1
+exec /usr/sbin/atd -f
diff --git a/lib/setup/sv/runit/bluetooth/run b/lib/setup/sv/runit/bluetooth/run
index 6202590..8c017d9 100755
--- a/lib/setup/sv/runit/bluetooth/run
+++ b/lib/setup/sv/runit/bluetooth/run
@@ -1,8 +1,3 @@
 #!/bin/sh
 exec 2>&1
-if [ -x /usr/bin/sv ]; then
-	sv start dbus >/dev/null 2>&1 || :
-elif [ -x /usr/bin/s6-svwait ] && [ -d /run/service/dbus ]; then
-	s6-svwait /run/service/dbus >/dev/null 2>&1 || :
-fi
 exec /usr/libexec/bluetooth/bluetoothd
diff --git a/lib/setup/sv/runit/caddy/run b/lib/setup/sv/runit/caddy/run
new file mode 100755
index 0000000..422adff
--- /dev/null
+++ b/lib/setup/sv/runit/caddy/run
@@ -0,0 +1,3 @@
+#!/bin/sh
+exec 2>&1
+exec /usr/bin/caddy run
diff --git a/lib/setup/sv/runit/chronyd/run b/lib/setup/sv/runit/chronyd/run
new file mode 100755
index 0000000..162c121
--- /dev/null
+++ b/lib/setup/sv/runit/chronyd/run
@@ -0,0 +1,3 @@
+#!/bin/sh
+exec 2>&1
+exec /usr/sbin/chronyd -d
diff --git a/lib/setup/sv/runit/crond/run b/lib/setup/sv/runit/crond/run
new file mode 100755
index 0000000..59f3e02
--- /dev/null
+++ b/lib/setup/sv/runit/crond/run
@@ -0,0 +1,3 @@
+#!/bin/sh
+exec 2>&1
+exec /usr/sbin/crond -n
diff --git a/lib/setup/sv/runit/cupsd/run b/lib/setup/sv/runit/cupsd/run
index 1ab8d08..667ab48 100755
--- a/lib/setup/sv/runit/cupsd/run
+++ b/lib/setup/sv/runit/cupsd/run
@@ -1,8 +1,3 @@
 #!/bin/sh
 exec 2>&1
-if [ -x /usr/bin/sv ]; then
-	sv start dbus >/dev/null 2>&1 || :
-elif [ -x /usr/bin/s6-svwait ] && [ -d /run/service/dbus ]; then
-	s6-svwait /run/service/dbus >/dev/null 2>&1 || :
-fi
 exec /usr/sbin/cupsd -f
diff --git a/lib/setup/sv/runit/elogind/run b/lib/setup/sv/runit/elogind/run
index e25b294..91dfb4a 100755
--- a/lib/setup/sv/runit/elogind/run
+++ b/lib/setup/sv/runit/elogind/run
@@ -1,8 +1,3 @@
 #!/bin/sh
 exec 2>&1
-if [ -x /usr/bin/sv ]; then
-	sv start dbus >/dev/null 2>&1 || :
-elif [ -x /usr/bin/s6-svwait ] && [ -d /run/service/dbus ]; then
-	s6-svwait /run/service/dbus >/dev/null 2>&1 || :
-fi
 exec /usr/libexec/elogind
diff --git a/lib/setup/sv/runit/haveged/run b/lib/setup/sv/runit/haveged/run
new file mode 100755
index 0000000..e7d31b4
--- /dev/null
+++ b/lib/setup/sv/runit/haveged/run
@@ -0,0 +1,3 @@
+#!/bin/sh
+exec 2>&1
+exec /usr/sbin/haveged -w 1024 -F
diff --git a/lib/setup/sv/runit/iwd/run b/lib/setup/sv/runit/iwd/run
index 28c9b6c..6b55c09 100755
--- a/lib/setup/sv/runit/iwd/run
+++ b/lib/setup/sv/runit/iwd/run
@@ -1,8 +1,3 @@
 #!/bin/sh
 exec 2>&1
-if [ -x /usr/bin/sv ]; then
-	sv start dbus >/dev/null 2>&1 || :
-elif [ -x /usr/bin/s6-svwait ] && [ -d /run/service/dbus ]; then
-	s6-svwait /run/service/dbus >/dev/null 2>&1 || :
-fi
 exec /usr/libexec/iwd
diff --git a/lib/setup/sv/runit/lxc-net/run b/lib/setup/sv/runit/lxc-net/run
index 74db834..ec34b6c 100755
--- a/lib/setup/sv/runit/lxc-net/run
+++ b/lib/setup/sv/runit/lxc-net/run
@@ -1,3 +1,4 @@
 #!/bin/sh
 exec 2>&1
-exec /usr/libexec/lxc/lxc-net start
+/usr/libexec/lxc/lxc-net start
+exec pause
diff --git a/lib/setup/sv/runit/nftables/run b/lib/setup/sv/runit/nftables/run
new file mode 100755
index 0000000..6091488
--- /dev/null
+++ b/lib/setup/sv/runit/nftables/run
@@ -0,0 +1,4 @@
+#!/bin/sh
+exec 2>&1
+/usr/sbin/nft -f /etc/nftables.conf
+exec pause
diff --git a/lib/setup/sv/runit/nginx/run b/lib/setup/sv/runit/nginx/run
new file mode 100755
index 0000000..97376c2
--- /dev/null
+++ b/lib/setup/sv/runit/nginx/run
@@ -0,0 +1,3 @@
+#!/bin/sh
+exec 2>&1
+exec /usr/bin/nginx -g 'daemon off;'
diff --git a/lib/setup/sv/runit/pipewire/run b/lib/setup/sv/runit/pipewire/run
index 2a9c89a..3559695 100755
--- a/lib/setup/sv/runit/pipewire/run
+++ b/lib/setup/sv/runit/pipewire/run
@@ -1,8 +1,3 @@
 #!/bin/sh
 exec 2>&1
-if [ -x /usr/bin/sv ]; then
-	sv start dbus >/dev/null 2>&1 || :
-elif [ -x /usr/bin/s6-svwait ] && [ -d /run/service/dbus ]; then
-	s6-svwait /run/service/dbus >/dev/null 2>&1 || :
-fi
 exec /usr/bin/pipewire
diff --git a/lib/setup/sv/runit/polkitd/run b/lib/setup/sv/runit/polkitd/run
new file mode 100755
index 0000000..24e555f
--- /dev/null
+++ b/lib/setup/sv/runit/polkitd/run
@@ -0,0 +1,3 @@
+#!/bin/sh
+exec 2>&1
+exec /usr/libexec/polkitd --no-debug
diff --git a/lib/setup/sv/runit/power-profiles-daemon/run b/lib/setup/sv/runit/power-profiles-daemon/run
index 9ee3756..c5dc3f9 100755
--- a/lib/setup/sv/runit/power-profiles-daemon/run
+++ b/lib/setup/sv/runit/power-profiles-daemon/run
@@ -1,8 +1,3 @@
 #!/bin/sh
 exec 2>&1
-if [ -x /usr/bin/sv ]; then
-	sv start dbus >/dev/null 2>&1 || :
-elif [ -x /usr/bin/s6-svwait ] && [ -d /run/service/dbus ]; then
-	s6-svwait /run/service/dbus >/dev/null 2>&1 || :
-fi
 exec /usr/libexec/power-profiles-daemon
diff --git a/lib/setup/sv/runit/redis/run b/lib/setup/sv/runit/redis/run
new file mode 100755
index 0000000..01c53be
--- /dev/null
+++ b/lib/setup/sv/runit/redis/run
@@ -0,0 +1,3 @@
+#!/bin/sh
+exec 2>&1
+exec /usr/bin/redis-server --daemonize no
diff --git a/lib/setup/sv/runit/sddm/run b/lib/setup/sv/runit/sddm/run
index a408aa9..2337320 100755
--- a/lib/setup/sv/runit/sddm/run
+++ b/lib/setup/sv/runit/sddm/run
@@ -1,8 +1,3 @@
 #!/bin/sh
 exec 2>&1
-if [ -x /usr/bin/sv ]; then
-	sv start dbus >/dev/null 2>&1 || :
-elif [ -x /usr/bin/s6-svwait ] && [ -d /run/service/dbus ]; then
-	s6-svwait /run/service/dbus >/dev/null 2>&1 || :
-fi
 exec /usr/bin/sddm
diff --git a/lib/setup/sv/runit/smartd/run b/lib/setup/sv/runit/smartd/run
new file mode 100755
index 0000000..78e4cd0
--- /dev/null
+++ b/lib/setup/sv/runit/smartd/run
@@ -0,0 +1,3 @@
+#!/bin/sh
+exec 2>&1
+exec /usr/sbin/smartd -n
diff --git a/lib/setup/sv/runit/sshd/run b/lib/setup/sv/runit/sshd/run
index 8056a0e..0e2d74b 100755
--- a/lib/setup/sv/runit/sshd/run
+++ b/lib/setup/sv/runit/sshd/run
@@ -1,3 +1,4 @@
 #!/bin/sh
 exec 2>&1
+if command -v ssh-keygen >/dev/null 2>&1; then ssh-keygen -A >/dev/null 2>&1 || :; fi
 exec /usr/sbin/sshd -D
diff --git a/lib/setup/sv/runit/syncthing/run b/lib/setup/sv/runit/syncthing/run
new file mode 100755
index 0000000..a57b6b8
--- /dev/null
+++ b/lib/setup/sv/runit/syncthing/run
@@ -0,0 +1,4 @@
+#!/bin/sh
+exec 2>&1
+install -d -m 0755 /var/lib/syncthing || :
+exec /usr/bin/syncthing serve --no-browser --home=/var/lib/syncthing
diff --git a/lib/setup/sv/runit/tlp/run b/lib/setup/sv/runit/tlp/run
new file mode 100755
index 0000000..0e04baa
--- /dev/null
+++ b/lib/setup/sv/runit/tlp/run
@@ -0,0 +1,4 @@
+#!/bin/sh
+exec 2>&1
+/usr/sbin/tlp init start
+exec pause
diff --git a/lib/setup/sv/runit/transmission-daemon/run b/lib/setup/sv/runit/transmission-daemon/run
new file mode 100755
index 0000000..c9e3418
--- /dev/null
+++ b/lib/setup/sv/runit/transmission-daemon/run
@@ -0,0 +1,3 @@
+#!/bin/sh
+exec 2>&1
+exec /usr/bin/transmission-daemon -f --log-level=error
diff --git a/lib/setup/sv/runit/udevd/run b/lib/setup/sv/runit/udevd/run
new file mode 100755
index 0000000..0f6df7d
--- /dev/null
+++ b/lib/setup/sv/runit/udevd/run
@@ -0,0 +1,3 @@
+#!/bin/sh
+exec 2>&1
+exec /usr/sbin/udevd
diff --git a/lib/setup/sv/runit/upowerd/run b/lib/setup/sv/runit/upowerd/run
new file mode 100755
index 0000000..288e313
--- /dev/null
+++ b/lib/setup/sv/runit/upowerd/run
@@ -0,0 +1,3 @@
+#!/bin/sh
+exec 2>&1
+exec /usr/libexec/upowerd
diff --git a/lib/setup/sv/runit/wireplumber/run b/lib/setup/sv/runit/wireplumber/run
index 1d78959..50575fc 100755
--- a/lib/setup/sv/runit/wireplumber/run
+++ b/lib/setup/sv/runit/wireplumber/run
@@ -1,8 +1,3 @@
 #!/bin/sh
 exec 2>&1
-if [ -x /usr/bin/sv ]; then
-	sv start dbus >/dev/null 2>&1 || :
-elif [ -x /usr/bin/s6-svwait ] && [ -d /run/service/dbus ]; then
-	s6-svwait /run/service/dbus >/dev/null 2>&1 || :
-fi
 exec /usr/bin/wireplumber
diff --git a/lib/setup/sv/runit/wpa_supplicant/run b/lib/setup/sv/runit/wpa_supplicant/run
new file mode 100755
index 0000000..1e854aa
--- /dev/null
+++ b/lib/setup/sv/runit/wpa_supplicant/run
@@ -0,0 +1,3 @@
+#!/bin/sh
+exec 2>&1
+exec /usr/sbin/wpa_supplicant -u -s
diff --git a/lib/setup/sv/s6/NetworkManager/run b/lib/setup/sv/s6/NetworkManager/run
index 8e226f1..133052a 100755
--- a/lib/setup/sv/s6/NetworkManager/run
+++ b/lib/setup/sv/s6/NetworkManager/run
@@ -1,8 +1,3 @@
 #!/bin/sh
 exec 2>&1
-if [ -x /usr/bin/sv ]; then
-	sv start dbus >/dev/null 2>&1 || :
-elif [ -x /usr/bin/s6-svwait ] && [ -d /run/service/dbus ]; then
-	s6-svwait /run/service/dbus >/dev/null 2>&1 || :
-fi
 exec /usr/sbin/NetworkManager --no-daemon
diff --git a/lib/setup/sv/s6/atd/run b/lib/setup/sv/s6/atd/run
new file mode 100755
index 0000000..085dff6
--- /dev/null
+++ b/lib/setup/sv/s6/atd/run
@@ -0,0 +1,3 @@
+#!/bin/sh
+exec 2>&1
+exec /usr/sbin/atd -f
diff --git a/lib/setup/sv/s6/bluetooth/run b/lib/setup/sv/s6/bluetooth/run
index 6202590..8c017d9 100755
--- a/lib/setup/sv/s6/bluetooth/run
+++ b/lib/setup/sv/s6/bluetooth/run
@@ -1,8 +1,3 @@
 #!/bin/sh
 exec 2>&1
-if [ -x /usr/bin/sv ]; then
-	sv start dbus >/dev/null 2>&1 || :
-elif [ -x /usr/bin/s6-svwait ] && [ -d /run/service/dbus ]; then
-	s6-svwait /run/service/dbus >/dev/null 2>&1 || :
-fi
 exec /usr/libexec/bluetooth/bluetoothd
diff --git a/lib/setup/sv/s6/caddy/run b/lib/setup/sv/s6/caddy/run
new file mode 100755
index 0000000..422adff
--- /dev/null
+++ b/lib/setup/sv/s6/caddy/run
@@ -0,0 +1,3 @@
+#!/bin/sh
+exec 2>&1
+exec /usr/bin/caddy run
diff --git a/lib/setup/sv/s6/chronyd/run b/lib/setup/sv/s6/chronyd/run
new file mode 100755
index 0000000..162c121
--- /dev/null
+++ b/lib/setup/sv/s6/chronyd/run
@@ -0,0 +1,3 @@
+#!/bin/sh
+exec 2>&1
+exec /usr/sbin/chronyd -d
diff --git a/lib/setup/sv/s6/crond/run b/lib/setup/sv/s6/crond/run
new file mode 100755
index 0000000..59f3e02
--- /dev/null
+++ b/lib/setup/sv/s6/crond/run
@@ -0,0 +1,3 @@
+#!/bin/sh
+exec 2>&1
+exec /usr/sbin/crond -n
diff --git a/lib/setup/sv/s6/cupsd/run b/lib/setup/sv/s6/cupsd/run
index 1ab8d08..667ab48 100755
--- a/lib/setup/sv/s6/cupsd/run
+++ b/lib/setup/sv/s6/cupsd/run
@@ -1,8 +1,3 @@
 #!/bin/sh
 exec 2>&1
-if [ -x /usr/bin/sv ]; then
-	sv start dbus >/dev/null 2>&1 || :
-elif [ -x /usr/bin/s6-svwait ] && [ -d /run/service/dbus ]; then
-	s6-svwait /run/service/dbus >/dev/null 2>&1 || :
-fi
 exec /usr/sbin/cupsd -f
diff --git a/lib/setup/sv/s6/elogind/run b/lib/setup/sv/s6/elogind/run
index e25b294..91dfb4a 100755
--- a/lib/setup/sv/s6/elogind/run
+++ b/lib/setup/sv/s6/elogind/run
@@ -1,8 +1,3 @@
 #!/bin/sh
 exec 2>&1
-if [ -x /usr/bin/sv ]; then
-	sv start dbus >/dev/null 2>&1 || :
-elif [ -x /usr/bin/s6-svwait ] && [ -d /run/service/dbus ]; then
-	s6-svwait /run/service/dbus >/dev/null 2>&1 || :
-fi
 exec /usr/libexec/elogind
diff --git a/lib/setup/sv/s6/haveged/run b/lib/setup/sv/s6/haveged/run
new file mode 100755
index 0000000..e7d31b4
--- /dev/null
+++ b/lib/setup/sv/s6/haveged/run
@@ -0,0 +1,3 @@
+#!/bin/sh
+exec 2>&1
+exec /usr/sbin/haveged -w 1024 -F
diff --git a/lib/setup/sv/s6/iwd/run b/lib/setup/sv/s6/iwd/run
index 28c9b6c..6b55c09 100755
--- a/lib/setup/sv/s6/iwd/run
+++ b/lib/setup/sv/s6/iwd/run
@@ -1,8 +1,3 @@
 #!/bin/sh
 exec 2>&1
-if [ -x /usr/bin/sv ]; then
-	sv start dbus >/dev/null 2>&1 || :
-elif [ -x /usr/bin/s6-svwait ] && [ -d /run/service/dbus ]; then
-	s6-svwait /run/service/dbus >/dev/null 2>&1 || :
-fi
 exec /usr/libexec/iwd
diff --git a/lib/setup/sv/s6/lxc-net/run b/lib/setup/sv/s6/lxc-net/run
index 74db834..ec34b6c 100755
--- a/lib/setup/sv/s6/lxc-net/run
+++ b/lib/setup/sv/s6/lxc-net/run
@@ -1,3 +1,4 @@
 #!/bin/sh
 exec 2>&1
-exec /usr/libexec/lxc/lxc-net start
+/usr/libexec/lxc/lxc-net start
+exec pause
diff --git a/lib/setup/sv/s6/nftables/run b/lib/setup/sv/s6/nftables/run
new file mode 100755
index 0000000..6091488
--- /dev/null
+++ b/lib/setup/sv/s6/nftables/run
@@ -0,0 +1,4 @@
+#!/bin/sh
+exec 2>&1
+/usr/sbin/nft -f /etc/nftables.conf
+exec pause
diff --git a/lib/setup/sv/s6/nginx/run b/lib/setup/sv/s6/nginx/run
new file mode 100755
index 0000000..97376c2
--- /dev/null
+++ b/lib/setup/sv/s6/nginx/run
@@ -0,0 +1,3 @@
+#!/bin/sh
+exec 2>&1
+exec /usr/bin/nginx -g 'daemon off;'
diff --git a/lib/setup/sv/s6/pipewire/run b/lib/setup/sv/s6/pipewire/run
index 2a9c89a..3559695 100755
--- a/lib/setup/sv/s6/pipewire/run
+++ b/lib/setup/sv/s6/pipewire/run
@@ -1,8 +1,3 @@
 #!/bin/sh
 exec 2>&1
-if [ -x /usr/bin/sv ]; then
-	sv start dbus >/dev/null 2>&1 || :
-elif [ -x /usr/bin/s6-svwait ] && [ -d /run/service/dbus ]; then
-	s6-svwait /run/service/dbus >/dev/null 2>&1 || :
-fi
 exec /usr/bin/pipewire
diff --git a/lib/setup/sv/s6/polkitd/run b/lib/setup/sv/s6/polkitd/run
new file mode 100755
index 0000000..24e555f
--- /dev/null
+++ b/lib/setup/sv/s6/polkitd/run
@@ -0,0 +1,3 @@
+#!/bin/sh
+exec 2>&1
+exec /usr/libexec/polkitd --no-debug
diff --git a/lib/setup/sv/s6/power-profiles-daemon/run b/lib/setup/sv/s6/power-profiles-daemon/run
index 9ee3756..c5dc3f9 100755
--- a/lib/setup/sv/s6/power-profiles-daemon/run
+++ b/lib/setup/sv/s6/power-profiles-daemon/run
@@ -1,8 +1,3 @@
 #!/bin/sh
 exec 2>&1
-if [ -x /usr/bin/sv ]; then
-	sv start dbus >/dev/null 2>&1 || :
-elif [ -x /usr/bin/s6-svwait ] && [ -d /run/service/dbus ]; then
-	s6-svwait /run/service/dbus >/dev/null 2>&1 || :
-fi
 exec /usr/libexec/power-profiles-daemon
diff --git a/lib/setup/sv/s6/redis/run b/lib/setup/sv/s6/redis/run
new file mode 100755
index 0000000..01c53be
--- /dev/null
+++ b/lib/setup/sv/s6/redis/run
@@ -0,0 +1,3 @@
+#!/bin/sh
+exec 2>&1
+exec /usr/bin/redis-server --daemonize no
diff --git a/lib/setup/sv/s6/sddm/run b/lib/setup/sv/s6/sddm/run
index a408aa9..2337320 100755
--- a/lib/setup/sv/s6/sddm/run
+++ b/lib/setup/sv/s6/sddm/run
@@ -1,8 +1,3 @@
 #!/bin/sh
 exec 2>&1
-if [ -x /usr/bin/sv ]; then
-	sv start dbus >/dev/null 2>&1 || :
-elif [ -x /usr/bin/s6-svwait ] && [ -d /run/service/dbus ]; then
-	s6-svwait /run/service/dbus >/dev/null 2>&1 || :
-fi
 exec /usr/bin/sddm
diff --git a/lib/setup/sv/s6/smartd/run b/lib/setup/sv/s6/smartd/run
new file mode 100755
index 0000000..78e4cd0
--- /dev/null
+++ b/lib/setup/sv/s6/smartd/run
@@ -0,0 +1,3 @@
+#!/bin/sh
+exec 2>&1
+exec /usr/sbin/smartd -n
diff --git a/lib/setup/sv/s6/sshd/run b/lib/setup/sv/s6/sshd/run
index 8056a0e..0e2d74b 100755
--- a/lib/setup/sv/s6/sshd/run
+++ b/lib/setup/sv/s6/sshd/run
@@ -1,3 +1,4 @@
 #!/bin/sh
 exec 2>&1
+if command -v ssh-keygen >/dev/null 2>&1; then ssh-keygen -A >/dev/null 2>&1 || :; fi
 exec /usr/sbin/sshd -D
diff --git a/lib/setup/sv/s6/syncthing/run b/lib/setup/sv/s6/syncthing/run
new file mode 100755
index 0000000..a57b6b8
--- /dev/null
+++ b/lib/setup/sv/s6/syncthing/run
@@ -0,0 +1,4 @@
+#!/bin/sh
+exec 2>&1
+install -d -m 0755 /var/lib/syncthing || :
+exec /usr/bin/syncthing serve --no-browser --home=/var/lib/syncthing
diff --git a/lib/setup/sv/s6/tlp/run b/lib/setup/sv/s6/tlp/run
new file mode 100755
index 0000000..0e04baa
--- /dev/null
+++ b/lib/setup/sv/s6/tlp/run
@@ -0,0 +1,4 @@
+#!/bin/sh
+exec 2>&1
+/usr/sbin/tlp init start
+exec pause
diff --git a/lib/setup/sv/s6/transmission-daemon/run b/lib/setup/sv/s6/transmission-daemon/run
new file mode 100755
index 0000000..c9e3418
--- /dev/null
+++ b/lib/setup/sv/s6/transmission-daemon/run
@@ -0,0 +1,3 @@
+#!/bin/sh
+exec 2>&1
+exec /usr/bin/transmission-daemon -f --log-level=error
diff --git a/lib/setup/sv/s6/udevd/run b/lib/setup/sv/s6/udevd/run
new file mode 100755
index 0000000..0f6df7d
--- /dev/null
+++ b/lib/setup/sv/s6/udevd/run
@@ -0,0 +1,3 @@
+#!/bin/sh
+exec 2>&1
+exec /usr/sbin/udevd
diff --git a/lib/setup/sv/s6/upowerd/run b/lib/setup/sv/s6/upowerd/run
new file mode 100755
index 0000000..288e313
--- /dev/null
+++ b/lib/setup/sv/s6/upowerd/run
@@ -0,0 +1,3 @@
+#!/bin/sh
+exec 2>&1
+exec /usr/libexec/upowerd
diff --git a/lib/setup/sv/s6/wireplumber/run b/lib/setup/sv/s6/wireplumber/run
index 1d78959..50575fc 100755
--- a/lib/setup/sv/s6/wireplumber/run
+++ b/lib/setup/sv/s6/wireplumber/run
@@ -1,8 +1,3 @@
 #!/bin/sh
 exec 2>&1
-if [ -x /usr/bin/sv ]; then
-	sv start dbus >/dev/null 2>&1 || :
-elif [ -x /usr/bin/s6-svwait ] && [ -d /run/service/dbus ]; then
-	s6-svwait /run/service/dbus >/dev/null 2>&1 || :
-fi
 exec /usr/bin/wireplumber
diff --git a/lib/setup/sv/s6/wpa_supplicant/run b/lib/setup/sv/s6/wpa_supplicant/run
new file mode 100755
index 0000000..1e854aa
--- /dev/null
+++ b/lib/setup/sv/s6/wpa_supplicant/run
@@ -0,0 +1,3 @@
+#!/bin/sh
+exec 2>&1
+exec /usr/sbin/wpa_supplicant -u -s
diff --git a/lib/setup/sv/shepherd/atd.scm b/lib/setup/sv/shepherd/atd.scm
new file mode 100644
index 0000000..6c770d9
--- /dev/null
+++ b/lib/setup/sv/shepherd/atd.scm
@@ -0,0 +1,9 @@
+(use-modules (shepherd service))
+(register-services
+ (list (service
+        '(atd)
+        #:requirement '()
+        #:documentation "at job scheduler"
+        #:start (make-forkexec-constructor '("/usr/sbin/atd" "-f"))
+        #:stop (make-kill-destructor)
+        #:respawn? #t)))
diff --git a/lib/setup/sv/shepherd/caddy.scm b/lib/setup/sv/shepherd/caddy.scm
new file mode 100644
index 0000000..e2efb6a
--- /dev/null
+++ b/lib/setup/sv/shepherd/caddy.scm
@@ -0,0 +1,9 @@
+(use-modules (shepherd service))
+(register-services
+ (list (service
+        '(caddy)
+        #:requirement '()
+        #:documentation "Caddy HTTP server"
+        #:start (make-forkexec-constructor '("/usr/bin/caddy" "run"))
+        #:stop (make-kill-destructor)
+        #:respawn? #t)))
diff --git a/lib/setup/sv/shepherd/chronyd.scm b/lib/setup/sv/shepherd/chronyd.scm
new file mode 100644
index 0000000..470051f
--- /dev/null
+++ b/lib/setup/sv/shepherd/chronyd.scm
@@ -0,0 +1,9 @@
+(use-modules (shepherd service))
+(register-services
+ (list (service
+        '(chronyd)
+        #:requirement '()
+        #:documentation "chrony NTP daemon"
+        #:start (make-forkexec-constructor '("/usr/sbin/chronyd" "-d"))
+        #:stop (make-kill-destructor)
+        #:respawn? #t)))
diff --git a/lib/setup/sv/shepherd/crond.scm b/lib/setup/sv/shepherd/crond.scm
new file mode 100644
index 0000000..1b1c253
--- /dev/null
+++ b/lib/setup/sv/shepherd/crond.scm
@@ -0,0 +1,9 @@
+(use-modules (shepherd service))
+(register-services
+ (list (service
+        '(crond)
+        #:requirement '()
+        #:documentation "cron daemon"
+        #:start (make-forkexec-constructor '("/usr/sbin/crond" "-n"))
+        #:stop (make-kill-destructor)
+        #:respawn? #t)))
diff --git a/lib/setup/sv/shepherd/haveged.scm b/lib/setup/sv/shepherd/haveged.scm
new file mode 100644
index 0000000..fa938bc
--- /dev/null
+++ b/lib/setup/sv/shepherd/haveged.scm
@@ -0,0 +1,9 @@
+(use-modules (shepherd service))
+(register-services
+ (list (service
+        '(haveged)
+        #:requirement '()
+        #:documentation "haveged entropy daemon"
+        #:start (make-forkexec-constructor '("/usr/sbin/haveged" "-w" "1024" "-F"))
+        #:stop (make-kill-destructor)
+        #:respawn? #t)))
diff --git a/lib/setup/sv/shepherd/nftables.scm b/lib/setup/sv/shepherd/nftables.scm
new file mode 100644
index 0000000..5276258
--- /dev/null
+++ b/lib/setup/sv/shepherd/nftables.scm
@@ -0,0 +1,9 @@
+(use-modules (shepherd service))
+(register-services
+ (list (service
+        '(nftables)
+        #:requirement '()
+        #:documentation "nftables packet filter"
+        #:start (make-forkexec-constructor '("/usr/sbin/nft" "-f" "/etc/nftables.conf"))
+        #:stop (make-kill-destructor)
+        #:respawn? #t)))
diff --git a/lib/setup/sv/shepherd/nginx.scm b/lib/setup/sv/shepherd/nginx.scm
new file mode 100644
index 0000000..64f7862
--- /dev/null
+++ b/lib/setup/sv/shepherd/nginx.scm
@@ -0,0 +1,9 @@
+(use-modules (shepherd service))
+(register-services
+ (list (service
+        '(nginx)
+        #:requirement '()
+        #:documentation "nginx HTTP server"
+        #:start (make-forkexec-constructor '("/usr/bin/nginx" "-g" "daemon off;"))
+        #:stop (make-kill-destructor)
+        #:respawn? #t)))
diff --git a/lib/setup/sv/shepherd/polkitd.scm b/lib/setup/sv/shepherd/polkitd.scm
new file mode 100644
index 0000000..fba2eeb
--- /dev/null
+++ b/lib/setup/sv/shepherd/polkitd.scm
@@ -0,0 +1,9 @@
+(use-modules (shepherd service))
+(register-services
+ (list (service
+        '(polkitd)
+        #:requirement '(dbus)
+        #:documentation "polkit authorization manager"
+        #:start (make-forkexec-constructor '("/usr/libexec/polkitd" "--no-debug"))
+        #:stop (make-kill-destructor)
+        #:respawn? #t)))
diff --git a/lib/setup/sv/shepherd/redis.scm b/lib/setup/sv/shepherd/redis.scm
new file mode 100644
index 0000000..5e25b0b
--- /dev/null
+++ b/lib/setup/sv/shepherd/redis.scm
@@ -0,0 +1,9 @@
+(use-modules (shepherd service))
+(register-services
+ (list (service
+        '(redis)
+        #:requirement '()
+        #:documentation "Redis data store"
+        #:start (make-forkexec-constructor '("/usr/bin/redis-server" "--daemonize" "no"))
+        #:stop (make-kill-destructor)
+        #:respawn? #t)))
diff --git a/lib/setup/sv/shepherd/smartd.scm b/lib/setup/sv/shepherd/smartd.scm
new file mode 100644
index 0000000..559e298
--- /dev/null
+++ b/lib/setup/sv/shepherd/smartd.scm
@@ -0,0 +1,9 @@
+(use-modules (shepherd service))
+(register-services
+ (list (service
+        '(smartd)
+        #:requirement '()
+        #:documentation "S.M.A.R.T. disk monitoring"
+        #:start (make-forkexec-constructor '("/usr/sbin/smartd" "-n"))
+        #:stop (make-kill-destructor)
+        #:respawn? #t)))
diff --git a/lib/setup/sv/shepherd/syncthing.scm b/lib/setup/sv/shepherd/syncthing.scm
new file mode 100644
index 0000000..7480b23
--- /dev/null
+++ b/lib/setup/sv/shepherd/syncthing.scm
@@ -0,0 +1,9 @@
+(use-modules (shepherd service))
+(register-services
+ (list (service
+        '(syncthing)
+        #:requirement '()
+        #:documentation "Syncthing file synchronization"
+        #:start (make-forkexec-constructor '("/usr/bin/syncthing" "serve" "--no-browser" "--home=/var/lib/syncthing"))
+        #:stop (make-kill-destructor)
+        #:respawn? #t)))
diff --git a/lib/setup/sv/shepherd/tlp.scm b/lib/setup/sv/shepherd/tlp.scm
new file mode 100644
index 0000000..7c62ecf
--- /dev/null
+++ b/lib/setup/sv/shepherd/tlp.scm
@@ -0,0 +1,9 @@
+(use-modules (shepherd service))
+(register-services
+ (list (service
+        '(tlp)
+        #:requirement '()
+        #:documentation "TLP laptop power management"
+        #:start (make-forkexec-constructor '("/usr/sbin/tlp" "init" "start"))
+        #:stop (make-kill-destructor)
+        #:respawn? #t)))
diff --git a/lib/setup/sv/shepherd/transmission-daemon.scm b/lib/setup/sv/shepherd/transmission-daemon.scm
new file mode 100644
index 0000000..74aeb2d
--- /dev/null
+++ b/lib/setup/sv/shepherd/transmission-daemon.scm
@@ -0,0 +1,9 @@
+(use-modules (shepherd service))
+(register-services
+ (list (service
+        '(transmission-daemon)
+        #:requirement '()
+        #:documentation "Transmission BitTorrent daemon"
+        #:start (make-forkexec-constructor '("/usr/bin/transmission-daemon" "-f" "--log-level=error"))
+        #:stop (make-kill-destructor)
+        #:respawn? #t)))
diff --git a/lib/setup/sv/shepherd/udevd.scm b/lib/setup/sv/shepherd/udevd.scm
new file mode 100644
index 0000000..3f4d44b
--- /dev/null
+++ b/lib/setup/sv/shepherd/udevd.scm
@@ -0,0 +1,9 @@
+(use-modules (shepherd service))
+(register-services
+ (list (service
+        '(udevd)
+        #:requirement '()
+        #:documentation "eudev device manager"
+        #:start (make-forkexec-constructor '("/usr/sbin/udevd"))
+        #:stop (make-kill-destructor)
+        #:respawn? #t)))
diff --git a/lib/setup/sv/shepherd/upowerd.scm b/lib/setup/sv/shepherd/upowerd.scm
new file mode 100644
index 0000000..f372557
--- /dev/null
+++ b/lib/setup/sv/shepherd/upowerd.scm
@@ -0,0 +1,9 @@
+(use-modules (shepherd service))
+(register-services
+ (list (service
+        '(upowerd)
+        #:requirement '(dbus)
+        #:documentation "UPower power management"
+        #:start (make-forkexec-constructor '("/usr/libexec/upowerd"))
+        #:stop (make-kill-destructor)
+        #:respawn? #t)))
diff --git a/lib/setup/sv/shepherd/wireplumber.scm b/lib/setup/sv/shepherd/wireplumber.scm
index cd349e2..497e14e 100644
--- a/lib/setup/sv/shepherd/wireplumber.scm
+++ b/lib/setup/sv/shepherd/wireplumber.scm
@@ -3,7 +3,7 @@
  (list (service
         '(wireplumber)
         #:requirement '(dbus)
-        #:documentation "WirePlumber session manager"
+        #:documentation "PipeWire session manager"
         #:start (make-forkexec-constructor '("/usr/bin/wireplumber"))
         #:stop (make-kill-destructor)
         #:respawn? #t)))
diff --git a/lib/setup/sv/shepherd/wpa_supplicant.scm b/lib/setup/sv/shepherd/wpa_supplicant.scm
new file mode 100644
index 0000000..978ca6f
--- /dev/null
+++ b/lib/setup/sv/shepherd/wpa_supplicant.scm
@@ -0,0 +1,9 @@
+(use-modules (shepherd service))
+(register-services
+ (list (service
+        '(wpa_supplicant)
+        #:requirement '(dbus)
+        #:documentation "wpa_supplicant Wi-Fi client"
+        #:start (make-forkexec-constructor '("/usr/sbin/wpa_supplicant" "-u" "-s"))
+        #:stop (make-kill-destructor)
+        #:respawn? #t)))
diff --git a/lib/setup/sv/systemd/NetworkManager.service b/lib/setup/sv/systemd/NetworkManager.service
index ec98913..b4080d4 100644
--- a/lib/setup/sv/systemd/NetworkManager.service
+++ b/lib/setup/sv/systemd/NetworkManager.service
@@ -1,7 +1,6 @@
 [Unit]
 Description=NetworkManager
-After=dbus.service
-Wants=dbus.service
+After=network.target dbus.service
 
 [Service]
 ExecStart=/usr/sbin/NetworkManager --no-daemon
diff --git a/lib/setup/sv/systemd/atd.service b/lib/setup/sv/systemd/atd.service
new file mode 100644
index 0000000..e0bf196
--- /dev/null
+++ b/lib/setup/sv/systemd/atd.service
@@ -0,0 +1,10 @@
+[Unit]
+Description=at job scheduler
+After=network.target
+
+[Service]
+ExecStart=/usr/sbin/atd -f
+Restart=on-failure
+
+[Install]
+WantedBy=multi-user.target
diff --git a/lib/setup/sv/systemd/bluetooth.service b/lib/setup/sv/systemd/bluetooth.service
index 746cf04..72e2d4b 100644
--- a/lib/setup/sv/systemd/bluetooth.service
+++ b/lib/setup/sv/systemd/bluetooth.service
@@ -1,7 +1,6 @@
 [Unit]
 Description=Bluetooth daemon
-After=dbus.service
-Wants=dbus.service
+After=network.target dbus.service
 
 [Service]
 ExecStart=/usr/libexec/bluetooth/bluetoothd
diff --git a/lib/setup/sv/systemd/caddy.service b/lib/setup/sv/systemd/caddy.service
new file mode 100644
index 0000000..cb6451f
--- /dev/null
+++ b/lib/setup/sv/systemd/caddy.service
@@ -0,0 +1,10 @@
+[Unit]
+Description=Caddy HTTP server
+After=network.target
+
+[Service]
+ExecStart=/usr/bin/caddy run
+Restart=on-failure
+
+[Install]
+WantedBy=multi-user.target
diff --git a/lib/setup/sv/systemd/chronyd.service b/lib/setup/sv/systemd/chronyd.service
new file mode 100644
index 0000000..75b828b
--- /dev/null
+++ b/lib/setup/sv/systemd/chronyd.service
@@ -0,0 +1,10 @@
+[Unit]
+Description=chrony NTP daemon
+After=network.target
+
+[Service]
+ExecStart=/usr/sbin/chronyd -d
+Restart=on-failure
+
+[Install]
+WantedBy=multi-user.target
diff --git a/lib/setup/sv/systemd/crond.service b/lib/setup/sv/systemd/crond.service
new file mode 100644
index 0000000..b115c71
--- /dev/null
+++ b/lib/setup/sv/systemd/crond.service
@@ -0,0 +1,10 @@
+[Unit]
+Description=cron daemon
+After=network.target
+
+[Service]
+ExecStart=/usr/sbin/crond -n
+Restart=on-failure
+
+[Install]
+WantedBy=multi-user.target
diff --git a/lib/setup/sv/systemd/cups.service b/lib/setup/sv/systemd/cups.service
index ef51683..96d05db 100644
--- a/lib/setup/sv/systemd/cups.service
+++ b/lib/setup/sv/systemd/cups.service
@@ -1,7 +1,6 @@
 [Unit]
 Description=CUPS printing service
-After=dbus.service
-Wants=dbus.service
+After=network.target dbus.service
 
 [Service]
 ExecStart=/usr/sbin/cupsd -f
diff --git a/lib/setup/sv/systemd/dbus.service b/lib/setup/sv/systemd/dbus.service
index e6f9cc0..0e20c6b 100644
--- a/lib/setup/sv/systemd/dbus.service
+++ b/lib/setup/sv/systemd/dbus.service
@@ -2,7 +2,6 @@
 Description=D-Bus system message bus
 
 [Service]
-ExecStartPre=/bin/sh -c 'mkdir -p /run/dbus /var/lib/dbus'
 ExecStart=/usr/bin/dbus-daemon --system --nofork --nopidfile --nosyslog
 Restart=on-failure
 
diff --git a/lib/setup/sv/systemd/dhcpcd.service b/lib/setup/sv/systemd/dhcpcd.service
index a01af61..19198a0 100644
--- a/lib/setup/sv/systemd/dhcpcd.service
+++ b/lib/setup/sv/systemd/dhcpcd.service
@@ -1,5 +1,6 @@
 [Unit]
 Description=DHCP client daemon
+After=network.target
 
 [Service]
 ExecStart=/usr/sbin/dhcpcd --nobackground
diff --git a/lib/setup/sv/systemd/elogind.service b/lib/setup/sv/systemd/elogind.service
index 3788be2..b9403b4 100644
--- a/lib/setup/sv/systemd/elogind.service
+++ b/lib/setup/sv/systemd/elogind.service
@@ -1,7 +1,6 @@
 [Unit]
 Description=elogind login manager
 After=dbus.service
-Wants=dbus.service
 
 [Service]
 ExecStart=/usr/libexec/elogind
diff --git a/lib/setup/sv/systemd/haveged.service b/lib/setup/sv/systemd/haveged.service
new file mode 100644
index 0000000..75526ad
--- /dev/null
+++ b/lib/setup/sv/systemd/haveged.service
@@ -0,0 +1,9 @@
+[Unit]
+Description=haveged entropy daemon
+
+[Service]
+ExecStart=/usr/sbin/haveged -w 1024 -F
+Restart=on-failure
+
+[Install]
+WantedBy=multi-user.target
diff --git a/lib/setup/sv/systemd/iwd.service b/lib/setup/sv/systemd/iwd.service
index c624bc9..4e3d132 100644
--- a/lib/setup/sv/systemd/iwd.service
+++ b/lib/setup/sv/systemd/iwd.service
@@ -1,7 +1,6 @@
 [Unit]
 Description=iNet wireless daemon
-After=dbus.service
-Wants=dbus.service
+After=network.target dbus.service
 
 [Service]
 ExecStart=/usr/libexec/iwd
diff --git a/lib/setup/sv/systemd/nftables.service b/lib/setup/sv/systemd/nftables.service
new file mode 100644
index 0000000..aec4d6d
--- /dev/null
+++ b/lib/setup/sv/systemd/nftables.service
@@ -0,0 +1,10 @@
+[Unit]
+Description=nftables packet filter
+
+[Service]
+ExecStart=/usr/sbin/nft -f /etc/nftables.conf
+Type=oneshot
+RemainAfterExit=yes
+
+[Install]
+WantedBy=multi-user.target
diff --git a/lib/setup/sv/systemd/nginx.service b/lib/setup/sv/systemd/nginx.service
new file mode 100644
index 0000000..651be05
--- /dev/null
+++ b/lib/setup/sv/systemd/nginx.service
@@ -0,0 +1,10 @@
+[Unit]
+Description=nginx HTTP server
+After=network.target
+
+[Service]
+ExecStart=/usr/bin/nginx -g 'daemon off;'
+Restart=on-failure
+
+[Install]
+WantedBy=multi-user.target
diff --git a/lib/setup/sv/systemd/pipewire.service b/lib/setup/sv/systemd/pipewire.service
index 8903960..314c71e 100644
--- a/lib/setup/sv/systemd/pipewire.service
+++ b/lib/setup/sv/systemd/pipewire.service
@@ -1,7 +1,6 @@
 [Unit]
 Description=PipeWire multimedia server
-After=dbus.service
-Wants=dbus.service
+After=network.target dbus.service
 
 [Service]
 ExecStart=/usr/bin/pipewire
diff --git a/lib/setup/sv/systemd/polkit.service b/lib/setup/sv/systemd/polkit.service
new file mode 100644
index 0000000..cd4f236
--- /dev/null
+++ b/lib/setup/sv/systemd/polkit.service
@@ -0,0 +1,10 @@
+[Unit]
+Description=polkit authorization manager
+After=dbus.service
+
+[Service]
+ExecStart=/usr/libexec/polkitd --no-debug
+Restart=on-failure
+
+[Install]
+WantedBy=multi-user.target
diff --git a/lib/setup/sv/systemd/power-profiles-daemon.service b/lib/setup/sv/systemd/power-profiles-daemon.service
index 104a806..7ac4baa 100644
--- a/lib/setup/sv/systemd/power-profiles-daemon.service
+++ b/lib/setup/sv/systemd/power-profiles-daemon.service
@@ -1,7 +1,6 @@
 [Unit]
 Description=Power profiles daemon
-After=dbus.service
-Wants=dbus.service
+After=network.target dbus.service
 
 [Service]
 ExecStart=/usr/libexec/power-profiles-daemon
diff --git a/lib/setup/sv/systemd/redis.service b/lib/setup/sv/systemd/redis.service
new file mode 100644
index 0000000..6345920
--- /dev/null
+++ b/lib/setup/sv/systemd/redis.service
@@ -0,0 +1,10 @@
+[Unit]
+Description=Redis data store
+After=network.target
+
+[Service]
+ExecStart=/usr/bin/redis-server --daemonize no
+Restart=on-failure
+
+[Install]
+WantedBy=multi-user.target
diff --git a/lib/setup/sv/systemd/sddm.service b/lib/setup/sv/systemd/sddm.service
index 60cd4df..cad3c2e 100644
--- a/lib/setup/sv/systemd/sddm.service
+++ b/lib/setup/sv/systemd/sddm.service
@@ -1,7 +1,6 @@
 [Unit]
 Description=Simple Desktop Display Manager
-After=dbus.service
-Wants=dbus.service
+After=network.target dbus.service
 
 [Service]
 ExecStart=/usr/bin/sddm
diff --git a/lib/setup/sv/systemd/seatd.service b/lib/setup/sv/systemd/seatd.service
index e56c062..037c874 100644
--- a/lib/setup/sv/systemd/seatd.service
+++ b/lib/setup/sv/systemd/seatd.service
@@ -1,5 +1,6 @@
 [Unit]
 Description=seat management daemon
+After=network.target
 
 [Service]
 ExecStart=/usr/bin/seatd -g video
diff --git a/lib/setup/sv/systemd/smartd.service b/lib/setup/sv/systemd/smartd.service
new file mode 100644
index 0000000..6f15008
--- /dev/null
+++ b/lib/setup/sv/systemd/smartd.service
@@ -0,0 +1,10 @@
+[Unit]
+Description=S.M.A.R.T. disk monitoring
+After=network.target
+
+[Service]
+ExecStart=/usr/sbin/smartd -n
+Restart=on-failure
+
+[Install]
+WantedBy=multi-user.target
diff --git a/lib/setup/sv/systemd/sshd.service b/lib/setup/sv/systemd/sshd.service
index fe63c0e..052400a 100644
--- a/lib/setup/sv/systemd/sshd.service
+++ b/lib/setup/sv/systemd/sshd.service
@@ -1,5 +1,6 @@
 [Unit]
 Description=OpenSSH daemon
+After=network.target
 
 [Service]
 ExecStart=/usr/sbin/sshd -D
diff --git a/lib/setup/sv/systemd/syncthing.service b/lib/setup/sv/systemd/syncthing.service
new file mode 100644
index 0000000..cf71975
--- /dev/null
+++ b/lib/setup/sv/systemd/syncthing.service
@@ -0,0 +1,10 @@
+[Unit]
+Description=Syncthing file synchronization
+After=network.target
+
+[Service]
+ExecStart=/usr/bin/syncthing serve --no-browser --home=/var/lib/syncthing
+Restart=on-failure
+
+[Install]
+WantedBy=multi-user.target
diff --git a/lib/setup/sv/systemd/tlp.service b/lib/setup/sv/systemd/tlp.service
new file mode 100644
index 0000000..ffd086f
--- /dev/null
+++ b/lib/setup/sv/systemd/tlp.service
@@ -0,0 +1,11 @@
+[Unit]
+Description=TLP laptop power management
+After=network.target
+
+[Service]
+ExecStart=/usr/sbin/tlp init start
+Type=oneshot
+RemainAfterExit=yes
+
+[Install]
+WantedBy=multi-user.target
diff --git a/lib/setup/sv/systemd/transmission-daemon.service b/lib/setup/sv/systemd/transmission-daemon.service
new file mode 100644
index 0000000..410deac
--- /dev/null
+++ b/lib/setup/sv/systemd/transmission-daemon.service
@@ -0,0 +1,10 @@
+[Unit]
+Description=Transmission BitTorrent daemon
+After=network.target
+
+[Service]
+ExecStart=/usr/bin/transmission-daemon -f --log-level=error
+Restart=on-failure
+
+[Install]
+WantedBy=multi-user.target
diff --git a/lib/setup/sv/systemd/udevd.service b/lib/setup/sv/systemd/udevd.service
new file mode 100644
index 0000000..2ec09dc
--- /dev/null
+++ b/lib/setup/sv/systemd/udevd.service
@@ -0,0 +1,9 @@
+[Unit]
+Description=eudev device manager
+
+[Service]
+ExecStart=/usr/sbin/udevd
+Restart=on-failure
+
+[Install]
+WantedBy=sysinit.target
diff --git a/lib/setup/sv/systemd/upower.service b/lib/setup/sv/systemd/upower.service
new file mode 100644
index 0000000..5f39f28
--- /dev/null
+++ b/lib/setup/sv/systemd/upower.service
@@ -0,0 +1,10 @@
+[Unit]
+Description=UPower power management
+After=network.target dbus.service
+
+[Service]
+ExecStart=/usr/libexec/upowerd
+Restart=on-failure
+
+[Install]
+WantedBy=multi-user.target
diff --git a/lib/setup/sv/systemd/wireplumber.service b/lib/setup/sv/systemd/wireplumber.service
index bcf433f..150a644 100644
--- a/lib/setup/sv/systemd/wireplumber.service
+++ b/lib/setup/sv/systemd/wireplumber.service
@@ -1,7 +1,6 @@
 [Unit]
-Description=WirePlumber session manager
-After=dbus.service
-Wants=dbus.service
+Description=PipeWire session manager
+After=network.target dbus.service
 
 [Service]
 ExecStart=/usr/bin/wireplumber
diff --git a/lib/setup/sv/systemd/wpa_supplicant.service b/lib/setup/sv/systemd/wpa_supplicant.service
new file mode 100644
index 0000000..4a90628
--- /dev/null
+++ b/lib/setup/sv/systemd/wpa_supplicant.service
@@ -0,0 +1,10 @@
+[Unit]
+Description=wpa_supplicant Wi-Fi client
+After=network.target dbus.service
+
+[Service]
+ExecStart=/usr/sbin/wpa_supplicant -u -s
+Restart=on-failure
+
+[Install]
+WantedBy=multi-user.target
diff --git a/lib/setup/sv/sysvinit/NetworkManager b/lib/setup/sv/sysvinit/NetworkManager
new file mode 100755
index 0000000..64d30a4
--- /dev/null
+++ b/lib/setup/sv/sysvinit/NetworkManager
@@ -0,0 +1,41 @@
+#!/bin/sh
+### BEGIN INIT INFO
+# Provides:          NetworkManager
+# Required-Start:    $remote_fs dbus
+# Required-Stop:     $remote_fs dbus
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+# Short-Description: NetworkManager
+### END INIT INFO
+
+if [ -f /etc/rc.d/init.d/functions ]; then
+	. /etc/rc.d/init.d/functions
+elif [ -f /etc/init.d/functions ]; then
+	. /etc/init.d/functions
+fi
+
+NAME=NetworkManager
+DAEMON="/usr/sbin/NetworkManager"
+DAEMON_ARGS="--no-daemon"
+PIDFILE="/run/NetworkManager.pid"
+USER=""
+
+start() {
+	start_daemon -p "$PIDFILE" ${USER:+-c "$USER"} "$DAEMON" $DAEMON_ARGS
+}
+
+stop() {
+	killproc -p "$PIDFILE" "$DAEMON"
+}
+
+status() {
+	pidofproc -p "$PIDFILE" "$DAEMON"
+}
+
+case $1 in
+	start) start ;;
+	stop) stop ;;
+	restart) stop; start ;;
+	status) status ;;
+	*) printf '%s\n' "Usage: $0 {start|stop|restart|status}" >&2; exit 1 ;;
+esac
diff --git a/lib/setup/sv/sysvinit/atd b/lib/setup/sv/sysvinit/atd
new file mode 100755
index 0000000..7157cc8
--- /dev/null
+++ b/lib/setup/sv/sysvinit/atd
@@ -0,0 +1,41 @@
+#!/bin/sh
+### BEGIN INIT INFO
+# Provides:          atd
+# Required-Start:    $remote_fs
+# Required-Stop:     $remote_fs
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+# Short-Description: at job scheduler
+### END INIT INFO
+
+if [ -f /etc/rc.d/init.d/functions ]; then
+	. /etc/rc.d/init.d/functions
+elif [ -f /etc/init.d/functions ]; then
+	. /etc/init.d/functions
+fi
+
+NAME=atd
+DAEMON="/usr/sbin/atd"
+DAEMON_ARGS="-f"
+PIDFILE="/run/atd.pid"
+USER=""
+
+start() {
+	start_daemon -p "$PIDFILE" ${USER:+-c "$USER"} "$DAEMON" $DAEMON_ARGS
+}
+
+stop() {
+	killproc -p "$PIDFILE" "$DAEMON"
+}
+
+status() {
+	pidofproc -p "$PIDFILE" "$DAEMON"
+}
+
+case $1 in
+	start) start ;;
+	stop) stop ;;
+	restart) stop; start ;;
+	status) status ;;
+	*) printf '%s\n' "Usage: $0 {start|stop|restart|status}" >&2; exit 1 ;;
+esac
diff --git a/lib/setup/sv/sysvinit/avahi-daemon b/lib/setup/sv/sysvinit/avahi-daemon
new file mode 100755
index 0000000..2725188
--- /dev/null
+++ b/lib/setup/sv/sysvinit/avahi-daemon
@@ -0,0 +1,41 @@
+#!/bin/sh
+### BEGIN INIT INFO
+# Provides:          avahi-daemon
+# Required-Start:    $remote_fs dbus
+# Required-Stop:     $remote_fs dbus
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+# Short-Description: Avahi mDNS/DNS-SD daemon
+### END INIT INFO
+
+if [ -f /etc/rc.d/init.d/functions ]; then
+	. /etc/rc.d/init.d/functions
+elif [ -f /etc/init.d/functions ]; then
+	. /etc/init.d/functions
+fi
+
+NAME=avahi-daemon
+DAEMON="/usr/sbin/avahi-daemon"
+DAEMON_ARGS="--no-chroot"
+PIDFILE="/run/avahi-daemon.pid"
+USER=""
+
+start() {
+	start_daemon -p "$PIDFILE" ${USER:+-c "$USER"} "$DAEMON" $DAEMON_ARGS
+}
+
+stop() {
+	killproc -p "$PIDFILE" "$DAEMON"
+}
+
+status() {
+	pidofproc -p "$PIDFILE" "$DAEMON"
+}
+
+case $1 in
+	start) start ;;
+	stop) stop ;;
+	restart) stop; start ;;
+	status) status ;;
+	*) printf '%s\n' "Usage: $0 {start|stop|restart|status}" >&2; exit 1 ;;
+esac
diff --git a/lib/setup/sv/sysvinit/bluetooth b/lib/setup/sv/sysvinit/bluetooth
new file mode 100755
index 0000000..d65130b
--- /dev/null
+++ b/lib/setup/sv/sysvinit/bluetooth
@@ -0,0 +1,41 @@
+#!/bin/sh
+### BEGIN INIT INFO
+# Provides:          bluetooth
+# Required-Start:    $remote_fs dbus
+# Required-Stop:     $remote_fs dbus
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+# Short-Description: Bluetooth daemon
+### END INIT INFO
+
+if [ -f /etc/rc.d/init.d/functions ]; then
+	. /etc/rc.d/init.d/functions
+elif [ -f /etc/init.d/functions ]; then
+	. /etc/init.d/functions
+fi
+
+NAME=bluetooth
+DAEMON="/usr/libexec/bluetooth/bluetoothd"
+DAEMON_ARGS=""
+PIDFILE="/run/bluetooth.pid"
+USER=""
+
+start() {
+	start_daemon -p "$PIDFILE" ${USER:+-c "$USER"} "$DAEMON" $DAEMON_ARGS
+}
+
+stop() {
+	killproc -p "$PIDFILE" "$DAEMON"
+}
+
+status() {
+	pidofproc -p "$PIDFILE" "$DAEMON"
+}
+
+case $1 in
+	start) start ;;
+	stop) stop ;;
+	restart) stop; start ;;
+	status) status ;;
+	*) printf '%s\n' "Usage: $0 {start|stop|restart|status}" >&2; exit 1 ;;
+esac
diff --git a/lib/setup/sv/sysvinit/caddy b/lib/setup/sv/sysvinit/caddy
new file mode 100755
index 0000000..7eca278
--- /dev/null
+++ b/lib/setup/sv/sysvinit/caddy
@@ -0,0 +1,41 @@
+#!/bin/sh
+### BEGIN INIT INFO
+# Provides:          caddy
+# Required-Start:    $remote_fs
+# Required-Stop:     $remote_fs
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+# Short-Description: Caddy HTTP server
+### END INIT INFO
+
+if [ -f /etc/rc.d/init.d/functions ]; then
+	. /etc/rc.d/init.d/functions
+elif [ -f /etc/init.d/functions ]; then
+	. /etc/init.d/functions
+fi
+
+NAME=caddy
+DAEMON="/usr/bin/caddy"
+DAEMON_ARGS="run"
+PIDFILE="/run/caddy.pid"
+USER=""
+
+start() {
+	start_daemon -p "$PIDFILE" ${USER:+-c "$USER"} "$DAEMON" $DAEMON_ARGS
+}
+
+stop() {
+	killproc -p "$PIDFILE" "$DAEMON"
+}
+
+status() {
+	pidofproc -p "$PIDFILE" "$DAEMON"
+}
+
+case $1 in
+	start) start ;;
+	stop) stop ;;
+	restart) stop; start ;;
+	status) status ;;
+	*) printf '%s\n' "Usage: $0 {start|stop|restart|status}" >&2; exit 1 ;;
+esac
diff --git a/lib/setup/sv/sysvinit/chronyd b/lib/setup/sv/sysvinit/chronyd
new file mode 100755
index 0000000..a171f43
--- /dev/null
+++ b/lib/setup/sv/sysvinit/chronyd
@@ -0,0 +1,41 @@
+#!/bin/sh
+### BEGIN INIT INFO
+# Provides:          chronyd
+# Required-Start:    $remote_fs
+# Required-Stop:     $remote_fs
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+# Short-Description: chrony NTP daemon
+### END INIT INFO
+
+if [ -f /etc/rc.d/init.d/functions ]; then
+	. /etc/rc.d/init.d/functions
+elif [ -f /etc/init.d/functions ]; then
+	. /etc/init.d/functions
+fi
+
+NAME=chronyd
+DAEMON="/usr/sbin/chronyd"
+DAEMON_ARGS="-d"
+PIDFILE="/run/chronyd.pid"
+USER=""
+
+start() {
+	start_daemon -p "$PIDFILE" ${USER:+-c "$USER"} "$DAEMON" $DAEMON_ARGS
+}
+
+stop() {
+	killproc -p "$PIDFILE" "$DAEMON"
+}
+
+status() {
+	pidofproc -p "$PIDFILE" "$DAEMON"
+}
+
+case $1 in
+	start) start ;;
+	stop) stop ;;
+	restart) stop; start ;;
+	status) status ;;
+	*) printf '%s\n' "Usage: $0 {start|stop|restart|status}" >&2; exit 1 ;;
+esac
diff --git a/lib/setup/sv/sysvinit/conntrackd b/lib/setup/sv/sysvinit/conntrackd
new file mode 100755
index 0000000..77271b5
--- /dev/null
+++ b/lib/setup/sv/sysvinit/conntrackd
@@ -0,0 +1,41 @@
+#!/bin/sh
+### BEGIN INIT INFO
+# Provides:          conntrackd
+# Required-Start:    $remote_fs
+# Required-Stop:     $remote_fs
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+# Short-Description: connection tracking daemon
+### END INIT INFO
+
+if [ -f /etc/rc.d/init.d/functions ]; then
+	. /etc/rc.d/init.d/functions
+elif [ -f /etc/init.d/functions ]; then
+	. /etc/init.d/functions
+fi
+
+NAME=conntrackd
+DAEMON="/usr/sbin/conntrackd"
+DAEMON_ARGS="-C /etc/conntrackd/conntrackd.conf"
+PIDFILE="/run/conntrackd.pid"
+USER=""
+
+start() {
+	start_daemon -p "$PIDFILE" ${USER:+-c "$USER"} "$DAEMON" $DAEMON_ARGS
+}
+
+stop() {
+	killproc -p "$PIDFILE" "$DAEMON"
+}
+
+status() {
+	pidofproc -p "$PIDFILE" "$DAEMON"
+}
+
+case $1 in
+	start) start ;;
+	stop) stop ;;
+	restart) stop; start ;;
+	status) status ;;
+	*) printf '%s\n' "Usage: $0 {start|stop|restart|status}" >&2; exit 1 ;;
+esac
diff --git a/lib/setup/sv/sysvinit/crond b/lib/setup/sv/sysvinit/crond
new file mode 100755
index 0000000..c4698af
--- /dev/null
+++ b/lib/setup/sv/sysvinit/crond
@@ -0,0 +1,41 @@
+#!/bin/sh
+### BEGIN INIT INFO
+# Provides:          crond
+# Required-Start:    $remote_fs
+# Required-Stop:     $remote_fs
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+# Short-Description: cron daemon
+### END INIT INFO
+
+if [ -f /etc/rc.d/init.d/functions ]; then
+	. /etc/rc.d/init.d/functions
+elif [ -f /etc/init.d/functions ]; then
+	. /etc/init.d/functions
+fi
+
+NAME=crond
+DAEMON="/usr/sbin/crond"
+DAEMON_ARGS="-n"
+PIDFILE="/run/crond.pid"
+USER=""
+
+start() {
+	start_daemon -p "$PIDFILE" ${USER:+-c "$USER"} "$DAEMON" $DAEMON_ARGS
+}
+
+stop() {
+	killproc -p "$PIDFILE" "$DAEMON"
+}
+
+status() {
+	pidofproc -p "$PIDFILE" "$DAEMON"
+}
+
+case $1 in
+	start) start ;;
+	stop) stop ;;
+	restart) stop; start ;;
+	status) status ;;
+	*) printf '%s\n' "Usage: $0 {start|stop|restart|status}" >&2; exit 1 ;;
+esac
diff --git a/lib/setup/sv/sysvinit/cupsd b/lib/setup/sv/sysvinit/cupsd
new file mode 100755
index 0000000..5bf1d55
--- /dev/null
+++ b/lib/setup/sv/sysvinit/cupsd
@@ -0,0 +1,41 @@
+#!/bin/sh
+### BEGIN INIT INFO
+# Provides:          cupsd
+# Required-Start:    $remote_fs dbus
+# Required-Stop:     $remote_fs dbus
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+# Short-Description: CUPS printing service
+### END INIT INFO
+
+if [ -f /etc/rc.d/init.d/functions ]; then
+	. /etc/rc.d/init.d/functions
+elif [ -f /etc/init.d/functions ]; then
+	. /etc/init.d/functions
+fi
+
+NAME=cupsd
+DAEMON="/usr/sbin/cupsd"
+DAEMON_ARGS="-f"
+PIDFILE="/run/cupsd.pid"
+USER=""
+
+start() {
+	start_daemon -p "$PIDFILE" ${USER:+-c "$USER"} "$DAEMON" $DAEMON_ARGS
+}
+
+stop() {
+	killproc -p "$PIDFILE" "$DAEMON"
+}
+
+status() {
+	pidofproc -p "$PIDFILE" "$DAEMON"
+}
+
+case $1 in
+	start) start ;;
+	stop) stop ;;
+	restart) stop; start ;;
+	status) status ;;
+	*) printf '%s\n' "Usage: $0 {start|stop|restart|status}" >&2; exit 1 ;;
+esac
diff --git a/lib/setup/sv/sysvinit/dbus b/lib/setup/sv/sysvinit/dbus
new file mode 100755
index 0000000..492da8e
--- /dev/null
+++ b/lib/setup/sv/sysvinit/dbus
@@ -0,0 +1,42 @@
+#!/bin/sh
+### BEGIN INIT INFO
+# Provides:          dbus
+# Required-Start:    $remote_fs
+# Required-Stop:     $remote_fs
+# Default-Start:     S
+# Default-Stop:      
+# Short-Description: D-Bus system message bus
+### END INIT INFO
+
+if [ -f /etc/rc.d/init.d/functions ]; then
+	. /etc/rc.d/init.d/functions
+elif [ -f /etc/init.d/functions ]; then
+	. /etc/init.d/functions
+fi
+
+NAME=dbus
+DAEMON="/usr/bin/dbus-daemon"
+DAEMON_ARGS="--system --nofork --nopidfile --nosyslog"
+PIDFILE="/run/dbus.pid"
+USER=""
+
+start() {
+	mkdir -p /run/dbus /var/lib/dbus
+	start_daemon -p "$PIDFILE" ${USER:+-c "$USER"} "$DAEMON" $DAEMON_ARGS
+}
+
+stop() {
+	killproc -p "$PIDFILE" "$DAEMON"
+}
+
+status() {
+	pidofproc -p "$PIDFILE" "$DAEMON"
+}
+
+case $1 in
+	start) start ;;
+	stop) stop ;;
+	restart) stop; start ;;
+	status) status ;;
+	*) printf '%s\n' "Usage: $0 {start|stop|restart|status}" >&2; exit 1 ;;
+esac
diff --git a/lib/setup/sv/sysvinit/dhcpcd b/lib/setup/sv/sysvinit/dhcpcd
new file mode 100755
index 0000000..b2829c7
--- /dev/null
+++ b/lib/setup/sv/sysvinit/dhcpcd
@@ -0,0 +1,41 @@
+#!/bin/sh
+### BEGIN INIT INFO
+# Provides:          dhcpcd
+# Required-Start:    $remote_fs
+# Required-Stop:     $remote_fs
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+# Short-Description: DHCP client daemon
+### END INIT INFO
+
+if [ -f /etc/rc.d/init.d/functions ]; then
+	. /etc/rc.d/init.d/functions
+elif [ -f /etc/init.d/functions ]; then
+	. /etc/init.d/functions
+fi
+
+NAME=dhcpcd
+DAEMON="/usr/sbin/dhcpcd"
+DAEMON_ARGS="--nobackground"
+PIDFILE="/run/dhcpcd.pid"
+USER=""
+
+start() {
+	start_daemon -p "$PIDFILE" ${USER:+-c "$USER"} "$DAEMON" $DAEMON_ARGS
+}
+
+stop() {
+	killproc -p "$PIDFILE" "$DAEMON"
+}
+
+status() {
+	pidofproc -p "$PIDFILE" "$DAEMON"
+}
+
+case $1 in
+	start) start ;;
+	stop) stop ;;
+	restart) stop; start ;;
+	status) status ;;
+	*) printf '%s\n' "Usage: $0 {start|stop|restart|status}" >&2; exit 1 ;;
+esac
diff --git a/lib/setup/sv/sysvinit/distccd b/lib/setup/sv/sysvinit/distccd
new file mode 100755
index 0000000..91fa93b
--- /dev/null
+++ b/lib/setup/sv/sysvinit/distccd
@@ -0,0 +1,41 @@
+#!/bin/sh
+### BEGIN INIT INFO
+# Provides:          distccd
+# Required-Start:    $remote_fs
+# Required-Stop:     $remote_fs
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+# Short-Description: distributed C/C++ compilation daemon
+### END INIT INFO
+
+if [ -f /etc/rc.d/init.d/functions ]; then
+	. /etc/rc.d/init.d/functions
+elif [ -f /etc/init.d/functions ]; then
+	. /etc/init.d/functions
+fi
+
+NAME=distccd
+DAEMON="/usr/bin/distccd"
+DAEMON_ARGS="--no-detach --allow 127.0.0.1 --log-stderr"
+PIDFILE="/run/distccd.pid"
+USER=""
+
+start() {
+	start_daemon -p "$PIDFILE" ${USER:+-c "$USER"} "$DAEMON" $DAEMON_ARGS
+}
+
+stop() {
+	killproc -p "$PIDFILE" "$DAEMON"
+}
+
+status() {
+	pidofproc -p "$PIDFILE" "$DAEMON"
+}
+
+case $1 in
+	start) start ;;
+	stop) stop ;;
+	restart) stop; start ;;
+	status) status ;;
+	*) printf '%s\n' "Usage: $0 {start|stop|restart|status}" >&2; exit 1 ;;
+esac
diff --git a/lib/setup/sv/sysvinit/dnsmasq b/lib/setup/sv/sysvinit/dnsmasq
new file mode 100755
index 0000000..f2aa933
--- /dev/null
+++ b/lib/setup/sv/sysvinit/dnsmasq
@@ -0,0 +1,41 @@
+#!/bin/sh
+### BEGIN INIT INFO
+# Provides:          dnsmasq
+# Required-Start:    $remote_fs
+# Required-Stop:     $remote_fs
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+# Short-Description: DNS and DHCP server
+### END INIT INFO
+
+if [ -f /etc/rc.d/init.d/functions ]; then
+	. /etc/rc.d/init.d/functions
+elif [ -f /etc/init.d/functions ]; then
+	. /etc/init.d/functions
+fi
+
+NAME=dnsmasq
+DAEMON="/usr/sbin/dnsmasq"
+DAEMON_ARGS="-k"
+PIDFILE="/run/dnsmasq.pid"
+USER=""
+
+start() {
+	start_daemon -p "$PIDFILE" ${USER:+-c "$USER"} "$DAEMON" $DAEMON_ARGS
+}
+
+stop() {
+	killproc -p "$PIDFILE" "$DAEMON"
+}
+
+status() {
+	pidofproc -p "$PIDFILE" "$DAEMON"
+}
+
+case $1 in
+	start) start ;;
+	stop) stop ;;
+	restart) stop; start ;;
+	status) status ;;
+	*) printf '%s\n' "Usage: $0 {start|stop|restart|status}" >&2; exit 1 ;;
+esac
diff --git a/lib/setup/sv/sysvinit/dropbear b/lib/setup/sv/sysvinit/dropbear
new file mode 100755
index 0000000..b4d565c
--- /dev/null
+++ b/lib/setup/sv/sysvinit/dropbear
@@ -0,0 +1,45 @@
+#!/bin/sh
+### BEGIN INIT INFO
+# Provides:          dropbear
+# Required-Start:    $remote_fs
+# Required-Stop:     $remote_fs
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+# Short-Description: Dropbear SSH server
+### END INIT INFO
+
+if [ -f /etc/rc.d/init.d/functions ]; then
+	. /etc/rc.d/init.d/functions
+elif [ -f /etc/init.d/functions ]; then
+	. /etc/init.d/functions
+fi
+
+NAME=dropbear
+DAEMON="/usr/sbin/dropbear"
+DAEMON_ARGS="-F -E"
+PIDFILE="/run/dropbear.pid"
+USER=""
+
+start() {
+	if command -v dropbearkey >/dev/null 2>&1; then
+	  mkdir -p /etc/dropbear
+	  [ -f /etc/dropbear/dropbear_rsa_host_key ] || dropbearkey -t rsa -f /etc/dropbear/dropbear_rsa_host_key >/dev/null
+	fi
+	start_daemon -p "$PIDFILE" ${USER:+-c "$USER"} "$DAEMON" $DAEMON_ARGS
+}
+
+stop() {
+	killproc -p "$PIDFILE" "$DAEMON"
+}
+
+status() {
+	pidofproc -p "$PIDFILE" "$DAEMON"
+}
+
+case $1 in
+	start) start ;;
+	stop) stop ;;
+	restart) stop; start ;;
+	status) status ;;
+	*) printf '%s\n' "Usage: $0 {start|stop|restart|status}" >&2; exit 1 ;;
+esac
diff --git a/lib/setup/sv/sysvinit/elogind b/lib/setup/sv/sysvinit/elogind
new file mode 100755
index 0000000..28c8cc7
--- /dev/null
+++ b/lib/setup/sv/sysvinit/elogind
@@ -0,0 +1,41 @@
+#!/bin/sh
+### BEGIN INIT INFO
+# Provides:          elogind
+# Required-Start:    $remote_fs dbus
+# Required-Stop:     $remote_fs dbus
+# Default-Start:     S
+# Default-Stop:      
+# Short-Description: elogind login manager
+### END INIT INFO
+
+if [ -f /etc/rc.d/init.d/functions ]; then
+	. /etc/rc.d/init.d/functions
+elif [ -f /etc/init.d/functions ]; then
+	. /etc/init.d/functions
+fi
+
+NAME=elogind
+DAEMON="/usr/libexec/elogind"
+DAEMON_ARGS=""
+PIDFILE="/run/elogind.pid"
+USER=""
+
+start() {
+	start_daemon -p "$PIDFILE" ${USER:+-c "$USER"} "$DAEMON" $DAEMON_ARGS
+}
+
+stop() {
+	killproc -p "$PIDFILE" "$DAEMON"
+}
+
+status() {
+	pidofproc -p "$PIDFILE" "$DAEMON"
+}
+
+case $1 in
+	start) start ;;
+	stop) stop ;;
+	restart) stop; start ;;
+	status) status ;;
+	*) printf '%s\n' "Usage: $0 {start|stop|restart|status}" >&2; exit 1 ;;
+esac
diff --git a/lib/setup/sv/sysvinit/fail2ban b/lib/setup/sv/sysvinit/fail2ban
new file mode 100755
index 0000000..1726512
--- /dev/null
+++ b/lib/setup/sv/sysvinit/fail2ban
@@ -0,0 +1,41 @@
+#!/bin/sh
+### BEGIN INIT INFO
+# Provides:          fail2ban
+# Required-Start:    $remote_fs
+# Required-Stop:     $remote_fs
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+# Short-Description: fail2ban authentication ban daemon
+### END INIT INFO
+
+if [ -f /etc/rc.d/init.d/functions ]; then
+	. /etc/rc.d/init.d/functions
+elif [ -f /etc/init.d/functions ]; then
+	. /etc/init.d/functions
+fi
+
+NAME=fail2ban
+DAEMON="/usr/bin/fail2ban-server"
+DAEMON_ARGS="-xf --logtarget=stdout"
+PIDFILE="/run/fail2ban.pid"
+USER=""
+
+start() {
+	start_daemon -p "$PIDFILE" ${USER:+-c "$USER"} "$DAEMON" $DAEMON_ARGS
+}
+
+stop() {
+	killproc -p "$PIDFILE" "$DAEMON"
+}
+
+status() {
+	pidofproc -p "$PIDFILE" "$DAEMON"
+}
+
+case $1 in
+	start) start ;;
+	stop) stop ;;
+	restart) stop; start ;;
+	status) status ;;
+	*) printf '%s\n' "Usage: $0 {start|stop|restart|status}" >&2; exit 1 ;;
+esac
diff --git a/lib/setup/sv/sysvinit/haproxy b/lib/setup/sv/sysvinit/haproxy
new file mode 100755
index 0000000..7c53338
--- /dev/null
+++ b/lib/setup/sv/sysvinit/haproxy
@@ -0,0 +1,41 @@
+#!/bin/sh
+### BEGIN INIT INFO
+# Provides:          haproxy
+# Required-Start:    $remote_fs
+# Required-Stop:     $remote_fs
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+# Short-Description: HAProxy load balancer
+### END INIT INFO
+
+if [ -f /etc/rc.d/init.d/functions ]; then
+	. /etc/rc.d/init.d/functions
+elif [ -f /etc/init.d/functions ]; then
+	. /etc/init.d/functions
+fi
+
+NAME=haproxy
+DAEMON="/usr/sbin/haproxy"
+DAEMON_ARGS="-f /etc/haproxy/haproxy.cfg -db"
+PIDFILE="/run/haproxy.pid"
+USER=""
+
+start() {
+	start_daemon -p "$PIDFILE" ${USER:+-c "$USER"} "$DAEMON" $DAEMON_ARGS
+}
+
+stop() {
+	killproc -p "$PIDFILE" "$DAEMON"
+}
+
+status() {
+	pidofproc -p "$PIDFILE" "$DAEMON"
+}
+
+case $1 in
+	start) start ;;
+	stop) stop ;;
+	restart) stop; start ;;
+	status) status ;;
+	*) printf '%s\n' "Usage: $0 {start|stop|restart|status}" >&2; exit 1 ;;
+esac
diff --git a/lib/setup/sv/sysvinit/haveged b/lib/setup/sv/sysvinit/haveged
new file mode 100755
index 0000000..5b5e5bd
--- /dev/null
+++ b/lib/setup/sv/sysvinit/haveged
@@ -0,0 +1,41 @@
+#!/bin/sh
+### BEGIN INIT INFO
+# Provides:          haveged
+# Required-Start:    $remote_fs
+# Required-Stop:     $remote_fs
+# Default-Start:     S
+# Default-Stop:      
+# Short-Description: haveged entropy daemon
+### END INIT INFO
+
+if [ -f /etc/rc.d/init.d/functions ]; then
+	. /etc/rc.d/init.d/functions
+elif [ -f /etc/init.d/functions ]; then
+	. /etc/init.d/functions
+fi
+
+NAME=haveged
+DAEMON="/usr/sbin/haveged"
+DAEMON_ARGS="-w 1024 -F"
+PIDFILE="/run/haveged.pid"
+USER=""
+
+start() {
+	start_daemon -p "$PIDFILE" ${USER:+-c "$USER"} "$DAEMON" $DAEMON_ARGS
+}
+
+stop() {
+	killproc -p "$PIDFILE" "$DAEMON"
+}
+
+status() {
+	pidofproc -p "$PIDFILE" "$DAEMON"
+}
+
+case $1 in
+	start) start ;;
+	stop) stop ;;
+	restart) stop; start ;;
+	status) status ;;
+	*) printf '%s\n' "Usage: $0 {start|stop|restart|status}" >&2; exit 1 ;;
+esac
diff --git a/lib/setup/sv/sysvinit/iwd b/lib/setup/sv/sysvinit/iwd
new file mode 100755
index 0000000..c3834a8
--- /dev/null
+++ b/lib/setup/sv/sysvinit/iwd
@@ -0,0 +1,41 @@
+#!/bin/sh
+### BEGIN INIT INFO
+# Provides:          iwd
+# Required-Start:    $remote_fs dbus
+# Required-Stop:     $remote_fs dbus
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+# Short-Description: iNet wireless daemon
+### END INIT INFO
+
+if [ -f /etc/rc.d/init.d/functions ]; then
+	. /etc/rc.d/init.d/functions
+elif [ -f /etc/init.d/functions ]; then
+	. /etc/init.d/functions
+fi
+
+NAME=iwd
+DAEMON="/usr/libexec/iwd"
+DAEMON_ARGS=""
+PIDFILE="/run/iwd.pid"
+USER=""
+
+start() {
+	start_daemon -p "$PIDFILE" ${USER:+-c "$USER"} "$DAEMON" $DAEMON_ARGS
+}
+
+stop() {
+	killproc -p "$PIDFILE" "$DAEMON"
+}
+
+status() {
+	pidofproc -p "$PIDFILE" "$DAEMON"
+}
+
+case $1 in
+	start) start ;;
+	stop) stop ;;
+	restart) stop; start ;;
+	status) status ;;
+	*) printf '%s\n' "Usage: $0 {start|stop|restart|status}" >&2; exit 1 ;;
+esac
diff --git a/lib/setup/sv/sysvinit/libvirtd b/lib/setup/sv/sysvinit/libvirtd
new file mode 100755
index 0000000..bc8eae1
--- /dev/null
+++ b/lib/setup/sv/sysvinit/libvirtd
@@ -0,0 +1,41 @@
+#!/bin/sh
+### BEGIN INIT INFO
+# Provides:          libvirtd
+# Required-Start:    $remote_fs dbus
+# Required-Stop:     $remote_fs dbus
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+# Short-Description: libvirt virtualization daemon
+### END INIT INFO
+
+if [ -f /etc/rc.d/init.d/functions ]; then
+	. /etc/rc.d/init.d/functions
+elif [ -f /etc/init.d/functions ]; then
+	. /etc/init.d/functions
+fi
+
+NAME=libvirtd
+DAEMON="/usr/sbin/libvirtd"
+DAEMON_ARGS=""
+PIDFILE="/run/libvirtd.pid"
+USER=""
+
+start() {
+	start_daemon -p "$PIDFILE" ${USER:+-c "$USER"} "$DAEMON" $DAEMON_ARGS
+}
+
+stop() {
+	killproc -p "$PIDFILE" "$DAEMON"
+}
+
+status() {
+	pidofproc -p "$PIDFILE" "$DAEMON"
+}
+
+case $1 in
+	start) start ;;
+	stop) stop ;;
+	restart) stop; start ;;
+	status) status ;;
+	*) printf '%s\n' "Usage: $0 {start|stop|restart|status}" >&2; exit 1 ;;
+esac
diff --git a/lib/setup/sv/sysvinit/lighttpd b/lib/setup/sv/sysvinit/lighttpd
new file mode 100755
index 0000000..746b234
--- /dev/null
+++ b/lib/setup/sv/sysvinit/lighttpd
@@ -0,0 +1,41 @@
+#!/bin/sh
+### BEGIN INIT INFO
+# Provides:          lighttpd
+# Required-Start:    $remote_fs
+# Required-Stop:     $remote_fs
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+# Short-Description: lighttpd web server
+### END INIT INFO
+
+if [ -f /etc/rc.d/init.d/functions ]; then
+	. /etc/rc.d/init.d/functions
+elif [ -f /etc/init.d/functions ]; then
+	. /etc/init.d/functions
+fi
+
+NAME=lighttpd
+DAEMON="/usr/sbin/lighttpd"
+DAEMON_ARGS="-D -f /etc/lighttpd/lighttpd.conf"
+PIDFILE="/run/lighttpd.pid"
+USER=""
+
+start() {
+	start_daemon -p "$PIDFILE" ${USER:+-c "$USER"} "$DAEMON" $DAEMON_ARGS
+}
+
+stop() {
+	killproc -p "$PIDFILE" "$DAEMON"
+}
+
+status() {
+	pidofproc -p "$PIDFILE" "$DAEMON"
+}
+
+case $1 in
+	start) start ;;
+	stop) stop ;;
+	restart) stop; start ;;
+	status) status ;;
+	*) printf '%s\n' "Usage: $0 {start|stop|restart|status}" >&2; exit 1 ;;
+esac
diff --git a/lib/setup/sv/sysvinit/lxc-net b/lib/setup/sv/sysvinit/lxc-net
new file mode 100755
index 0000000..ae328c5
--- /dev/null
+++ b/lib/setup/sv/sysvinit/lxc-net
@@ -0,0 +1,42 @@
+#!/bin/sh
+### BEGIN INIT INFO
+# Provides:          lxc-net
+# Required-Start:    $remote_fs
+# Required-Stop:     $remote_fs
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+# Short-Description: LXC bridge networking
+### END INIT INFO
+
+if [ -f /etc/rc.d/init.d/functions ]; then
+	. /etc/rc.d/init.d/functions
+elif [ -f /etc/init.d/functions ]; then
+	. /etc/init.d/functions
+fi
+
+NAME=lxc-net
+DAEMON="/usr/libexec/lxc/lxc-net"
+DAEMON_ARGS="start"
+PIDFILE="/run/lxc-net.pid"
+USER=""
+
+start() {
+	eval "$DAEMON" $DAEMON_ARGS
+	return $?
+}
+
+stop() {
+	return 0
+}
+
+status() {
+	pidofproc -p "$PIDFILE" "$DAEMON"
+}
+
+case $1 in
+	start) start ;;
+	stop) stop ;;
+	restart) stop; start ;;
+	status) status ;;
+	*) printf '%s\n' "Usage: $0 {start|stop|restart|status}" >&2; exit 1 ;;
+esac
diff --git a/lib/setup/sv/sysvinit/mariadbd b/lib/setup/sv/sysvinit/mariadbd
new file mode 100755
index 0000000..6ad1e6d
--- /dev/null
+++ b/lib/setup/sv/sysvinit/mariadbd
@@ -0,0 +1,42 @@
+#!/bin/sh
+### BEGIN INIT INFO
+# Provides:          mariadbd
+# Required-Start:    $remote_fs
+# Required-Stop:     $remote_fs
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+# Short-Description: MariaDB database server
+### END INIT INFO
+
+if [ -f /etc/rc.d/init.d/functions ]; then
+	. /etc/rc.d/init.d/functions
+elif [ -f /etc/init.d/functions ]; then
+	. /etc/init.d/functions
+fi
+
+NAME=mariadbd
+DAEMON="/usr/sbin/mariadbd"
+DAEMON_ARGS="--datadir=/var/lib/mysql"
+PIDFILE="/run/mariadbd.pid"
+USER="mysql"
+
+start() {
+	install -d -m 0750 /run/mysqld /var/lib/mysql || :
+	start_daemon -p "$PIDFILE" ${USER:+-c "$USER"} "$DAEMON" $DAEMON_ARGS
+}
+
+stop() {
+	killproc -p "$PIDFILE" "$DAEMON"
+}
+
+status() {
+	pidofproc -p "$PIDFILE" "$DAEMON"
+}
+
+case $1 in
+	start) start ;;
+	stop) stop ;;
+	restart) stop; start ;;
+	status) status ;;
+	*) printf '%s\n' "Usage: $0 {start|stop|restart|status}" >&2; exit 1 ;;
+esac
diff --git a/lib/setup/sv/sysvinit/memcached b/lib/setup/sv/sysvinit/memcached
new file mode 100755
index 0000000..d26101b
--- /dev/null
+++ b/lib/setup/sv/sysvinit/memcached
@@ -0,0 +1,41 @@
+#!/bin/sh
+### BEGIN INIT INFO
+# Provides:          memcached
+# Required-Start:    $remote_fs
+# Required-Stop:     $remote_fs
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+# Short-Description: memcached object cache
+### END INIT INFO
+
+if [ -f /etc/rc.d/init.d/functions ]; then
+	. /etc/rc.d/init.d/functions
+elif [ -f /etc/init.d/functions ]; then
+	. /etc/init.d/functions
+fi
+
+NAME=memcached
+DAEMON="/usr/bin/memcached"
+DAEMON_ARGS="-u nobody"
+PIDFILE="/run/memcached.pid"
+USER=""
+
+start() {
+	start_daemon -p "$PIDFILE" ${USER:+-c "$USER"} "$DAEMON" $DAEMON_ARGS
+}
+
+stop() {
+	killproc -p "$PIDFILE" "$DAEMON"
+}
+
+status() {
+	pidofproc -p "$PIDFILE" "$DAEMON"
+}
+
+case $1 in
+	start) start ;;
+	stop) stop ;;
+	restart) stop; start ;;
+	status) status ;;
+	*) printf '%s\n' "Usage: $0 {start|stop|restart|status}" >&2; exit 1 ;;
+esac
diff --git a/lib/setup/sv/sysvinit/nfs-server b/lib/setup/sv/sysvinit/nfs-server
new file mode 100755
index 0000000..467db75
--- /dev/null
+++ b/lib/setup/sv/sysvinit/nfs-server
@@ -0,0 +1,44 @@
+#!/bin/sh
+### BEGIN INIT INFO
+# Provides:          nfs-server
+# Required-Start:    $remote_fs
+# Required-Stop:     $remote_fs
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+# Short-Description: NFS server
+### END INIT INFO
+
+if [ -f /etc/rc.d/init.d/functions ]; then
+	. /etc/rc.d/init.d/functions
+elif [ -f /etc/init.d/functions ]; then
+	. /etc/init.d/functions
+fi
+
+NAME=nfs-server
+DAEMON="/usr/sbin/rpc.mountd"
+DAEMON_ARGS="-F"
+PIDFILE="/run/nfs-server.pid"
+USER=""
+
+start() {
+	if command -v exportfs >/dev/null 2>&1; then exportfs -ra || :; fi
+	if command -v rpc.statd >/dev/null 2>&1; then rpc.statd --no-notify || :; fi
+	if command -v rpc.nfsd >/dev/null 2>&1; then rpc.nfsd 8 || :; fi
+	start_daemon -p "$PIDFILE" ${USER:+-c "$USER"} "$DAEMON" $DAEMON_ARGS
+}
+
+stop() {
+	killproc -p "$PIDFILE" "$DAEMON"
+}
+
+status() {
+	pidofproc -p "$PIDFILE" "$DAEMON"
+}
+
+case $1 in
+	start) start ;;
+	stop) stop ;;
+	restart) stop; start ;;
+	status) status ;;
+	*) printf '%s\n' "Usage: $0 {start|stop|restart|status}" >&2; exit 1 ;;
+esac
diff --git a/lib/setup/sv/sysvinit/nftables b/lib/setup/sv/sysvinit/nftables
new file mode 100755
index 0000000..7d7d6f8
--- /dev/null
+++ b/lib/setup/sv/sysvinit/nftables
@@ -0,0 +1,42 @@
+#!/bin/sh
+### BEGIN INIT INFO
+# Provides:          nftables
+# Required-Start:    $remote_fs
+# Required-Stop:     $remote_fs
+# Default-Start:     S
+# Default-Stop:      
+# Short-Description: nftables packet filter
+### END INIT INFO
+
+if [ -f /etc/rc.d/init.d/functions ]; then
+	. /etc/rc.d/init.d/functions
+elif [ -f /etc/init.d/functions ]; then
+	. /etc/init.d/functions
+fi
+
+NAME=nftables
+DAEMON="/usr/sbin/nft"
+DAEMON_ARGS="-f /etc/nftables.conf"
+PIDFILE="/run/nftables.pid"
+USER=""
+
+start() {
+	eval "$DAEMON" $DAEMON_ARGS
+	return $?
+}
+
+stop() {
+	return 0
+}
+
+status() {
+	pidofproc -p "$PIDFILE" "$DAEMON"
+}
+
+case $1 in
+	start) start ;;
+	stop) stop ;;
+	restart) stop; start ;;
+	status) status ;;
+	*) printf '%s\n' "Usage: $0 {start|stop|restart|status}" >&2; exit 1 ;;
+esac
diff --git a/lib/setup/sv/sysvinit/nginx b/lib/setup/sv/sysvinit/nginx
new file mode 100755
index 0000000..4929769
--- /dev/null
+++ b/lib/setup/sv/sysvinit/nginx
@@ -0,0 +1,41 @@
+#!/bin/sh
+### BEGIN INIT INFO
+# Provides:          nginx
+# Required-Start:    $remote_fs
+# Required-Stop:     $remote_fs
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+# Short-Description: nginx HTTP server
+### END INIT INFO
+
+if [ -f /etc/rc.d/init.d/functions ]; then
+	. /etc/rc.d/init.d/functions
+elif [ -f /etc/init.d/functions ]; then
+	. /etc/init.d/functions
+fi
+
+NAME=nginx
+DAEMON="/usr/bin/nginx"
+DAEMON_ARGS="-g daemon off;"
+PIDFILE="/run/nginx.pid"
+USER=""
+
+start() {
+	start_daemon -p "$PIDFILE" ${USER:+-c "$USER"} "$DAEMON" $DAEMON_ARGS
+}
+
+stop() {
+	killproc -p "$PIDFILE" "$DAEMON"
+}
+
+status() {
+	pidofproc -p "$PIDFILE" "$DAEMON"
+}
+
+case $1 in
+	start) start ;;
+	stop) stop ;;
+	restart) stop; start ;;
+	status) status ;;
+	*) printf '%s\n' "Usage: $0 {start|stop|restart|status}" >&2; exit 1 ;;
+esac
diff --git a/lib/setup/sv/sysvinit/openvpn b/lib/setup/sv/sysvinit/openvpn
new file mode 100755
index 0000000..b97b38a
--- /dev/null
+++ b/lib/setup/sv/sysvinit/openvpn
@@ -0,0 +1,41 @@
+#!/bin/sh
+### BEGIN INIT INFO
+# Provides:          openvpn
+# Required-Start:    $remote_fs
+# Required-Stop:     $remote_fs
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+# Short-Description: OpenVPN server
+### END INIT INFO
+
+if [ -f /etc/rc.d/init.d/functions ]; then
+	. /etc/rc.d/init.d/functions
+elif [ -f /etc/init.d/functions ]; then
+	. /etc/init.d/functions
+fi
+
+NAME=openvpn
+DAEMON="/usr/sbin/openvpn"
+DAEMON_ARGS="--config /etc/openvpn/server.conf"
+PIDFILE="/run/openvpn.pid"
+USER=""
+
+start() {
+	start_daemon -p "$PIDFILE" ${USER:+-c "$USER"} "$DAEMON" $DAEMON_ARGS
+}
+
+stop() {
+	killproc -p "$PIDFILE" "$DAEMON"
+}
+
+status() {
+	pidofproc -p "$PIDFILE" "$DAEMON"
+}
+
+case $1 in
+	start) start ;;
+	stop) stop ;;
+	restart) stop; start ;;
+	status) status ;;
+	*) printf '%s\n' "Usage: $0 {start|stop|restart|status}" >&2; exit 1 ;;
+esac
diff --git a/lib/setup/sv/sysvinit/pipewire b/lib/setup/sv/sysvinit/pipewire
new file mode 100755
index 0000000..58d2e87
--- /dev/null
+++ b/lib/setup/sv/sysvinit/pipewire
@@ -0,0 +1,41 @@
+#!/bin/sh
+### BEGIN INIT INFO
+# Provides:          pipewire
+# Required-Start:    $remote_fs dbus
+# Required-Stop:     $remote_fs dbus
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+# Short-Description: PipeWire multimedia server
+### END INIT INFO
+
+if [ -f /etc/rc.d/init.d/functions ]; then
+	. /etc/rc.d/init.d/functions
+elif [ -f /etc/init.d/functions ]; then
+	. /etc/init.d/functions
+fi
+
+NAME=pipewire
+DAEMON="/usr/bin/pipewire"
+DAEMON_ARGS=""
+PIDFILE="/run/pipewire.pid"
+USER=""
+
+start() {
+	start_daemon -p "$PIDFILE" ${USER:+-c "$USER"} "$DAEMON" $DAEMON_ARGS
+}
+
+stop() {
+	killproc -p "$PIDFILE" "$DAEMON"
+}
+
+status() {
+	pidofproc -p "$PIDFILE" "$DAEMON"
+}
+
+case $1 in
+	start) start ;;
+	stop) stop ;;
+	restart) stop; start ;;
+	status) status ;;
+	*) printf '%s\n' "Usage: $0 {start|stop|restart|status}" >&2; exit 1 ;;
+esac
diff --git a/lib/setup/sv/sysvinit/polkitd b/lib/setup/sv/sysvinit/polkitd
new file mode 100755
index 0000000..1cb3b58
--- /dev/null
+++ b/lib/setup/sv/sysvinit/polkitd
@@ -0,0 +1,41 @@
+#!/bin/sh
+### BEGIN INIT INFO
+# Provides:          polkitd
+# Required-Start:    $remote_fs dbus
+# Required-Stop:     $remote_fs dbus
+# Default-Start:     S
+# Default-Stop:      
+# Short-Description: polkit authorization manager
+### END INIT INFO
+
+if [ -f /etc/rc.d/init.d/functions ]; then
+	. /etc/rc.d/init.d/functions
+elif [ -f /etc/init.d/functions ]; then
+	. /etc/init.d/functions
+fi
+
+NAME=polkitd
+DAEMON="/usr/libexec/polkitd"
+DAEMON_ARGS="--no-debug"
+PIDFILE="/run/polkitd.pid"
+USER=""
+
+start() {
+	start_daemon -p "$PIDFILE" ${USER:+-c "$USER"} "$DAEMON" $DAEMON_ARGS
+}
+
+stop() {
+	killproc -p "$PIDFILE" "$DAEMON"
+}
+
+status() {
+	pidofproc -p "$PIDFILE" "$DAEMON"
+}
+
+case $1 in
+	start) start ;;
+	stop) stop ;;
+	restart) stop; start ;;
+	status) status ;;
+	*) printf '%s\n' "Usage: $0 {start|stop|restart|status}" >&2; exit 1 ;;
+esac
diff --git a/lib/setup/sv/sysvinit/postgresql b/lib/setup/sv/sysvinit/postgresql
new file mode 100755
index 0000000..15606be
--- /dev/null
+++ b/lib/setup/sv/sysvinit/postgresql
@@ -0,0 +1,42 @@
+#!/bin/sh
+### BEGIN INIT INFO
+# Provides:          postgresql
+# Required-Start:    $remote_fs
+# Required-Stop:     $remote_fs
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+# Short-Description: PostgreSQL database server
+### END INIT INFO
+
+if [ -f /etc/rc.d/init.d/functions ]; then
+	. /etc/rc.d/init.d/functions
+elif [ -f /etc/init.d/functions ]; then
+	. /etc/init.d/functions
+fi
+
+NAME=postgresql
+DAEMON="/usr/bin/postgres"
+DAEMON_ARGS="-D /var/lib/postgres/data"
+PIDFILE="/run/postgresql.pid"
+USER="postgres"
+
+start() {
+	install -d -m 0755 /run/postgresql /var/lib/postgres/data || :
+	start_daemon -p "$PIDFILE" ${USER:+-c "$USER"} "$DAEMON" $DAEMON_ARGS
+}
+
+stop() {
+	killproc -p "$PIDFILE" "$DAEMON"
+}
+
+status() {
+	pidofproc -p "$PIDFILE" "$DAEMON"
+}
+
+case $1 in
+	start) start ;;
+	stop) stop ;;
+	restart) stop; start ;;
+	status) status ;;
+	*) printf '%s\n' "Usage: $0 {start|stop|restart|status}" >&2; exit 1 ;;
+esac
diff --git a/lib/setup/sv/sysvinit/power-profiles-daemon b/lib/setup/sv/sysvinit/power-profiles-daemon
new file mode 100755
index 0000000..d74f2eb
--- /dev/null
+++ b/lib/setup/sv/sysvinit/power-profiles-daemon
@@ -0,0 +1,41 @@
+#!/bin/sh
+### BEGIN INIT INFO
+# Provides:          power-profiles-daemon
+# Required-Start:    $remote_fs dbus
+# Required-Stop:     $remote_fs dbus
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+# Short-Description: Power profiles daemon
+### END INIT INFO
+
+if [ -f /etc/rc.d/init.d/functions ]; then
+	. /etc/rc.d/init.d/functions
+elif [ -f /etc/init.d/functions ]; then
+	. /etc/init.d/functions
+fi
+
+NAME=power-profiles-daemon
+DAEMON="/usr/libexec/power-profiles-daemon"
+DAEMON_ARGS=""
+PIDFILE="/run/power-profiles-daemon.pid"
+USER=""
+
+start() {
+	start_daemon -p "$PIDFILE" ${USER:+-c "$USER"} "$DAEMON" $DAEMON_ARGS
+}
+
+stop() {
+	killproc -p "$PIDFILE" "$DAEMON"
+}
+
+status() {
+	pidofproc -p "$PIDFILE" "$DAEMON"
+}
+
+case $1 in
+	start) start ;;
+	stop) stop ;;
+	restart) stop; start ;;
+	status) status ;;
+	*) printf '%s\n' "Usage: $0 {start|stop|restart|status}" >&2; exit 1 ;;
+esac
diff --git a/lib/setup/sv/sysvinit/redis b/lib/setup/sv/sysvinit/redis
new file mode 100755
index 0000000..8bb8b5a
--- /dev/null
+++ b/lib/setup/sv/sysvinit/redis
@@ -0,0 +1,41 @@
+#!/bin/sh
+### BEGIN INIT INFO
+# Provides:          redis
+# Required-Start:    $remote_fs
+# Required-Stop:     $remote_fs
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+# Short-Description: Redis data store
+### END INIT INFO
+
+if [ -f /etc/rc.d/init.d/functions ]; then
+	. /etc/rc.d/init.d/functions
+elif [ -f /etc/init.d/functions ]; then
+	. /etc/init.d/functions
+fi
+
+NAME=redis
+DAEMON="/usr/bin/redis-server"
+DAEMON_ARGS="--daemonize no"
+PIDFILE="/run/redis.pid"
+USER=""
+
+start() {
+	start_daemon -p "$PIDFILE" ${USER:+-c "$USER"} "$DAEMON" $DAEMON_ARGS
+}
+
+stop() {
+	killproc -p "$PIDFILE" "$DAEMON"
+}
+
+status() {
+	pidofproc -p "$PIDFILE" "$DAEMON"
+}
+
+case $1 in
+	start) start ;;
+	stop) stop ;;
+	restart) stop; start ;;
+	status) status ;;
+	*) printf '%s\n' "Usage: $0 {start|stop|restart|status}" >&2; exit 1 ;;
+esac
diff --git a/lib/setup/sv/sysvinit/sddm b/lib/setup/sv/sysvinit/sddm
new file mode 100755
index 0000000..6033f8f
--- /dev/null
+++ b/lib/setup/sv/sysvinit/sddm
@@ -0,0 +1,41 @@
+#!/bin/sh
+### BEGIN INIT INFO
+# Provides:          sddm
+# Required-Start:    $remote_fs dbus
+# Required-Stop:     $remote_fs dbus
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+# Short-Description: Simple Desktop Display Manager
+### END INIT INFO
+
+if [ -f /etc/rc.d/init.d/functions ]; then
+	. /etc/rc.d/init.d/functions
+elif [ -f /etc/init.d/functions ]; then
+	. /etc/init.d/functions
+fi
+
+NAME=sddm
+DAEMON="/usr/bin/sddm"
+DAEMON_ARGS=""
+PIDFILE="/run/sddm.pid"
+USER=""
+
+start() {
+	start_daemon -p "$PIDFILE" ${USER:+-c "$USER"} "$DAEMON" $DAEMON_ARGS
+}
+
+stop() {
+	killproc -p "$PIDFILE" "$DAEMON"
+}
+
+status() {
+	pidofproc -p "$PIDFILE" "$DAEMON"
+}
+
+case $1 in
+	start) start ;;
+	stop) stop ;;
+	restart) stop; start ;;
+	status) status ;;
+	*) printf '%s\n' "Usage: $0 {start|stop|restart|status}" >&2; exit 1 ;;
+esac
diff --git a/lib/setup/sv/sysvinit/seatd b/lib/setup/sv/sysvinit/seatd
new file mode 100755
index 0000000..7b5235e
--- /dev/null
+++ b/lib/setup/sv/sysvinit/seatd
@@ -0,0 +1,41 @@
+#!/bin/sh
+### BEGIN INIT INFO
+# Provides:          seatd
+# Required-Start:    $remote_fs
+# Required-Stop:     $remote_fs
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+# Short-Description: seat management daemon
+### END INIT INFO
+
+if [ -f /etc/rc.d/init.d/functions ]; then
+	. /etc/rc.d/init.d/functions
+elif [ -f /etc/init.d/functions ]; then
+	. /etc/init.d/functions
+fi
+
+NAME=seatd
+DAEMON="/usr/bin/seatd"
+DAEMON_ARGS="-g video"
+PIDFILE="/run/seatd.pid"
+USER=""
+
+start() {
+	start_daemon -p "$PIDFILE" ${USER:+-c "$USER"} "$DAEMON" $DAEMON_ARGS
+}
+
+stop() {
+	killproc -p "$PIDFILE" "$DAEMON"
+}
+
+status() {
+	pidofproc -p "$PIDFILE" "$DAEMON"
+}
+
+case $1 in
+	start) start ;;
+	stop) stop ;;
+	restart) stop; start ;;
+	status) status ;;
+	*) printf '%s\n' "Usage: $0 {start|stop|restart|status}" >&2; exit 1 ;;
+esac
diff --git a/lib/setup/sv/sysvinit/smartd b/lib/setup/sv/sysvinit/smartd
new file mode 100755
index 0000000..3971310
--- /dev/null
+++ b/lib/setup/sv/sysvinit/smartd
@@ -0,0 +1,41 @@
+#!/bin/sh
+### BEGIN INIT INFO
+# Provides:          smartd
+# Required-Start:    $remote_fs
+# Required-Stop:     $remote_fs
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+# Short-Description: S.M.A.R.T. disk monitoring
+### END INIT INFO
+
+if [ -f /etc/rc.d/init.d/functions ]; then
+	. /etc/rc.d/init.d/functions
+elif [ -f /etc/init.d/functions ]; then
+	. /etc/init.d/functions
+fi
+
+NAME=smartd
+DAEMON="/usr/sbin/smartd"
+DAEMON_ARGS="-n"
+PIDFILE="/run/smartd.pid"
+USER=""
+
+start() {
+	start_daemon -p "$PIDFILE" ${USER:+-c "$USER"} "$DAEMON" $DAEMON_ARGS
+}
+
+stop() {
+	killproc -p "$PIDFILE" "$DAEMON"
+}
+
+status() {
+	pidofproc -p "$PIDFILE" "$DAEMON"
+}
+
+case $1 in
+	start) start ;;
+	stop) stop ;;
+	restart) stop; start ;;
+	status) status ;;
+	*) printf '%s\n' "Usage: $0 {start|stop|restart|status}" >&2; exit 1 ;;
+esac
diff --git a/lib/setup/sv/sysvinit/sshd b/lib/setup/sv/sysvinit/sshd
new file mode 100755
index 0000000..12b88b3
--- /dev/null
+++ b/lib/setup/sv/sysvinit/sshd
@@ -0,0 +1,42 @@
+#!/bin/sh
+### BEGIN INIT INFO
+# Provides:          sshd
+# Required-Start:    $remote_fs
+# Required-Stop:     $remote_fs
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+# Short-Description: OpenSSH daemon
+### END INIT INFO
+
+if [ -f /etc/rc.d/init.d/functions ]; then
+	. /etc/rc.d/init.d/functions
+elif [ -f /etc/init.d/functions ]; then
+	. /etc/init.d/functions
+fi
+
+NAME=sshd
+DAEMON="/usr/sbin/sshd"
+DAEMON_ARGS="-D"
+PIDFILE="/run/sshd.pid"
+USER=""
+
+start() {
+	if command -v ssh-keygen >/dev/null 2>&1; then ssh-keygen -A >/dev/null 2>&1 || :; fi
+	start_daemon -p "$PIDFILE" ${USER:+-c "$USER"} "$DAEMON" $DAEMON_ARGS
+}
+
+stop() {
+	killproc -p "$PIDFILE" "$DAEMON"
+}
+
+status() {
+	pidofproc -p "$PIDFILE" "$DAEMON"
+}
+
+case $1 in
+	start) start ;;
+	stop) stop ;;
+	restart) stop; start ;;
+	status) status ;;
+	*) printf '%s\n' "Usage: $0 {start|stop|restart|status}" >&2; exit 1 ;;
+esac
diff --git a/lib/setup/sv/sysvinit/syncthing b/lib/setup/sv/sysvinit/syncthing
new file mode 100755
index 0000000..de0b162
--- /dev/null
+++ b/lib/setup/sv/sysvinit/syncthing
@@ -0,0 +1,42 @@
+#!/bin/sh
+### BEGIN INIT INFO
+# Provides:          syncthing
+# Required-Start:    $remote_fs
+# Required-Stop:     $remote_fs
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+# Short-Description: Syncthing file synchronization
+### END INIT INFO
+
+if [ -f /etc/rc.d/init.d/functions ]; then
+	. /etc/rc.d/init.d/functions
+elif [ -f /etc/init.d/functions ]; then
+	. /etc/init.d/functions
+fi
+
+NAME=syncthing
+DAEMON="/usr/bin/syncthing"
+DAEMON_ARGS="serve --no-browser --home=/var/lib/syncthing"
+PIDFILE="/run/syncthing.pid"
+USER=""
+
+start() {
+	install -d -m 0755 /var/lib/syncthing || :
+	start_daemon -p "$PIDFILE" ${USER:+-c "$USER"} "$DAEMON" $DAEMON_ARGS
+}
+
+stop() {
+	killproc -p "$PIDFILE" "$DAEMON"
+}
+
+status() {
+	pidofproc -p "$PIDFILE" "$DAEMON"
+}
+
+case $1 in
+	start) start ;;
+	stop) stop ;;
+	restart) stop; start ;;
+	status) status ;;
+	*) printf '%s\n' "Usage: $0 {start|stop|restart|status}" >&2; exit 1 ;;
+esac
diff --git a/lib/setup/sv/sysvinit/tinyproxy b/lib/setup/sv/sysvinit/tinyproxy
new file mode 100755
index 0000000..51e7b9c
--- /dev/null
+++ b/lib/setup/sv/sysvinit/tinyproxy
@@ -0,0 +1,41 @@
+#!/bin/sh
+### BEGIN INIT INFO
+# Provides:          tinyproxy
+# Required-Start:    $remote_fs
+# Required-Stop:     $remote_fs
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+# Short-Description: Tinyproxy HTTP proxy
+### END INIT INFO
+
+if [ -f /etc/rc.d/init.d/functions ]; then
+	. /etc/rc.d/init.d/functions
+elif [ -f /etc/init.d/functions ]; then
+	. /etc/init.d/functions
+fi
+
+NAME=tinyproxy
+DAEMON="/usr/bin/tinyproxy"
+DAEMON_ARGS="-d"
+PIDFILE="/run/tinyproxy.pid"
+USER=""
+
+start() {
+	start_daemon -p "$PIDFILE" ${USER:+-c "$USER"} "$DAEMON" $DAEMON_ARGS
+}
+
+stop() {
+	killproc -p "$PIDFILE" "$DAEMON"
+}
+
+status() {
+	pidofproc -p "$PIDFILE" "$DAEMON"
+}
+
+case $1 in
+	start) start ;;
+	stop) stop ;;
+	restart) stop; start ;;
+	status) status ;;
+	*) printf '%s\n' "Usage: $0 {start|stop|restart|status}" >&2; exit 1 ;;
+esac
diff --git a/lib/setup/sv/sysvinit/tlp b/lib/setup/sv/sysvinit/tlp
new file mode 100755
index 0000000..92e4411
--- /dev/null
+++ b/lib/setup/sv/sysvinit/tlp
@@ -0,0 +1,42 @@
+#!/bin/sh
+### BEGIN INIT INFO
+# Provides:          tlp
+# Required-Start:    $remote_fs
+# Required-Stop:     $remote_fs
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+# Short-Description: TLP laptop power management
+### END INIT INFO
+
+if [ -f /etc/rc.d/init.d/functions ]; then
+	. /etc/rc.d/init.d/functions
+elif [ -f /etc/init.d/functions ]; then
+	. /etc/init.d/functions
+fi
+
+NAME=tlp
+DAEMON="/usr/sbin/tlp"
+DAEMON_ARGS="init start"
+PIDFILE="/run/tlp.pid"
+USER=""
+
+start() {
+	eval "$DAEMON" $DAEMON_ARGS
+	return $?
+}
+
+stop() {
+	return 0
+}
+
+status() {
+	pidofproc -p "$PIDFILE" "$DAEMON"
+}
+
+case $1 in
+	start) start ;;
+	stop) stop ;;
+	restart) stop; start ;;
+	status) status ;;
+	*) printf '%s\n' "Usage: $0 {start|stop|restart|status}" >&2; exit 1 ;;
+esac
diff --git a/lib/setup/sv/sysvinit/tor b/lib/setup/sv/sysvinit/tor
new file mode 100755
index 0000000..3ab81ed
--- /dev/null
+++ b/lib/setup/sv/sysvinit/tor
@@ -0,0 +1,41 @@
+#!/bin/sh
+### BEGIN INIT INFO
+# Provides:          tor
+# Required-Start:    $remote_fs
+# Required-Stop:     $remote_fs
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+# Short-Description: Tor anonymity daemon
+### END INIT INFO
+
+if [ -f /etc/rc.d/init.d/functions ]; then
+	. /etc/rc.d/init.d/functions
+elif [ -f /etc/init.d/functions ]; then
+	. /etc/init.d/functions
+fi
+
+NAME=tor
+DAEMON="/usr/bin/tor"
+DAEMON_ARGS="--RunAsDaemon 0"
+PIDFILE="/run/tor.pid"
+USER=""
+
+start() {
+	start_daemon -p "$PIDFILE" ${USER:+-c "$USER"} "$DAEMON" $DAEMON_ARGS
+}
+
+stop() {
+	killproc -p "$PIDFILE" "$DAEMON"
+}
+
+status() {
+	pidofproc -p "$PIDFILE" "$DAEMON"
+}
+
+case $1 in
+	start) start ;;
+	stop) stop ;;
+	restart) stop; start ;;
+	status) status ;;
+	*) printf '%s\n' "Usage: $0 {start|stop|restart|status}" >&2; exit 1 ;;
+esac
diff --git a/lib/setup/sv/sysvinit/transmission-daemon b/lib/setup/sv/sysvinit/transmission-daemon
new file mode 100755
index 0000000..c106520
--- /dev/null
+++ b/lib/setup/sv/sysvinit/transmission-daemon
@@ -0,0 +1,41 @@
+#!/bin/sh
+### BEGIN INIT INFO
+# Provides:          transmission-daemon
+# Required-Start:    $remote_fs
+# Required-Stop:     $remote_fs
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+# Short-Description: Transmission BitTorrent daemon
+### END INIT INFO
+
+if [ -f /etc/rc.d/init.d/functions ]; then
+	. /etc/rc.d/init.d/functions
+elif [ -f /etc/init.d/functions ]; then
+	. /etc/init.d/functions
+fi
+
+NAME=transmission-daemon
+DAEMON="/usr/bin/transmission-daemon"
+DAEMON_ARGS="-f --log-level=error"
+PIDFILE="/run/transmission-daemon.pid"
+USER=""
+
+start() {
+	start_daemon -p "$PIDFILE" ${USER:+-c "$USER"} "$DAEMON" $DAEMON_ARGS
+}
+
+stop() {
+	killproc -p "$PIDFILE" "$DAEMON"
+}
+
+status() {
+	pidofproc -p "$PIDFILE" "$DAEMON"
+}
+
+case $1 in
+	start) start ;;
+	stop) stop ;;
+	restart) stop; start ;;
+	status) status ;;
+	*) printf '%s\n' "Usage: $0 {start|stop|restart|status}" >&2; exit 1 ;;
+esac
diff --git a/lib/setup/sv/sysvinit/udevd b/lib/setup/sv/sysvinit/udevd
new file mode 100755
index 0000000..2dd8b82
--- /dev/null
+++ b/lib/setup/sv/sysvinit/udevd
@@ -0,0 +1,41 @@
+#!/bin/sh
+### BEGIN INIT INFO
+# Provides:          udevd
+# Required-Start:    $remote_fs
+# Required-Stop:     $remote_fs
+# Default-Start:     S
+# Default-Stop:      
+# Short-Description: eudev device manager
+### END INIT INFO
+
+if [ -f /etc/rc.d/init.d/functions ]; then
+	. /etc/rc.d/init.d/functions
+elif [ -f /etc/init.d/functions ]; then
+	. /etc/init.d/functions
+fi
+
+NAME=udevd
+DAEMON="/usr/sbin/udevd"
+DAEMON_ARGS=""
+PIDFILE="/run/udevd.pid"
+USER=""
+
+start() {
+	start_daemon -p "$PIDFILE" ${USER:+-c "$USER"} "$DAEMON" $DAEMON_ARGS
+}
+
+stop() {
+	killproc -p "$PIDFILE" "$DAEMON"
+}
+
+status() {
+	pidofproc -p "$PIDFILE" "$DAEMON"
+}
+
+case $1 in
+	start) start ;;
+	stop) stop ;;
+	restart) stop; start ;;
+	status) status ;;
+	*) printf '%s\n' "Usage: $0 {start|stop|restart|status}" >&2; exit 1 ;;
+esac
diff --git a/lib/setup/sv/sysvinit/unbound b/lib/setup/sv/sysvinit/unbound
new file mode 100755
index 0000000..d5e1f30
--- /dev/null
+++ b/lib/setup/sv/sysvinit/unbound
@@ -0,0 +1,41 @@
+#!/bin/sh
+### BEGIN INIT INFO
+# Provides:          unbound
+# Required-Start:    $remote_fs
+# Required-Stop:     $remote_fs
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+# Short-Description: validating recursive DNS resolver
+### END INIT INFO
+
+if [ -f /etc/rc.d/init.d/functions ]; then
+	. /etc/rc.d/init.d/functions
+elif [ -f /etc/init.d/functions ]; then
+	. /etc/init.d/functions
+fi
+
+NAME=unbound
+DAEMON="/usr/sbin/unbound"
+DAEMON_ARGS="-d"
+PIDFILE="/run/unbound.pid"
+USER=""
+
+start() {
+	start_daemon -p "$PIDFILE" ${USER:+-c "$USER"} "$DAEMON" $DAEMON_ARGS
+}
+
+stop() {
+	killproc -p "$PIDFILE" "$DAEMON"
+}
+
+status() {
+	pidofproc -p "$PIDFILE" "$DAEMON"
+}
+
+case $1 in
+	start) start ;;
+	stop) stop ;;
+	restart) stop; start ;;
+	status) status ;;
+	*) printf '%s\n' "Usage: $0 {start|stop|restart|status}" >&2; exit 1 ;;
+esac
diff --git a/lib/setup/sv/sysvinit/upowerd b/lib/setup/sv/sysvinit/upowerd
new file mode 100755
index 0000000..92c2cbf
--- /dev/null
+++ b/lib/setup/sv/sysvinit/upowerd
@@ -0,0 +1,41 @@
+#!/bin/sh
+### BEGIN INIT INFO
+# Provides:          upowerd
+# Required-Start:    $remote_fs dbus
+# Required-Stop:     $remote_fs dbus
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+# Short-Description: UPower power management
+### END INIT INFO
+
+if [ -f /etc/rc.d/init.d/functions ]; then
+	. /etc/rc.d/init.d/functions
+elif [ -f /etc/init.d/functions ]; then
+	. /etc/init.d/functions
+fi
+
+NAME=upowerd
+DAEMON="/usr/libexec/upowerd"
+DAEMON_ARGS=""
+PIDFILE="/run/upowerd.pid"
+USER=""
+
+start() {
+	start_daemon -p "$PIDFILE" ${USER:+-c "$USER"} "$DAEMON" $DAEMON_ARGS
+}
+
+stop() {
+	killproc -p "$PIDFILE" "$DAEMON"
+}
+
+status() {
+	pidofproc -p "$PIDFILE" "$DAEMON"
+}
+
+case $1 in
+	start) start ;;
+	stop) stop ;;
+	restart) stop; start ;;
+	status) status ;;
+	*) printf '%s\n' "Usage: $0 {start|stop|restart|status}" >&2; exit 1 ;;
+esac
diff --git a/lib/setup/sv/sysvinit/usbmuxd b/lib/setup/sv/sysvinit/usbmuxd
new file mode 100755
index 0000000..afc082d
--- /dev/null
+++ b/lib/setup/sv/sysvinit/usbmuxd
@@ -0,0 +1,41 @@
+#!/bin/sh
+### BEGIN INIT INFO
+# Provides:          usbmuxd
+# Required-Start:    $remote_fs
+# Required-Stop:     $remote_fs
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+# Short-Description: iOS USB multiplexing daemon
+### END INIT INFO
+
+if [ -f /etc/rc.d/init.d/functions ]; then
+	. /etc/rc.d/init.d/functions
+elif [ -f /etc/init.d/functions ]; then
+	. /etc/init.d/functions
+fi
+
+NAME=usbmuxd
+DAEMON="/usr/sbin/usbmuxd"
+DAEMON_ARGS="-f"
+PIDFILE="/run/usbmuxd.pid"
+USER=""
+
+start() {
+	start_daemon -p "$PIDFILE" ${USER:+-c "$USER"} "$DAEMON" $DAEMON_ARGS
+}
+
+stop() {
+	killproc -p "$PIDFILE" "$DAEMON"
+}
+
+status() {
+	pidofproc -p "$PIDFILE" "$DAEMON"
+}
+
+case $1 in
+	start) start ;;
+	stop) stop ;;
+	restart) stop; start ;;
+	status) status ;;
+	*) printf '%s\n' "Usage: $0 {start|stop|restart|status}" >&2; exit 1 ;;
+esac
diff --git a/lib/setup/sv/sysvinit/valkey b/lib/setup/sv/sysvinit/valkey
new file mode 100755
index 0000000..0f5e46c
--- /dev/null
+++ b/lib/setup/sv/sysvinit/valkey
@@ -0,0 +1,41 @@
+#!/bin/sh
+### BEGIN INIT INFO
+# Provides:          valkey
+# Required-Start:    $remote_fs
+# Required-Stop:     $remote_fs
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+# Short-Description: Valkey data store
+### END INIT INFO
+
+if [ -f /etc/rc.d/init.d/functions ]; then
+	. /etc/rc.d/init.d/functions
+elif [ -f /etc/init.d/functions ]; then
+	. /etc/init.d/functions
+fi
+
+NAME=valkey
+DAEMON="/usr/bin/valkey-server"
+DAEMON_ARGS="--daemonize no --bind 127.0.0.1"
+PIDFILE="/run/valkey.pid"
+USER=""
+
+start() {
+	start_daemon -p "$PIDFILE" ${USER:+-c "$USER"} "$DAEMON" $DAEMON_ARGS
+}
+
+stop() {
+	killproc -p "$PIDFILE" "$DAEMON"
+}
+
+status() {
+	pidofproc -p "$PIDFILE" "$DAEMON"
+}
+
+case $1 in
+	start) start ;;
+	stop) stop ;;
+	restart) stop; start ;;
+	status) status ;;
+	*) printf '%s\n' "Usage: $0 {start|stop|restart|status}" >&2; exit 1 ;;
+esac
diff --git a/lib/setup/sv/sysvinit/wireplumber b/lib/setup/sv/sysvinit/wireplumber
new file mode 100755
index 0000000..2324c37
--- /dev/null
+++ b/lib/setup/sv/sysvinit/wireplumber
@@ -0,0 +1,41 @@
+#!/bin/sh
+### BEGIN INIT INFO
+# Provides:          wireplumber
+# Required-Start:    $remote_fs dbus
+# Required-Stop:     $remote_fs dbus
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+# Short-Description: PipeWire session manager
+### END INIT INFO
+
+if [ -f /etc/rc.d/init.d/functions ]; then
+	. /etc/rc.d/init.d/functions
+elif [ -f /etc/init.d/functions ]; then
+	. /etc/init.d/functions
+fi
+
+NAME=wireplumber
+DAEMON="/usr/bin/wireplumber"
+DAEMON_ARGS=""
+PIDFILE="/run/wireplumber.pid"
+USER=""
+
+start() {
+	start_daemon -p "$PIDFILE" ${USER:+-c "$USER"} "$DAEMON" $DAEMON_ARGS
+}
+
+stop() {
+	killproc -p "$PIDFILE" "$DAEMON"
+}
+
+status() {
+	pidofproc -p "$PIDFILE" "$DAEMON"
+}
+
+case $1 in
+	start) start ;;
+	stop) stop ;;
+	restart) stop; start ;;
+	status) status ;;
+	*) printf '%s\n' "Usage: $0 {start|stop|restart|status}" >&2; exit 1 ;;
+esac
diff --git a/lib/setup/sv/sysvinit/wpa_supplicant b/lib/setup/sv/sysvinit/wpa_supplicant
new file mode 100755
index 0000000..25b3e1a
--- /dev/null
+++ b/lib/setup/sv/sysvinit/wpa_supplicant
@@ -0,0 +1,41 @@
+#!/bin/sh
+### BEGIN INIT INFO
+# Provides:          wpa_supplicant
+# Required-Start:    $remote_fs dbus
+# Required-Stop:     $remote_fs dbus
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+# Short-Description: wpa_supplicant Wi-Fi client
+### END INIT INFO
+
+if [ -f /etc/rc.d/init.d/functions ]; then
+	. /etc/rc.d/init.d/functions
+elif [ -f /etc/init.d/functions ]; then
+	. /etc/init.d/functions
+fi
+
+NAME=wpa_supplicant
+DAEMON="/usr/sbin/wpa_supplicant"
+DAEMON_ARGS="-u -s"
+PIDFILE="/run/wpa_supplicant.pid"
+USER=""
+
+start() {
+	start_daemon -p "$PIDFILE" ${USER:+-c "$USER"} "$DAEMON" $DAEMON_ARGS
+}
+
+stop() {
+	killproc -p "$PIDFILE" "$DAEMON"
+}
+
+status() {
+	pidofproc -p "$PIDFILE" "$DAEMON"
+}
+
+case $1 in
+	start) start ;;
+	stop) stop ;;
+	restart) stop; start ;;
+	status) status ;;
+	*) printf '%s\n' "Usage: $0 {start|stop|restart|status}" >&2; exit 1 ;;
+esac
diff --git a/man/mkiso.1 b/man/mkiso.1
index f50de4e..4b1f4a8 100644
--- a/man/mkiso.1
+++ b/man/mkiso.1
@@ -66,9 +66,22 @@ or
 .TP
 .BI --init " name"
 .B systemd
-or
-.B openrc .
-Default systemd.
+,
+.B openrc
+,
+.B s6
+,
+.B runit
+,
+.B dinit
+,
+.B shepherd
+, or
+.B sysvinit .
+This is the default
+.I /etc/sps/init
+on the disc. Live PID 1 stays busybox unless the build host has systemd
+or OpenRC binaries. Default systemd.
 .TP
 .BI --busybox " file"
 Static busybox used for the initramfs and live
diff --git a/man/pkin.1 b/man/pkin.1
index 8af0234..e16b784 100644
--- a/man/pkin.1
+++ b/man/pkin.1
@@ -37,7 +37,8 @@ After a successful post-install,
 .B pkin
 enables a mapped service for the init recorded in
 .I $SPS_ROOT/etc/sps/init
-(systemd, OpenRC, s6, runit, dinit, or Shepherd). Stock scripts under
+(systemd, OpenRC, s6, runit, dinit, Shepherd, or SysV). Daemon packages
+ship a script for every init into that init's directory. Stock scripts under
 .I $SPS_LIBDIR/setup/sv
 are copied when the package did not ship a file for that init.
 .SH OWNERSHIP
diff --git a/man/setup.1 b/man/setup.1
index 86979dc..2ef7ce1 100644
--- a/man/setup.1
+++ b/man/setup.1
@@ -54,17 +54,20 @@ with
 .B --init runit
 ,
 .B --init dinit
-, or
+,
 .B --init shepherd
+, or
+.B --init sysvinit
 selects PID 1;
 .B sget
 will not install more than one of those families.
 After packages land,
 .B setup
-copies stock service scripts from
+enables the scripts each daemon package already installed for that init
+(stock copies from
 .I $SPS_LIBDIR/setup/sv
-when a package did not ship a file for the chosen init, then enables
-known services (SDDM, dbus, sshd, NetworkManager, and others listed in
+fill a gap). Known services include SDDM, dbus, sshd, NetworkManager,
+and others listed in
 .I $SPS_LIBDIR/setup/services ).
 Pass
 .B --services no
@@ -198,13 +201,13 @@ see
 .B --flatpak yes|no
 Install the Flatpak set and attempt to add Flathub after packages land.
 .TP
-.B --init systemd|openrc|s6|runit|dinit|shepherd|none
+.B --init systemd|openrc|s6|runit|dinit|shepherd|sysvinit|none
 PID 1 on the installed system. Scripts default to none so a fixture
 install does not pull an init. The interactive screen defaults to the
 live image's
 .I /etc/sps/init
 when that file names a known init, otherwise systemd.
-Supervision inits pull eudev and elogind the same way OpenRC does.
+Supervision inits and SysV pull eudev and elogind the same way OpenRC does.
 The power set does not pull elogind; systemd gets logind from systemd
 itself so a Plasma install can use systemd without a conflict.
 .TP
diff --git a/tests/test_services.sh b/tests/test_services.sh
index d47d882..f87a415 100644
--- a/tests/test_services.sh
+++ b/tests/test_services.sh
@@ -118,6 +118,26 @@ setup_service_enable_one "$root2" runit openssh >/dev/null ||
 grep -q '/opt/custom/sshd' "$root2/etc/sv/sshd/run" ||
 	fail 'stock runit script overwrote a package-shipped run file'
 
+enabled=$(setup_service_enable_one "$root2" sysvinit sshd) ||
+	fail 'sysvinit enable of sshd from stock scripts failed'
+[ -f "$root2/etc/rc.d/init.d/sshd" ] ||
+	fail 'stock sysvinit sshd was not copied'
+[ -L "$root2/etc/rc.d/rc3.d/S50sshd" ] ||
+	fail 'sysvinit sshd was not linked into rc3.d'
+
+# Detected init follows the landed init-* package, not a stale marker
+# and never the host PID 1.
+root3=$tmp/detect
+mkdir -p "$root3/usr/share/sps/sets" "$root3/etc/sps"
+printf '%s\n' none >"$root3/etc/sps/init"
+printf '%s\n' sysvinit >"$root3/usr/share/sps/sets/init-sysvinit"
+got=$(setup_service_init_of "$root3") || fail 'init_of failed'
+[ "$got" = sysvinit ] || fail "init_of ignored init-sysvinit set file: $got"
+
+printf '%s\n' systemd >"$root3/etc/sps/init"
+got=$(setup_service_init_of "$root3") || fail 'init_of package vs file'
+[ "$got" = sysvinit ] || fail "landed init-* must win over stale /etc/sps/init: $got"
+
 if grep -q '^package[[:space:]]*elogind' "$project_dir/lib/setup/sets/power.set"
 then
 	fail 'power set must not pull elogind (conflicts with systemd)'
diff --git a/tests/test_setup.sh b/tests/test_setup.sh
index b1b3bca..21a58c3 100755
--- a/tests/test_setup.sh
+++ b/tests/test_setup.sh
@@ -343,6 +343,10 @@ contains "$plan" 'init-dinit'
 plan=$("$setup" --plan --target /mnt --profile minimal --init shepherd --disable qol-cli)
 contains "$plan" 'init-shepherd'
 
+plan=$("$setup" --plan --target /mnt --profile minimal --init sysvinit --disable qol-cli)
+contains "$plan" 'Init:       sysvinit'
+contains "$plan" 'init-sysvinit'
+
 set +e
 "$setup" --plan --target /mnt --profile minimal --init systemd \
 	--disable qol-cli --extra elogind >/dev/null 2>"$tmp/err"
@@ -365,6 +369,13 @@ case $plan in
 	*init-systemd*) fail 'plasma + s6 must not pull init-systemd' ;;
 esac
 
+plan=$("$setup" --plan --target /mnt --profile plasma-desktop --init sysvinit \
+	--disable qol-cli --disable firmware)
+contains "$plan" 'init-sysvinit'
+case $plan in
+	*init-systemd*) fail 'plasma + sysvinit must not pull init-systemd' ;;
+esac
+
 plan=$("$setup" --plan --target /mnt --profile minimal --init systemd \
 	--disable qol-cli --extra sddm --services no)
 contains "$plan" 'sddm'
diff --git a/tests/test_stock_services.sh b/tests/test_stock_services.sh
index a999eae..501c8e8 100755
--- a/tests/test_stock_services.sh
+++ b/tests/test_stock_services.sh
@@ -23,6 +23,7 @@ while read -r pkg unit _wanted rc _level; do
 	[ -f "$sv/s6/$rc/run" ] || fail "missing s6 stock $rc/run ($pkg)"
 	[ -f "$sv/dinit/$rc" ] || fail "missing dinit stock $rc ($pkg)"
 	[ -f "$sv/shepherd/$rc.scm" ] || fail "missing shepherd stock $rc.scm ($pkg)"
+	[ -f "$sv/sysvinit/$rc" ] || fail "missing sysvinit stock $rc ($pkg)"
 	count=$((count + 1))
 done <"$map"
 
diff --git a/tools/write-stock-services.py b/tools/write-stock-services.py
index 6535c4b..6f99eed 100755
--- a/tools/write-stock-services.py
+++ b/tools/write-stock-services.py
@@ -1,8 +1,8 @@
 #!/usr/bin/env python3
-"""Write stock init scripts for every supported init, and ship systemd plus
-OpenRC copies next to extra recipes that provide the daemon.
+"""Write stock init scripts for every supported init, and ship a copy of
+each script with the daemon recipe so pkin only has to enable.
 
-Supported inits: systemd, openrc, s6, runit, dinit, shepherd.
+Supported inits: systemd, openrc, s6, runit, dinit, shepherd, sysvinit.
 """
 from __future__ import annotations
 
@@ -14,8 +14,103 @@ SV = SPS / "lib" / "setup" / "sv"
 MAP = SPS / "lib" / "setup" / "services"
 
 # package, rc, unit, wanted, runlevel, description, argv, flags
-# flags: dbus, user, pre (list of shell lines for supervised run scripts)
+# flags: dbus, user, pre, oneshot, prio
 SERVICES = [
+    ("dbus", "dbus", "dbus.service", "multi-user.target", "sysinit",
+     "D-Bus system message bus",
+     ["/usr/bin/dbus-daemon", "--system", "--nofork", "--nopidfile", "--nosyslog"],
+     {"pre": ["mkdir -p /run/dbus /var/lib/dbus"]}),
+    ("eudev", "udevd", "udevd.service", "sysinit.target", "sysinit",
+     "eudev device manager",
+     ["/usr/sbin/udevd"], {}),
+    ("elogind", "elogind", "elogind.service", "multi-user.target", "sysinit",
+     "elogind login manager",
+     ["/usr/libexec/elogind"], {"dbus": True}),
+    ("sddm", "sddm", "sddm.service", "graphical.target", "default",
+     "Simple Desktop Display Manager",
+     ["/usr/bin/sddm"], {"dbus": True}),
+    ("networkmanager", "NetworkManager", "NetworkManager.service",
+     "multi-user.target", "default",
+     "NetworkManager",
+     ["/usr/sbin/NetworkManager", "--no-daemon"], {"dbus": True}),
+    ("openssh", "sshd", "sshd.service", "multi-user.target", "default",
+     "OpenSSH daemon",
+     ["/usr/sbin/sshd", "-D"],
+     {"pre": ["if command -v ssh-keygen >/dev/null 2>&1; then ssh-keygen -A >/dev/null 2>&1 || :; fi"]}),
+    ("cups", "cupsd", "cups.service", "multi-user.target", "default",
+     "CUPS printing service",
+     ["/usr/sbin/cupsd", "-f"], {"dbus": True}),
+    ("bluez", "bluetooth", "bluetooth.service", "multi-user.target", "default",
+     "Bluetooth daemon",
+     ["/usr/libexec/bluetooth/bluetoothd"], {"dbus": True}),
+    ("iwd", "iwd", "iwd.service", "multi-user.target", "default",
+     "iNet wireless daemon",
+     ["/usr/libexec/iwd"], {"dbus": True}),
+    ("dhcpcd", "dhcpcd", "dhcpcd.service", "multi-user.target", "default",
+     "DHCP client daemon",
+     ["/usr/sbin/dhcpcd", "--nobackground"], {}),
+    ("seatd", "seatd", "seatd.service", "multi-user.target", "default",
+     "seat management daemon",
+     ["/usr/bin/seatd", "-g", "video"], {}),
+    ("power-profiles-daemon", "power-profiles-daemon",
+     "power-profiles-daemon.service", "multi-user.target", "default",
+     "Power profiles daemon",
+     ["/usr/libexec/power-profiles-daemon"], {"dbus": True}),
+    ("pipewire", "pipewire", "pipewire.service", "default.target", "default",
+     "PipeWire multimedia server",
+     ["/usr/bin/pipewire"], {"dbus": True}),
+    ("wireplumber", "wireplumber", "wireplumber.service", "default.target",
+     "default",
+     "PipeWire session manager",
+     ["/usr/bin/wireplumber"], {"dbus": True}),
+    ("polkit", "polkitd", "polkit.service", "multi-user.target", "sysinit",
+     "polkit authorization manager",
+     ["/usr/libexec/polkitd", "--no-debug"], {"dbus": True}),
+    ("cronie", "crond", "crond.service", "multi-user.target", "default",
+     "cron daemon",
+     ["/usr/sbin/crond", "-n"], {}),
+    ("at", "atd", "atd.service", "multi-user.target", "default",
+     "at job scheduler",
+     ["/usr/sbin/atd", "-f"], {}),
+    ("chrony", "chronyd", "chronyd.service", "multi-user.target", "default",
+     "chrony NTP daemon",
+     ["/usr/sbin/chronyd", "-d"], {}),
+    ("haveged", "haveged", "haveged.service", "multi-user.target", "sysinit",
+     "haveged entropy daemon",
+     ["/usr/sbin/haveged", "-w", "1024", "-F"], {}),
+    ("nginx", "nginx", "nginx.service", "multi-user.target", "default",
+     "nginx HTTP server",
+     ["/usr/bin/nginx", "-g", "daemon off;"], {}),
+    ("caddy", "caddy", "caddy.service", "multi-user.target", "default",
+     "Caddy HTTP server",
+     ["/usr/bin/caddy", "run"], {}),
+    ("redis", "redis", "redis.service", "multi-user.target", "default",
+     "Redis data store",
+     ["/usr/bin/redis-server", "--daemonize", "no"], {}),
+    ("syncthing", "syncthing", "syncthing.service", "multi-user.target", "default",
+     "Syncthing file synchronization",
+     ["/usr/bin/syncthing", "serve", "--no-browser", "--home=/var/lib/syncthing"],
+     {"pre": ["install -d -m 0755 /var/lib/syncthing || :"]}),
+    ("wpa_supplicant", "wpa_supplicant", "wpa_supplicant.service",
+     "multi-user.target", "default",
+     "wpa_supplicant Wi-Fi client",
+     ["/usr/sbin/wpa_supplicant", "-u", "-s"], {"dbus": True}),
+    ("tlp", "tlp", "tlp.service", "multi-user.target", "default",
+     "TLP laptop power management",
+     ["/usr/sbin/tlp", "init", "start"], {"oneshot": True}),
+    ("smartmontools", "smartd", "smartd.service", "multi-user.target", "default",
+     "S.M.A.R.T. disk monitoring",
+     ["/usr/sbin/smartd", "-n"], {}),
+    ("upower", "upowerd", "upower.service", "multi-user.target", "default",
+     "UPower power management",
+     ["/usr/libexec/upowerd"], {"dbus": True}),
+    ("transmission", "transmission-daemon", "transmission-daemon.service",
+     "multi-user.target", "default",
+     "Transmission BitTorrent daemon",
+     ["/usr/bin/transmission-daemon", "-f", "--log-level=error"], {}),
+    ("nftables", "nftables", "nftables.service", "multi-user.target", "sysinit",
+     "nftables packet filter",
+     ["/usr/sbin/nft", "-f", "/etc/nftables.conf"], {"oneshot": True}),
     ("fail2ban", "fail2ban", "fail2ban.service", "multi-user.target", "default",
      "fail2ban authentication ban daemon",
      ["/usr/bin/fail2ban-server", "-xf", "--logtarget=stdout"], {}),
@@ -77,7 +172,8 @@ SERVICES = [
     ("valkey", "valkey", "valkey.service", "multi-user.target", "default",
      "Valkey data store",
      ["/usr/bin/valkey-server", "--daemonize", "no", "--bind", "127.0.0.1"], {}),
-    ("conntrack-tools", "conntrackd", "conntrackd.service", "multi-user.target", "default",
+    ("conntrack-tools", "conntrackd", "conntrackd.service", "multi-user.target",
+     "default",
      "connection tracking daemon",
      ["/usr/sbin/conntrackd", "-C", "/etc/conntrackd/conntrackd.conf"], {}),
     ("usbmuxd", "usbmuxd", "usbmuxd.service", "multi-user.target", "default",
@@ -100,11 +196,29 @@ ALIASES = {
     "mariadbd": "mariadb",
     "distccd": "distcc",
     "lxc-net": "lxc",
+    "sshd": "openssh",
+    "cupsd": "cups",
+    "bluetooth": "bluez",
+    "NetworkManager": "networkmanager",
+    "udevd": "eudev",
+    "polkitd": "polkit",
+    "crond": "cronie",
+    "atd": "at",
+    "chronyd": "chrony",
+    "smartd": "smartmontools",
+    "upowerd": "upower",
+    "transmission-daemon": "transmission",
 }
 
 
 def sh_join(argv: list[str]) -> str:
-    return " ".join(argv)
+    out = []
+    for a in argv:
+        if any(c in a for c in ' \t;"'):
+            out.append("'" + a.replace("'", "'\\''") + "'")
+        else:
+            out.append(a)
+    return " ".join(out)
 
 
 def scm_list(argv: list[str]) -> str:
@@ -112,17 +226,19 @@ def scm_list(argv: list[str]) -> str:
 
 
 def systemd_unit(svc: dict) -> str:
-    after = ["network.target"]
+    after = []
+    if svc["level"] != "sysinit":
+        after.append("network.target")
     if svc["flags"].get("dbus"):
         after.append("dbus.service")
+    wanted = svc["wanted"]
     lines = [
         "[Unit]",
         f"Description={svc['desc']}",
-        f"After={' '.join(after)}",
-        "",
-        "[Service]",
-        f"ExecStart={sh_join(svc['argv'])}",
     ]
+    if after:
+        lines.append(f"After={' '.join(after)}")
+    lines += ["", "[Service]", f"ExecStart={sh_join(svc['argv'])}"]
     if svc["flags"].get("oneshot"):
         lines.append("Type=oneshot")
         lines.append("RemainAfterExit=yes")
@@ -131,12 +247,14 @@ def systemd_unit(svc: dict) -> str:
     user = svc["flags"].get("user")
     if user:
         lines.append(f"User={user}")
-    lines += ["", "[Install]", f"WantedBy={svc['wanted']}", ""]
+    lines += ["", "[Install]", f"WantedBy={wanted}", ""]
     return "\n".join(lines)
 
 
 def openrc_script(svc: dict) -> str:
     depend = ["    use net", "    after net"]
+    if svc["level"] == "sysinit":
+        depend = ["    need localmount"]
     if svc["flags"].get("dbus"):
         depend = ["    need dbus", "    after dbus"]
     pre = svc["flags"].get("pre") or []
@@ -173,18 +291,29 @@ def supervised_run(svc: dict) -> str:
     lines = ["#!/bin/sh", "exec 2>&1"]
     for line in svc["flags"].get("pre") or []:
         lines.append(line)
-    lines.append(f"exec {sh_join(svc['argv'])}")
+    if svc["flags"].get("oneshot"):
+        lines.append(f"{sh_join(svc['argv'])}")
+        lines.append("exec pause")
+    else:
+        lines.append(f"exec {sh_join(svc['argv'])}")
     lines.append("")
     return "\n".join(lines)
 
 
 def dinit_file(svc: dict) -> str:
-    lines = [
-        "type = process",
-        f"command = {sh_join(svc['argv'])}",
-        "restart = true",
-        "smooth-recovery = true",
-    ]
+    if svc["flags"].get("oneshot"):
+        lines = [
+            "type = script",
+            f"command = {sh_join(svc['argv'])}",
+            "restart = false",
+        ]
+    else:
+        lines = [
+            "type = process",
+            f"command = {sh_join(svc['argv'])}",
+            "restart = true",
+            "smooth-recovery = true",
+        ]
     if svc["flags"].get("dbus"):
         lines.append("depends-on = dbus")
     lines.append("")
@@ -206,6 +335,78 @@ def shepherd_file(svc: dict) -> str:
     )
 
 
+def sysvinit_script(svc: dict) -> str:
+    if svc["level"] == "sysinit":
+        start, stop = "S", ""
+    else:
+        start, stop = "2 3 4 5", "0 1 6"
+    req = "$remote_fs"
+    if svc["flags"].get("dbus"):
+        req = "$remote_fs dbus"
+    args = " ".join(svc["argv"][1:])
+    user = svc["flags"].get("user") or ""
+    pre = svc["flags"].get("pre") or []
+    oneshot = bool(svc["flags"].get("oneshot"))
+    lines = [
+        "#!/bin/sh",
+        "### BEGIN INIT INFO",
+        f"# Provides:          {svc['rc']}",
+        f"# Required-Start:    {req}",
+        f"# Required-Stop:     {req}",
+        f"# Default-Start:     {start}",
+        f"# Default-Stop:      {stop}",
+        f"# Short-Description: {svc['desc']}",
+        "### END INIT INFO",
+        "",
+        "if [ -f /etc/rc.d/init.d/functions ]; then",
+        "	. /etc/rc.d/init.d/functions",
+        "elif [ -f /etc/init.d/functions ]; then",
+        "	. /etc/init.d/functions",
+        "fi",
+        "",
+        f"NAME={svc['rc']}",
+        f'DAEMON="{svc["argv"][0]}"',
+        f'DAEMON_ARGS="{args}"',
+        f'PIDFILE="/run/{svc["rc"]}.pid"',
+        f'USER="{user}"',
+        "",
+        "start() {",
+    ]
+    for line in pre:
+        lines.append(f"	{line}")
+    if oneshot:
+        lines.append('	eval "$DAEMON" $DAEMON_ARGS')
+        lines.append("	return $?")
+    else:
+        lines.append('	start_daemon -p "$PIDFILE" ${USER:+-c "$USER"} "$DAEMON" $DAEMON_ARGS')
+    lines += [
+        "}",
+        "",
+        "stop() {",
+    ]
+    if oneshot:
+        lines.append("	return 0")
+    else:
+        lines.append('	killproc -p "$PIDFILE" "$DAEMON"')
+    lines += [
+        "}",
+        "",
+        "status() {",
+        '	pidofproc -p "$PIDFILE" "$DAEMON"',
+        "}",
+        "",
+        'case $1 in',
+        "	start) start ;;",
+        "	stop) stop ;;",
+        "	restart) stop; start ;;",
+        "	status) status ;;",
+        '	*) printf \'%s\\n\' "Usage: $0 {start|stop|restart|status}" >&2; exit 1 ;;',
+        "esac",
+        "",
+    ]
+    return "\n".join(lines)
+
+
 def write_file(path: Path, text: str, mode: int = 0o644) -> None:
     path.parent.mkdir(parents=True, exist_ok=True)
     path.write_text(text, encoding="utf-8")
@@ -230,37 +431,42 @@ def write_stock(services: list[dict]) -> None:
         write_file(SV / "s6" / svc["rc"] / "run", supervised_run(svc), 0o755)
         write_file(SV / "dinit" / svc["rc"], dinit_file(svc), 0o644)
         write_file(SV / "shepherd" / f"{svc['rc']}.scm", shepherd_file(svc), 0o644)
+        write_file(SV / "sysvinit" / svc["rc"], sysvinit_script(svc), 0o755)
 
 
-def update_map(services: list[dict]) -> None:
-    existing = MAP.read_text(encoding="utf-8")
-    lines = existing.rstrip() + "\n"
+def update_map(services: list[dict]) -> list[str]:
+    header = (
+        "# package  systemd-unit  wanted-by  rc-name  runlevel\n"
+        "# Scripts for every init live in lib/setup/sv and are also shipped\n"
+        "# in the daemon recipe (systemd, OpenRC, runit, s6, dinit,\n"
+        "# Shepherd, SysV). pkin enables the detected target init.\n"
+    )
+    rows = []
     have = set()
-    for raw in existing.splitlines():
-        if not raw.strip() or raw.lstrip().startswith("#"):
-            continue
-        have.add(raw.split()[0])
     added = []
+
+    def add_row(name: str, svc: dict) -> None:
+        if name in have:
+            return
+        rows.append(
+            f"{name}\t{svc['unit']}\t{svc['wanted']}\t{svc['rc']}\t{svc['level']}\n"
+        )
+        have.add(name)
+        added.append(name)
+
     for svc in services:
-        row = f"{svc['pkg']}\t{svc['unit']}\t{svc['wanted']}\t{svc['rc']}\t{svc['level']}\n"
-        if svc["pkg"] not in have:
-            lines += row
-            have.add(svc["pkg"])
-            added.append(svc["pkg"])
+        add_row(svc["pkg"], svc)
         for alias, pkg in ALIASES.items():
-            if pkg == svc["pkg"] and alias not in have:
-                lines += (
-                    f"{alias}\t{svc['unit']}\t{svc['wanted']}\t"
-                    f"{svc['rc']}\t{svc['level']}\n"
-                )
-                have.add(alias)
-                added.append(alias)
-    MAP.write_text(lines, encoding="utf-8")
+            if pkg == svc["pkg"]:
+                add_row(alias, svc)
+    MAP.write_text(header + "".join(rows), encoding="utf-8")
     return added
 
 
 def find_recipe(tree: Path, name: str) -> Path | None:
     for recipe in tree.rglob("recipe"):
+        if ".git" in recipe.parts:
+            continue
         try:
             for line in recipe.read_text(encoding="utf-8").splitlines():
                 if line.startswith("name"):
@@ -289,6 +495,30 @@ def bump_release(text: str) -> str:
     return "".join(out)
 
 
+def recipe_install_block(svc: dict) -> str:
+    rc = svc["rc"]
+    unit = svc["unit"]
+    return (
+        'install     mkdir -p "$PKG/usr/lib/systemd/system" "$PKG/etc/init.d" '
+        f'"$PKG/etc/sv/{rc}" "$PKG/etc/s6/sv/{rc}" '
+        '"$PKG/etc/dinit.d" "$PKG/etc/shepherd.d" "$PKG/etc/rc.d/init.d"\n'
+        f'install     install -m 0644 "$SRC/files/{unit}" '
+        f'"$PKG/usr/lib/systemd/system/{unit}"\n'
+        f'install     install -m 0755 "$SRC/files/openrc-{rc}" '
+        f'"$PKG/etc/init.d/{rc}"\n'
+        f'install     install -m 0755 "$SRC/files/runit-{rc}" '
+        f'"$PKG/etc/sv/{rc}/run"\n'
+        f'install     install -m 0755 "$SRC/files/s6-{rc}" '
+        f'"$PKG/etc/s6/sv/{rc}/run"\n'
+        f'install     install -m 0644 "$SRC/files/dinit-{rc}" '
+        f'"$PKG/etc/dinit.d/{rc}"\n'
+        f'install     install -m 0644 "$SRC/files/shepherd-{rc}.scm" '
+        f'"$PKG/etc/shepherd.d/{rc}.scm"\n'
+        f'install     install -m 0755 "$SRC/files/sysvinit-{rc}" '
+        f'"$PKG/etc/rc.d/init.d/{rc}"\n'
+    )
+
+
 def install_recipe_files(tree: Path, services: list[dict]) -> list[str]:
     touched = []
     for svc in services:
@@ -296,21 +526,21 @@ def install_recipe_files(tree: Path, services: list[dict]) -> list[str]:
         if recipe is None:
             continue
         files = recipe.parent / "files"
+        rc = svc["rc"]
         write_file(files / svc["unit"], systemd_unit(svc), 0o644)
-        write_file(files / f"openrc-{svc['rc']}", openrc_script(svc), 0o755)
+        write_file(files / f"openrc-{rc}", openrc_script(svc), 0o755)
+        write_file(files / f"runit-{rc}", supervised_run(svc), 0o755)
+        write_file(files / f"s6-{rc}", supervised_run(svc), 0o755)
+        write_file(files / f"dinit-{rc}", dinit_file(svc), 0o644)
+        write_file(files / f"shepherd-{rc}.scm", shepherd_file(svc), 0o644)
+        write_file(files / f"sysvinit-{rc}", sysvinit_script(svc), 0o755)
         text = recipe.read_text(encoding="utf-8")
-        marker = f"$SRC/files/{svc['unit']}"
+        marker = f"$SRC/files/sysvinit-{rc}"
         if marker not in text:
             text = bump_release(text)
             if not text.endswith("\n"):
                 text += "\n"
-            text += (
-                'install     mkdir -p "$PKG/usr/lib/systemd/system" "$PKG/etc/init.d"\n'
-                f'install     install -m 0644 "$SRC/files/{svc["unit"]}" '
-                f'"$PKG/usr/lib/systemd/system/{svc["unit"]}"\n'
-                f'install     install -m 0755 "$SRC/files/openrc-{svc["rc"]}" '
-                f'"$PKG/etc/init.d/{svc["rc"]}"\n'
-            )
+            text += recipe_install_block(svc)
             recipe.write_text(text, encoding="utf-8")
         touched.append(str(recipe))
     return touched
@@ -334,7 +564,7 @@ def main() -> int:
         if core.is_dir():
             touched.extend(install_recipe_files(core, services))
     print(f"stock services: {len(services)}")
-    print(f"map added: {', '.join(added) if added else '(none)'}")
+    print(f"map rows written: {len(added)}")
     print(f"recipes updated: {len(touched)}")
     return 0