SPS · log · files · refs · tags · releases · people · languages · GitHub · commit
bf0ad20
Add SysV init and ship daemon scripts for every PID 1.
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