You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

8.7 KiB

Schleuder in docker

Dockerized version of the encrypted mailinglist and group mail manager [schleuder].

If a valid database is not found, schleuder install is run inside the container to set-up a basic valid database. You can manage the listserver by docker exec-ing into the container and using schleuder-cli installed within. Or, set-up a webschlocker3 for your web interfacing pleasure.

Running and testing

You need docker, obviously. So first, go and install it. Then it's a simple matter of:

$ git clone
$ docker build --no-cache -t 'schlocker' schlocker/
$ my_api_key=$( head -c 500 /dev/urandom | sha256sum | awk '{print $1}' )
$ docker run --rm --name schlocker --env SCHLOCKER_CONFIG_API_KEYS=$my_api_key -p schlocker

To log into the container run in a second terminal:

$ docker exec -ti schlocker /bin/bash

You can watch the output of schleuder-api-daemon in the first terminal, and interface with it using schleuder-cli in the second. Or, you can use the webschlocker3 image.

By default schleuder-api-daemon listens on port 4443 on all interfaces in the container; you can get the IP of the container with:

docker inspect -f '{{.NetworkSettings.IPAddress}}' schlocker-test

Handling mail

Unfortunately, schleuder needs to be run directly to ingest new mail (expecting it on stdin), and it requires the target list name (including the domain name) as the first argument. This makes dockerizing it a bit more complicated, as to do that, the MTA that actually receives mail would have to run in the same container. Not perfect.

Two possible work-arounds are possible with this image.

Pipe mail directly into schleuder (EXPERIMENTAL)

One method is to volume-mount the /usr/local/bundle directory from container running this image into a container running the SMTP daemon, and use /usr/local/bundle/bin/schleuder binary to pipe messages to; the full command would be:

/usr/local/bundle/bin/schleuder work

This approach also requries volume-mounting the list directory ($SCHLOCKER_CONFIG_LISTS_DIR) and the config directory ($SCHLOCKER_CONFIG_PATH) to make them available to schleuder process run in the SMTP daemon container.

Queue folder

Alternatively, a "queue folder" approach can be used. Mail is expected to be deposited by the MTA in the SCHLOCKER_MAILDIR directory, into Maildir-structured subdirectories that match list names. The script runs inotifywait in the background watching these, and when new mail arrives, it's moved to the SCHLOCKER_TMPDIR temporary directory's subdirectory matching the list's name, and from there schleuder is run with list name gotten from the directory name, and domain name from SCHLOCKER_HOSTNAME (this is precisely the reason behind the "only one domain" limitation, by the way).

Hence, SCHLOCKER_MAILDIR directory should be bind-mounted into the container, and on the other hand be the place where the MTA drops all mail meant to hit the lists.

Environment variables

  • SCHLOCKER_HOMEDIR (default: /var/schlocker)

Path to the home directory of the $SCHLOCKER_USER user. By default used as base directory for SCHLOCKER_MAILDIR, SCHLOCKER_CONFIG_LISTS_DIR, SCHLOCKER_DB_DATABASE, SCHLOCKER_TMPDIR. Ownership will be automagically set to $SCHLOCKER_USER:$SCHLOCKER_GROUP. If the directory doesn't exist, it will be created.


Path to the Maildir directory being watched for new messages. This directory should reside on the same filesystem/volume/mount as the SCHLOCKER_TMPDIR directory, as the script relies on file moves between them being atomic!

If set to a non-empty string, the "queue folder" mail handling method above will be used. If set to an empty string, the "pipe" mail handling method will be used instead (and no inotify watches will be set).

  • SCHLOCKER_USER (default: schlocker)

The username to run the schleuder-api-daemon daemon and schleuder mail ingest process as. If the user does not exist, it will be created (with SCHLOCKER_UID as uid, if provided; first available uid otherwise), and will be put in SCHLOCKER_GROUP group.

If both SCHLOCKER_USER and SCHLOCKER_UID are provided, and there is an existing user with SCHLOCKER_USER, but with a different uid, the startup script will fail with an error.

  • SCHLOCKER_GROUP (default: schlocker)

The group to run the schleuder-api-daemon daemon and schleuder mail ingest process as. If the group does not exist, it will be created (with SCHLOCKER_GID as uid, if provided; first available gid otherwise).

If both SCHLOCKER_GROUP and SCHLOCKER_GID are provided, and there is an existing user with SCHLOCKER_GROUP, but with a different uid, the startup script will fail with an error.

  • SCHLOCKER_HOSTNAME (default: hostname of the container)

Hostname/domain name of the mailing list server. Only one hostname/domain name is supported at this time (i.e. you cannot have mailing lists with different domain names on a single schlocker instance). This is a schlocker's limitation, not schleuder's!


Path to the temporary directory being used for new messages ingestion into schleuder. This directory should reside on the same filesystem/volume/mount as the SCHLOCKER_MAILDIR directory, as the script relies on file moves between them being atomic!

  • SCHLOCKER_CONFIG_PATH (default: /etc/schleuder/schleuder.yml)

Location of the config file. Currently this should not be changed from the default.

Schleuder config variables

These are used to populate the schleuder.yml config file.

  • SCHLOCKER_CONFIG_SUPERADMIN (default: root@localhost)

The superadmin user, able to execute all administrative commands via list commands e-mails and webschleuder3 (if set-up).


Location of the directory containing schleuder lists data.

  • SCHLOCKER_CONFIG_PLUGINS_DIR (default: /etc/schleuder/plugins)

Plugins directory path.

  • SCHLOCKER_CONFIG_LOG_LEVEL (default: warn)

Log level. Valid values are (from most to least verbose): debug, info, warn, error

  • SCHLOCKER_CONFIG_SMTP_HOST (default: localhost)

SMTP server host to use when sending mail.


SMTP server port used when sending mail.

  • SCHLOCKER_CONFIG_API_KEYS (default: autogenerated)

A whitespace-separated list of hexadecimal API keys to be added to the valid_api_keys config key. Keys should be at least 64 characters long. If no keys are provided, a key will be autogenerated and added to valid_api_keys.

You can retrieve the keys from the config (including the autogenerated one) by running:

docker exec <schlocker_container_name> grep -v '#' /etc/schleuder/schleuder.yml | grep -A 10 valid_api_keys

Database settings

These are used to populate the database part of the schleuder.yml config file. Separate databases are used by schleuder3 and webschleuder3; these settings should thus be different from the ones used for webschlocker3 when used in tandem.

  • SCHLOCKER_DB_ADAPTER (default: sqlite3)

Database adapter.


Database name (or database file path when using sqlite3 adapter).


Database encoding (not used for sqlite3).


Database user (not used for sqlite3).


Database user password (not used for sqlite3).


Database host (not used for sqlite3).


  • How are we going to have our MTA invoke schleuder? Maybe it should live in the same docker instance. done, inotifywait and some bash magic
  • currently only supports a single listserver domain
  • handle failed mail better (move it out of the way, into a separate directory perhaps)
  • make the port and interface schleuder-api-daemon binds to configurable
  • don't run as root!