Daemonize With Runit

You may have a load of services/applications that you want to daemonize on production server. This post will introduce you runit, and guide you through the configurations on Debian-like systems.

I’ve been working on an interesting monitoring application for Superfeedr. There’re a couple of ruby processes I’d like to daemonize on the production server, though I’m yet too new to work with Process.fork stuff. Then Superfeedr’s Julien kinda introduced me runit.

runit is a Unix init scheme written by Gerrit Pape, it works like /etc/init.d/ (i.e. SysVinit), though with good benefits. We’ll utilize its simple scheme to help us supervising background processes.

Installing runit

$ sudo apt-get install runit runit-services

This will only install the runit’s supervision module, which is enough for our use case. Though there’s another package runit-run that (if installed) will completely replace your /sbin/init and take charge of your system boot, so take care. If you really want to, ref this.

It will create you /etc/sv/ and /etc/service respectively, if on a recent Debian-like system. Or if no /etc/service/ on your system, it may be at /service/ or /var/service/. Additionally, it comes with executables like sv, update-service, runsv, etc. Mostly, we’ll only use sv and update-service to manage background services.

How It Works

For every service (or application) you want to run in background, you need create a subdirectory in /etc/sv/, with a executable run in. Then update-service will tell runit to manage this service. The service will be picked up, and run in background. And it automatically get started on system restart.

Let’s say, we have a worker /path/to/worker/bin/workerd that want to be managed via runit.

Add daemonize script

$ cat /etc/sv/worker/run
#!/bin/sh
env RACK_ENV=production
cd /path/to/worker; bin/workerd
$ sudo chmod +x /etc/sv/woker/run

The run executable is just a shell script, so you could adjust environments, make housekeepings. The script is like /etc/init.d , but much simpler.

Update service

Then we need tell runit to mange this worker service.

$ sudo update-service --add /etc/sv/worker

This will add a service called worker (instead of workerd) to runit. The update-service just sym-linked /etc/sv/worker in /etc/service/, then runit knows about this new service, and will start it automatically.

Play more with it:

$ sudo update-service --help

Service management

The sv command comes on stage.

$ sudo sv status worker 
$ sudo sv start worker 
$ sudo sv kill worker 
$ sudo sv hup worker # send hup signal
$ man sv

Conclusion

While /etc/init.d scripts might do the job as well, it feels more free and enjoyble to work with runit. Though your preference may vary, choose what you like with wisdom. Thanks!