drood(8) FreeBSD System Manager's Manual drood(8)
NAME
Drood -- Minimal KQueue-Based HTTP/1.1 Server
SYNOPSIS
drood -r <server-root> [-m <instances> -i <interface> -p <port> -e
<root-resource> -d <cgi-dir> -t <read-timeout> -w <write-timeout>
-u <user> -g <group> -l <logfile> -q <backlog> -s
<host|port|suffix> -x]
DESCRIPTION
Drood is a small and fast, partially-compliant, HTTP/1.1 server, intended
as an alternative to heavyweight web servers for websites where the
server requirements are simple. The server is configured with command-
line options. The drood distribution includes a generic SCGI application
server, named plunger(8), which is documented in its own manual.
WHAT DROOD DOES
o Drood services both IPv4 and IPv6 connections.
o Drood understands the HEAD, GET, and POST request methods, only.
o Drood supports HTTP/1.1 persistent connections.
o Drood supports name-based virtual hosting.
o Drood supports both CGI and SCGI.
o Drood supports gzip content-encoding.
WHAT DROOD DOES NOT DO
o Drood does not accept HTTPS connections.
o Drood does not perform access authentication.
o Drood does request logging instead of transaction logging.
o Drood does not restart "gracefully". Established connections will be
dropped without allowing transactions in progress to complete.
o Drood Does not perform content negotiation beyond recognizing the
"Accept-Encoding", "If-Modified-Since", and "If-Unmodified-Since"
request headers. The only accept-encoding supported is gzip.
o Drood does not provide any response headers useful for caching server
responses beyond the "Date" and "Last-Modified" headers.
o Drood will not generate directory listings for clients.
o drood does not support the ~user notation to provide access to
resources in user directories, but this may be simulated with sym-
bolic links.
SYSTEM CONFIGURATION
Drood is a kqueue(2)-based multiplexer. By default, FreeBSD limits each
process to having a maximum of 64 simultaneously open descriptors. This
places a limit on the number of connections drood may multiplex. The
sysctl settings below, allow for a generous number of connections. These
values can be set at the command-line with the "sysctl" utility. It is
recommended that they be enabled permanently by placing these lines in
/etc/sysctl.conf on the host machine.
kern.maxfiles=16384
kern.maxfilesperproc=16384
kern.kq_calloutmax=65536
kern.ipc.nmbclusters=25600
kern.ipc.maxsockets=25600
Drood will attempt to set the accf_http accept filter on the listening
socket, to increase performance. For this to succeed, you will need to
load the module before starting drood with:
kldload accf_http
To load the module automatically at system boot-up, add the following
line to /boot/loader.conf:
accf_http_load="YES"
DROOD CONFIGURATION
Drood writes its pid into /var/run/drood.pid, if it can (ie., it is
started as root), and may be stopped with a SIGTERM. A rc.d script is
provided and installed in /usr/local/etc/rc.d/. Add the following lines
to /etc/rc.conf to start drood on system boot-up. Replace the items in
brackets with values appropriate for your system. These are the minimal
set of options one should start with. These and all of the other avail-
able options are described in full at the end of this manual page.
plunger_enable="NO"
drood_enable="YES"
drood_flags="-r <server-root> -u <user> -g <group> -m <instances>"
Once your system is configured you may start, stop, or restart drood, or
determine if it is running with the following commands:
/usr/local/etc/rc.d/drood start
/usr/local/etc/rc.d/drood stop
/usr/local/etc/rc.d/drood restart
/usr/local/etc/rc.d/drood status
If you do not want drood started on system start, then set
drood_enable="NO"
and use the following commands:
/usr/local/etc/rc.d/drood forcestart
/usr/local/etc/rc.d/drood forcestop
/usr/local/etc/rc.d/drood forcerestart
/usr/local/etc/rc.d/drood forcestatus
GZIP CONTENT ENCODING
To enable gzip content-encoding for static resources, the webmaster must
manually gzip the resources he or she would like to make available in
that encoding. The original resource should not be replaced by the
gzipped version, but should also be available in the same directory for
clients which cannot handle the encoding. The gzipped version must have
the ".gz" filename suffix. If a client indicates it is acceptable for a
requested resource to be gzipped, then drood will attempt to send the
gzipped version of the resource. If this attempt fails, drood will
attempt to send the non-compressed version of the requested resource.
Do not confuse gzip content-encoding with naturally gzipped resources,
such as tar.gz files. An explicit request for a gzipped resource will be
cause the resource to be transferred to the client, as expected. With
gzip content-encoding, the client requests a resource, such as an *.html
file, indicating it can accept that resource gzipped, to save bandwidth
and decrease transfer time. Drood will look for a gzipped version of the
requested resource and send it instead, if it exists. All major browsers
support gzip content-encoding, so creating gzipped versions of your
static resources is a useful thing to do, to both speed up transfers and
lower the server's bandwidth consumption.
Note that drood does not compare the modification times of the uncom-
pressed and compressed resources. It will always send the compressed
resource if it exists, is acceptable to the client, and drood has permis-
sion to read it. One can keep Makefiles in one's html directories to
compress all the resources whose compressed versions are out of date,
with gzip -k. As long as the Makefiles are not readable by the user or
group drood is running as, client requests for them will fail.
MAPPING FILENAME SUFFIXES TO MIME TYPES
These are the mappings from filename suffixes to MIME types which drood
recognizes out-of-the-box. They are listed in types.tab in
/usr/local/etc/drood/. Any file which cannot be identified by these map-
pings is identified by the server as "text/plain; charset=utf-8". To add
a mapping, simply add a line to types.tab. Each line must consist of the
filename suffix to be mapped, followed by one or more tab characters,
followed by the MIME type, followed by a newline. Blank lines are
ignored, after the first line. The first line must not be blank. If
drood finds empty fields in types.tab it will refuse to run. If you mod-
ify types.tab, you must restart drood for the changes to take effect.
Suffix MIME Type
html text/html; charset=utf-8
htm text/html; charset=utf-8
xml text/xml; charset-utf-8
txt text/plain; charset=utf-8
css text/css
ico image/vnd.microsoft.icon
png image/png
jpg image/jpeg
jpeg image/jpeg
tiff image/tiff
tif image/tiff
gif image/gif
tgz application/x-compressed
zip application/zip
ps application/postscript
eps application/postscript
gz application/x-gzip
tgz application/x-compressed
pdf application/pdf
swf application/x-shockwave-flash
js application/x-javascript
mov video/quicktime
qt video/quicktime
mpg video/mpeg
mp2 video/mpeg
mpa video/mpeg
mpe video/mpeg
avi video/x-msvideo
asf video/x-ms-asf
asx video/x-ms-asf
asr video/x-ms-asf
flv video/x-flv
ra audio/x-pn-realaudio
ram audio/x-pn-realaudio
wav audio/x-wav
mp3 audio/mpeg
COMMAND-LINE OPTIONS
The following options are recognized. Only the -r option is required,
but you will probably want to include at least the -u, and -g options
when you are starting the server for production use. For optimal perfor-
mance, employ the -m option, and use the -q and -t options to match your
load levels. If you wish to service CGI and/or SCGI requests, add the -d
option. If you wish to service SCGI requests, you must add one or more
-s options.
-r The -r option is mandatory and specifies the server root directory,
which drood will make its current working directory.
The resources served-up by drood are determined by the "Host" header
of requests, thus implementing name-based virtual hosting. For every
hostname you wish to be recognized by the server, an identically-
named subdirectory of the server root directory must be created. The
static files served up by each virtual host are placed into the iden-
tically-named subdirectory. Any or all of the subdirectories may be
symbolic links. One subdirectory must be named "default". This is
the directory which will be used to fulfill static requests when no
"Host" header is supplied by a client (eg., HTTP/1.0 requests). The
"default" directory can and should be a symbolic link. If you would
like a directory to be used for more than one hostname, you must cre-
ate links for the extra hostnames.
For example, I could have, in my server root directory, the following
subdirectories. Note the symlink for the loopback addresses. With-
out it, drood will not be able to find resources for requests from
loopback connections, if clients use the address in URIs, instead of
the local hostname. Note the link for the IP address of the server,
to allow clients to connect using URIs containing the server's IP
address instead of its hostname. Note that if you are using IPv6,
you will need to create links which include the surrounding square
brackets which are used to identify IPv6 addresses in URIs (rfc3986).
The last three entries express the IPv4 address in different but
valid formats. These can be useful to clients connecting to your
server if they are behind a dumb filter, and that filter is blocking
your hostname and/or decimal IP addresses.
mammothcheese.ca -> actual subdirectory (IPv4)
www.mammothcheese.ca -> symlink to mammothcheese.ca (IPv4)
default -> symlink to mammothcheese.ca (IPv4/IPv6)
[mammothcheese.ca] -> symlink to mammothcheese.ca (IPv6)
[www.mammothcheese.ca] -> symlink to mammothcheese.ca (IPv6)
127.0.0.1 -> symlink to mammothcheese.ca (IPv4 Loopback)
[::1] -> symlink to mammothcheese.ca (IPv6 Loopback)
64.15.138.206 -> symlink to mammothcheese.ca (IPv4 Decimal)
0100.017.0212.0316 -> symlink to mammothcheese.ca (IPv4 Octal)
0x40.0x0f.0x8a.0xce -> symlink to mammothcheese.ca (IPv4 Hexadecimal)
1074760398 -> symlink to mammothcheese.ca (IPv4 IP Number)
Drood will reject any request whose host header contains a virgule
"/", or starts with "." in order to prevent clients from accessing
resources outside of the virtual host subdirectories. Note this does
not prevent you from symlinking a directory outside of the server
root directory hierarchy into the server root directory.
Symbolic links can be used to provide access to user websites. For
example, if I wished to expose the personal website of user "ella" on
mammothcheese.ca to drood, I could create a symbolic link inside the
mammothcheese.ca directory named "ella" pointing to her ~/public_html
directory. This would allow access via URIs such as http://www.mam-
mothcheese.ca/ella/. Note that drood will recognize a request ending
in a virgule "/" as a request for the root resource in the directory
specified by the request. Note also, if the root resource has been
set to a dynamic resource, this won't work. In that case, the full
path to ella's root resource will have to be specified by clients.
Eg., http:www.mammothcheese.ca/ella/index.html. See the entry for
the -e option for information on the root resource.
Remember to set the ownership and permissions of the directories and
their contents according to the values you give for the -u and -g
options. Static resources must be set readable by the user or group
drood will be running as. Directories must similarly be searchable.
If the -d option is present, requests whose "Host" headers reference
the directory specified by that option, will be rejected. This pre-
vents clients from requesting data files in the (S)CGI directory.
Drood will refuse to send files to clients, if they are executable by
drood, regardless of where they reside.
-e The root resource of all virtual hosts defaults to a static resource
named "index.html", which itself may be a symbolic link. This may be
changed with the -e option. Note this changes the name of the root
resource of all virtual hosts served-up by drood. The value speci-
fied must not begin with a virgule "/".
You may, with the -e option, specify a dynamic resource as the root
resource. If you do, you must be sure to include the -d option to
tell the server where (S)CGI programs live. Eg.,
drood -r /usr/local/www/drood -d cgi-bin -e cgi-bin/index.cgi
To summarize, every virtual host has its own static root resource in
its own subdirectory, but all virtual hosts' static root resources
must have the same name, either the default "index.html" or another
name specified by the -e option. If a dynamic resource is specified
as the root resource, then it is shared by all virtual hosts, and
resides in the (S)CGI subdirectory, as defined by the -d option. If
a dynamic root resource needs to know the virtual host for which it
is being executed, it must examine the SERVER_NAME environment vari-
able.
If a request is received ending with a virgule "/", that request is
interpreted as a request for the root resource residing in the direc-
tory specified by the request. If the root resource is a dynamic
resource, such a request will not make sense, and fail, unless the
request is for the toplevel root resource of a host.
If the root resource is a symbolic link and you wish to make use of
gzip content-encoding for that resource when requested via the sym-
bolic link, make a symbolic link to the compressed version of the
root resource as well. For example, if you have index.html linked to
another_file.html, create a compressed version of another_file.html
if one does not already exist, with "gzip -k another_file.html".
Then create a link for it with "ln -s another_file.html.gz
index.html.gz" Remember to set the file permissions accordingly for
the values you have used for the -u and -g options.
-d The -d option, if present, specifies the subdirectory of the server
root directory which contains CGI and/or SCGI resources. The value
given to this option cannot contain the directory separator character
"/" anywhere in it, nor can it be ".." or "." by itself. The direc-
tory specified must be one level below the server root directory.
The directory must be readable and searchable for the user or group
specified with the -u and -g options. The directory may contain any
subdirectory structure the user wishes to create in it. Only exe-
cutables in the (S)CGI directory, or its subdirectories, can be run.
Drood refuses to execute symbolic links.
All virtual hosts share the (S)CGI directory. If (S)CGI programs
wish to know what hostname they have been invoked for, they must
examine the SERVER_NAME environment variable. If no "Host" header
was supplied with the request, then SERVER_NAME will be set to the
string "default". If the -d option is not present, executables can-
not be run. Requests for dynamic resources must include the dynamic
path in their URIs, because this is how drood differentiates static
requests from dynamic requests. Eg., if -d is "cgi-bin", then
http://host.domain/cgi-bin/foobar.cgi
is a request to run foobar.cgi from the cgi-bin subdirectory of the
server root directory. If the -d option was not set, then this would
be interpreted as a request for a static resource named foobar.cgi
located in the cgi-bin subdirectory of the host.domain subdirectory
of the server root directory.
Note that if you have a (S)CGI directory and you subsequently decide
to run drood without the -d option, that directory will be considered
a valid directory containing static resources for a virtual host, and
clients may request the non-executable resources in the directory, if
the client knows their names, by providing a "Host" header set to the
name of the directory. Drood will always refuse to send files to
which it has executable permission to clients, no matter where they
reside, but if you have data files in your (S)CGI directory, it's a
good idea to remove the (S)CGI directory if you are not running drood
with the -d option anymore. You should at least change the (S)CGI
directory's ownership and/or permissions to make it inaccessible by
drood.
(S)CGI programs need only precede their response bodies with a "Con-
tent-Type" header and a blank line. Drood will chunk response data
for (S)CGI programs invoked over persistent connections. The (S)CGI
program's response header will be supplemented with a response status
line, a "Date" header if one is missing, a "Server" header, and if
the (S)CGI response header does not include a "Content-Length" header
and the connection is persistent, a "Transfer-Encoding: chunked"
header. If a "Location" header is provided by the (S)CGI program,
then drood with create a "302 Found" response to send to the client,
which will cause the client to redirect itself to the URI specified
in the "Location" header. Otherwise, drood will compose a "200 OK"
response status line.
It is crucial that CGI programs invoked with the POST method read
from stdin exactly the number of characters specified by the CONTENT-
LENGTH environment variable. Reading too much or too little will
prevent drood from reading the next request over a persistent connec-
tion, and it will then drop the connection. For GET requests, the
stdin of CGI programs will be connected to /dev/null.
The stderr of CGI programs is connected to /dev/null. For testing
purposes run drood with -x option and the CGI stderr will be con-
nected to the terminal from which drood is running. For production
use, CGI programs must send diagnostic output to files, or use sys-
log(3).
The following environment variables are set for (S)CGI programs:
REMOTE_ADDR, REQUEST_METHOD, SCRIPT_NAME, QUERY_STRING,
HTTP_USER_AGENT, HTTP_COOKIE, SERVER_SOFTWARE, SERVER_NAME, GATE-
WAY_INTERFACE, CONTENT_TYPE, and CONTENT_LENGTH.
Additionally, SCGI is set for SCGI resources, only.
Drood cannot recognize virtual paths for (S)CGI programs, so
PATH_TRANSLATED and PATH_INFO are not set.
-s Including this option on the command line, if and only if the -d
option has also been included, causes drood to forward requests for
items in the (S)CGI directory, with a specified filename suffix, to a
specified SCGI Server. Starting-up and shutting-down processes for
traditional CGI programs becomes a performance bottleneck on busy
servers. The SCGI protocol specifies a simple means by which a web
server can forward a request to a persistent application to generate
the response. Process start-up and shut-down, and application ini-
tialization costs are eliminated for each request, resulting in sig-
nificantly better performance over traditional CGI.
Multiple instances of this option may be present on the command line.
Each option value must have form: <host>|<port>|<suffix>, where
<host> is the name of the host the SCGI server is running on, or its
IP address expressed in either IPv4 or IPv6 presentation format,
<port> is the port number the SCGI server is listening on, and suffix
is the filename suffix to associate with this SCGI server. Requests
for items in the (S)CGI directory (specified by the -d option) whose
filenames are terminated by this sequence of characters, will be for-
warded to the SCGI server at <host> listening on <port>. The suffix
value must not contain a dot.
For example, to forward requests for files matching *.foo to a local
server listening on port 4000, and forward requests for files match-
ing *.bar to a local server listening on port 5000, one would include
-s '127.0.0.1|4000|foo' -s '127.0.0.1|5000|bar'
on the drood command line. Note that it is necessary to quote the
option values to prevent the shell from interpreting them as pipe-
lines.
A generic multi-process SCGI server is included in the drood distri-
bution. The server has its own rc script and manual page
(plunger.8), and is used by the author to test drood's SCGI support.
It allows filter programs to be used as SCGI servers.
-p The -p option specifies the port to listen on. This defaults to 80
if not specified.
-i By default, drood accepts connections on all interfaces it can find
capable of IPv4 or IPv6. The -i option, when present, overrides this
behavior, by limiting drood to accepting connections from a specified
interface only. The option accepts the IP address of the desired
interface as an argument. The address must be expressed in the pre-
sentation format for either IPv4 or IPv6.
The intent of this option is to allow the administrator to prevent
the outside world from accessing a server during testing by making
drood bind only to one interface (eg., the loopback address).
-u
-g Drood must be started as root in order to bind to port 80. The -u
and the -g options may be used to specify the user and group for
(S)CGI programs. If not specified, both values default to "nobody".
If you employ the -m option to run one instance of drood for each
processor core, as it is recommended you do, the child drood pro-
cesses will also be launched as this user and group. The main drood
process does not change its user or group so that it may restart upon
receipt of SIGHUP with the same privileges it had when it began run-
ning.
-t When reading a request header from a client, drood drops the connec-
tion if it cannot read the complete request header within twenty sec-
onds. The -t option, if present, specifies a different read timeout
value, in seconds. Clients typically keep a connection to a server
open to aid responsiveness if the user subsequently requests more
resources from the same server, and rely on the server to timeout
idle connections. The value must be in the range 1-60 seconds. It
is important this value take into consideration the latency of drood
on your system under load, and the latency of your network inter-
faces, and the possible latency of clients behind firewalls on busy
networks. If the server starts dropping connections under load, and
you haven't run out of resources, you may have the read timeout set
too low.
-w When drood is in the process of writing a requested resource to a
client, the connection will be dropped if 60 minutes has elapsed
since it started writing the resource. This value may be changed
with the -w option, and must be in range of 0-120 minutes. Setting
this value to 0, disables the write timeout. In this case, the
client may take as long as it likes to read a requested resource.
Note that persistent connections may exist for longer periods than
this value specifies, but each individual resource requested over
such a connection must be read by the client within this number of
minutes, or the connection will be dropped.
-q The -q option, if present, specifies the backlog of client connec-
tions queued by the OS kernel for the server to subsequently service.
This value defaults to 1000. Note that the OS kernel actually uses a
queue of 1.5 times the size of the specified value. Connections
arriving when the queue is full are dropped by the kernel. This
value should be set to a generous value. If the system starts
rejecting connections under load, and you're sure you haven't run out
of resources, try increasing the size of the backlog queue.
-x The -x option, if present, prevents drood from becoming a daemon. It
will then run in the foreground of the terminal where it was started,
and may be stopped with signals (ie., Control-C). The server also
will not write its pid to /var/run/drood.pid when the -x option is
used.
-m The -m option specifies how many instances of drood should be run,
and defaults to 1. This option is intended for use on multiple-core
or multiple-processor machines, where running a separate instance of
drood for each core/processor will drastically increase the number of
requests per second drood can process.
-l The -l option turns-on request logging. If present it must specify
the fully-qualified filename of a file to hold the request log. The
file must be writeable by the user that drood starts as. If the file
does not exist, drood will attempt to create it, so the directory in
which the file resides should be writeable by the initial user, as
well.
Logging is turned-off by default. Request logging differs from
transaction logging in that requests are logged as they arrive,
instead of after they have been processed. In particular, this means
the response code and the number of bytes transferred are not
recorded in log records, because they are not known at the time the
request is logged. Drood does not use the common log file format.
It uses its own, simpler-to-parse format.
Each line of the logfile is a complete request record. The fields of
request records are ordered as follows, with all fields separated by
single | characters: The date and time of the request, the client IP
address, the request User-Agent header, the request method, the
request URL, and finally, the request Referer (sic) header. If no
User-Agent or Referer header is present in a request, these items
will be the strings, "no user-agent header", or "no referrer header",
respectively.
Note that the IP address will be expressed in IPv6 presentation for-
mat by default. Clients making IPv4 connections will have their IP
addresses written as IPv4-mapped IPv6 addresses, unless the -i option
has been specified with an IPv4 address. In that case the address
with appear in the presentation format for IPv4.
Read the manual for newsyslog.conf(5) to learn how have your logfile
automatically rotated. An example is shown below. Adding this line
to /etc/newsyslog.conf will cause the file /var/drood-requests.log to
be turned-over every night at midnight, with the five most recent
logfiles kept on-hand, renamed and compressed with gzip.
/var/log/drood-requests.log 600 5 * T00 Z /var/run/drood.pid
newsyslog(8) can be scheduled to run with crontab(1,5). Here is a
sample crontab for root. Copying these lines to a file and invoking
/usr/bin/crontab <filename>
will cause crontab to run newsyslog at midnight every night:
SHELL=/bin/sh
PATH=/usr/sbin
HOME=/var/log
# insert your email address below to be notified by mail when newsyslog
# emits output on its stderr.
MAILTO=user@host.domain
0 0 * * * /usr/sbin/newsyslog.
AUTHORS
James Bailie <jimmy@mammothcheese.ca>
http://www.mammothcheese.ca
Sep 10, 2009