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, minimal web server. It is configured with
command-line options.
WHAT DROOD DOES
o Drood supports 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.
o Drood supports requests for single byte ranges.
o Drood performs request logging instead of transaction logging.
o Drood stops and restarts gracefully. Already established connections
are allowed to terminate naturally before server processes stop.
WHAT DROOD DOES NOT DO
o Drood does not support TLS/SSL.
o Drood does not perform access authentication.
o Drood Does not perform content negotiation beyond recognizing the
"Accept-Encoding", "If-Modified-Since", "If-Unmodified-Since", and
"Range" 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.
drood_enable="YES"
drood_flags="-r <server-root> -u <user> -g <group>"
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.
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 and the client wants 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.
Note that when sending responses to requests with Range headers, Drood
will always send the requested byte ranges from the uncompressed
resource. Gzip content encoding is only used for responses containing
entire static resources.
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
svg image/svg+xml
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.
-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. For every hostname you wish to be recognized by the
server, an identically-named subdirectory of the server root direc-
tory must be created. The static files served up by each virtual
host are placed into the identically-named subdirectory. Any or all
of the subdirectories may be hard or symbolic links. One subdirec-
tory 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 link. If you would like a directory to be used for more
than one hostname, you must create links for the extra hostnames.
An example root directory specifying entries for one hostname is
below. Only the first entry is an actual virtual host subdirectory.
mammothcheese.ca -> actual subdirectory (IPv4)
www.mammothcheese.ca -> link to above (IPv4)
default -> link (IPv4/IPv6 HTTP/1.0)
If you wish to accept connections specified by IP address, you must
include links for valid addresses:
64.15.138.206 -> link (IPv4 Decimal)
127.0.0.1 -> link (IPv4 Loopback)
The following three entries specify valid, but rarely used forms of
IPv4 addresses, which could be included for completeness sake:
0100.017.0212.0316 -> link (IPv4 Octal)
0x40.0x0f.0x8a.0xce -> link (IPv4 Hexadecimal)
1074760398 -> link (IPv4 IP Number)
If you wish to accept IPv6 connections, you will need to add entries
where the hostname is delimited with square brackets per RFC3986:
[mammothcheese.ca] -> link for IPv6 connections
[www.mammothcheese.ca] -> link for IPv6 connections
[::1] -> link (IPv6 Loopback)
If you cause drood to listen on a port other than port 80, that port
number will appear in client "Host" headers. You must adjust your
entries accordingly:
mammothcheese.ca:8080 -> actual subdirectory (IPv4)
www.mammothcheese.ca:8080 -> link to above
(etc)
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 files in the (S)CGI directory hierar-
chy.
-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 "/".
If a request is received for a directory, that request is interpreted
as a request for the root resource residing in that directory.
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
-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".
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 a request to run
foobar.cgi would look like this:
http://host.domain/cgi-bin/foobar.cgi
Note that if you have a (S)CGI directory and you subsequently decide
to run drood without the -d option, that directory will be treated as
a virtual host subdirectory. 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 ignores Status header
lines from (S)CGI programs. If a "Location" header is provided by
the (S)CGI program, then drood will create a "302 Found" status line
to send to the client. Otherwise, drood will compose a "200 OK" sta-
tus line. This means errors must be reported to the client using
HTML responses.
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,
SERVER_PORT, GATEWAY_INTERFACE, CONTENT_TYPE, SCGI, GZIP, and CON-
TENT_LENGTH.
SCGI is set to 1 for SCGI resources, and to 0 for plain CGI. If the
client request included an Accept-Encoding header indicating the
client can receive gzipped data, GZIP is set to 1. Otherwise it is
set to 0.
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. The filesystem entries must exist, but they
may be empty files.
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 whose filenames are terminated by
this sequence of characters, will be forwarded 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 argument to the -p option specifies the port to listen on. This
defaults to 80 if the -p option is not present on the command-line.
-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.
-u
-g The -u and the -g options may be used to specify the user and group
of drood server processes. If not specified, both values default to
"nobody".
-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. The value must be in the range 1-60 seconds.
-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.
-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.
-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 the number of CPUs on the host system. On a four-
core machine, four instances of drood would be run automatically.
-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
Jul 30, 2011