iocaine can be configured via a TOML-format configuration file, or via the environment. Almost everything has sane defaults, but providing a wordlist, and at least one source for the markov generator is required. Providing a request handler - while not required - is strongly recommended.
The configuration file is split into five main sections: [server], [sources], [generator], [templates], and [metrics].
When configured through environment variables, the naming follows the IOCAINE__<section>__<property> pattern. If subsections are involved, those are also separated by double underscores. For example, the bind option under the [server] section can be set via IOCAINE__SERVER__BIND, and the path option under [server.request-handler] translates to IOCAINE__SERVER__REQUEST_HANDLER__PATH. As you see, dashes are translated to underscores. Options where the value is a list, or a map, such as IOCAINE__SOURCES__MARKOV, the value of the environment variable must be a TOML-formatted array or map.
[server]
The [server] section is used to configure the address iocaine will bind to, the optional request handler, and the bind address of the optional control socket. The default bind address is shown below:
[server]
bind = "127.0.0.1:42069"
Important
Binding to anything but a TCP port is only available in iocaine 2.2.0 and later, as are any other parameters than
bind.
The bind address can be set to not only a TCP address and port pair, but to a Unix Domain Socket path, or - on Linux - to an Abstract Unix Domain Socket too (if the value begins with @).
When using a Unix Domain Socket, permissions on the created socket file can be controlled by the [server].unix_listen_access setting. By default, the permissions will not be touched, and will inherit umask. Valid values for this setting are: owner, group, and everybody.
[server]
bind = "/run/iocaine/iocaine.socket"
unix_listen_access = "group"
[server.control]
Introduced in: iocaine 2.2.0
Built-in reload introduced in: iocaine 2.3.0
Starting with iocaine 2.2.0, iocaine supports limited configuration reloading. This requires a control socket, and is not enabled by default. Otherwise it follows the same pattern as the [server] bind.
When enabled, it is possible to send a reload request to iocaine through that socket, to deploy a new configuration, without restarting the service. This will only succeed if the configurations are compatible: no bind addresses are changed, and the [metrics] section is unchanged. This limitation may be lifted in the future.
[server.control]
bind = "/run/iocaine/control.socket"
unix_listen_access = "owner"
Important
It is highly recommended to use a Unix Domain Socket here, and restrict the permissions to “owner” or “group”.
Starting with iocaine 2.3.0, there is a built in reload command, which supports every kind of binding out of the box.
iocaine --config /etc/iocaine/config.toml reload
Prior to that version, a reload request can be sent with - for example - curl:
curl -s --fail --unix-socket /run/iocaine/control.socket \
--json '{"path": "/etc/iocaine/config.toml"}' \
http://iocaine/config/load
[server.request-handler]
Introduced in: iocaine 2.2.0
Lua and Fennel introduced in: iocaine 2.4.0
[server.request-handler]
path = "/path/to/iocaine-modules"
language = "roto" # or lua, or fennel
# options = { compiler = "/path/to/fennel.lua" }
If one wishes to use iocaine for more than just garbage generation, that’s where the scriptable request handler support comes into play. With it, it is possible to write short programs that decide the fate of any incoming requests - see the request handler documentation for more information.
Within the configuration file, a path must be specified to use this feature, along with a language (which defaults to “roto”). This path must point to a directory that contains the appropriate entry point for the selected language. For Roto, this is pkg.roto, for Lua and Fennel, this is main.lua and main.fnl, respectively.
[sources]
The [sources] section is the only section without defaults, specifying both options here is mandatory.
[sources]
words = "/usr/share/dict/wamerican.txt"
markov = [
"/var/lib/iocaine/markov/bee-movie.txt",
"/var/lib/iocaine/markov/moby-dick.txt"
]
The first option, words, refers to a word list file, with one word per line. When generating links, the path of the link will be a word chosen from this word list.
The second option, markov, is a list of files used to train the markov chain generator. These will be used to generate the main content. The files are read as-is, and, and the software works best if there’s a large amount of text to train on, text without any kind of markup. Giving it the complete works of Shakespeare, the script of the Bee Movie, or other larger bodies of text will yield good results. The text to train on need not be related in any way to the content iocaine is supposed to shadow.
[generator]
The [generator] section is used to set an initial seed for the random number generator used when rendering garbage.
[generator]
initial_seed = ""
[templates]
[templates]
# directory =
The [templates].directory property can be set to a directory containing custom templates. If not set (the default), iocaine will use its own default template. If configured, the directory must contain main.jinja and challenge.jinja files. See the templating documentation for more information about changing the templates.
[templates.minify]
Introduced in: iocaine 2.0.0
Starting with the iocaine 2.0.0, iocaine supports minifying its output. This is most useful with custom templates with CSS, as the savings can be substantial there.
[templates.minify]
enable = false
minify_css = false
By default, minification is turned off. When enabled, only the HTML is minified, to minify any CSS, that minifications need to be opted into.
[metrics]
iocaine can be configured to emit Prometheus-compatible metrics, on a separate port (configurable via the [metrics].bind setting). By default, metrics are turned off, they can be enabled with [metrics].enable. By default, the metrics do not include any labels, those can be configured via [metrics].labels, which is an array of string values. Valid values within the array are: "Host", "UserAgent", "UserAgentGroup", and "Verdict".
When enabled, metrics can be scraped from the /metrics endpoint of the configured bind address. For a detailed guide, and examples, please see the monitoring howto.
[metrics]
enable = false
bind = "127.0.0.1:42042"
#labels = [ "Host", "UserAgent", "UserAgentGroup", "Verdict" ]
#persist-path = "/var/lib/iocaine/metrics.json"
persist-pathintroduced in: iocaine 2.4.0
When the "UserAgentGroup" label is enabled, iocaine will try to map user agents to specific groups, configurable via [[metrics.agent_group]], as detailed below. Each member of the array has an agent and a group field, where agent is a regexp, and the group is the string that will be added as the user_agent_group label, if the agent regexp matched. Matching is done in the same order as these groups are listed in the configuration, and will stop at the first match.
To keep the number of metrics balooning, it is advised to use either a single "Host" label, or a combination of "Host" and "UserAgentGroup", with a catch-all entry at the end of [[metrics.agent_group]], to limit the number of combinations.
[[metrics.agent_group]]
agent = "(?i:ClaudeBot)"
group = "ClaudeBot"
[[metrics.agent_group]]
agent = "."
group = "Other"
The "Verdict" label is only available in iocaine 2.2.0 or later.
When a persist-path is set, iocaine will save its metrics to the file specified therein when shutting down, and will attempt to reload them on startup, preserving all compatible counters. This is disabled by default.