Daemontools
As i was running Linux-VServer, i couldn’t use runit (that is, i couldn’t figure how to do it); so i was using daemontools.
As inittab doesn’t work within a vserver, you need an init script (see attachment attachment:svscan) to start svscan; i used http://flounder.net/qmail/svscan-init as a template for that (i don’t know how google found that, as it seems no site links this file, and the site seems down now).
Services
The basic idea is always the same; you have a daemon and a log daemon; the start scripts are named “run”.
I maintain the services in /etc/sv/
, and symlink the services i want to run to /etc/service
.
You could use different log users, i chose to just use always the same user log
and to put the logs into /var/log/sv/*/
:
1 |
$ adduser --system --home /nonexistent --no-create-home --disabled-password --disabled-login log
|
Base setup for $service
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
cd /etc/sv/
mkdir "$service"
cd "$service"
vim run
chmod +x run
mkdir -p log
# put log files into /var/log/sv/$service
mkdir -p "/var/log/sv/$service"
ln -s "/var/log/sv/$service" log/main
echo -e '#!/bin/bash\nexec setuidgid log multilog t ./main\n' > log/run
chmod +x log/run
chown log:nogroup log/run log/main
# let it create supervise dirs into /var/run/
ln -s "/var/run/sv.$service" supervise
ln -s "/var/run/sv.$service.log" log/supervise
# start it now
ln -s "/etc/sv/$service" /etc/service
|
The examples below will only describe the main run
and additional files.
spawn-fcgi
You will need the spawn-fcgi program; you can use the one from http://cgit.stbuehler.de/gitosis/spawn-fcgi/about/ (“version 2.0”, debian packages are in my repo http://debian.stbuehler.de), or version 1.6.x from http://redmine.lighttpd.net/projects/spawn-fcgi (which doesn’t support the -l
option yet, so you have to set limits directly via ulimit
if you want them).
Don’t use the one from older lighttpd versions (1.4 and 1.5), as it doesn’t support some important options (-U, -G), and you need an extra wrapper script of the following form (e.g. as ./php in your service directory):
If you have to, you can use something like this (i really recommend using 1.6.x or 2.0):
1 2 3 4 5 6 |
#!/bin/sh
# chown socket so webserver can access it
chown www-data:www-data /var/run/lighttpd/yourphpsocketname.sock
# change user for target application
exec setuidgid yourphpuser /usr/bin/php5-cgi
|
And use a run script like this:
1 2 3 4 5 |
#!/bin/sh
exec 2>&1
# do not change user here, as we need to be root to chown the socket!
exec /usr/sbin/spawn-fcgi -f./php -s /var/run/lighttpd/yourphpsocketname.sock -n
|
Examples
The examples assume you are using my spawn-fcgi, read previous section for details.
spawn-fcgi options:
- “-u” username: change user for target application (and use his primary group)
- “-s” socket: bind to specified socket file (use this filename in lighttpd config)
- “-n” : don’t fork
- “-f fcgiapp”: run fcgiapp as application. Not used in the following examples, as you can specify it after
--
too with params for the target application.
The following two are not supported by lighty’s spawn-fci 1.4/1.5:
- -U username: change user of the unix-domain socket (and use his primary group)
- -l : use limits for the user specified with -u from /etc/security/limits.conf (this is only supported in 2.0)
PHP
To restart a php service use svc -t $service
instead of svc -h $service
(at least that is how it works for me)
$service/run
:
1 2 3 4 |
#!/bin/sh
exec 2>&1
exec /usr/bin/spawn-fcgi -s /var/run/lighttpd/php-webuser.sock -n -u webuser -U www-data -l -- /usr/bin/php5-cgi
|
The lighttpd config for this looks like this:
1 2 3 4 |
fastcgi.server = (
".php" =>
( "local" => ( "socket" => "/var/run/lighttpd/yourphpsocketname.sock" ) ),
)
|
Rails (redmine in my case)
$service/run
:
1 2 3 4 5 6 7 8 |
#!/bin/sh
exec 2>&1
export RAILS_ENV=production
export LANG=en_US.UTF-8
exec /usr/bin/spawn-fcgi -s /var/run/lighttpd/rails-user.sock -n -u railsuser -U www-data -l -- /path/to/railapp/dispatch.fcgi
|
Lighttpd config part (needs http://nordisch.org/cleanurl.lua from http://nordisch.org/):
1 2 3 4 5 6 7 8 |
server.document-root = "/path/to/railapp/public"
magnet.attract-physical-path-to = ( "/etc/lighttpd/cleanurl-v5.lua" )
fastcgi.server = ( "dispatch.fcgi" =>
((
"socket" => "/var/run/lighttpd/rails-user.sock",
"broken-scriptfilename" => "enable"
))
)
|
TurboGears
$service/run
:
1 2 3 4 5 6 |
#!/bin/sh
exec 2>&1
cd /path/to/project
exec /usr/bin/spawn-fcgi -s /var/run/lighttpd/project-user.sock -n -u tguser -U www-data -l -- /path/to/project/start-project-fcgi.py prod.cfg
|
You need a fastcgi starter (/path/to/project/start-project-fcgi.py) for turbogears, i use something like that (replace project with your project name):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
#!/usr/bin/env python
import pkg_resources
import cherrypy
import sys
cherrypy.lowercase_api = True
pkg_resources.require("TurboGears")
from cherrypy._cpwsgi import wsgiApp
from flup.server.fcgi import WSGIServer
from os.path import *
import turbogears
if len(sys.argv) > 1:
configfile = sys.argv[1]
elif exists(join(dirname(__file__), "setup.py")):
configfile = "dev.cfg"
else:
configfile = "prod.cfg"
turbogears.update_config(configfile=configfile, modulename="project.config")
from project.controllers import Root
cherrypy.root = Root()
cherrypy.server.start(initOnly=True, serverClass=None)
WSGIServer(application=wsgiApp).run()
|
lighttpd config part:
1 2 3 4 5 6 7 8 |
fastcgi.server = (
"/" =>
( "local" => (
"socket" => "/var/run/lighttpd/project-user.sock",
"check-local" => "disable",
"broken-scriptfilename" => "enable",
) ),
)
|
git-daemon
Share the gitosis repositories, if they are configured as “daemon=yes” (there is a git-daemon-run
package in debian; it doesn’t use the gitosis user of course).
$service/run
:
1 2 3 4 5 6 7 |
#!/bin/sh
exec 2>&1
exec $(git --exec-path)/git-daemon \
--user=gitosis --group=gitosis \
--reuseaddr \
--base-path=/var/cache/gitosis/repositories
|