Setting an initial password when deploying Seq to Docker

We love all things Docker, especially the opportunity it presents for streamlining how apps like Seq are deployed and operated.

Running Seq under Docker is ridiculously easy:

$ docker run -e ACCEPT_EULA -p 5341:80 datalust/seq

But this will start Seq with authentication wide open: probably okay locally, behind a firewall, if you then set a password through the web UI, but it's not ideal for production deployment.

On Windows, the Seq installation process prompts for an administrator username and password, which it sets locally before the service is started.

In a remote setting, prompting isn't feasible - so how can we set default credentials securely on, say, a Kubernetes cluster?

The SEQ_FIRSTRUN_* variables

There are three environment variables that Seq, in Docker, will check the very first time it starts up:

  • SEQ_FIRSTRUN_ADMINUSERNAME - this one's easy to guess the purpose of: it sets the username of the first administrator account (admin, if none is specified).
  • SEQ_FIRSTRUN_ADMINPASSWORDHASH - similarly, this will set the first administrator's password, but we'll discuss how it's used, below.
  • SEQ_FIRSTRUN_REQUIREAUTHENTICATIONFORHTTPINGESTION - a mouthful of a variable name! If the first administrator's password is set, providing the value True in this variable will turn on authentication for log event ingestion, too.

So, how is that admin password set?

SEQ_FIRSTRUN_ADMINPASSWORDHASH and the seq config hash command

It's normal to pass default passwords to applications via STDIN, since environment variables and command-line arguments are considered poor choices for sensitive values.

Seq can accept an initial password through STDIN, but doing this isn't always trivial in orchestrated environments.

Faced with only bad options 😅 the scheme we settled on is:

  1. Create a salted 10k-round PBKDF2 hash of the desired password offline
  2. Pass this to the container in an environment variable, for direct initialization of the underlying database

Why is passing a hash better than passing the raw password? Even if the hash is leaked, as long as the password has sufficient entropy it's unlikely to be crackable in a useful timeframe. The hash can't be used as a password itself - in order to log into Seq you need the original password.

The hash can be created on any machine, using the container or local Seq executable:

$ echo 'p@ssw0rd' | docker run --rm -i datalust/seq config hash
FCfNlV8nyAIBkrXHtKGK3A6rJ15CFPNykGLdEsi98tUeqFInZg==

This is the value you can provide for SEQ_FIRSTRUN_ADMINPASSWORDHASH in whatever system you use to deploy/orchestrate the container.

With the hash stored in an environment variable $PH, the corresponding docker run command invocation that puts it all together is:

docker run \
  --name seq \
  -d \
  --restart unless-stopped \
  -e ACCEPT_EULA=Y \
  -e SEQ_FIRSTRUN_ADMINUSERNAME=nblumhardt \
  -e SEQ_FIRSTRUN_ADMINPASSWORDHASH="$PH" \
  -e SEQ_FIRSTRUN_REQUIREAUTHENTICATIONFORHTTPINGESTION=True \
  -v /path/to/seq/data:/data \
  -p 80:80 \
  -p 5341:5341 \
  datalust/seq

Voila! And don't forget you can email support@datalust.co if you need help with it. Happy logging 😎.