I concur, runit absolutely rocks. Haven't tried systemd yet, I wonder if the two play nice together (if they don't, it won't be runits' fault, that's for sure).
From your other comments I can tell you're a seasoned daemontools user, so let me just put in a quick plug for daemontools-encore [1]. Like runit, daemontools-encore can now run services in separate process groups with setsid(1). Why is this so darn important? Well, under classic daemontools a ./run file with a pipeline in it -- or really anything that forked -- would spin off orphans every time you did `svc -t|-k`. Very bad stuff to deal with in a production environment.
Yup, it's one of those annoying things that makes run scripts more complicated. I rewrote phusion's runit setuser helper in Go because it didn't set all the right env vars.
Huh, looks pretty similar to envuidgid(8) from daemontools. [1]
Another plug for daemontools-encore (last one I promise). The setuidgid(8) program in classic daemontools doesn't set supplementary groups, and a lot of people I know just end up just using sudo in their run files. If you use daemontools-encore though, you can just use `setuidgid -s` instead.
PS. Really, daemontools-encore should imo be called daemontools 1.x, but you know how djb feels about forks of his projects...
The problem as per the Phusion blog article is that the runit and possibly daemontools equivalent commands don't set all env vars: HOME, USER, GID & UID, it only calls setgid() & setuid() IIRC. (envuidgid only sets UID and GID[0]) This causes breakage for lots of apps that end up inheriting root's env instead. :(
Here's the go version I wrote, so there's no need for dep on Python/Ruby/etc on the target system:
setuser USERNAME COMMAND [args...]
# how to build it
go get github.com/steakknife/my_init/setuser
go build github.com/steakknife/my_init/setuser
# creates setuser exe here