tipidee
Software
skarnet.org

The tipideed program

tipideed is the binary that actually does what you want from a web server package: it serves files over HTTP.

Interface

     tipideed [ -v verbosity ] [ -f cdbfile ] [ -d basedir ] [ -R ] [ -U ]

Common usage

tipideed is intended to be run under a TCP super-server such as s6-tcpserver, for plain text HTTP, or s6-tlsserver, for HTTPS. It delegates to the super-server the job of binding and listening to the socket, accepting connections, spawning a separate process to handle a given connection, and potentially establishing a TLS tunnel with the client for secure communication.

As such, a command line for tipideed, running as user www, listening on address ${ip}, would typically look like this, for HTTP:

     s6-envuidgid www s6-tcpserver -U -- ${ip} 80 s6-tcpserver-access -- tipideed

or, for HTTPS:

     s6-envuidgid www env KEYFILE=/path/to/private/key CERTFILE=/path/to/certificate s6-tlsserver -U -- ${ip} 443 tipideed

Most users will want to run these command lines as services, i.e. daemons run in the background when the machine starts. The examples/ subdirectory of the tipidee package provides service templates to help you run tipideed under OpenRC, s6 and s6-rc.

Exit codes

0
Clean exit. The client closed the connection after a stream of HTTP exchanges.
1
Illicit client behaviour. tipideed exited because it could not serve the client in good faith.
2
Illicit CGI script behaviour. tipideed exited because the invoked CGI script made it impossible to continue. Before exiting, tipideed likely has sent a 502 (Bad Gateway) response to the client.
100
Bad usage. tipideed has been run in an incorrect way: bad command line options, or missing environment variables, etc.
101
Cannot happen. This signals a bug in tipideed, and comes with an error message asking you to report the bug. Please do so, on the skaware mailing-list.
111
System call failed. If this happens while serving a request, tipideed likely has sent a 500 (Internal Server Error) response to the client before exiting.

Environment variables

Reading - mandatory

tipideed expects the following variables in its environment, and will exit with an error message if they are undefined. When tipideed is run under s6-tcpserver (with s6-tcpserver-access or s6-tlsserver, these variables are automatically set by the super-server. This is the way tipidee gets its network information without having to perform network operations itself.

PROTO
The network protocol, normally TCP.
TCPLOCALIP
The IP address the server is bound to. It will be passed as SERVER_ADDR to CGI scripts.
TCPLOCALPORT
The port the server is bound to. It will be passed as SERVER_PORT to CGI scripts.
TCPLOCALHOST
The domain name associated to the local IP address. It will be passed as SERVER_NAME to CGI scripts.
TCPREMOTEIP
The IP address of the client. It will be passed as REMOTE_ADDR to CGI scripts.
TCPREMOTEPORT
The port of the client socket. It will be passed as REMOTE_PORT to CGI scripts.

Reading - optional

tipideed can function without these variables, but if they're present, it uses them to get more information.

TCPREMOTEHOST
The domain name associated to the IP address of the client. It will be passed as REMOTE_HOST to CGI scripts; if absent, the value of TCPREMOTEIP will be used instead.
TCPREMOTEINFO
The name provided by an IDENT server running on the client, if any. This is obsolete and not expected to be present; but if present, it will be passed as REMOTE_IDENT to CGI scripts.
SSL_PROTOCOL
The version of the TLS protocol used to cipher communications between the client and the server. If present, tipideed will assume that the client connection is secure, and will pass HTTPS=on to CGI scripts; otherwise, it will assume it is running plaintext HTTP.

Writing

When spawning a CGI or NPH script, tipideed clears all the previous variables, so the passed environment is as close as possible to the environment of the super-server; and it adds all the variables that are required by the CGI 1.1 specification. It does not add PATH_TRANSLATED, which CGI scripts should not rely on.

Options

-v verbosity
The level of log verbosity. This is the same as the global verbosity setting in the configuration file; an explicit command line option overrides any setting present in the configuration file.
-f file
Use file as the compiled configuration database, typically obtained by running tipidee-config -o file. The default is /etc/tipidee.conf.cdb.
-d docroot
Change the working directory to docroot before serving. Default is serving from the current working directory. Note that documents need to be located in subdirectories of docroot, one subdirectory per virtual domain tipideed is serving.
-R
chroot. If the underlying operating system has the chroot() system call, use it before serving. This always happens after opening the configuration database, after changing the working directory, and before dropping privileges. The idea is that chrooting helps with security, but the configuration database should be located outside of the document space.
-U
Drop root privileges. If this option is given, tipideed expects two additional environment variables, UID and GID, containing the uid and gid it should run as; it will drop its privileges to $UID:$GID before serving. This option is mainly useful when paired with -R, because chrooting can only be performed as root, so root privileges need to be kept all the way to tipideed then dropped after tipideed has chrooted. In a non-chrooted setup, it is simpler and more secure to run the super-server with the -U option instead: root privileges will be dropped as soon as the super-server has bound to its socket, and all the subsequent operations, including the spawning of tipideed processes, are performed as a normal user.

Detailed operation

Performance considerations

On systems that implement posix_spawn(), the s6-tcpserver super-server (and the s6-tlsserver one as well, since both use the same underlying program) uses it instead of fork(), and that partly alleviates the performance penalty usually associated with servers that spawn one process per connection.

One of tipidee's stated goals is to explore what kind of performance is achievable for a fully compliant Web server within the limits of that model. To that effect, tipideed is meant to be fast. It should serve static files as fast as any server out there, especially on Linux (or other systems supporting splice()) where it uses zero-copy transfer. CGI performance should be limited by the performance of the CGI script itself, never by tipideed.

tipideed itself does not use fork() if the system supports posix_spawn() — with one exception, that you will not hit, and if you do, fork() will not be the bottleneck. (Can you guess which case it is, without looking at the code?) tipideed does not parse its configuration file itself, delegating the task to the offline tipidee-config program and directly mapping a binary file instead. To parse a client request, it uses a deterministic finite automaton, only reading the request once, and only backtracking in pathological cases. This should streamline request processing as much as possible.

If you have benchmarks, results of comparative testing of tipideed against other Web servers, please share them on the skaware mailing-list.

Notes