TIPIDEE.CONF(5)

NAME
tipidee.conf - text file written by the web administrator to configure the tipideed(8) server

DESCRIPTION
/usr/pkg/etc/tipidee.conf is a text file written by the web administrator to configure the tipideed(8) server. After writing or modifying this file, the administrator is expected to run the tipidee-config(8) program, that will read /usr/pkg/etc/tipidee.conf and output a /usr/pkg/etc/tipidee.conf.cdb file that will be suitable for tipidee.conf to use.

tipidee-config(8) provides sane defaults, so an empty /usr/pkg/etc/tipidee.conf file is perfectly usable for purely static installations. But an empty file still needs to be created, unless tipidee-config(8) is run with the ‘-i /dev/null’ option.

The /usr/pkg/etc/tipidee.conf file contains a series of lines; every line is an instruction. Lines do not wrap around and there is no quoting, so a newline is always the end of an instruction. Empty lines, or lines containing only whitespace, or lines beginning with ‘#’ ( comments), are ignored. If a line contains a ‘#’ that is not in the middle or end of a word, the rest of the line is also considered a comment, and ignored.

Words on a line are separated by whitespace ( spaces or tabs). Instructions are one directive, the first word in the line, followed by one or more arguments. Most directives take a fixed number of arguments; some of them take a variable number. There are several types of directives.

  Preprocessing directives
These are meta-directives: they do not control tipideed(8)' s behaviour directly, but tell tipidee-config(8) to include other files. They allow administrators and packagers to write modular, pluggable configuration files. Preprocessing directives always start with a ‘’! ( exclamation point, or bang) character.

You will probably never see preprocessing directives in simple configuration files. They are meant for bigger or more generic configurations.

The !include directive

    !include file

•   This directive will replace itself with the contents of file.

•   file can be a relative or absolute path. If relative, then it is relative to the directory of the file being currently processed, i.e. the file containing the ‘!include’ directive. In other words, things will work as you intuitively expect.

The !includedir directive

    !includedir dir

•   This directive will include every file in directory dir.

•   File names starting with a ‘’. ( dot) will be ignored ( i.e. not included).

•   The inclusion order is deterministic: file names are sorted according to the C locale.

•   dir can be a relative or absolute path. If relative, then it is relative to the directory of the file being currently processed, i.e. the file containing the !includedir directive. In other words, things will work as you intuitively expect.

The !included: directive

    !included: unique
    !included: multiple

•   This directive is usually written at the beginning of a file. Only one such directive per file is allowed.

•   ‘!included:’ governs what happens when a file is included more than once.

    •   If a file contains an ‘!included: unique’ line, then all inclusions of this file after the first one will be ignored: the contents of the file will appear only once.

    •   If a file contains an ‘!included: multiple’ line, then the file will be expanded into its contents every time the file is included.

    •   If a file does not contain an ‘!included:’ directive, then including it twice is an error, and tipidee-config-preprocess(8), the program in charge of the preprocessing directives, will complain and exit.

•   Don't forget the ‘’: ( colon) at the end of the !included: directive!

  Simple global settings
Global directives control global aspects of tipideed(8) — values that apply to the server itself, no matter what domain it is serving.

Some global directives are introduced by their own keywords, see below. Others are simple configuration values that would clutter up the directive namespace, so we put them together under a unique umbrella, the ‘global’ directive. ‘global’ takes two arguments: the name of a setting and its value.

read_timeout

    global read_timeout t

•   t is a non-negative integer, in milliseconds. It represents the maximum duration that a client is allowed to be idle.

•   If t milliseconds elapse without the client sending a request, tipideed(8) will assume it is done, close the connection and exit. Also, if t milliseconds elapse while the client is sending a request, and the request is still not complete, tipideed(8) will also close the connection.

•   The default is 0, meaning infinite: tipideed(8) will never slam the door into a client's face, even if the client is excessively slow or fails to close a connection it's not using anymore.

•   A good setting is ‘global read_timeout 60000’, closing connections after one minute of inactivity.

write_timeout

    global write_timeout t

•   t is a non-negative integer, in milliseconds. It represents the maximum duration that tipideed(8) will accept to wait when sending data to the client.

•   If t milliseconds elapse while tipideed(8) is sending data to the client, tipideed(8) will give up and exit with an error message.

•   This typically happens when the network is congested, and the kernel's socket send buffers are full. It could also mean that a client is failing to read the data it has requested; or that the data is very large and taking time to transfer.

•   The default is 0, meaning infinite: tipideed(8) will wait forever until the network uncongests and its client starts to behave.

•   An example setting is ‘global write_timeout 600000’, closing connections if a transfer takes more than 10 minutes; but servers serving large files to clients on slow connections will want a larger value.

cgi_timeout

    global cgi_timeout t

•   t is a non-negative integer, in milliseconds. It represents the maximum duration that a CGI script spawned by tipideed is allowed to run.

•   If t milliseconds elapse while a CGI script is running, and tipideed(8) hasn't gotten a full response yet, the script will be killed, and tipideed(8) will send a ‘504 (Gateway Timeout)’ response to the client.

•   The default is 0, meaning infinite: tipideed(8) will wait forever until CGI scripts write their output.

•   An example setting is ‘global cgi_timeout 10000’, giving any CGI scripts 10 seconds to complete — most users aren't willing to wait more than a few seconds for a page to render anyway.

max_request_body_length

    global max_request_body_length n

•   n is a non-negative integer, in bytes. It represents the maximum size that tipideed(8) will accept for the body of an HTTP request.

•   If the client sends a request with a body larger than n bytes, tipideed(8) will send a ‘413 (Content Too Large)’ response and close the connection.

•   The default is 8192, which is large enough for most.

•   An example setting is ‘global max_request_body_length 500’, when the administrator knows that no script on the site needs an input of more than 500 bytes and anything larger is malicious.

max_cgi_body_length

    global max_cgi_body_length n

•   n is a non-negative integer, in bytes. It represents the maximum size that tipideed(8) will accept for a CGI script's answer that it needs to process.

•   If a CGI script writes more than n bytes to its stdout, tipideed(8) will send a ‘502 (Bad Gateway)’ response to the client and die with an error message.

•   This limit does not apply to NPH scripts, which send their stdout directly to the client without any processing by tipideed(8).

•   The default is 4194304 ( 4 mebibytes).

•   An example setting is ‘global max_cgi_body_length 100000000’, when the administrator knows that CGI scripts can write up to 100 megabytes. Note that the CGI specification forces web servers to read the whole CGI output in memory, so the larger the value, the more RAM tipideed(8) may consume in order to hold CGI output data. And this is “private dirty” memory, i.e. memory that really counts towards resource use on your server, so be careful with that setting — and with the CGI scripts you choose to run.

executable_means_cgi

    global executable_means_cgi value

•   value is a non-negative integer. If it is nonzero, then all the documents that have an executable bit for “others” will be considered CGI scripts by default.

•   This is useful when your CGI scripts are scattered among your documents and you cannot gather them under a hierarchy like /cgi-bin/.

•   On the other hand, it should only be used by administrators who keep a tight control on their documents. It is dangerous to activate this option with dynamically managed content, because there could be files created with the wrong permissions and improperly identified as CGI scripts, resulting in failures or even security holes.

•   The classification of a given executable file as a CGI script can be overridden by a local ‘noncgi’ directive, see below. Such a directive can protect dynamically managed content that is restricted to a given hierarchy.

XXX_no_translate

    global XXX_no_translate value

•   This directive is dangerous and significantly changes the behaviour of tipideed(8), which is why it is marked with the ‘XXX_’ prefix. If you are not 100% certain that you need it, do not use it.

•   value is a non-negative integer. If it is nonzero, then:

    •   Symbolic links are not resolved when tipidee looks for resources or error pages. This means that host names and resource paths will be looked up in the configuration database as they are given by the client, not as they appear in the filesystem.

        •   In particular, a same resource could have different attributes depending on how it is accessed: it could be seen as a CGI script from one URI and as a regular file from another.

        •   This also means that if your configuration file needs local directives, you must specify them for every host/port combination your server is listening on.

    •   If tipideed is not chrooted, symbolic links may point outside of the server root: this will not be checked. This allows you to serve data from other parts of the filesystem.

The ‘index-file’ directive

    index-file file1 file2 ...

‘index-file’ is a global directive, the first one in this list that is introduced by its own keyword and does not use ‘global’.

•   The ‘index-file’ directive has a variable number of arguments. file1, file2, and so on are the names of the files that should be used to try and complete the URI when a client request resolves to a directory.

•   For instance: ‘index-file index.cgi index.html index.htm’ means that when tipideed(8) is asked to serve ‘http://example.com’, it will first try to serve as if the request had been ‘http://example.com/index.cgi’, then ‘http://example.com/index.html’, then ‘http://example.com/index.htm’. The first resource found is the one that is served; if none of the resources exist, tipideed(8) responds ‘404 (Not Found)’.

•   This is valid for any subdirectory: ‘http://example.com/foo’, if the /foo resource resolves to a directory, is expanded to ‘http://example.com/foo/index.cgi’, then ( if not found) ‘http://example.com/foo/index.html’, then ( if not found) ‘http://example.com/foo/index.htm’.

•   The default is ‘index-file index.html’, meaning that only the index.html file will be looked up when a resource resolves to a directory.

The ‘log’ directive

‘log’ is a global directive, introduced by the keyword ‘log’. It allows the user to control what will appear in tipideed(8)' s log output.

    log nothing
    log keyword1 keyword2 ...

•   tipideed(8) writes all its logs to stderr. It prints fatal error messages with the prefix ‘tipideed: pid pid: fatal: ’, and warning messages with the prefix ‘tipideed: pid pid: warning: ’. In normal operation, if everything goes well, you should never see any of these.

•   Depending on what the ‘log’ directive says, it also prints informational messages related to what it's doing. These informational messages all have the prefix ‘tipideed: pid pid: info: ’.

    •   One line when tipideed(8) starts and one when it exits, if the ‘log’ directive includes the ‘start’ keyword.

    •   Up to three lines per client request, controlled by the ‘request’, ‘resource’ and ‘answer’ keywords. If you have a CGI script outputting local redirections ( which is rare), there may be several ‘resource’ lines.

•   If no ‘log’ directive has been provided, the default is ‘log request answer answer_size’.

Here is the full list of keywords and what they do:

‘nothing’
    Don't log anything else than warning and error messages. This keyword cannot be given with other keywords.

‘start’
    Log a ‘start’ line when tipideed(8) starts and an ‘exit exitcode’ line when it exits.

‘ip’
    Add an ‘ip client_ip’ field to the ‘start’ line. This is potentially PII, so make sure to stay compliant with your local laws if you activate it. client_ip is read from the TCPREMOTEIP environment variable. This keyword has no effect when given without the ‘start’ keyword.

‘hostname’
    Add a ‘host client_hostname’ field to the ‘start’ line. This is potentially PII, so make sure to stay compliant with your local laws if you activate it. client_hostname is read from the TCPREMOTEHOST environment variable if it exists, or made up from TCPREMOTEIP otherwise. Make sure to invoke s6-tcpserver-access(8) before tipideed(8) in order to get meaningful values for this field. This keyword has no effect when given without the ‘start’ keyword.

‘host_as_prefix’
    Prepend all ‘request’, ‘resource’ and ‘answer’ lines with a ‘host host’ field. ( This field will not be repeated in the ‘request’ line, so it changes the order of the fields in that line.) host is the virtual host the request is addressed to. ‘host_as_prefix’ is useful when you want to log entries for different virtual hosts to different locations: for instance, if you're using s6-log(8), and want entries for ‘example.com’ and ‘example.org’ to be logged to different backends, you would use the ‘host_as_prefix’ directive, and use ‘- +"^tipidee: pid [[:digit:]]*: info: host example\.com "’ in your logging script to select ‘example.com’ -related lines, and ‘- +"^tipidee: pid [[:digit:]]*: info: host example\.org "’ to select ‘example.org’ -related lines. Note that warning and error messages would still need an additional backend, as well as potential ‘start’ and ‘exit’ lines.

‘request’
    Log a ‘request’ line when tipideed(8) receives a request from its client. The line looks like ‘request method host host path "path" http version’. The path is decoded, but if there are non-printable characters in it, they are encoded as hexadecimal values ‘ xab’. If the request line includes a query, a ‘query query’ field is added before the ‘http’ field.

‘referrer’
    Add a ‘referrer "referrer"’ field to the ‘request’ line, for requests that include a ‘Referer:’ header. referrer is quoted like path, to avoid malicious clients messing with log lines. This keyword has no effect when given without the ‘request’ keyword.

user-agent
    Add a ‘user-agent "user-agent"’ field to the ‘request’ line, for requests that include a ‘User-Agent:’ header. user-agent is quoted like path, to avoid malicious clients messing with log lines. This keyword has no effect when given without the request keyword.

‘x-forwarded-for’
    Add an ‘x-forwarded-for “xff”’ field to the ‘request’ line, for requests that include an ‘X-Forwarded-For:’ header. xff is quoted like path and user-agent, for the same reasons. This keyword has no effect when given without the ‘request’ keyword.

    Note that if the connection is proxied, the ‘start’ line, if any, will only have information about the proxy, and only ‘x-forwarded-for’ will have information about the client. Also note that the information in an ‘X-Forwarded-For:’ header is potentially PII, so make sure to stay compliant with your local laws if you activate the option.

‘resource’
    Log a ‘resource’ line when tipideed(8) has found a resource corresponding to the URI and is willing to serve it. The line looks like ‘resource file type type’. file is the path to the served file; the first component of that path is always the document root of the virtual host. type is ‘nph’ for an NPH script, ‘cgi’ for a CGI script, or the Content-Type for a regular file. If it's a CGI or NPH script being called with a non-empty PATH_INFO, an additional ‘path_info path_info’ field is added to the log line. If a served CGI script outputs a local redirection, several ‘resource’ lines may appear for a single request.

‘answer’
    Log an ‘answer’ line when tipideed(8) answers the currently processed request. The line looks like ‘answer status’, where status is the 3-digit status code returned to the client. Note that there will be no ‘answer’ line when a NPH script is being run ( because tipideed(8) exec(3) s into the NPH script).

‘answer_size’
    Add a ‘size size’ field to the ‘answer’ line, containing the Content-Length of the answer. This keyword has no effect when given without the ‘answer’ keyword.

‘debug’
    Log debug information. You should not need this in regular use.

The content-type directive

‘content-type’ is a global directive, introduced by the keyword ‘content-type’. It allows the user to define mappings from a document's extension to a standard Content-Type.

    content-type type extension1 extension2 ...

•   Files ending with extension1, extension2, and so on, will be served to clients with the ‘Content-Type: type’ header.

•   Extensions must be listed with their initial dot.

•   Example: ‘content-type text/html .html .htm’ means that files ending in ‘.html’ or ‘.htm’ should be served as ‘text/html’.

•   As a special case, ‘content-type some/thing ""’ means that files without an extension should be served as ‘some/thing’.

•   tipidee already comes with a large list of default Content-Type mappings; this directive should only be necessary if you're serving files with uncommon extensions or have specific needs.

The ‘custom-header’ directive

‘custom-header’ is global directive, introduced by the keyword ‘custom-header’. It allows the user to define custom headers that are to be added to every response. It takes a subcommand, that is used to define what should be done with the header:

    custom-header add name value
    custom-header always name value
    custom-header remove name
    custom-header never name

•   ‘custom-header add’ tells tipidee to add a header named name with the value value to all its answers. A CGI script can override value by providing its own name header.

•   ‘custom-header always’ is like ‘custom-header add’, except a CGI script cannot override value, which will always be used.

•   ‘custom-header remove’ tells tipidee to not provide a name header. This is only useful for a few overridable headers that tipidee provides by default, such as ‘Content-Security-Policy’ or ‘Referrer-Policy’. If a CGI script provides such a header, the CGI header will be used despite the directive.

•   ‘custom-header never’ is like ‘custom-header remove’, except even a CGI script cannot provide a name header, which will be stripped from its output.

•   Some headers cannot be customized. tipidee-config(8) will reject an attempt to add, or remove, a ‘Connection’ header, for instance.

  Local directives
All the other directives are local: they only apply to the current domain. Except for ‘domain’, they can only be used after a ‘domain’ directive.

domain

    domain domain

•   domain is a special directive in that it is stateful. Instead of having a direct effect on the configuration, it merely defines the domain that the next local directives will apply to. ‘domain example.com’ means that a subsequent ‘cgi /cgi-bin/’ line will declare that a resource under //example.com/cgi-bin/ is a CGI script.

•   The current domain remains defined and active until the next ‘domain’ directive.

•   Global directives are unaffected by the current domain. It is good practice to declare global directives before the first domain line, but it is not mandatory.

•   If your resources are accessible via several URIs, the declared domain should be the canonical one, i.e. the name of the real directory hosting them, and not the symlinks. E.g. if you are serving files in the real directory /home/www/docs/example.com, with example.com:80 and example.com:443 being symlinks to example.com, then ‘domain example.com’ is the correct declaration for settings that will apply to these files. And if you are hosting a different set of documents in the real directory /home/www/docs/example.com:81, and example.com:444 is a symlink to example.com:81, then these will be affected by the settings declared under ‘domain example.com:81’.

•   The point of all this is to make virtual hosting as flexible as possible, allowing you to have different configurations for different virtual hosts — including serving different sets of documents for the same host on different ports! — without needing to duplicate the configuration when you are serving the same sets of documents over several ports, e.g. when you're serving both HTTP and HTTPS.

•   Complex configurations can benefit from the ‘!include’ or ‘!includedir’ primitives, by putting the configuration related to one domain in a dedicated file, and having the main /usr/pkg/etc/tipidee.conf only declare global configuration and include all the domain-specific files.

cgi

    cgi directory
    cgi file

•   The ‘cgi directory’ directive tells tipideed(8) that under the current domain, all the files under directory ( and its whole sub-hierarchy) are CGI scripts. directory is absolute ( it must start with a slash, referring to the document root for the current domain), and must end with a slash as well.

•   The ‘cgi file’ directive tells tipideed(8) that under the current domain, file is a CGI script, regardless of its location. file is absolute ( it must start with a slash, referring to the document root for the current domain), but must not end with a slash.

•   A common use is: ‘cgi /cgi-bin/’

•   By default, no CGI directories or files are defined, so an empty tipidee configuration will only serve static files.

noncgi

    noncgi directory
    noncgi file

•   The ‘noncgi directory’ directive tells tipideed(8) that under the current domain, all the files under directory ( and its whole sub-hierarchy) are not CGI scripts.

•   The ‘noncgi file’ directive tells tipideed(8) that under the current domain, file is not a CGI script, regardless of its location.

•   This is a rare directive, only useful if for some reason you have a static document under /cgi-bin or equivalent.

‘nph-prefix’

    nph-prefix prefix

•   This directive tells tipideed(8) that CGI scripts ( recognized as such by a ‘cgi’ directive) whose name starts with prefix are non-parsed header[1] scripts.

•   Common usage is ‘nph-prefix nph- —’ paired with ‘cgi /cgi-bin/’, this means that under the current domain, scripts of the form /cgi-bin/nph-foobar are NPH.

nph

    nph directory
    nph file

•   This is an alternative way of specifying which scripts are NPH. This directive says that CGI scripts under directory are NPH ( provided they're also recognized as CGI), and that file is NPH ( provided it's also recognized as CGI).

•   For instance, having both ‘cgi /cgi-bin/’ and ‘nph /cgi-bin/’ means that all the CGI scripts under /cgi-bin are considered NPH.

nonnph

    nonnph directory
    nonnph file

•   This is the opposite, saying that CGI scripts under directory, or CGI script file, are not NPH.

•   This is a rare directive, only useful if the vast majority of your scripts, but not all of them, are NPH.

basic-auth

    basic-auth directory
    basic-auth file

•   This directive tells tipideed(8) that file file, or all files under directory, are protected by Basic HTTP authentication[2].

•   This feature is currently unimplemented, so tipidee-config(8) will print a warning if it finds such a directive in your configuration file.

•   Implementation of this feature has been delayed because it needs an additional database to store the ‘resource:user:password’ tuples, with more restricted permissions than /usr/pkg/etc/tipidee.conf.cdb, since passwords are confidential information. This is planned in a future version of tipidee. And yes, existing web servers that make the administrator store cleartext passwords in the generic configuration file are terrible.

no-auth

    no-auth directory
    no-auth file

•   This is the opposite, saying that files under directory, or specific file file, do not require authentication.

•   This is a rare directive, only useful if you have a whole directory under ‘basic-auth’ but want to carve exceptions.

file-type

    file-type directory type
    file-type file ar type

•   ‘file-type’ is similar to ‘content-type’, but local. For files under directory, or for specific file file, it overrides the default Content-Type associated with their extension, and gives them the Content-Type type instead.

•   ‘file-type /source/ text/plain’ will serve all files under the current domain under the /source directory as ‘text/plain’.

•   ‘file-type /source/file.html text/html’ will serve /source/file.html under the current domain as ‘text/html’, even with the previous more generic rule applying to /source.

redirect

    redirect resource rtype target

•   resource is the URI to redirect, relative to the current domain. For instance, if the current domain is ‘example.com’ and resource is ‘foobar.html’, then a request for ‘http://example.com/foobar.html’ will be redirected to target.

•   rtype is the type of redirection. It is one of the following four numbers:

    •   308[3]: permanent redirection

    •   307[4]: temporary redirection

    •   301[5]: permanent redirection while allowing the client to change the request method. You generally should not need this.

    •   302[6]: temporary redirection while allowing the client to change the request method. You generally should not need this.

•   target is the target of the redirection. It should be a full URL starting with ‘http://’ or ‘https://’; it can also be a simple path, indicating a local redirection, in which case tipideed(8) will process it under the requested host.

•   Unlike files or directories given as arguments in other local directives, resource does not need to exist in the filesystem. tipideed(8) processes redirections before looking up resources in the filesystem. This is more efficient, but comes with a caveat: a file will only be served if there is no redirection directive for that resource, so make sure to keep your configuration file up-to-date.

•   This also means that the “real directory” rule does not apply to redirections. Instead, you can declare a redirection under the example.com:80 domain, whether or not /home/www/docs/example.com:80 is a real directory; the redirection will only apply to requests received on port 80 ( and not, for instance, to requests received on port 443). But if you declare a redirection under the example.com domain, it will apply to requests received on any port.

‘custom-response’

    custom-response status file

•   ‘custom-response’ allows you to customize the contents of HTTP error responses for the current domain.

•   status is the 3-digit HTTP response code you want to specify a custom response for.

•   file is the file containing the body of the HTTP response that will be sent to the client if tipideed(8) finds that it must answer with a status code.

    •   file is used relative to tipideed(8)' s working directory ( even if it is given absolute). It does not have to be under the current domain's document root: it is not a resource, and is not handled as such. However, file cannot go up the filesystem hierarchy: it will always be under tipideed(8)' s working directory.

    •   The Content-Type for file is determined by its extension, and mappings you add via ‘content-type’ directives will work. However, since file is not a resource, ‘file-type’ directives will not work, even if file is under the current virtual domain's document root. Don't try to be smart with this. Just name your custom files ‘e404.html’ or something.

•   The instruction is only valid for status responses to requests targetting the current domain. You can specify another ‘custom-response’, or even the same one, after the next ‘domain’ directive.

•   An example: ‘custom-response 404 /errors/404.html’ under a domain ‘example.com’ line will mean that the ‘errors/404.html’ file will be served as the text/html body of any “ 404 Not Found ” response tipideed(8) may send to requests addressed to ‘example.com’. The errors subdirectory is at the same level as the example.com subdirectory.

•   If tipideed(8) cannot open file, it will log a warning message and answer the client with a basic builtin response.

•   Not every HTTP status code is used by tipideed(8). Nothing will happen if you define custom responses for codes that aren't used.

SEE ALSO
tipidee-config(8), tipidee-config-preprocess(8), tipideed(8)

[1] https://datatracker.ietf.org/doc/html/rfc3875#section-5

[2] https://datatracker.ietf.org/doc/html/rfc7617

[3] https://datatracker.ietf.org/doc/html/rfc9110#section-15.4.9

[4] https://datatracker.ietf.org/doc/html/rfc9110#section-15.4.8

[5] https://datatracker.ietf.org/doc/html/rfc9110#section-15.4.2

[6] https://datatracker.ietf.org/doc/html/rfc9110#section-15.4.3

This man page is ported from the authoritative documentation at: https://skarnet.org/software/tipidee/tipidee.conf.html

AUTHORS
Laurent Bercot Alexis <flexibeast@gmail.com> (man page port)