systemd alternatives for servers: the real cost
Devuan, Alpine, Void, Artix, Gentoo, Chimera and Slackware ship without systemd. What a server admin gives up, and who has a real reason to switch.
Who avoids systemd, and what they run instead
The systemd alternatives that still work on a server in September 2026 are a short list: Devuan, Alpine, Void, Artix, Gentoo, Chimera and Slackware. Each one replaces systemd with a smaller init, and each one costs you the same set of features: journald, timers, socket activation, unit sandboxing and per-service cgroup limits. On a VPS the price is higher, because the standard provider images (Ubuntu, Debian, Rocky, Alma, Fedora) all ship systemd, so running without it means a custom install before you have typed a single command.
The argument itself is old, and it is settled. systemd won the init question on every major distribution by 2015, for reasons that had more to do with dependency ordering and cgroup tracking than with anyone's opinion of its author. If you want the full story, how systemd won the init argument covers it. Take that as read. The practical question is what people who avoid it actually run, and what that choice costs on a server you are paid to keep up.
One clarification first, because the two words get mixed up in forum posts. systemd is the init and service manager, the process that runs as PID 1 and starts everything else. systemctl is the command-line client that sends requests to it. Remove systemd and systemctl goes with it, because it has nothing to talk to. A distro "without systemctl" is a distro without systemd. There is no version of one without the other.
The live systemd alternatives, checked on each project's own site
Defaults change, so every entry below was checked against the project's own site or handbook on 2026-09-18. Recheck before you commit to one.
Devuan: sysvinit by default, OpenRC and runit at install time
Devuan is Debian with systemd removed. The current stable release is Excalibur 6, based on Debian 13. Its init page lists sysvinit as the default and openrc and runit as install-time choices. s6 and GNU Shepherd are listed as under consideration. Everything else is Debian: apt and the same package names. This is the lowest-friction option for someone who already knows Debian, because the muscle memory carries over and only service management changes. Devuan pulls unmodified packages straight from Debian's repositories through its merge layer, so most security updates arrive at Debian's pace. Only the packages Devuan rebuilds to strip the systemd dependency lag behind, and that list is short.
Alpine: OpenRC, musl and BusyBox
Alpine is the one entry on this list that a server admin might already be running without having chosen it, because it is the base of half the container images in existence. It is built on the musl C library and BusyBox. Packages come from apk, and OpenRC is the init. A minimal install to disk takes around 130 MB, and it boots in a few seconds on a small VPS. Alpine is also the one alternative that shows up on some provider image menus, which removes the custom-install problem entirely. The cost is musl: software that assumes glibc behaviour and most proprietary binaries need extra work or the gcompat shim.
Void: runit
Void Linux is an independent distribution that uses runit as both its init and its service supervisor. There is no enable command. A service is a directory under /etc/sv/ holding an executable named run, which must exec the daemon in the foreground, and you enable it by symlinking that directory into /var/service/. Removing the symlink disables it. sv status reports state. It is the simplest service model on this list, and the least featureful. Void ships a rolling release with its own package manager, xbps, and its handbook is short and accurate.
Artix: OpenRC, runit, s6 or dinit
Artix is Arch Linux without systemd, and it does not pick an init for you. The download page offers base ISOs for openrc, runit, s6 and dinit, with the same date stamp on each. That is four different service-management vocabularies on one distro, which makes Artix the best place to compare them and the worst place to find a copy-paste answer, because most forum posts do not say which init the author was on. Artix follows Arch's rolling model, so it also inherits Arch's expectation that you read the news before you update.
Gentoo: OpenRC by default, systemd supported
Gentoo's OpenRC page is careful with its wording. OpenRC ships as part of the default OpenRC profile, and by default it is invoked by sysvinit as PID 1, so Gentoo is technically sysvinit plus OpenRC. Gentoo officially supports both OpenRC and systemd, which makes it the only distribution here where switching init is a supported profile change rather than a fork. The cost on a server is compile time. A source-based distribution on a two-core VPS turns a security update into an afternoon. The official binary package host Gentoo added in late 2023 helps, and it does not cover every USE flag combination.
Chimera: dinit
Chimera Linux is the newest project here and the most different. It uses FreeBSD's core userland and the LLVM toolchain, on musl, and its service manager is dinit, which its documentation describes as dependency-based (unlike runit) and supervising (unlike sysvinit). dinit's service files look closer to a unit file than anything else on this list, with declared dependencies and restart behaviour. Chimera is young and moving fast, so treat it as a lab system rather than a place to put a customer database.
Slackware: sysvinit with BSD-style scripts
Slackware keeps the oldest model of all: sysvinit reading /etc/inittab, then BSD-style scripts under /etc/rc.d/, with rc.S bringing up the system and rc.M starting multi-user services. There are no runlevel directories full of symlinks. You enable a service by making its rc. script executable and disable it by removing that bit. There is no dependency resolution and no supervision. A daemon that crashes stays down until you notice. It is a coherent design, and it is also the most manual one here.
What a server admin gives up without systemd
This is the honest ledger. Each item is a feature people rely on daily on an Ubuntu or Rocky box, with what replaces it on the systems above.
journald
journalctl -u nginx --since "1 hour ago" is the single most-used debugging command on a systemd server, and it is gone. What replaces it is a syslog daemon writing text files. Alpine enables BusyBox syslogd at install and writes everything to /var/log/messages. Devuan installs rsyslog and keeps the Debian layout under /var/log/. Void installs no syslog at all by default; its handbook recommends the socklog-void package, which adds two runit services, socklog-unix and nanoklogd, and writes to subdirectories of /var/log/socklog/. Per-service output under runit goes wherever the service's log/run script sends it, which is svlogd to a directory in most packages. The logs themselves survive. What you lose is the index: filtering by unit, by boot, by priority and by time in one command, with structured fields. On the alternatives you get grep and tail -f, and you learn each package's log path.
Timers
A systemd timer is a unit with an OnCalendar= schedule. Persistent=true catches up a missed run after a reboot, and each run logs under the timer's own name. None of the inits here have one. The replacement is cron: BusyBox crond on Alpine (rc-update add crond) and Debian's usual cron on Devuan, while Void leaves you to pick cronie or dcron from its repos. Cron works. What it lacks is the catch-up behaviour, the randomised delay, the per-timer log name and the systemctl list-timers view of what will run next. If your backup schedule currently lives in a systemd timer with Persistent=true, you rewrite it as a crontab line and add your own guard against overlapping runs.
Socket activation
Socket activation lets systemd own a listening socket and start the service on the first connection. OpenRC and runit have no equivalent. s6 has s6-fdholder, which keeps a file descriptor alive across a service restart, and that is a different feature. On a server this matters less than it sounds: nginx, Postgres, sshd and dockerd all open their own sockets, and the docker.socket unit is a convenience rather than a requirement. Where it bites is software written to expect LISTEN_FDS from its parent and nothing else. That software needs a wrapper or a config change to bind its own port. The same goes for Type=notify readiness, which is covered in Type=notify and the other service types. Without systemd there is no sd_notify reader, so "started" means "the process exists", and a dependency that needs the database to be accepting connections has to poll for it.
Unit-level sandboxing
ProtectSystem=strict, PrivateTmp=yes, NoNewPrivileges=yes, ProtectHome=yes and the capability bounding set are one line each in a unit file. Nothing in OpenRC, runit, s6 or dinit does this. The kernel features exist, mount namespaces, seccomp filters, capability sets and user namespaces, so the equivalent is possible, but you assemble it yourself with bwrap (bubblewrap) or firejail in the service's run script, or you put the service in a container and let the runtime do it. If you have been hardening services with ProtectSystem and PrivateTmp, that work does not port. It gets redone with a different tool and a wider set of ways to get it wrong.
cgroup resource limits
Here the gap is narrower than people assume, but only for OpenRC. MemoryMax= and CPUQuota= in a unit have an OpenRC equivalent, because OpenRC manages cgroups itself. Unified (v2) cgroups became the default in OpenRC 0.51, and Alpine has shipped rc_cgroup_mode="unified" as the default since 3.19. A per-service limit goes in /etc/conf.d/<service>:
rc_cgroup_settings="
cpu.max 1500000 1000000
memory.high 4G
memory.max 5G
"That example caps the service at 1.5 CPUs and applies memory pressure at 4 GiB, with a hard kill at 5 GiB. The values are written in the kernel's own cgroup v2 syntax rather than a translated one. runit has no cgroup support at all. A runit service is a process tree with no group boundary, so a limit means wrapping the daemon in prlimit or a container. Compare that with the one-line MemoryMax and CPUQuota change on a systemd box and the difference is clear.
Supervision is the same story. OpenRC has supervise-daemon: set supervisor=supervise-daemon at the top of an init script and the service is restarted on exit, with respawn_max defaulting to 10 attempts and respawn_delay defaulting to immediate. runit and dinit supervise every service by design. sysvinit on Devuan or Slackware supervises nothing, so Restart=on-failure has no equivalent there at all.
The VPS image menu
This is the cost that is specific to a VPS. Ubuntu, Debian, Rocky, Alma and Fedora all boot systemd, and they are the menu at nearly every provider. Alpine appears at some. Nothing else on this list appears anywhere mainstream. So the alternatives mean one of two paths: upload a custom ISO where the panel allows it, or boot the provider's rescue system and bootstrap the distro into the disk by hand. Both work. Both also mean the provider's cloud-init integration, its password reset, its automatic network config and its rebuild button either do not work or work by accident. You own the whole box from the bootloader up, which is the point for some readers and a liability for the rest.
What still works: Docker, Podman, nginx and Postgres
The services people actually run care about the kernel, not the init. All four below run under OpenRC and runit. The integration differences are real but small.
Docker
On Alpine:
apk add docker
rc-update add docker boot
service docker start
docker info | grep -i cgroupOn Void:
xbps-install -S docker
ln -s /etc/sv/docker /var/service
sv status dockerdocker info should report Cgroup Driver: cgroupfs, because there is no systemd cgroup tree for the daemon to delegate into, and Cgroup Version: 2 on a current Alpine. Both facts are fine. The integration difference is restart handling. On a systemd host, Restart= on the unit and --restart unless-stopped on the container overlap, and Docker's own documentation warns not to combine restart policies with a host-level process manager. Under runit the supervisor restarts dockerd and Docker's restart policy restarts the containers, which is a clean split. The docker.socket unit does not exist, so the daemon simply starts at boot and stays up.
Podman
Podman is the more interesting case because it was built alongside systemd. Its documented default cgroup manager is systemd unless containers.conf overrides it. In practice Podman checks for a running systemd and falls back to cgroupfs when it finds none, and podman info shows which one it picked under cgroupManager. If you ever see an error about the systemd cgroup manager on one of these hosts, set cgroup_manager = "cgroupfs" under [engine] in /etc/containers/containers.conf. Quadlet and podman generate systemd are unavailable, since both produce systemd units, so "start this container at boot" becomes a run script under /etc/sv/ or an OpenRC script calling podman start. That is the biggest practical gap in Podman versus Docker on a VPS once systemd is out of the picture, because Docker's daemon-side restart policy covers the same ground without help from the init.
apk add podman
rc-update add cgroups
rc-service cgroups startRootless Podman needs more: the tun kernel module loaded, rc_cgroup_mode="unified" in /etc/rc.conf (the default on Alpine 3.19 and later), user ID ranges in /etc/subuid and /etc/subgid, and a writable XDG_RUNTIME_DIR, because rootless Podman keeps its runtime state under ${XDG_RUNTIME_DIR}/containers. On systemd that directory is created by logind at login. Without it, you create it yourself and export the variable in the service environment, or podman commands fail complaining about the runtime directory. If rootless Podman for an LLM server is the workload, that one variable is the difference between a working service and a confusing one.
nginx
Nothing to report, which is the point. apk add nginx && rc-update add nginx default && rc-service nginx start on Alpine. xbps-install -S nginx && ln -s /etc/sv/nginx /var/service on Void. nginx forks, drops privileges, reopens its logs and reloads its config on its own, and it did all that before systemd existed. Certificate renewal is the one wrinkle: certbot's Ubuntu package schedules renewal with a systemd timer, so on these systems you schedule certbot renew from cron yourself.
PostgreSQL
Alpine packages Postgres by major version, postgresql16 and postgresql17 in 3.21, with a matching -openrc subpackage that pulls in the init script:
apk add postgresql17
su postgres -c 'initdb -D /var/lib/postgresql/17/data --locale=C.UTF-8 --encoding=UTF8'
rc-update add postgresql default
rc-service postgresql startThe difference from a systemd host is readiness. Postgres's unit on Ubuntu uses Type=notify, so an app service with After=postgresql.service starts only once the database accepts connections. OpenRC's need postgresql in an app's init script waits for the Postgres start script to return, and whether that means "accepting connections" depends on whether the script waits with pg_ctl -w or just launches the process. Check yours after a cold boot with rc-service postgresql start && psql -U postgres -c 'select 1'. Under runit there is no dependency at all: both services start in parallel and your app retries its connection or crashes and gets restarted until Postgres is up. That works, and it fills the log with connection errors on every reboot.
Can you choose systemd-boot instead of GRUB on a VPS?
Rarely, and it is the wrong question. systemd-boot is a UEFI boot manager, with no legacy BIOS mode. Most VPS images boot through GRUB, in BIOS mode or in UEFI mode depending on the provider, and the bootloader is baked into the provider's image rather than chosen by the tenant. On a distro without systemd the question does not arise, since systemd-boot is part of the systemd package. On a distro with it, switching to systemd-boot on a VPS means confirming the instance actually boots UEFI (ls /sys/firmware/efi succeeds) and then replacing a working GRUB install for no operational gain. The provider's rebuild and rescue tooling assumes GRUB. Leave it.
Verdict: a deliberate hobby, or a specific need
On a VPS, running without systemd is a deliberate hobby or a specific need, never a default. It also buys no security by itself. Every mainstream image ships systemd and every runbook you will find assumes it. The features above are the ones you will miss on the first bad day: journalctl -b -1 after a crash, a timer that catches up after downtime, a sandbox line that stops a compromised process reading /home, a memory cap that keeps one runaway process from taking the box down.
The specific-need reader is real, and looks like one of these:
- You are building small, single-purpose hosts and Alpine's 130 MB footprint and musl attack surface are the goal. This is the strongest case, and Alpine is the answer.
- You already run Void or Gentoo on physical machines and want one set of habits everywhere. Consistency is worth something, and the custom install is a one-time cost.
- You maintain an appliance or an embedded image where every megabyte and every daemon is accounted for, and a supervisor you can read end to end in an hour matters more than features.
- You have a policy or licensing reason that rules out systemd, in which case you were never choosing.
If none of those is you, the sensible read is which OS to pick for a VPS, which comes down to Ubuntu or Debian for most workloads and Rocky or Alma where an enterprise baseline matters. And if the thing that attracted you to the alternatives was a smaller, more predictable base system, look at immutable server distros before you look at init systems. They keep systemd and remove most of the drift that makes a server hard to reason about, which is usually the actual complaint.
FAQ
Which Linux distributions do not use systemd in 2026?
The maintained ones are Devuan (sysvinit by default, OpenRC or runit optional), Alpine (OpenRC), Void (runit), Artix (a choice of OpenRC, runit, s6 or dinit), Gentoo (OpenRC by default, systemd supported), Chimera (dinit) and Slackware (sysvinit with BSD-style scripts). Each was checked against its own site on 2026-09-18. Alpine is the only one that appears on mainstream VPS image menus.
What is the difference between systemd and systemctl?
systemd is the init and service manager running as PID 1. systemctl is the command-line tool that sends it instructions such as start, enable, status and daemon-reload. They ship together. A system without systemd has no systemctl, and the replacement command depends on the init: rc-service and rc-update on OpenRC, sv on runit, dinitctl on dinit, and the /etc/rc.d/rc.<name> scripts on Slackware.
Does Docker work without systemd?
Yes. Docker needs the kernel's namespaces and cgroups, not systemd. On Alpine, apk add docker and rc-update add docker boot are enough; on Void it is xbps-install -S docker and a symlink from /etc/sv/docker into /var/service. docker info will report the cgroupfs cgroup driver instead of systemd, which is normal. Podman also works but loses Quadlet, and for rootless use it needs a manually created XDG_RUNTIME_DIR.
What replaces journalctl on a system without systemd?
A syslog daemon writing text files. Alpine uses BusyBox syslogd writing to /var/log/messages. Devuan installs rsyslog and keeps the Debian /var/log/ layout. Void ships no logger until you install socklog-void, which writes under /var/log/socklog/. Per-service output under runit goes through svlogd to the service's own log directory. You lose the single indexed query across units, boots, priorities and time ranges, and you use grep and tail -f instead.
Can I use systemd-boot on a VPS?
Almost never. systemd-boot is UEFI-only, and the bootloader on a VPS is part of the provider's image, which is GRUB in nearly every case. On a distro without systemd the option does not exist, because systemd-boot ships inside the systemd package. There is no operational reason to replace a working GRUB on a rented virtual machine.