Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,12 @@ __OFFICIAL MAIL ENVIRONMENT VARIABLES__
- POSTFIX_MYDESTINATION
- specify the domains which this mail-box handles

- INET_PROTOCOLS
- which IP versions postfix listens on and uses: `all`, `ipv4` or `ipv6`
- _default: auto_ — `all` if the container has IPv6 (Docker network with `enable_ipv6`), otherwise `ipv4`
- AUTO_TRUST_NETWORKS
- add all networks this container is connected to and trust them to send mails
- includes IPv6 networks (as `[prefix]/len`) when the container has IPv6
- _set to any value to enable_
- ADDITIONAL_MYNETWORKS
- add this specific network to the automatically trusted onces
Expand Down Expand Up @@ -142,6 +146,27 @@ __OFFICIAL MAIL ENVIRONMENT VARIABLES__
- POSTFIX_QUEUE_LIFETIME_MAX
- maximum lifetime of regular (non bounce) messages


## IPv6

Postfix and Dovecot listen on IPv6 whenever the container has it. With
plain Docker defaults a container is IPv4-only, and published ports reach it
over IPv6 through `docker-proxy`, which connects to the container over IPv4 —
so every IPv6 client shows up as the Docker network gateway (`172.x.0.1`).
To see real IPv6 client addresses, give the network IPv6 and let Docker NAT
IPv6 itself (`/etc/docker/daemon.json`: `"ip6tables": true`, plus
`"experimental": true` on Docker < 27):

```yaml
networks:
default:
enable_ipv6: true
ipam:
config:
- subnet: 172.19.0.0/16
- subnet: fd00:d0c:25::/64
```

## Volumes

- /etc/postfix/tls
Expand Down
18 changes: 18 additions & 0 deletions scripts/entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,29 @@ cat /container/config/postfix/master.conf > /etc/postfix/master.cf
cat /container/config/dovecot/dovecot.conf > /etc/dovecot/dovecot.conf
/container/scripts/add-mail-accounts.sh

##
# POSTFIX IP PROTOCOLS
##

# Listen on IPv6 too whenever the container has it (Docker network with
# enable_ipv6). IPv4-only containers stay on ipv4 — Postfix would otherwise
# warn about missing IPv6 support on every start. INET_PROTOCOLS overrides.
if [ -z ${INET_PROTOCOLS+x} ]; then
if grep -q . /proc/net/if_inet6 2>/dev/null; then
INET_PROTOCOLS=all
else
INET_PROTOCOLS=ipv4
fi
fi
echo ">> postfix inet_protocols: $INET_PROTOCOLS"
postconf -e "inet_protocols=$INET_PROTOCOLS"

##
# POSTFIX MYNETWORKS
##

AVAILABLE_NETWORKS="127.0.0.0/8"
[ "$INET_PROTOCOLS" = "ipv4" ] || AVAILABLE_NETWORKS="$AVAILABLE_NETWORKS,[::1]/128"
if [ ! -z ${AUTO_TRUST_NETWORKS+x} ]; then
AVAILABLE_NETWORKS=$(/container/scripts/list-available-networks.sh | tr '\n' ',' | sed 's/,$//g')
echo ">> trust all available networks: $AVAILABLE_NETWORKS"
Expand Down
25 changes: 15 additions & 10 deletions scripts/list-available-networks.sh
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
#!/bin/sh
# Print every network this container is directly attached to, one per line,
# in Postfix mynetworks notation (IPv4 a.b.c.d/n, IPv6 [prefix]/n).
# Used by AUTO_TRUST_NETWORKS.
#
# Connected routes are exactly the attached networks, with the host bits
# already zeroed — no netmask arithmetic, and IPv6 works the same way.
# Link-local and multicast IPv6 prefixes are never trusted.

IFS=$'\n' # make newlines the only separator
for j in $(ifconfig | grep inet | tr ' ' '\n' | grep 'Mask\|add' | tr '\n' ' ' | sed 's/addr/\naddr/g' | grep . | sed 's/[^0-9. ]//g')
do
ADDR=$(echo "$j" | cut -d' ' -f1)
MASK=$(echo "$j" | cut -d' ' -f2)
echo "127.0.0.0/8"
ip -4 route show 2>/dev/null \
| awk '$1 ~ /\// && $1 != "default" && !/ via / { print $1 }'

NETWORK=$(ipcalc -n $ADDR $MASK | sed 's/^.*=//g')
CIDR=$(ipcalc -p $ADDR $MASK | sed 's/^.*=//g')

echo "$NETWORK/$CIDR"
done
grep -q . /proc/net/if_inet6 2>/dev/null || exit 0
echo "[::1]/128"
ip -6 route show 2>/dev/null \
| awk '$1 ~ /\// && $1 != "default" && !/ via / && $1 !~ /^(fe80|ff[0-9a-f][0-9a-f]):/ {
split($1, p, "/"); print "[" p[1] "]/" p[2] }'
Loading