Fix: use static IP for mailman-core and update documentation
Some checks failed
Publish docs via GitHub Pages / Deploy docs (push) Has been cancelled
Mark stale issues and pull requests / stale (push) Has been cancelled

- Assign static IP 172.29.199.10 to mailman-core to ensure host Postfix can reach LMTP.
- Update MM_HOSTNAME and mailman-extra.cfg to use the static IP.
- Update README.md with correct networking recommendations for host-based MTAs.
- Add missing configuration files to repository.
This commit is contained in:
2026-03-18 11:34:02 -04:00
parent 180491a4d6
commit 8a950614ec
4 changed files with 179 additions and 68 deletions

View File

@@ -190,33 +190,29 @@ For more details on how to configure this image, please look at
### Mailman-Core ### Mailman-Core
These are the variables that you MUST change in your docker-compose.yaml before deploying: The `mailman-core` container's entrypoint script automatically generates its configuration from environment variables. For advanced or custom settings not exposed via environment variables, you can use the `/opt/mailman/core/mailman-extra.cfg` file.
- `HYPERKITTY_API_KEY`: Hyperkitty's API Key, should be set to the same value as **Important:** Avoid duplicating configuration sections like `[webservice]` or `[mta]` in `mailman-extra.cfg` if you are setting them with environment variables, as this can lead to unexpected behavior.
set for the mailman-web. Skip the variable in case of non-Hyperkitty deployment.
- `DATABASE_URL`: URL of the type These are the variables that you SHOULD review and set in your `docker-compose.yaml` before deploying:
`driver://user:password@hostname:port/databasename` for the django to use. If
not set, the default is set to
`sqlite:///opt/mailman-web-data/mailmanweb.db`. The standard
docker-compose.yaml comes with it set to a postgres database. There is no need
to change this if you are happy with PostgreSQL.
- `DATABASE_TYPE`: Its value can be one of `sqlite`, `postgres` or `mysql` as - `DATABASE_URL`: URL for the database connection. The default is pre-configured for the included PostgreSQL container.
these are the only three database types that Mailman 3 supports. Its default - `MAILMAN_REST_USER`: The username for the Mailman Core REST API. Defaults to `restadmin`.
value is set to `sqlite` along with the default database class and default - `MAILMAN_REST_PASSWORD`: The password for the Mailman Core REST API. It is **highly recommended** to set this to a secure, randomly generated value. For production, this should be sourced from a `.env` file or Docker secrets. **The current value is for testing purposes only and must be changed.**
database url above. - `HYPERKITTY_API_KEY`: Hyperkitty's API Key, should be set to the same value as set for the mailman-web. Skip the variable in case of non-Hyperkitty deployment.
- `DATABASE_CLASS`: Default value is These variables are also available for configuration:
`mailman.database.sqlite.SQLiteDatabase`. The values for this can be found in
the mailman's documentation [here][11]. - `MM_HOSTNAME`: The hostname or IP address the container should bind to for its LMTP and REST services. For reliable communication between Docker containers, it is recommended to set this to the service name (e.g., `mailman-core`).
- `SMTP_HOST` : outgoing host for SMTP connections - `DATABASE_TYPE`: Can be `sqlite`, `postgres`, or `mysql`. Defaults to `postgres` if `DATABASE_URL` is set.
- `SMTP_PORT` : use this port. 25, 587, whatever your host asks for. - `DATABASE_CLASS`: The Python class for the database driver. This is typically inferred from `DATABASE_TYPE`.
- `SMTP_HOST_USER`: authenticate this user - `SMTP_HOST`: Outgoing host for SMTP connections.
- `SMTP_HOST_PASSWORD`: and use this password - `SMTP_PORT`: Port for the outgoing SMTP connection (e.g., 25, 587).
- `SMTP_SECURE_MODE`: security mode for smtp connection - can be `smtp` (no encryption), `smtps` or `starttls` - `SMTP_HOST_USER`: Username for SMTP authentication.
- `SMTP_VERIFY_HOSTNAME`: defaults to `true` - verify, that certificate hostname is identical to `SMTP_HOST` - `SMTP_HOST_PASSWORD`: Password for SMTP authentication.
- `SMTP_VERIFY_CERT`: defaults to `true` - verify, that certificate is valid - `SMTP_SECURE_MODE`: Security mode for the SMTP connection (`smtp`, `smtps`, or `starttls`).
- `SMTP_VERIFY_HOSTNAME`: Defaults to `true` to verify the certificate hostname.
- `SMTP_VERIFY_CERT`: Defaults to `true` to verify the certificate's validity.
For more details on how to configure this image, please look [Mailman-core's For more details on how to configure this image, please look [Mailman-core's
Readme](core/) Readme](core/)
@@ -354,10 +350,7 @@ configuration: python:mailman.config.exim4
### Postfix ### Postfix
To use [Postfix][12], edit the `main.cf` configuration file, which is typically To use [Postfix][12], first edit its `main.cf` configuration file (typically at `/etc/postfix/main.cf`). Add the Docker network to `mynetworks` so Postfix will relay emails from the containers, and add the following configuration lines to integrate with Mailman's auto-generated transport maps:
at `/etc/postfix/main.cf` on Debian-based operating systems. Add
mailman-core and mailman-web to `mynetworks` so it will relay emails from
the containers and add the following configuration lines:
``` ```
# main.cf # main.cf
@@ -367,6 +360,9 @@ recipient_delimiter = +
unknown_local_recipient_reject_code = 550 unknown_local_recipient_reject_code = 550
owner_request_special = no owner_request_special = no
# Path to Mailman's generated Postfix maps.
# Ensure the path '/opt/mailman/core' corresponds to the volume mount
# for the mailman-core container in your docker-compose.yaml.
transport_maps = transport_maps =
regexp:/opt/mailman/core/var/data/postfix_lmtp regexp:/opt/mailman/core/var/data/postfix_lmtp
local_recipient_maps = local_recipient_maps =
@@ -375,25 +371,18 @@ relay_domains =
regexp:/opt/mailman/core/var/data/postfix_domains regexp:/opt/mailman/core/var/data/postfix_domains
``` ```
To configure Mailman to use Postfix, add `MTA=postfix` under mailman-core's Next, configure the `mailman-core` service to use Postfix. In `docker-compose.yaml`, add `MTA=postfix` to the `environment` section:
environment section in the `docker-compose.yaml`:
``` ```yaml
mailman-core: mailman-core:
<snip> <snip>
environment: environment:
- MTA=postfix - MTA=postfix
``` ```
This will auto-generate the configuration to talk to Postfix assuming that This `MTA` variable is critical. If it is missing, the container will default to Exim, which will likely cause startup errors if the rest of your configuration is for Postfix.
Postfix is available at the gateway address for the container's bridge network
at port 25. The final configuration can be found by executing:
``` The entrypoint script will then auto-generate the necessary MTA configuration. For reference, it looks like this:
$ docker exec mailman-core cat /etc/mailman.cfg
```
The postfix configuration that is generated looks like this:
``` ```
[mta] [mta]
incoming: mailman.mta.postfix.LMTP incoming: mailman.mta.postfix.LMTP
@@ -405,16 +394,31 @@ smtp_port: $SMTP_PORT
configuration: /etc/postfix-mailman.cfg configuration: /etc/postfix-mailman.cfg
``` ```
So, if you need to update the values, you can set `SMTP_HOST`, `SMTP_PORT`, #### Networking Configuration
`MM_HOSTNAME` environment variables in `mailman-core` container.
Please verify the output for `[mta]` section to ensure that it points to For the most reliable networking between your Postfix MTA (running on the host) and the `mailman-core` container, it is recommended to use **static IP addresses** instead of Docker service names, as the host's Postfix may not be able to resolve Docker internal hostnames.
the right `smtp_host` (address to reach postfix from mailman-core container)
and `lmtp_host` (address to reach mailman-core container from postfix).
The configuration file `/etc/postfix-mailman.cfg` is also generated automatically 1. In your `docker-compose.yaml`, assign a static IP to the `mailman-core` service and set the `MM_HOSTNAME` environment variable to that IP:
inside the `mailman-core` container and contains the configuration specific ```yaml
for Postfix. mailman-core:
<snip>
environment:
- MM_HOSTNAME=172.29.199.10
- MTA=postfix
networks:
mailman:
ipv4_address: 172.29.199.10
```
2. If you use `mailman-extra.cfg` to customize MTA settings, ensure `lmtp_host` also uses the static IP:
```
# /opt/mailman/core/mailman-extra.cfg
[mta]
lmtp_host: 172.29.199.10
```
This ensures that Postfix on the host can always find the `mailman-core` container at the specified IP, and the container correctly identifies itself.
After applying these changes, restart your services with `docker compose down && docker compose up -d`. Check the container logs (`docker compose logs mailman-core`) to ensure the service starts with "Using Postfix configuration".
## Site Owner ## Site Owner

View File

@@ -0,0 +1,36 @@
[mailman]
# This address is the "site owner" address. Certain messages which must be
# delivered to a human, but which can't be delivered to a list owner (e.g. a
# bounce from a list owner), will be sent to this address. It should point to
# a human.
site_owner: scott.idem+admin@oneskyit.com
[mta]
incoming: mailman.mta.postfix.LMTP
outgoing: mailman.mta.deliver.deliver
# I am pretty sure lmtp_host should *not* be the same as the $MM_HOSTNAME! It should be the hostname of the Postfix server running the MTA.
# The lmtp_host value is used exactly as is. It does not seem to replace the environment variable.
# lmtp_host:
# lmtp_host: $MM_HOSTNAME
# lmtp_host: localhost
# lmtp_host: mailman-core
# lmtp_host: dgr-srv-prime
# lmtp_host: 127.0.0.1
# lmtp_host: 104.237.143.4
# lmtp_host: 172.29.199.1 # No
lmtp_host: 172.29.199.10
lmtp_port: 8024
# smtp_host: 127.0.0.1
smtp_host: 104.237.143.4
# smtp_port: 25
# smtp_port: 465
smtp_port: 587
smtp_use_tls: True
# smtp_host_user: scott
# smtp_host_password: Adapting.7df
smtp_secure_mode: starttls
smtp_verify_hostname: False
smtp_verify_cert: False
configuration: /etc/postfix-mailman.cfg

View File

@@ -0,0 +1,9 @@
/var/log/mailman-core/*.log /var/log/mailman-web/*.log {
daily
rotate 7
compress
delaycompress
notifempty
missingok
create 0640 root adm
}

View File

@@ -1,13 +1,12 @@
version: '2'
services: services:
mailman-core: mailman-core:
image: maxking/mailman-core:0.4 # Use a specific version tag (tag latest is not published) image: maxking/mailman-core:0.5 # Use a specific version tag (tag latest is not published)
container_name: mailman-core container_name: mailman-core
hostname: mailman-core hostname: mailman-core
restart: unless-stopped restart: unless-stopped
volumes: volumes:
- /opt/mailman/core:/opt/mailman/ - ./conf/mailman-core:/opt/mailman/
- ./logs/mailman-core:/opt/mailman/var/logs/
stop_grace_period: 30s stop_grace_period: 30s
links: links:
- database:database - database:database
@@ -15,18 +14,35 @@ services:
database: database:
condition: service_healthy condition: service_healthy
environment: environment:
- DATABASE_URL=postgresql://mailman:mailmanpass@database/mailmandb - PUID=1000
- PGID=1000
- DATABASE_URL=postgresql://mailman:idaamailmanpass@database/mailmandb
- DATABASE_TYPE=postgres - DATABASE_TYPE=postgres
- DATABASE_CLASS=mailman.database.postgresql.PostgreSQLDatabase - DATABASE_CLASS=mailman.database.postgresql.PostgreSQLDatabase
- HYPERKITTY_API_KEY=someapikey - HYPERKITTY_API_KEY=${HYPERKITTY_API_KEY}
- SMTP_HOST_USER=${MAILMAN_SMTP_USER}
- SMTP_HOST_PASSWORD=${MAILMAN_SMTP_PASSWORD}
- SMTP_SECURE_MODE=starttls
- SMTP_VERIFY_HOSTNAME=False
- SMTP_VERIFY_CERT=False
- MTA=postfix
- MM_HOSTNAME=172.29.199.10
- MAILMAN_REST_USER=restadmin
- MAILMAN_REST_PASSWORD=NewSimplePassword-2026
ports: ports:
- "127.0.0.1:8001:8001" # API - "8008:8001" # API
- "127.0.0.1:8024:8024" # LMTP - incoming emails - "8024:8024" # LMTP - incoming emails
# - "127.0.0.1:8024:8024" # LMTP - incoming emails
networks: networks:
mailman: mailman:
ipv4_address: 172.29.199.10
extra_hosts:
- "dgr-srv-prime:192.168.32.7"
- "linode.oneskyit.com:104.237.143.4"
- "mail.oneskyit.com:104.237.143.4"
mailman-web: mailman-web:
image: maxking/mailman-web:0.4 # Use a specific version tag (tag latest is not published) image: maxking/mailman-web:0.5 # Use a specific version tag (tag latest is not published)
container_name: mailman-web container_name: mailman-web
hostname: mailman-web hostname: mailman-web
restart: unless-stopped restart: unless-stopped
@@ -37,25 +53,58 @@ services:
- mailman-core:mailman-core - mailman-core:mailman-core
- database:database - database:database
volumes: volumes:
- /opt/mailman/web:/opt/mailman-web-data - ./conf/mailman-web:/opt/mailman-web-data
- ./logs/mailman-web:/opt/mailman-web-data/logs/
environment: environment:
- PUID=1000
- PGID=1000
- DATABASE_TYPE=postgres - DATABASE_TYPE=postgres
- DATABASE_URL=postgresql://mailman:mailmanpass@database/mailmandb - DATABASE_URL=postgresql://mailman:idaamailmanpass@database/mailmandb
- HYPERKITTY_API_KEY=someapikey # - SERVE_FROM_DOMAIN=lists.idaa.org
- SERVE_FROM_DOMAIN=idaa.org
# - ALLOWED_HOSTS=mailman3.idaa.org,lists.idaa.org,dgr-srv-prime,dgr-srv-prime:8000,dgr-srv-prime:8080
- DJANGO_ALLOWED_HOSTS=mailman3.idaa.org,lists.idaa.org,lists.oneskyit.com,lists.dgrzone.com,dgr-srv-prime,dgr-srv-prime:8000,dgr-srv-prime:8080,192.168.32.7
- DJANGO_CSRF_TRUSTED_ORIGINS=mailman3.idaa.org,lists.idaa.org,lists.oneskyit.com,lists.dgrzone.com,dgr-srv-prime,dgr-srv-prime:8000,dgr-srv-prime:8080,192.168.32.7
- MAILMAN_REST_USER=restadmin
- MAILMAN_REST_PASSWORD=NewSimplePassword-2026
- HYPERKITTY_API_KEY=${HYPERKITTY_API_KEY}
- MAILMAN_ADMIN_USER=administrator
- MAILMAN_ADMIN_EMAIL=scott.idem+admin@oneskyit.com
- SECRET_KEY=${DJANGO_SECRET_KEY}
- UWSGI_STATIC_MAP=/static=/opt/mailman-web-data/static
# - SMTP_HOST=127.0.0.1
# - SMTP_HOST=104.237.143.4
- SMTP_HOST=linode.oneskyit.com
- SMTP_PORT=587
- SMTP_HOST_USER=${MAILMAN_SMTP_USER}
- SMTP_HOST_PASSWORD=${MAILMAN_SMTP_PASSWORD}
- SMTP_SECURE_MODE=starttls
- SMTP_USE_TLS=True
# Do not set SMTP_USE_SSL
# Setting the verify hostname/cert seems to have no effect
- SMTP_VERIFY_HOSTNAME=False
- SMTP_VERIFY_CERT=False
ports: ports:
- "127.0.0.1:8000:8000" # HTTP - "8000:8000" # HTTP
- "127.0.0.1:8080:8080" # uwsgi - "8080:8080" # uwsgi
networks: networks:
mailman: mailman:
extra_hosts:
- "dgr-srv-prime:192.168.32.7"
- "linode.oneskyit.com:104.237.143.4"
- "mail.oneskyit.com:104.237.143.4"
database: database:
environment: environment:
- PUID=1000
- PGID=1000
- POSTGRES_DB=mailmandb - POSTGRES_DB=mailmandb
- POSTGRES_USER=mailman - POSTGRES_USER=mailman
- POSTGRES_PASSWORD=mailmanpass - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
image: postgres:12-alpine # Can not use PostgreSQL 17 at this time 2025-02-04
image: postgres:16-alpine
volumes: volumes:
- /opt/mailman/database:/var/lib/postgresql/data - ./srv/postgresql16:/var/lib/postgresql/data
healthcheck: healthcheck:
test: ["CMD-SHELL", "pg_isready --dbname mailmandb --username mailman"] test: ["CMD-SHELL", "pg_isready --dbname mailmandb --username mailman"]
interval: 10s interval: 10s
@@ -64,6 +113,19 @@ services:
networks: networks:
mailman: mailman:
logrotate:
image: alpine:latest
container_name: logrotate
hostname: logrotate
restart: always
volumes:
- ./logs/mailman-core:/var/log/mailman-core
- ./logs/mailman-web:/var/log/mailman-web
- ./config/cron.d:/etc/periodic/daily
command: ["crond", "-f", "-L", "/dev/stdout"]
networks:
- mailman
networks: networks:
mailman: mailman:
driver: bridge driver: bridge
@@ -71,4 +133,4 @@ networks:
driver: default driver: default
config: config:
- -
subnet: 172.19.199.0/24 subnet: 172.29.199.0/24