Installs runit and provides the runit_service
service resource for managing processes (services) under runit.
This cookbook does not use runit to replace system init, nor are there plans to do so.
For more information about runit:
NOTE: The 5.0 release of this cookbook requires the ChefSpec which shipped in the later versions of ChefDK 3. If you use this cookbook along with ChefSpec in your environment then you will need to upgrade to the latest version of ChefDK / Workstation to prevent spec failures.
node['runit']['prefer_local_yum']
- If true
, assumes that a runit
package is available on an already configured local yum repository. By default, the recipe installs the runit
package from a Package Cloud repository (see below). This is set to the value of node['runit']['use_package_from_yum']
for backwards compatibility, but otherwise defaults to false
.The default recipe installs runit and starts runsvdir
to supervise the services in runit's service directory (e.g., /etc/service
).
On RHEL-family systems, it will install the runit RPM using Ian Meyer's Package Cloud repository for runit. This replaces the previous functionality where the RPM was build using his runit RPM SPEC. However, if the attribute node['runit']['prefer_local_yum']
is set to true
, the packagecloud repository creation will be skipped and it is assumed that a runit
package is available on an otherwise configured (outside this cookbook) local repository.
On Debian family systems, the runit packages are maintained by the runit author, Gerrit Pape, and the recipe will use that for installation.
This cookbook has a resource, runit_service
, for managing services under runit.
sv start
sv stop
sv down
and removes the service symlinksv restart
sv force-reload
sv once
.HUP
signal to the service with sv hup
CONT
signal to the serviceTERM
signal to the serviceKILL
signal to the servicesv up
sv down
USR1
signal to the service with sv 1
USR2
signal to the service with sv 2
Service management actions are taken with runit's "sv
" program.
Read the sv(8)
man page for more information on the sv
program.
The first three properties, sv_dir
, service_dir
, and sv_bin
will attempt to use the legacy node attributes, and fall back to hardcoded default values that match the settings used on Debian platform systems.
Many of these properties are only used in the :enable
action.
node['runit']['sv_dir']
attribute, and falls back to /etc/sv
.runsvdir
. By default, this will attempt to use the node['runit']['service_dir']
attribute, and falls back to /etc/service
.node['runit']['lsb_init_dir']
attribute, and falls back to /etc/init.d
.sv
program binary. This will attempt to use the node['runit']['sv_bin']
attribute, and falls back to /usr/bin/sv
.sv_dir
and service_dir
.sv
timeout of 7 seconds.sv
verbose mode. Default is false
.:enable
action will create the service directory with the appropriate templates. Default is true
. Set this to false
if the service has a package that provides its own service directory. See Usage examples.env
directory. Default is an empty hash. When this hash is non-empty, the contents of the runit service's env
directory will be managed by Chef in order to conform to the declared state.sv-service_name-log-run.erb
to configure the log's run script. Default is true.log/run
script should be set up. If true, the default content of the run script will use svlogd
to write logs to /var/log/service_name
. Default is false.svlogd
log service will run. Used when default_logger
is true
. Default is /var/log/service_name
svlogd
command. Used when default_logger
is true
. Default is -tt
log_size
or not. Default is no timeout.enable
action.sv-service_name-check.erb
sv-service_name-finish.erb
sv-service_name-signal.erb
.service_name
.service_name
.service_name
.service_name
.service_name
./usr/bin/sv
due to the aforementioned cookbook load order.true
. Set to false
if the service shouldn't be restarted when the run script is updated.<sv_dir>/down
file. Defaults to false
. Services using start_down
will not be notified to restart when their run script is updated.<sv_dir>/down
fileUnlike previous versions of the cookbook using the runit_service
definition, the runit_service
resource can be notified. See Usage examples below.
To get runit installed on supported platforms, use recipe[runit]
. Once it is installed, use the runit_service
resource to set up services to be managed by runit.
In order to use the runit_service
resource in your cookbook(s), each service managed will also need to have sv-service_name-run.erb
and sv-service_name-log-run.erb
templates created. If the log
property is false, the log run script isn't created. If the log
property is true, and default_logger
is also true, the log run script will be created with the default content:
#!/bin/sh
exec svlogd -tt /var/log/service_name
These are example use cases of the runit_service
resource described above. There are others in the runit_test
cookbook that is included in the git repository.
Default Example
This example uses all the defaults in the :enable
action to set up the service.
We'll set up chef-client
to run as a service under runit, such as is done in the chef-client
cookbook. This example will be more simple than in that cookbook. First, create the required run template, chef-client/templates/default/sv-chef-client-run.erb
.
#!/bin/sh
exec 2>&1
exec /usr/bin/env chef-client -i 1800 -s 30
Then create the required log/run template, chef-client/templates/default/sv-chef-client-log-run.erb
.
#!/bin/sh
exec svlogd -tt ./main
Note This will cause output of the running process to go to /etc/sv/chef-client/log/main/current
. Some people may not like this, see the following example. This is preserved for compatibility reasons.
Finally, set up the service in the recipe with:
runit_service "chef-client"
Default Logger Example
To use a default logger with svlogd which will log to /var/log/chef-client/current
, instead, use the default_logger
option.
runit_service "chef-client" do
default_logger true
end
No Log Service
If there isn't an appendant log service, set log
to false, and the log/run script won't be created.
runit_service "no-svlog" do
log false
end
Check Script
To create a service that has a check script in its service directory, set the check
property to true
, and create a sv-checker-check.erb
template.
runit_service "checker" do
check true
end
This will create /etc/sv/checker/check
.
Finish Script
To create a service that has a finish script in its service directory, set the finish
property to true
, and create a sv-finisher-finish.erb
template.
runit_service "finisher" do
finish true
end
This will create /etc/sv/finisher/finish
.
Alternate service directory
If the service directory for the managed service isn't the sv_dir
(/etc/sv
), then specify it:
runit_service "custom_service" do
sv_dir "/etc/custom_service/runit"
end
No Service Directory
If the service to manage has a package that provides its service directory, such as git-daemon
on Debian systems, set sv_templates
to false.
package "git-daemon-run"
runit_service "git-daemon" do
sv_templates false
end
This will create the service symlink in /etc/service
, but it will not manage any templates in the service directory.
User Controlled Services
To set up services controlled by a non-privileged user, we follow the recommended configuration in the runit documentation (Is it possible to allow a user other than root to control a service?).
Suppose the user's name is floyd, and floyd wants to run floyds-app. Assuming that the floyd user and group are already managed with Chef, create a runsvdir-floyd
runit_service.
runit_service "runsvdir-floyd"
Create the sv-runsvdir-floyd-log-run.erb
template, or add log false
. Also create the sv-runsvdir-floyd-run.erb
with the following content:
#!/bin/sh
exec 2>&1
exec chpst -ufloyd runsvdir /home/floyd/service
Next, create the runit_service
resource for floyd's app:
runit_service "floyds-app" do
sv_dir "/home/floyd/sv"
service_dir "/home/floyd/service"
owner "floyd"
group "floyd"
end
And now floyd can manage the service with sv:
$ id
uid=1000(floyd) gid=1001(floyd) groups=1001(floyd)
$ sv stop /home/floyd/service/floyds-app/
ok: down: /home/floyd/service/floyds-app/: 0s, normally up
$ sv start /home/floyd/service/floyds-app/
ok: run: /home/floyd/service/floyds-app/: (pid 5287) 0s
$ sv status /home/floyd/service/floyds-app/
run: /home/floyd/service/floyds-app/: (pid 5287) 13s; run: log: (pid 4691) 726s
Options
Next, let's set up memcached under runit with some additional options using the options
property. First, the memcached/templates/default/sv-memcached-run.erb
template:
#!/bin/sh
exec 2>&1
exec chpst -u <%= @options[:user] %> /usr/bin/memcached -v -m <%= @options[:memory] %> -p <%= @options[:port] %>
Note that the script uses chpst
(which comes with runit) to set the user option, then starts memcached on the specified memory and port (see below).
The log/run template, memcached/templates/default/sv-memcached-log-run.erb
:
#!/bin/sh
exec svlogd -tt ./main
Finally, the runit_service
in our recipe:
runit_service "memcached" do
options({
:memory => node[:memcached][:memory],
:port => node[:memcached][:port],
:user => node[:memcached][:user]
}.merge(params))
end
This is where the user, port and memory options used in the run template are used.
Notifying Runit Services
In previous versions of this cookbook where the definition was used, it created a service
resource that could be notified. With the runit_service
resource, recipes need to use the full resource name.
For example:
runit_service "my-service"
template "/etc/my-service.conf" do
notifies :restart, "runit_service[my-service]"
end
Because the resource implements actions for various commands that sv
can send to the service, any of those actions could be used for notification. For example, chef-client
supports triggering a Chef run with a USR1 signal.
template "/tmp/chef-notifier" do
notifies :usr1, "runit_service[chef-client]"
end
For older implementations of services that used runit_service
as a definition, but may support alternate service styles, use a conditional, such as based on an attribute:
service_to_notify = case node['nginx']['init_style']
when "runit"
"runit_service[nginx]"
else
"service[nginx]"
end
template "/etc/nginx/nginx.conf" do
notifies :restart, service_to_notify
end
More Examples
For more examples, see the runit_test
cookbook's service
recipe in the git repository.
You may use test kitchen with either the vagrant or docker drivers to run integration tests.
Note: When using the docker driver please ensure that the container you are using has a working init system, as runit expects to be started by init. In some cases, systemd may need to be run in privileged mode.
For instance, for ubuntu with upstart:
driver_config:
image: ubuntu-upstart:14.04
run_command: /sbin/init
For redhat derivatives:
driver_config:
image: dockerhub/image-with-systemd
run_command: /usr/sbin/init
privileged: true
Copyright:: 2008-2019, Chef Software, Inc
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.