From fd721d0dd857110435a47cfdb883380e6fd9c51e Mon Sep 17 00:00:00 2001
From: Janne Koschinski <janne@kuschku.de>
Date: Tue, 3 Sep 2019 00:07:58 +0200
Subject: [PATCH] Allow configuring CLI arguments via environment

---
 .gitignore           |   4 +
 Dockerfile           |  81 ++++++++++++-
 README.md            | 280 +++++++++++++++++++++++++++++++++++++------
 docker-entrypoint.sh | 176 +++++++++++++++++++++++++++
 4 files changed, 500 insertions(+), 41 deletions(-)
 create mode 100644 .gitignore
 create mode 100755 docker-entrypoint.sh

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..4f9cefd
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+*.iml
+/.idea/*
+!/.idea/copyright/
+.DS_Store
diff --git a/Dockerfile b/Dockerfile
index ab88131..7ca9056 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -30,7 +30,7 @@ ARG QUASSEL_BRANCH="master"
 RUN mkdir /quassel && \
     git clone -b "$QUASSEL_BRANCH" --single-branch https://github.com/quassel/quassel /quassel/src && \
     cd /quassel/src && \
-    if [ ! -z "$QUASSEL_VERSION"]; then \
+    if [ ! -z "$QUASSEL_VERSION" ]; then \
       git checkout $QUASSEL_VERSION; \
     fi
 
@@ -60,6 +60,7 @@ FROM $BASE
 
 # install runtime dependencies
 RUN apk add --no-cache \
+  bash \
   icu-libs \
   libressl \
   libldap \
@@ -82,20 +83,92 @@ VOLUME /config
 EXPOSE 4242/tcp
 EXPOSE 10113/tcp
 
-# setup default configuration
+# Specify the directory holding configuration files, the SQlite database and the SSL certificate.
+ENV CONFIG_DIR="/config"
+
+# The address(es) quasselcore will listen on.
+ENV QUASSEL_LISTEN="::,0.0.0.0"
+# The port quasselcore will listen at.
+ENV QUASSEL_PORT="4242"
+
+# Don't restore last core's state.
+ENV NORESTORE="false"
+
+# Use users' quasselcore username as ident reply. Ignores each user's configured ident setting.
+ENV STRICT_IDENT="false"
+
+# Enable internal ident daemon.
+ENV IDENT_ENABLED="false"
+# The address(es) quasselcore will listen on for ident requests. Same format as --listen.
+ENV IDENT_LISTEN="::1,127.0.0.1"
+# The port quasselcore will listen at for ident requests. Only meaningful with --ident-daemon.
+ENV IDENT_PORT="10113"
+
+# Enable oidentd integration. In most cases you should also enable --strict-ident.
+ENV OIDENTD_ENABLED="false"
+# Set path to oidentd configuration file.
+ENV OIDENTD_CONF_FILE=""
+
+# Require SSL for remote (non-loopback) client connections.
+ENV SSL_REQUIRED="false"
+# Specify the path to the SSL certificate.
+ENV SSL_CERT_FILE=""
+# Specify the path to the SSL key.
+ENV SSL_KEY_FILE=""
+
+# Enable metrics API.
+ENV METRICS_ENABLED="false"
+# The address(es) quasselcore will listen on for metrics requests. Same format as --listen.
+ENV METRICS_LISTEN="::1,127.0.0.1"
+# The port quasselcore will listen at for metrics requests. Only meaningful with --metrics-daemon.
+ENV METRICS_PORT="9558"
+
+# Supports one of Debug|Info|Warning|Error; default is Info.
+ENV LOGLEVEL="Info"
+
+# Enable logging of all SQL queries to debug log, also sets --loglevel Debug automatically
+ENV DEBUG_ENABLED="false"
+# Enable logging of all raw IRC messages to debug log, including passwords!  In most cases you should also set --loglevel Debug
+ENV DEBUG_IRC_ENABLED="false"
+# Limit raw IRC logging to this network ID.  Implies --debug-irc
+ENV DEBUG_IRC_ID=""
+# Enable logging of all parsed IRC messages to debug log, including passwords!  In most cases you should also set --loglevel Debug
+ENV DEBUG_IRC_PARSED_ENABLED="false"
+# Limit parsed IRC logging to this network ID.  Implies --debug-irc-parsed
+ENV DEBUG_IRC_PARSED_ID=""
+
+# Load configuration from environment variables.
+ENV CONFIG_FROM_ENVIRONMENT="true"
+
+# Specify the database backend.  Allowed values: SQLite or PostgreSQL
 ENV DB_BACKEND="SQLite"
-ENV AUTH_AUTHENTICATOR="Database"
+# If the backend is PostgreSQL, specify the database user username
 ENV DB_PGSQL_USERNAME="quassel"
+# If the backend is PostgreSQL, specify the database user password
 ENV DB_PGSQL_PASSWORD=""
+# If the backend is PostgreSQL, specify the hostname of the database
 ENV DB_PGSQL_HOSTNAME="localhost"
+# If the backend is PostgreSQL, specify the port of the database
 ENV DB_PGSQL_PORT="5432"
+# If the backend is PostgreSQL, specify the database of the PostgreSQL cluster
 ENV DB_PGSQL_DATABASE="quassel"
+
+# Specify the authenticator backend.  Allowed values: Database or Ldap
+ENV AUTH_AUTHENTICATOR="Database"
+# If the authenticator is Ldap, specify the hostname of the directory server
 ENV AUTH_LDAP_HOSTNAME="ldap://localhost"
+# If the authenticator is Ldap, specify the port of the directory server
 ENV AUTH_LDAP_PORT="389"
+# If the authenticator is Ldap, specify the bind dn
 ENV AUTH_LDAP_BIND_DN=""
+# If the authenticator is Ldap, specify the bind password
 ENV AUTH_LDAP_BIND_PASSWORD=""
+# If the authenticator is Ldap, specify the base dn
 ENV AUTH_LDAP_BASE_DN=""
+# If the authenticator is Ldap, specify the filter query
 ENV AUTH_LDAP_FILTER=""
+# If the authenticator is Ldap, specify the attribute to be used as userid
 ENV AUTH_LDAP_UID_ATTRIBUTE="uid"
 
-ENTRYPOINT ["quasselcore", "--configdir", "/config"]
+ADD docker-entrypoint.sh /
+ENTRYPOINT ["/docker-entrypoint.sh"]
diff --git a/README.md b/README.md
index ab5f621..f62de9f 100644
--- a/README.md
+++ b/README.md
@@ -8,6 +8,228 @@
 | aarch64      | `0.13.1-aarch64`, `aarch64` |
 | armhf        | `0.13.1-armhf`, `armhf`     |
 
+## Configuration
+
+### CONFIG_DIR
+
+Specify the directory holding configuration files, the SQlite database and the
+SSL certificate.
+
+Default: `/config`
+
+### QUASSEL_LISTEN
+
+The address(es) quasselcore will listen on.
+
+Default: `::,0.0.0.0`
+
+### QUASSEL_PORT
+
+The port quasselcore will listen at.
+
+Default: `4242`
+
+### NORESTORE
+
+Don't restore last core's state.
+
+Default: `false`
+
+### STRICT_IDENT
+
+Use users' quasselcore username as ident reply. Ignores each user's configured
+ident setting.
+
+Default: `false`
+
+### IDENT_ENABLED
+
+Enable internal ident daemon.
+
+Default: `false`
+
+### IDENT_LISTEN
+
+The address(es) quasselcore will listen on for ident requests. Same format as
+[QUASSEL_LISTEN](#quassel_listen). Only meaningful with
+[IDENT_ENABLED](#ident_enabled).
+
+Default: `::1,127.0.0.1`
+
+### IDENT_PORT
+
+The port quasselcore will listen at for ident requests. Only meaningful with
+[IDENT_ENABLED](#ident_enabled).
+
+Default: `10113`
+
+### OIDENTD_ENABLED
+
+Enable oidentd integration. In most cases you should also enable
+[STRICT_IDENT](#strict_ident).
+
+Default: `false`
+
+### OIDENTD_CONF_FILE
+
+Set path to oidentd configuration file.
+
+### SSL_REQUIRED
+
+Require SSL for remote (non-loopback) client connections.
+
+Default: `false`
+
+### SSL_CERT_FILE
+
+Specify the path to the SSL certificate.
+
+### SSL_KEY_FILE
+
+Specify the path to the SSL key.
+
+### METRICS_ENABLED
+
+Enable metrics API.
+
+Default: `false`
+
+### METRICS_LISTEN
+
+The address(es) quasselcore will listen on for metrics requests. Same format as
+[QUASSEL_LISTEN](#quassel_listen).
+
+Default: `::1,127.0.0.1`
+
+### METRICS_PORT
+
+The port quasselcore will listen at for metrics requests. Only meaningful with
+[METRICS_ENABLED](#metrics_enabled).
+
+Default: `9558`
+
+### LOGLEVEL
+
+Supports one of Debug|Info|Warning|Error; default is Info.
+
+Default: `Info`
+
+### DEBUG_ENABLED
+
+Enable logging of all SQL queries to debug log, also sets [LOGLEVEL](#loglevel)
+to `Debug` automatically
+
+Default: `false`
+
+### DEBUG_IRC_ENABLED
+
+Enable logging of all raw IRC messages to debug log, including passwords!  
+In most cases you should also set [LOGLEVEL](#loglevel) to Debug
+
+Default: `false`
+
+### DEBUG_IRC_ID
+
+Limit raw IRC logging to this network ID.  Implies
+[DEBUG_IRC_ENABLED](#debug_irc_enabled).
+
+### DEBUG_IRC_PARSED_ENABLED
+
+Enable logging of all parsed IRC messages to debug log, including passwords!  
+In most cases you should also set [LOGLEVEL](#loglevel) to Debug
+
+Default: `false`
+
+### DEBUG_IRC_PARSED_ID
+
+Limit parsed IRC logging to this network ID.  Implies
+[DEBUG_IRC_PARSED_ENABLED](#debug_irc_parsed_enabled).
+
+### CONFIG_FROM_ENVIRONMENT
+
+Load configuration from environment variables.
+
+Default: `true`
+
+### DB_BACKEND
+
+Specify the database backend.  Allowed values: SQLite or PostgreSQL
+
+In case `SQLite` is used, the database will be stored by default in
+`/config/quassel-storage.sqlite` (affected by [CONFIG_DIR](#config_dir))
+
+Default: `SQLite`
+
+### DB_PGSQL_USERNAME
+
+If the backend is PostgreSQL, specify the database user username
+
+Default: `quassel`
+
+### DB_PGSQL_PASSWORD
+
+If the backend is PostgreSQL, specify the database user password
+
+### DB_PGSQL_HOSTNAME
+
+If the backend is PostgreSQL, specify the hostname of the database
+
+Default: `localhost`
+
+### DB_PGSQL_PORT
+
+If the backend is PostgreSQL, specify the port of the database
+
+Default: `5432`
+
+### DB_PGSQL_DATABASE
+
+If the backend is PostgreSQL, specify the database of the PostgreSQL cluster
+
+Default: `quassel`
+
+
+### AUTH_AUTHENTICATOR
+
+Specify the authenticator backend.  Allowed values: Database or Ldap
+
+Default: `Database`
+
+### AUTH_LDAP_HOSTNAME
+
+If the authenticator is Ldap, specify the hostname of the directory server
+
+Default: `ldap://localhost`
+
+### AUTH_LDAP_PORT
+
+If the authenticator is Ldap, specify the port of the directory server
+
+Default: `389`
+
+### AUTH_LDAP_BIND_DN
+
+If the authenticator is Ldap, specify the bind dn
+
+### AUTH_LDAP_BIND_PASSWORD
+
+If the authenticator is Ldap, specify the bind password
+
+### AUTH_LDAP_BASE_DN
+
+If the authenticator is Ldap, specify the base dn
+
+### AUTH_LDAP_FILTER
+
+If the authenticator is Ldap, specify the filter query
+
+### AUTH_LDAP_UID_ATTRIBUTE
+
+If the authenticator is Ldap, specify the attribute to be used as userid
+
+Default: `uid`
+
+
 ## Stateful usage (with UI Wizard)
 
 By default, the core will be run in stateful mode.
@@ -23,40 +245,31 @@ docker run \
   k8r.eu/justjanne/quassel-docker:v0.13.1
 ```
 
-## Stateless usage
-
-To use Quassel in stateless mode, where it needs to be configured through
-environment arguments, run it with the `--config-from-environment` argument.
-
-`DB_BACKEND` defines the backend used for the database, this can be `SQLite` or
-`PostgreSQL`. In case `SQLite` is used, the database will be stored in
-`/config/quassel-storage.sqlite`. If `PostgreSQL` is used instead, these
-variables determine the connection details: `DB_PGSQL_USERNAME`,
-`DB_PGSQL_PASSWORD`, `DB_PGSQL_HOSTNAME`, `DB_PGSQL_PORT`, `DB_PGSQL_DATABASE`.
-
-`AUTH_AUTHENTICATOR` defines the backend used for authentication, this can be
-`Database` or `LDAP`. In case `LDAP` is used, the following environment
-variables determine the connection details: `AUTH_LDAP_HOSTNAME`,
-`AUTH_LDAP_PORT`, `AUTH_LDAP_BIND_DN`, `AUTH_LDAP_BIND_PASSWORD`,
-`AUTH_LDAP_BASE_DN`, `AUTH_LDAP_FILTER`, `AUTH_LDAP_UID_ATTRIBUTE`.
-
-Minimal example with SQLite:
+## Example: Stateless usage (minimal)
 
 ```bash
 docker run \
   -v /path/to/quassel/volume:/config \
+  -e CONFIG_FROM_ENVIRONMENT=true \
   -e DB_BACKEND=SQLite \
   -e AUTH_AUTHENTICATOR=Database \
-  k8r.eu/justjanne/quassel-docker:v0.13.1 \
-  --config-from-environment
+  k8r.eu/justjanne/quassel-docker:v0.13.1
 ```
 
-Full example with PostgreSQL and examples of other options:
+## Example: Stateless usage (common)
 
 ```bash
 docker run \
+  -e STRICT_IDENT=true \
+  -e IDENT_ENABLED=true \
+  -e IDENT_PORT=10113 \
+  -e IDENT_LISTEN=::,0.0.0.0 \
+  -e SSL_REQUIRED=true \
+  -e SSL_CERT_FILE=/tls.crt \
   -v /path/to/certificates/tls.crt:/tls.crt \
+  -e SSL_KEY_FILE=/tls.key \
   -v /path/to/certificates/tls.key:/tls.key \
+  -e CONFIG_FROM_ENVIRONMENT=true \
   -e DB_BACKEND=PostgreSQL \
   -e AUTH_AUTHENTICATOR=Database \
   -e DB_PGSQL_USERNAME=quassel \
@@ -64,33 +277,26 @@ docker run \
   -e DB_PGSQL_HOSTNAME=postgresql.default.svc.cluster.local \
   -e DB_PGSQL_PORT=5432 \
   -e DB_PGSQL_DATABASE=quassel \
-  k8r.eu/justjanne/quassel-docker:v0.13.1 \
-  --config-from-environment \
-  --strict-ident \
-  --ident-daemon \
-  --ident-port "10113" \
-  --ident-listen "::,0.0.0.0" \
-  --ssl-cert /tls.crt \
-  --ssl-key /tls.key \
-  --require-ssl
+  k8r.eu/justjanne/quassel-docker:v0.13.1
 ```
 
 ## SSL
 
 You can use the core with SSL, in this case you should either put a
 `quasselCert.pem` file with the full certificate chain and private key into
-the `/config` volume, or you can use the `--ssl-cert` and `--ssl-key`
-arguments to use separate key and certificate.
+the `/config` volume, or you can use the [SSL_CERT_FILE](#ssl_cert_file) and
+[SSL_KEY_FILE](#ssl_key_file) arguments to use separate key and certificate.
 
 ## Ports
 
 Per default, the container will listen on the port 4242 for connections.
-This can be configured with `--port` and `--listen`.
+This can be configured with [QUASSEL_PORT](#quassel_port) and
+[QUASSEL_LISTEN](#quassel_listen).
 
-If the `--ident-daemon` argument is passed, the ident daemon will additionally
-listen on 10113. You can configure this with `--ident-port`.
+If [IDENT_ENABLED](#ident_enabled) is set, the ident daemon will additionally
+listen on 10113. You can configure this with [IDENT_PORT](#ident_port).
 This by default only listens on localhost, which obviously will cause issues
-when used in a container like this, so make sure to add the
-`--ident-listen ::,0.0.0.0` argument.  
+when used in a container like this, so make sure to configure
+[IDENT_LISTEN](#ident_listen).  
 You’ll also want to bind this to port 113 on the host, as IRC networks will
 expect to find the ident daemon on that port.
diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh
new file mode 100755
index 0000000..f7ce10b
--- /dev/null
+++ b/docker-entrypoint.sh
@@ -0,0 +1,176 @@
+#!/bin/bash
+declare -a quasselcore_args
+
+# Specify the directory holding configuration files, the SQlite database and the SSL certificate.
+# format: path
+quasselcore_args+=(
+  --configdir "${CONFIG_DIR}"
+)
+  
+# The address(es) quasselcore will listen on.
+# format: <address>[,<address>[,...]]
+if [[ "${QUASSEL_PORT}" != "4242" ]]; then
+  quasselcore_args+=(
+    --port "${QUASSEL_PORT}"
+  )
+fi
+  
+# The port quasselcore will listen at.
+# format: port
+if [[ "${QUASSEL_LISTEN}" != "::,0.0.0.0" ]]; then
+  quasselcore_args+=(
+    --listen "${QUASSEL_LISTEN}"
+  )
+fi
+
+# Don't restore last core's state.
+if [[ "${NORESTORE}" == "true" ]]; then
+  quasselcore_args+=(
+    --norestore
+  )
+fi
+
+# Load configuration from environment variables.
+if [[ "${CONFIG_FROM_ENVIRONMENT}" == "true" ]]; then
+  quasselcore_args+=(
+    --config-from-environment
+  )
+fi
+
+# Use users' quasselcore username as ident reply. Ignores each user's configured ident setting.
+if [[ "${STRICT_IDENT}" == "true" ]]; then
+  quasselcore_args+=(
+    --strict-ident
+  )
+fi
+
+# Enable internal ident daemon.
+if [[ "${IDENT_ENABLED}" == "true" ]]; then
+  quasselcore_args+=(
+    --ident-daemon
+  )
+fi
+
+# The address(es) quasselcore will listen on for ident requests. Same format as --listen.
+# format: <address>[,<address>[,...]]
+if [[ "${IDENT_LISTEN}" != "::1,127.0.0.1" ]]; then
+  quasselcore_args+=(
+    --ident-listen "${IDENT_LISTEN}"
+  )
+fi
+  
+# The port quasselcore will listen at for ident requests. Only meaningful with --ident-daemon.
+# format: port
+if [[ "${IDENT_PORT}" != "10113" ]]; then
+  quasselcore_args+=(
+    --ident-port "${IDENT_PORT}"
+  )
+fi
+
+# Enable oidentd integration. In most cases you should also enable --strict-ident.
+if [[ "${OIDENTD_ENABLED}" == "true" ]]; then
+  quasselcore_args+=(
+    --oidentd
+  )
+fi
+
+# Set path to oidentd configuration file.
+# format: file
+if [[ ! -z "${OIDENTD_CONFIG_FILE}" ]]; then
+  quasselcore_args+=(
+    --oidentd-conffile "${OIDENTD_CONFIG_FILE}"
+  )
+fi
+
+# Require SSL for remote (non-loopback) client connections.
+if [[ "${SSL_REQUIRED}" == "true" ]]; then
+  quasselcore_args+=(
+    --require-ssl
+  )
+fi
+
+# Specify the path to the SSL certificate.
+# format: path
+if [[ ! -z "${SSL_CERT_FILE}" ]]; then
+  quasselcore_args+=(
+    --ssl-cert "${SSL_CERT_FILE}"
+  )
+fi
+
+# Specify the path to the SSL key.
+# format: path
+if [[ ! -z "${SSL_KEY_FILE}" ]]; then
+  quasselcore_args+=(
+    --ssl-key "${SSL_KEY_FILE}"
+  )
+fi
+
+# Enable metrics API.
+if [[ "${METRICS_ENABLED}" == "true" ]]; then
+  quasselcore_args+=(
+    --metrics-daemon
+  )
+fi
+
+# The address(es) quasselcore will listen on for metrics requests. Same format as --listen.
+# format: <address>[,<address>[,...]]
+if [[ "${METRICS_LISTEN}" != "::1,127.0.0.1" ]]; then
+  quasselcore_args+=(
+    --metrics-listen "${METRICS_LISTEN}"
+  )
+fi
+
+# The port quasselcore will listen at for metrics requests. Only meaningful with --metrics-daemon.
+# format: port
+if [[ "${METRICS_PORT}" != "9558" ]]; then
+  quasselcore_args+=(
+    --metrics-port "${METRICS_PORT}"
+  )
+fi
+
+# Supports one of Debug|Info|Warning|Error; default is Info.
+# format: level
+if [[ "${LOGLEVEL}" != "Info" ]]; then
+  quasselcore_args+=(
+    --loglevel "${LOGLEVEL}"
+  )
+fi
+
+# Enable logging of all SQL queries to debug log, also sets --loglevel Debug automatically
+if [[ "${DEBUG_ENABLED}" == "true" ]]; then
+  quasselcore_args+=(
+    --debug
+  )
+fi
+
+# Enable logging of all raw IRC messages to debug log, including passwords!  In most cases you should also set --loglevel Debug
+if [[ "${DEBUG_IRC_ENABLED}" == "true" ]]; then
+  quasselcore_args+=(
+    --debug-irc
+  )
+fi
+
+# Limit raw IRC logging to this network ID.  Implies --debug-irc
+# format: database_network_ID
+if [[ ! -z "${DEBUG_IRC_ID}" ]]; then
+  quasselcore_args+=(
+    --debug-irc-id "${DEBUG_IRC_ID}"
+  )
+fi
+
+# Enable logging of all parsed IRC messages to debug log, including passwords!  In most cases you should also set --loglevel Debug
+if [[ "${DEBUG_IRC_PARSED_ENABLED}" == "true" ]]; then
+  quasselcore_args+=(
+    --debug-irc-parsed
+  )
+fi
+
+# Limit parsed IRC logging to this network ID.  Implies --debug-irc-parsed
+# format: database_network_ID
+if [[ ! -z "${DEBUG_IRC_PARSED_ID}" ]]; then
+  quasselcore_args+=(
+    --debug-irc-parsed-id "${DEBUG_IRC_PARSED_ID}"
+  )
+fi
+
+exec quasselcore "${quasselcore_args[@]}" "$@"
-- 
GitLab