update to multiarch
This commit is contained in:
47
.drone.yml
Normal file
47
.drone.yml
Normal file
@@ -0,0 +1,47 @@
|
||||
kind: pipeline
|
||||
type: kubernetes
|
||||
name: default
|
||||
|
||||
node_selector:
|
||||
physical-node: dev2
|
||||
|
||||
trigger:
|
||||
branch:
|
||||
- master
|
||||
event:
|
||||
- push
|
||||
workspace:
|
||||
path: /drone/src
|
||||
|
||||
steps:
|
||||
- name: build multiarch from dev
|
||||
image: docker.io/owncloudci/drone-docker-buildx:4
|
||||
privileged: true
|
||||
settings:
|
||||
cache-from: [ "registry.dev.format.hu/smtp" ]
|
||||
registry: registry.dev.format.hu
|
||||
repo: registry.dev.format.hu/smtp
|
||||
tags: latest
|
||||
dockerfile: Dockerfile
|
||||
username:
|
||||
from_secret: dev-hu-registry-username
|
||||
password:
|
||||
from_secret: dev-hu-registry-password
|
||||
platforms:
|
||||
- linux/amd64
|
||||
- linux/arm64
|
||||
|
||||
- name: pull image to dockerhub
|
||||
image: docker.io/owncloudci/drone-docker-buildx:4
|
||||
privileged: true
|
||||
settings:
|
||||
cache-from: [ "safebox/smtp" ]
|
||||
repo: safebox/smtp
|
||||
tags: latest
|
||||
username:
|
||||
from_secret: dockerhub-username
|
||||
password:
|
||||
from_secret: dockerhub-password
|
||||
platforms:
|
||||
- linux/amd64
|
||||
- linux/arm64
|
33
Dockerfile
Normal file
33
Dockerfile
Normal file
@@ -0,0 +1,33 @@
|
||||
FROM alpine:3.20
|
||||
|
||||
ARG BUILD_DATE
|
||||
|
||||
LABEL \
|
||||
maintainer="Logan Marchione <logan@loganmarchione.com>" \
|
||||
org.opencontainers.image.authors="Logan Marchione <logan@loganmarchione.com>" \
|
||||
org.opencontainers.image.title="docker-postfixrelay" \
|
||||
org.opencontainers.image.description="Runs Postfix (as a relay) in Docker" \
|
||||
org.opencontainers.image.created=$BUILD_DATE
|
||||
|
||||
RUN apk add --no-cache --update \
|
||||
bash \
|
||||
ca-certificates \
|
||||
cyrus-sasl-login \
|
||||
dumb-init \
|
||||
postfix \
|
||||
postfix-doc \
|
||||
tzdata
|
||||
|
||||
EXPOSE 25
|
||||
|
||||
VOLUME [ "/var/spool/postfix" ]
|
||||
|
||||
COPY ./entrypoint.sh /
|
||||
|
||||
COPY VERSION /
|
||||
|
||||
RUN chmod +x /entrypoint.sh
|
||||
|
||||
ENTRYPOINT ["/usr/bin/dumb-init", "--", "/entrypoint.sh"]
|
||||
|
||||
HEALTHCHECK CMD netstat -ltn | grep -c ":25" || exit 1
|
21
LICENSE
Normal file
21
LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2024 Logan Marchione
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
132
README.md
132
README.md
@@ -1,2 +1,132 @@
|
||||
# smtp-client
|
||||
# docker-postfixrelay
|
||||
|
||||
[](https://github.com/loganmarchione/docker-postfixrelay/actions/workflows/main.yml)
|
||||
[](https://hub.docker.com/r/loganmarchione/docker-postfixrelay)
|
||||
|
||||
Runs Postfix (as a relay) in Docker
|
||||
- Source code: [GitHub](https://github.com/loganmarchione/docker-postfixrelay)
|
||||
- Docker container: [Docker Hub](https://hub.docker.com/r/loganmarchione/docker-postfixrelay)
|
||||
- Image base: [Alpine Linux](https://hub.docker.com/_/alpine/)
|
||||
- Init system: [dumb-init](https://github.com/Yelp/dumb-init)
|
||||
- Application: [Postfix](http://www.postfix.org/)
|
||||
- Architecture: `linux/amd64,linux/arm64,linux/arm/v7`
|
||||
|
||||
## Explanation
|
||||
|
||||
- This runs Postfix (as a relay) in Docker.
|
||||
- Most home ISPs block port 25, so outbound emails must be relayed through an external SMTP server (e.g., Gmail).
|
||||
- This container acts as a single collections point for devices needing to send email.
|
||||
- ⚠️ Postfix acts as an open relay. As such, this is not meant to be run on the internet, only on a trusted internal network! ⚠️
|
||||
|
||||
```
|
||||
Internal (LAN) network Public internet
|
||||
|
||||
------------------
|
||||
| |
|
||||
| Device sending | | |
|
||||
| email alert | ------------- | |
|
||||
| | | | |
|
||||
------------------ | | |
|
||||
| | F |
|
||||
------------------ v | i |
|
||||
| | ------------------ | r | ----------------------------- -------------------
|
||||
| Device sending | | | | e | | | | |
|
||||
| email alert | ----> | This container | --| w |--> | SMTP server (e.g., Gmail) | ----> | Recipient email |
|
||||
| | | | | a | | | | |
|
||||
------------------ ------------------ | l | ----------------------------- -------------------
|
||||
^ | l |
|
||||
------------------ | | |
|
||||
| | | | |
|
||||
| Device sending | | | |
|
||||
| email alert | ------------- | |
|
||||
| |
|
||||
------------------
|
||||
```
|
||||
|
||||
## Requirements
|
||||
|
||||
- You must already have an account on an external SMTP server (e.g., Gmail, AWS SES, etc...).
|
||||
- Your external SMTP server must be using encryption (i.e., plaintext is not allowed)
|
||||
|
||||
## Docker image information
|
||||
|
||||
### Docker image tags
|
||||
- `latest`: Latest version
|
||||
- `X.X.X`: [Semantic version](https://semver.org/) (use if you want to stick on a specific version)
|
||||
|
||||
### Environment variables
|
||||
| Variable | Required? | Definition | Example | Comments |
|
||||
|-------------|---------------------------|---------------------------------------------|----------------------------|--------------------------------------------------------------|
|
||||
| TZ | Yes | Timezone | America/New_York | https://en.wikipedia.org/wiki/List_of_tz_database_time_zones |
|
||||
| RELAY_HOST | Yes | Public SMTP server to use | smtp.gmail.com | |
|
||||
| RELAY_PORT | Yes | Public SMTP port to use | 587 | |
|
||||
| RELAY_USER | No | Address to login to $RELAY_HOST | SMTP username | |
|
||||
| RELAY_PASS | No | Password to login to $RELAY_HOST | SMTP password | If using Gmail 2FA, you will need to setup an app password |
|
||||
| TEST_EMAIL | No | Address to receive test email | receive_address@domain.com | If not set, test email will **not** be sent |
|
||||
| MYORIGIN | No | Domain of the "from" address | domain.com | Needed for things like AWS SES where the domain must be set |
|
||||
| FROMADDRESS | No | Changes the "from" address | my_email@domain.com | Needed for some SMTP services where the FROM address needs to be set, [fixes issue 19](https://github.com/loganmarchione/docker-postfixrelay/issues/19) |
|
||||
| MYNETWORKS | No (default: 0.0.0.0/0) | Networks that Postfix will forward mail for | 1.2.3.4/24, 5.6.7.8/24 | Single or multiple trusted networks separated with a comma |
|
||||
| MSG_SIZE | No (default: 10240000) | Postfix `message_size_limit` in bytes | 30720000 | |
|
||||
| LOG_DISABLE | No (default: false) | Setting to `true` disables logging | true | |
|
||||
|
||||
### Ports
|
||||
| Port on host | Port in container | Comments |
|
||||
|---------------------------|-------------------|---------------------|
|
||||
| Choose at your discretion | 25 | Postfix SMTP server |
|
||||
|
||||
### Volumes
|
||||
| Volume on host | Volume in container | Comments |
|
||||
|---------------------------|---------------------|------------------------------------|
|
||||
| Choose at your discretion | /var/spool/postfix | Used to store Postfix's mail spool |
|
||||
|
||||
### Example usage
|
||||
Below is an example docker-compose.yml file.
|
||||
```
|
||||
version: '3'
|
||||
services:
|
||||
postfixrelay:
|
||||
container_name: docker-postfixrelay
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- TZ=America/New_York
|
||||
- RELAY_HOST=smtp.gmail.com
|
||||
- RELAY_PORT=587
|
||||
- RELAY_USER=your_email_here@gmail.com
|
||||
- RELAY_PASS=your_password_here
|
||||
- TEST_EMAIL=test_email@domain.com
|
||||
- MYORIGIN=domain.com
|
||||
- FROMADDRESS=my_email@domain.com
|
||||
- MYNETWORKS=1.2.3.4/24
|
||||
- MSG_SIZE=30720000
|
||||
- LOG_DISABLE=true
|
||||
networks:
|
||||
- postfixrelay
|
||||
ports:
|
||||
- '25:25'
|
||||
volumes:
|
||||
- 'postfixrelay_data:/var/spool/postfix'
|
||||
image: loganmarchione/docker-postfixrelay:latest
|
||||
|
||||
networks:
|
||||
postfixrelay:
|
||||
|
||||
volumes:
|
||||
postfixrelay_data:
|
||||
driver: local
|
||||
```
|
||||
|
||||
Below is an example of running locally (used to edit/test/debug).
|
||||
```
|
||||
# Build the Dockerfile
|
||||
docker compose -f docker-compose-dev.yml up -d
|
||||
|
||||
# View logs
|
||||
docker compose -f docker-compose-dev.yml logs -f
|
||||
|
||||
# Destroy when done
|
||||
docker compose -f docker-compose-dev.yml down
|
||||
```
|
||||
|
||||
## TODO
|
||||
- [x] ~~Add a [healthcheck](https://docs.docker.com/engine/reference/builder/#healthcheck)~~
|
||||
- [ ] Add TLS support for SMTPD and listen on 587
|
||||
|
33
docker-compose-dev.yml
Normal file
33
docker-compose-dev.yml
Normal file
@@ -0,0 +1,33 @@
|
||||
version: '3'
|
||||
services:
|
||||
postfixrelay:
|
||||
container_name: docker-postfixrelay
|
||||
restart: unless-stopped
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
environment:
|
||||
- TZ=America/New_York
|
||||
- RELAY_HOST=smtp.gmail.com
|
||||
- RELAY_PORT=587
|
||||
- RELAY_USER=your_email_here@gmail.com
|
||||
- RELAY_PASS=your_password_here
|
||||
- TEST_EMAIL=test_email@domain.com
|
||||
- MYORIGIN=domain.com
|
||||
- FROMADDRESS=my_email@domain.com
|
||||
- MYNETWORKS=1.2.3.4/24
|
||||
- MSG_SIZE=30720000
|
||||
- LOG_DISABLE=true
|
||||
networks:
|
||||
- postfixrelay
|
||||
ports:
|
||||
- '25:25'
|
||||
volumes:
|
||||
- 'postfixrelay_data:/var/spool/postfix'
|
||||
|
||||
networks:
|
||||
postfixrelay:
|
||||
|
||||
volumes:
|
||||
postfixrelay_data:
|
||||
driver: local
|
108
entrypoint.sh
Normal file
108
entrypoint.sh
Normal file
@@ -0,0 +1,108 @@
|
||||
#!/bin/sh -e
|
||||
|
||||
printf "#####\n"
|
||||
printf "# Container starting up!\n"
|
||||
printf "#####\n"
|
||||
|
||||
# Test variables for timezone
|
||||
if [ -z "$TZ" ]; then
|
||||
printf "# ERROR: TZ is undefined, exiting!\n"
|
||||
else
|
||||
printf "# STATE: Setting container timezone to $TZ\n"
|
||||
ln -sf /usr/share/zoneinfo/"$TZ" /etc/localtime
|
||||
echo "$TZ" > /etc/timezone
|
||||
fi
|
||||
|
||||
# Test variables for relay
|
||||
if [[ -z "$RELAY_HOST" || -z "$RELAY_PORT" ]]; then
|
||||
printf "# ERROR: Either RELAY_HOST or RELAY_PORT are undefined, exiting!\n"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Create directories
|
||||
printf "# STATE: Changing permissions\n"
|
||||
postfix set-permissions
|
||||
|
||||
# Set logging
|
||||
if [[ "$LOG_DISABLE" == "true" ]]; then
|
||||
printf "# WARN: Setting Postfix logging to /dev/null\n"
|
||||
else
|
||||
printf "# STATE: Setting Postfix logging to /dev/stdout\n"
|
||||
postconf -e "maillog_file = /dev/stdout"
|
||||
fi
|
||||
|
||||
# Configure Postfix
|
||||
printf "# STATE: Configuring Postfix\n"
|
||||
postconf -e "inet_interfaces = all"
|
||||
postconf -e "mydestination ="
|
||||
postconf -e "mynetworks = ${MYNETWORKS:=0.0.0.0/0}"
|
||||
postconf -e "relayhost = [$RELAY_HOST]:$RELAY_PORT"
|
||||
|
||||
# Set the "from" domain, needed for things like AWS SES
|
||||
if [[ -z "$MYORIGIN" ]]; then
|
||||
printf "# WARN: MYORIGIN is undefined, continuing\n"
|
||||
else
|
||||
printf "# STATE: MYORIGIN is defined as $MYORIGIN\n"
|
||||
postconf -e "myorigin = $MYORIGIN"
|
||||
fi
|
||||
|
||||
# Set the "from" address, needed for some SMTP providers
|
||||
# https://serverfault.com/questions/147921/forcing-the-from-address-when-postfix-relays-over-smtp
|
||||
if [[ -z "$FROMADDRESS" ]]; then
|
||||
printf "# WARN: FROMADDRESS is undefined, continuing\n"
|
||||
else
|
||||
printf "# STATE: FROMADDRESS is defined as $FROMADDRESS\n"
|
||||
postconf -e "smtp_header_checks = regexp:/etc/postfix/header_checks"
|
||||
echo "/^From:.*/ REPLACE From: $FROMADDRESS" | tee /etc/postfix/header_checks > /dev/null
|
||||
postconf -e "sender_canonical_maps = regexp:/etc/postfix/sender_canonical_maps"
|
||||
echo "/.+/ $FROMADDRESS" | tee /etc/postfix/sender_canonical_maps > /dev/null
|
||||
fi
|
||||
|
||||
# Set the message_size_limit
|
||||
if [[ -z "$MSG_SIZE" ]]; then
|
||||
printf "# WARN: MSG_SIZE is undefined, continuing\n"
|
||||
else
|
||||
printf "# STATE: MSG_SIZE is defined as $MSG_SIZE\n"
|
||||
postconf -e "message_size_limit = $MSG_SIZE"
|
||||
fi
|
||||
|
||||
# Client settings (for sending to the relay)
|
||||
postconf -e "smtp_tls_security_level = encrypt"
|
||||
postconf -e "smtp_tls_loglevel = 1"
|
||||
postconf -e "smtp_tls_note_starttls_offer = yes"
|
||||
postconf -e "smtp_sasl_auth_enable = yes"
|
||||
postconf -e "smtp_sasl_security_options = noanonymous"
|
||||
postconf -e "smtp_sasl_password_maps = lmdb:/etc/postfix/sasl_passwd"
|
||||
postconf -e "smtp_tls_CAfile = /etc/ssl/certs/ca-certificates.crt"
|
||||
|
||||
# Create password file
|
||||
# Alpine 3.13 dropped support for Berkeley DB, so using lmdb instead
|
||||
# https://wiki.alpinelinux.org/wiki/Release_Notes_for_Alpine_3.13.0#Deprecation_of_Berkeley_DB_.28BDB.29
|
||||
echo "[$RELAY_HOST]:$RELAY_PORT $RELAY_USER:$RELAY_PASS" > /etc/postfix/sasl_passwd
|
||||
chown root:root /etc/postfix/sasl_passwd
|
||||
chmod 600 /etc/postfix/sasl_passwd
|
||||
postmap lmdb:/etc/postfix/sasl_passwd
|
||||
rm -f /etc/postfix/sasl_passwd
|
||||
chown root:root /etc/postfix/sasl_passwd.lmdb
|
||||
chmod 600 /etc/postfix/sasl_passwd.lmdb
|
||||
|
||||
# Rebuild the database for the mail aliases file
|
||||
newaliases
|
||||
|
||||
# Send test email
|
||||
# Test for variable and queue the message now, it will send when Postfix starts
|
||||
if [[ -z "$TEST_EMAIL" ]]; then
|
||||
printf "# WARN: TEST_EMAIL is undefined, continuing without a test email\n"
|
||||
else
|
||||
printf "# STATE: Sending test email\n"
|
||||
echo -e "Subject: Postfix relay test \r\nTest of Postfix relay from Docker container startup\nSent on $(date)\n" | sendmail -F "[Alert from Postfix]" "$TEST_EMAIL"
|
||||
fi
|
||||
|
||||
# Start Postfix
|
||||
# Nothing else can log after this
|
||||
printf "# STATE: Starting Postfix\n"
|
||||
if [[ "$LOG_DISABLE" == "true" ]]; then
|
||||
postfix start-fg > /dev/null
|
||||
else
|
||||
postfix start-fg
|
||||
fi
|
Reference in New Issue
Block a user