diff --git a/.envrc.sample b/.envrc.sample new file mode 100644 index 0000000..0452aa9 --- /dev/null +++ b/.envrc.sample @@ -0,0 +1,28 @@ +export APP=mailman3 + +export DOMAIN=lists.autonomic.zone +export LETS_ENCRYPT_ENV=production + +# mailman-core +export MTA=postfix +export SMTP_HOST=mail.autonomic.zone +export SMTP_PORT=25 + +# mailman-web +export DJANGO_ALLOWED_HOSTS=lists.autonomic.zone +export MAILMAN_ADMIN_EMAIL=helo@autonomic.zone +export MAILMAN_ADMIN_USER=autonomic +export SERVE_FROM_DOMAIN=lists.autonomic.zone +export SMTP_HOST=mail.autonomic.zone +export SMTP_HOST_USER=mailman@lists.autonomic.zone +export SMTP_PORT=25 +export SMTP_USE_TLS=True + +export SECRET_DB_PASSWORD_VERSION=v1 +export SECRET_DJANGO_SECRET_KEY_VERSION=v1 +export SECRET_HYPERKITTY_API_KEY_VERSION=v1 +export SECRET_MAILMAIN_REST_PASSWORD_VERSION=v1 +export SECRET_SMTP_HOST_PASSWORD_VERSION=v1 + +export CORE_ENTRYPOINT_CONF_VERSION=v1 +export WEB_ENTRYPOINT_CONF_VERSION=v1 diff --git a/compose.yml b/compose.yml index 7af3fcc..43f08dd 100644 --- a/compose.yml +++ b/compose.yml @@ -3,61 +3,68 @@ version: "3.8" # TODO(decentral1se): # - healthchecks -# - how do i expose multiple ports, core and web both need to have open ports -# - core receives relayed emails, web receives typical http traffic -# - ahhh! do $name-http, $name-ltmp, "name-$proto" for entrypoints on same service -# - inspect if we need a nginx proxy for mailman-web, it is currently using uwsgi -# but apparently it can serve http but in a very limited way, need to investigate -# this -# - re-wire up all that static IP stuff so things know where each other are in -# the stack, e.g. https://github.com/maxking/docker-mailman/blob/master/docker-compose.yaml#L55 +# - networks services: - # TODO(decentral1se): https://github.com/maxking/docker-mailman#mailman-core-1 core: image: "maxking/mailman-core:0.3" + hostname: mailman-core volumes: - "core:/opt/mailman/" - configs: - - source: entrypoint_conf - target: /docker-entrypoint.sh - mode: 0555 - # TODO(decentral1se): https://github.com/maxking/docker-mailman/blob/master/core/Dockerfile - # build up the right env vars required in the entrypoint via the secrets loading - entrypoint: /docker-entrypoint.sh + secrets: + - db_password + - hyperkitty_api_key + - mailman_rest_password environment: - DATABASE_CLASS=mailman.database.postgresql.PostgreSQLDatabase + - DATABASE_D - DATABASE_DB=mailman + - DATABASE_HOST=db - DATABASE_NAME=mailman + - DATABASE_PASSWORD_FILE=/run/secrets/db_password - DATABASE_TYPE=postgres - DATABASE_USER=mailman - # TODO(decentral1se): https://github.com/maxking/docker-mailman/blob/master/core/Dockerfile + - HYPERKITTY_API_KEY_FILE=/run/secrets/hyperkitty_api_key + - MAILMAN_REST_PASSWORD_FILE=/run/secrets/mailman_rest_password + - MAILMAN_REST_USER=restadmin + - MTA + - SMTP_HOST + - SMTP_PORT + configs: + - source: core_entrypoint_sh + target: /usr/local/bin/docker-entrypoint-custom.sh + mode: 0555 + entrypoint: /usr/local/bin/docker-entrypoint-custom.sh - # TODO(decentral1se): https://github.com/maxking/docker-mailman#mailman-web-1 web: image: "maxking/mailman-web:0.3" + hostname: mailman-web volumes: - "web:/opt/mailman-web-data" - configs: - - source: entrypoint_conf - target: /docker-entrypoint.sh - mode: 0555 - # TODO(decentral1se): https://github.com/maxking/docker-mailman/blob/master/core/Dockerfile - # build up the right env vars required in the entrypoint via the secrets loading - entrypoint: /docker-entrypoint.sh + secrets: + - db_password + - django_secret_key + - hyperkitty_api_key + - smtp_host_password environment: + - DATABASE_PASSWORD_FILE=/run/secrets/db_password - DATABASE_TYPE=postgres - deploy: - update_config: - failure_action: rollback - order: start-first - labels: - - "traefik.enable=true" - # TODO(decentral1se): https://github.com/maxking/docker-mailman/blob/master/web/Dockerfile - - "traefik.http.services.${STACK_NAME}.loadbalancer.server.port=${8000}" - - "traefik.http.routers.${STACK_NAME}.rule=Host(`${DOMAIN}`)" - - "traefik.http.routers.${STACK_NAME}.entrypoints=web-secure" - - "traefik.http.routers.${STACK_NAME}.tls.certresolver=${LETS_ENCRYPT_ENV}" + - DJANGO_ALLOWED_HOSTS + - HYPERKITTY_API_KEY_FILE=/run/secrets/hyperkitty_api_key + - MAILMAN_ADMIN_EMAIL + - MAILMAN_ADMIN_USER + - SECRET_KEY_FILE=/run/secrets/django_secret_key + - SERVE_FROM_DOMAIN + - SMTP_HOST + - SMTP_HOST_PASSWORD_FILE=/run/secrets/smtp_host_password + - SMTP_HOST_USER + - SMTP_PORT + - SMTP_USE_TLS + configs: + - source: web_entrypoint_sh + target: /usr/local/bin/docker-entrypoint-ustom.sh + mode: 0555 + entrypoint: /usr/local/bin/docker-entrypoint-custom.sh db: image: "postgres:13-alpine" @@ -78,10 +85,26 @@ volumes: secrets: db_password: external: true - name: ${STACK_NAME}_db_root_password_${DB_ROOT_PASSWORD_VERSION} + name: ${STACK_NAME}_db_password_${SECRET_DB_PASSWORD_VERSION} + hyperkitty_api_key: + external: true + name: ${STACK_NAME}_hyperkitty_api_key_${SECRET_HYPERKITTY_API_KEY_VERSION} + django_secret_key: + external: true + name: ${STACK_NAME}_django_secret_key_${SECRET_DJANGO_SECRET_KEY_VERSION} + mailman_rest_password: + external: true + name: ${STACK_NAME}_mailman_rest_password_${SECRET_MAILMAIN_REST_PASSWORD_VERSION} + smtp_host_password: + external: true + name: ${STACK_NAME}_smtp_host_password_${SECRET_SMTP_HOST_PASSWORD_VERSION} configs: - entrypoint_conf: - name: ${STACK_NAME}_entrypoint_conf_${ENTRYPOINT_CONF_VERSION} - file: entrypoint.sh.tmpl + core_entrypoint_sh: + name: ${STACK_NAME}_core_entrypoint_conf_${CORE_ENTRYPOINT_CONF_VERSION} + file: entrypoint.core.sh.tmpl + template_driver: golang + web_entrypoint_sh: + name: ${STACK_NAME}_web_entrypoint_conf_${WEB_ENTRYPOINT_CONF_VERSION} + file: entrypoint.web.sh.tmpl template_driver: golang diff --git a/entrypoint.core.sh.tmpl b/entrypoint.core.sh.tmpl new file mode 100644 index 0000000..519497e --- /dev/null +++ b/entrypoint.core.sh.tmpl @@ -0,0 +1,34 @@ +#!/bin/bash + +set -eu + +file_env() { + # https://medium.com/@adrian.gheorghe.dev/using-docker-secrets-in-your-environment-variables-7a0609659aab + + local var="$1" + local fileVar="${var}_FILE" + local def="${2:-}" + + if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then + echo >&2 "error: both $var and $fileVar are set (but are exclusive)" + exit 1 + fi + + local val="$def" + if [ "${!var:-}" ]; then + val="${!var}" + elif [ "${!fileVar:-}" ]; then + val="$(< "${!fileVar}")" + fi + + export "$var"="$val" + unset "$fileVar" +} + +file_env "DATABASE_PASSWORD" +file_env "HYPERKITTY_API_KEY" +file_env "MAILMAN_REST_PASSWORD" + +export DATABASE_URL="postgres://${DATABASE_USER}:${DATABASE_PASSWORD}@${DATABASE_HOST}/${DATABASE_NAME}" + +/opt/mailman/docker-entrypoint.sh "$@" diff --git a/entrypoint.sh.tmpl b/entrypoint.sh.tmpl deleted file mode 100644 index a9bf588..0000000 --- a/entrypoint.sh.tmpl +++ /dev/null @@ -1 +0,0 @@ -#!/bin/bash diff --git a/entrypoint.web.sh.tmpl b/entrypoint.web.sh.tmpl new file mode 100644 index 0000000..9cd0b34 --- /dev/null +++ b/entrypoint.web.sh.tmpl @@ -0,0 +1,35 @@ +#!/bin/bash + +set -eu + +file_env() { + # https://medium.com/@adrian.gheorghe.dev/using-docker-secrets-in-your-environment-variables-7a0609659aab + + local var="$1" + local fileVar="${var}_FILE" + local def="${2:-}" + + if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then + echo >&2 "error: both $var and $fileVar are set (but are exclusive)" + exit 1 + fi + + local val="$def" + if [ "${!var:-}" ]; then + val="${!var}" + elif [ "${!fileVar:-}" ]; then + val="$(< "${!fileVar}")" + fi + + export "$var"="$val" + unset "$fileVar" +} + +file_env "DATABASE_PASSWORD" +file_env "HYPERKITTY_API_KEY" +file_env "MAILMAN_REST_PASSWORD" +file_env "SMTP_HOST_PASSWORD" + +export DATABASE_URL="postgres://${DATABASE_USER}:${DATABASE_PASSWORD}@${DATABASE_HOST}/${DATABASE_NAME}" + +/opt/mailman-web/docker-entrypoint.sh "$@"