Release 3.0.0 - See CHANGELOG.md

This commit is contained in:
Dave Conroy 2021-10-06 08:40:14 -07:00
parent c45ca48a48
commit 798f4fd35c
21 changed files with 335 additions and 262 deletions

View file

@ -1,3 +1,14 @@
## 3.0.0 2021-10-06 <dave at tiredofit dot ca>
### Added
- Updated to support new Postal 2.x release
- Alpine 3.14
### Changed
- Changes to environment variables, mapped folders, and persistent configuration files. See README.md
- Upgrading from existing install is possible without much effort, just madke sure to map /config and /logs
## 2.1.6 2020-09-27 <dave at tiredofit dot ca>
### Changed

View file

@ -1,11 +1,11 @@
FROM tiredofit/nginx:alpine-3.13
LABEL maintainer="Dave Conroy (dave at tiredofit dot ca)"
FROM docker.io/tiredofit/alpine:3.14
LABEL maintainer="Dave Conroy (github.com/tiredofit)"
ENV POSTAL_VERSION=master \
POSTAL_REPO_URL=https://github.com/postalhq/postal \
POSTAL_CONFIG_ROOT=/app/config \
ENABLE_SMTP=FALSE \
ZABBIX_HOSTNAME=postal-app
POSTAL_CONFIG_ROOT=/app/config/ \
CONTAINER_ENABLE_MESSAGING=FALSE \
RAILS_ENV=production
RUN set -x && \
addgroup -g 2525 postal && \
@ -18,8 +18,8 @@ RUN set -x && \
git \
mariadb-dev \
ruby-dev \
&& \
\
&& \
\
apk add -t .postal-run-deps \
expect \
fail2ban \
@ -29,24 +29,27 @@ RUN set -x && \
mariadb-connector-c \
openssl \
ruby \
ruby-bigdecimal \
ruby-io-console \
ruby-etc \
&& \
\
### Fetch Source and install Ruby Dependencies
\
gem install bundler -v 1.17.2 && \
gem install procodile && \
\
### Fetch Source and install Ruby Dependencies
git clone https://github.com/postalhq/postal /app/ && \
\
### Install Ruby Gems and dependencies
/app/bin/postal bundle /app/vendor/bundle && \
\
### Housekeeping
ln -s /usr/local/bundle/bin/procodile /usr/sbin && \
cd /app && \
bundle install -j "$(nproc)" && \
if [ $POSTAL_VERSION = "main" ] || [ $POSTAL_VERSION = "master" ] ; then git -C /app rev-parse HEAD > /app/VERSION ; else echo $POSTAL_VERSION > /app/VERSION ; fi ; \
\
# Cleanup
chown -R postal. /app/ && \
apk del .postal-build-deps && \
rm -rf /app/docker-compose.yml /app/Dockerfile /app/Makefile && \
rm -rf /app/log & \
rm -rf /root/.bundle /root/.gem && \
cd /etc/fail2ban && \
rm -rf fail2ban.conf fail2ban.d jail.conf jail.d paths-*.conf && \
apk del .postal-build-deps && \
rm -rf /tmp/* /var/cache/apk/*
### Networking Setup

View file

@ -1,6 +1,6 @@
The MIT License (MIT)
Copyright (c) 2020 Dave Conroy
Copyright (c) 2021 Dave Conroy
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View file

@ -11,7 +11,7 @@
## About
Dockerfile to build a [Postal](https://github.com/atech/postal) SMTP server for sending and receiving SMTP / HTTP API email.
Dockerfile to build a [Postal](https://github.com/postalserver/postal) SMTP server for sending and receiving SMTP / HTTP API email.
* Contains Fail2Ban for blocking repeat authentication offenders
@ -33,13 +33,13 @@ Clone this repository and build the image with `docker build <arguments> (imagen
### Prebuilt Images
Builds of the image are available on [Docker Hub](https://hub.docker.com/r/tiredofit/postal) and is the recommended method of installation.
The following image tags are available along with their taged release based on what's written in the [Changelog](CHANGELOG.md):
The following image tags are available along with their tagged release based on what's written in the [Changelog](CHANGELOG.md):
| Container OS | Tag |
| ------------ | --------- |
| Alpine | `:latest` |
#### Multi Archictecture
#### Multi Architecture
Images are built primarily for `amd64` architecture, and may also include builds for `arm/v6`, `arm/v7`, `arm64` and others. These variants are all unsupported. Consider [sponsoring](https://github.com/sponsors/tiredofit) my work so that I can work with various hardware. To see if this image supports multiple architecures, type `docker manifest (image):(tag)`
## Configuration
@ -51,7 +51,16 @@ Images are built primarily for `amd64` architecture, and may also include builds
* Set various [environment variables](#environment-variables) to understand the capabilities of this image.
* Map [persistent storage](#data-volumes) for access to configuration and data files for backup.
*
### Persistent Storage
The following directories are used for configuration and can be mapped for persistent storage.
| Directory | Description |
| ---------------- | ---------------------------------------------------------------------------------------------------- |
| `/config/` | Auto generated Postal Config and Signing Key resides here |
| `/logs/` | Logfiles |
| `/assets/custom` | *Optional* Use this to drop files overop of the Postal sourcode for cherry picked overrides of files |
### Environment Variables
#### Base Images used
@ -63,8 +72,14 @@ Be sure to view the following repositories to understand all the customizable op
| Image | Description |
| ------------------------------------------------------ | -------------------------------------- |
| [OS Base](https://github.com/tiredofit/docker-alpine/) | Customized Image based on Alpine Linux |
| [Nginx](https://github.com/tiredofit/docker-nginx/) | Nginx webserver |
#### Admin Accounts
| Parameter | Description | Default |
| ----------- | ------------------------ | -------------------- |
| ADMIN_EMAIL | Email address of admin | `postal@example.com` |
| ADMIN_FNAME | Name of Admin First Name | `Postal` |
| ADMIN_LNAME | Name of Admin Last Name | `Admin` |
| ADMIN_PASS | Password of Admin user | `PostalMailServer` |
#### Application Settings
| Parameter | Description | Default |
| ------------------------- | ---------------------------------------- | ------- |
@ -95,21 +110,18 @@ Be sure to view the following repositories to understand all the customizable op
| `FAIL2BAN_TIME_BAN` | Time to ban repeat offenders | `10m` |
| `FAIL2BAN_MAX_RETRY` | Ban after how many tries during time period | `5` |
#### Performance Settings
| Parameter | Description | Default |
| ----------------- | ---------------------------- | ------- |
| `WORKERS_AMOUNT` | Amount of Workers | `1` |
| `WORKERS_THREADS` | Amount of Threads per worker | `4` |
#### Logging Settings
| Parameter | Description | Default |
| ------------------ | -------------------------------------------------------- | -------- |
| `LOG_AUTH_FAILURE` | Log Authentication Failures (Used for Fail2ban blocking) | `TRUE` |
| `LOG_CONSOLE` | Log to Stdout Console `true` or `false` | `true` |
| `LOG_LOCATION` | Log Location | `/logs/` |
| `LOG_SIZE_MAX` | Maximum Log Size in KB | `9999` |
| Parameter | Description | Default |
| -------------- | --------------------------------------- | -------- |
| `LOG_CONSOLE` | Log to Stdout Console `true` or `false` | `true` |
| `LOG_PATH` | Log Location | `/logs/` |
| `LOG_SIZE_MAX` | Maximum Log Size in KB | `9999` |
#### Database Settings
| Parameter | Description | Default |
@ -133,6 +145,20 @@ Be sure to view the following repositories to understand all the customizable op
| `SPAMASSASSIN_HOST` | Hostname of Spamassassin daemon | |
| `SPAMASSASSIN_PORT` | TCP Port of spamassassin daemon | `737` |
| Parameter | Description | Default |
| --------------- | ---------------------------------------- | ------- |
| `ENABLE_RSPAMD` | Enable RSpamD checking `true` or `false` | `false` |
| `RSPAMD_FLAGS` | Flags to pass to rspamd daemon | `null` |
| `RSPAMD_HOST` | Hostname of rspamd daemon | |
| `RSPAMD_PASS` | RSpamd controller password | `null` |
| `RSPAMD_PORT` | TCP Port of rspamd daemon | `11334` |
| `RSPAMD_SSL` | Use SSL for connecting to rspamd | `FALSE` |
| Parameter | Description | Default |
| ------------------------ | -------------------------- | ------- |
| `SPAM_THRESHOLD` | Amount to classify as Spam | `5.0` |
| `SPAM_FAILURE_THRESHOLD` | Amount to fail as Spam | `5.0` |
#### Anti Virus Settings
| Parameter | Description | Default |
| --------------- | ------------------------------- | ------- |
@ -180,19 +206,21 @@ Be sure to view the following repositories to understand all the customizable op
| `SMTP_RELAY_SSL_MODE` | Relay SSL / TLS Mode | `Auto` |
#### Other Settings
| Parameter | Description | Default |
| --------------------------- | ---------------------------------------------------------------------------- | ------------------------ |
| `CONFIG_LOCATION` | Configuration File | `/app/config/postal.yml` |
| `SETUP_TYPE` | Choose `AUTO` or `MANUAL` Setup type - Auto uses these environment variables | `AUTO` |
| `FAST_SERVER_BIND_IP` | Bind IP for the Web Interface | `0.0.0.0` |
| `FAST_SERVER_BIND_PORT_TLS` | Bind Port for the TLS Tracking Service | `8443` |
| `FAST_SERVER_BIND_PORT` | Bind Port for the Tracking Server | `8080` |
| `WEB_BIND_IP` | Bind IP for the Web Interface | `0.0.0.0` |
| `WEB_BIND_PORT` | Bind Port for the Web Interface | `5000` |
| `WEB_HOSTNAME` | Hostname for Web Interface | `postal.example.com` |
| `WEB_MAX_THREADS` | Max Threads for Web Interface | `5` |
| `WEB_PROTOCOL` | Protocol for Web Interface `http` or `https` | `http` |
| Parameter | Description | Default |
| --------------------------- | ---------------------------------------------------------------------------- | -------------------- |
| `CONFIG_FILE` | Configuration File | `postal.yml` |
| `CONFIG_PATH` | Configuration Path | `/config/` |
| `FAST_SERVER_BIND_IP` | Bind IP for the Web Interface | `0.0.0.0` |
| `FAST_SERVER_BIND_PORT_TLS` | Bind Port for the TLS Tracking Service | `8443` |
| `FAST_SERVER_BIND_PORT` | Bind Port for the Tracking Server | `8080` |
| `SETUP_TYPE` | Choose `AUTO` or `MANUAL` Setup type - Auto uses these environment variables | `AUTO` |
| `SIGNING_KEY_FILE` | Signing Key File | `signing.key` |
| `SIGNING_KEY_SIZE` | Signing Key Size | `1024` |
| `WEB_BIND_IP` | Bind IP for the Web Interface | `0.0.0.0` |
| `WEB_BIND_PORT` | Bind Port for the Web Interface | `5000` |
| `WEB_HOSTNAME` | Hostname for Web Interface | `postal.example.com` |
| `WEB_MAX_THREADS` | Max Threads for Web Interface | `5` |
| `WEB_PROTOCOL` | Protocol for Web Interface `http` or `https` | `http` |
### Networking
| Port | Description |

View file

@ -2,7 +2,7 @@ version: '3.7'
services:
postal-app:
image: tiredofit/postal
image: tiredofit/postal:latest
container_name: postal-app
ports:
- 25:2525
@ -15,15 +15,15 @@ services:
- traefik.backend=postal-app
volumes:
- ./logs/postal:/logs
environment:
- ZABBIX_HOSTNAME=postal-app
environment:
- CONTAINER_NAME=postal-app
- DB_HOST=postal-db
- DB_PORT=3306
- DB_NAME=postal
- DB_USER=postal
- DB_PASS=postalpass
## A great idea is to delete this block after first install.
- DB_ROOT_PASS=rootpassword
- ADMIN_EMAIL=example@hostname.com
@ -40,9 +40,12 @@ services:
- ENABLE_SPAMASSASSIN=false
- SPAMASSASSIN_HOST=postal-spamassassin
- ENABLE_RSPAMD=false
- RSPAMD_HOST=postal-rspamd
- ENABLE_CLAMAV=false
- CLAMAV_HOST=postal-clamav
- DNS_HOSTNAME=postal.example.com
- DNS_MX=mx.example.com
- DNS_RETURN_PATH=rp.example.com
@ -68,29 +71,29 @@ services:
restart: always
postal-db:
image: tiredofit/mariadb
image: tiredofit/mariadb:latest
container_name: postal-db
volumes:
- ./db:/var/lib/mysql
environment:
- MYSQL_ROOT_PASSWORD=rootpassword
- MYSQL_DATABASE=postal
- MYSQL_USER=postal
- MYSQL_PASSWORD=postalpass
- ZABBIX_HOSTNAME=postal-db
- ROOT_PASS=rootpassword
- DB_NAME=postal
- DB_USER=postal
- DB_PASS=postalpass
- CONTAINER_NAME=postal-db
networks:
- services
restart: always
postal-db-backup:
image: tiredofit/db-backup
image: tiredofit/db-backup:latest
container_name: postal-db-backup
links:
- postal-db
volumes:
- ./dbbackup:/backup
environment:
- ZABBIX_HOSTNAME=postal-db-backup
- CONTAINER_NAME=postal-db-backup
- DB_HOST=postal-db
- DB_TYPE=mariadb
- DB_NAME=postal
@ -99,7 +102,7 @@ services:
- DB_DUMP_FREQ=1440
- DB_DUMP_BEGIN=0000
- DB_CLEANUP_TIME=8640
- COMPRESSION=BZ
- COMPRESSION=ZSTD
- MD5=TRUE
networks:
- services
@ -112,7 +115,7 @@ services:
- RABBITMQ_DEFAULT_USER=postal
- RABBITMQ_DEFAULT_PASS=password
- RABBITMQ_DEFAULT_VHOST=/postal
- ZABBIX_HOSTNAME=postal-rabbitmq
- CONTAINER_NAME=postal-rabbitmq
networks:
- services
restart: always
@ -124,7 +127,7 @@ services:
- ./data/clamav:/data
- ./logs/clamav:/var/log/clamav
environment:
- ZABBIX_HOSTNAME=postal-clamav
- CONTAINER_NAME=postal-clamav
networks:
- services
restart: always
@ -137,7 +140,7 @@ services:
- ./data/spamassassin/conf:/etc/mail/spamassassin
- ./data/spamassassin/data:/var/lib/spamassassin
environment:
- ZABBIX_HOSTNAME=postal-spamassassin
- CONTAINER_NAME=postal-spamassassin
networks:
- services
restart: always

View file

@ -9,7 +9,8 @@ FAIL2BAN_DB_PURGE_AGE=${FAIL2BAN_DB_PURGE_AGE:-"86400"}
FAIL2BAN_DB_TYPE=${FAIL2BAN_DB_TYPE:-"FILE"}
FAIL2BAN_IGNORE_IP=${FAIL2BAN_IGNORE_IP:-"127.0.0.1/8 ::1"}
FAIL2BAN_IGNORE_SELF=${FAIL2BAN_IGNORE_SELF:-"TRUE"}
FAIL2BAN_LOG_FILE=${FAIL2BAN_LOG_FILE:-"/logs/fail2ban/fail2ban.log"}
FAIL2BAN_LOG_PATH=${FAIL2BAN_LOG_PATH:-"/logs/fail2ban/"}
FAIL2BAN_LOG_FILE=${FAIL2BAN_LOG_FILE:-"fail2ban.log"}
FAIL2BAN_LOG_LEVEL=${FAIL2BAN_LOG_LEVEL:-"INFO"}
FAIL2BAN_LOG_TYPE=${FAIL2BAN_LOG_TYPE:-"FILE"}
FAIL2BAN_MAX_RETRY=${FAIL2BAN_MAX_RETRY:-"5"}

View file

@ -1,8 +1,9 @@
#!/usr/bin/with-contenv /bin/bash
CLAMAV_PORT=${CLAMAV_PORT:-3310}
CONFIG_LOCATION=${CONFIG_LOCATION:-"/app/config/postal.yml"}
DB_PORT=${DB_PORT:-3306}
CLAMAV_PORT=${CLAMAV_PORT:-"3310"}
CONFIG_FILE=${CONFIG_FILE:-"postal.yml"}
CONFIG_PATH=${CONFIG_PATH:-"/config/"}
DB_PORT=${DB_PORT:-"3306"}
DNS_DKIM_IDENTIFIER=${DNS_DKIM_IDENTIFIER:-"postal"}
DNS_DOMAIN_VERIFY_PREFIX=${DNS_DOMAIN_VERIFY_PREFIX:-"postal-verification"}
DNS_HOSTNAME=${DNS_HOSTNAME:-"postal.example.com"}
@ -12,32 +13,33 @@ DNS_RETURN_PATH_PREFIX=${DNS_RETURN_PATH_PREFIX:-"psrp"}
DNS_ROUTE_DOMAIN=${DNS_ROUTE_DOMAIN:-"routes."$DNS_HOSTNAME}
DNS_SPF=${DNS_SPF:-"spf."$DNS_HOSTNAME}
DNS_TRACK_DOMAIN=${DNS_TRACK_DOMAIN:-"track."$DNS_HOSTNAME}
ENABLE_CLAMAV=${ENABLE_CLAMAV:-false}
ENABLE_SPAMASSASSIN=${ENABLE_SPAMASSASSIN:-false}
ENABLE_FAST_SERVER=${ENABLE_FAST_SERVER:-true}
FAST_SERVER_BIND_IP=${FAST_SERVER_BIND_IP:-0.0.0.0}
FAST_SERVER_BIND_PORT=${FAST_SERVER_BIND_PORT:-8080}
FAST_SERVER_BIND_PORT_TLS=${FAST_SERVER_BIND_PORT_TLS:-8443}
FAST_SERVER_ENABLE_PROXY_PROTOCOL=${FAST_SERVER_ENABLE_PROXY_PROTOCOL:-false}
LOG_AUTH_FAILURE=${LOG_AUTH_FAILURE:-"TRUE"}
LOG_CONSOLE=${LOG_CONSOLE:-true}
LOG_LOCATION=${LOG_LOCATION:-"/logs/"}
ENABLE_CLAMAV=${ENABLE_CLAMAV:-"false"}
ENABLE_RSPAMD=${ENABLE_RSPAMD:-"false"}
ENABLE_SPAMASSASSIN=${ENABLE_SPAMASSASSIN:-"false"}
LOG_CONSOLE=${LOG_CONSOLE:-false}
LOG_PATH=${LOG_PATH:-"/logs/"}
LOG_SIZE_MAX=${LOG_SIZE_MAX:-9999}
MAX_DELIVERY_ATTEMPTS=${MAX_DELIVERY_ATTEMPTS:-18}
MAX_HOLD_EXPIRY_DAYS=${MAX_HOLD_EXPIRY_DAYS:-7}
RABBITMQ_PORT=${RABBITMQ_PORT:-5672}
MAX_DELIVERY_ATTEMPTS=${MAX_DELIVERY_ATTEMPTS:-"18"}
MAX_HOLD_EXPIRY_DAYS=${MAX_HOLD_EXPIRY_DAYS:-"7"}
RABBITMQ_PORT=${RABBITMQ_PORT:-"5672"}
RSPAMD_FLAGS=${RSPAMD_FLAGS:-"null"}
RSPAMD_PASS=${RSPAMD_PASS:-"null"}
RSPAMD_PORT=${RSPAMD_PORT:-"11334"}
RSPAMD_SSL=${RSPAMD_SSL:-"FALSE"}
SETUP_TYPE=${SETUP_TYPE:-"AUTO"}
SMTP_CLIENT_OPEN_TIMEOUT=${SMTP_CLIENT_OPEN_TIMEOUT:-30}
SMTP_CLIENT_READ_TIMEOUT=${SMTP_CLIENT_READ_TIMEOUT:-60}
SIGNING_KEY_FILE=${SIGNING_KEY_FILE:-"signing.key"}
SIGNING_KEY_BITS=${SIGNING_KEY_BITS:-"1024"}
SMTP_CLIENT_OPEN_TIMEOUT=${SMTP_CLIENT_OPEN_TIMEOUT:-"30"}
SMTP_CLIENT_READ_TIMEOUT=${SMTP_CLIENT_READ_TIMEOUT:-"60"}
SMTP_FROM_ADDRESS=${SMTP_FROM_ADDRESS:-"postal@yourdomain.com"}
SMTP_FROM_NAME=${SMTP_FROM_NAME:-"Postal"}
SMTP_HOST=${SMTP_HOST:-127.0.0.1}
SMTP_PORT=${SMTP_PORT:-25}
SMTP_HOST=${SMTP_HOST:-"127.0.0.1"}
SMTP_PORT=${SMTP_PORT:-"25"}
SMTP_RELAY_HOST=${SMTP_RELAY_HOST:-""}
SMTP_RELAY_PORT=${SMTP_RELAY_PORT:-25}
SMTP_RELAY_PORT=${SMTP_RELAY_PORT:-"25"}
SMTP_RELAY_SSL_MODE=${SMTP_RELAY_SSL_MODE:-"Auto"}
SMTP_SERVER_ENABLE_TLS=${SMTP_SERVER_ENABLE_TLS:-"false"}
SMTP_SERVER_HELO_HOSTNAME=${SMTP_SERVER_HELO_HOSTNAME:-$DNS_HOSTNAME}
SMTP_SERVER_HELO_HOSTNAME=${SMTP_SERVER_HELO_HOSTNAME:-"$DNS_HOSTNAME"}
SMTP_SERVER_LOG_CONNECTIONS=${SMTP_SERVER_LOG_CONNECTIONS:-"true"}
SMTP_SERVER_MAX_MESSAGE_SIZE=${SMTP_SERVER_MAX_MESSAGE_SIZE:-50}
SMTP_SERVER_PORT=${SMTP_SERVER_PORT:-"25"}
@ -47,12 +49,14 @@ SMTP_SERVER_STRIP_RECEIVED_HEADERS=${SMTP_SERVER_STRIP_RECEIVED_HEADERS:-"false"
SMTP_SERVER_TLS_CERT=${SMTP_SERVER_TLS_CERT:-"/certs/cert.pem"}
SMTP_SERVER_TLS_CIPHERS=${SMTP_SERVER_TLS_CIPHERS:-""}
SMTP_SERVER_TLS_KEY=${SMTP_SERVER_TLS_KEY:-"/certs/key.pem"}
SPAMASSASSIN_PORT=${SPAMASSASSIN_PORT:-783}
SUPPRESSION_LIST_EXPIRY=${SUPPRESSION_LIST_EXPIRY:-30}
SPAM_THRESHOLD=${SPAM_THRESHOLD:-"5.0"}
SPAM_FAILURE_THRESHOLD=${SPAM_FAILURE_THRESHOLD:-"5.0"}
SPAMASSASSIN_PORT=${SPAMASSASSIN_PORT:-"783"}
SUPPRESSION_LIST_EXPIRY=${SUPPRESSION_LIST_EXPIRY:-"30"}
WEB_BIND_IP=${WEB_BIND_IP:-"0.0.0.0"}
WEB_BIND_PORT=${WEB_BIND_PORT:-5000}
WEB_BIND_PORT=${WEB_BIND_PORT:-"5000"}
WEB_HOST=${WEB_HOST:-"postal.example.com"}
WEB_MAX_THREADS=${WEB_MAX_THREADS:-5}
WEB_MAX_THREADS=${WEB_MAX_THREADS:-"5"}
WEB_PROTOCOL=${WEB_PROTOCOL:-"http"}
WORKERS_AMOUNT=${WORKERS_AMOUNT:-1}
WORKERS_THREADS=${WORKERS_THREADS:-4}
WORKERS_AMOUNT=${WORKERS_AMOUNT:-"1"}
WORKERS_THREADS=${WORKERS_THREADS:-"4"}

View file

@ -2,35 +2,29 @@
fail2ban_configure_logging() {
print_debug "Fail2ban: Configure Logging"
mkdir -p $(dirname ${FAIL2BAN_LOG_FILE})
touch ${FAIL2BAN_LOG_FILE}
sed -i "s|<FAIL2BAN_LOG_LOCATION>|$(dirname ${FAIL2BAN_LOG_FILE})|g" /etc/logrotate.d/fail2ban
if [ "${FAIL2BAN_LOG_TYPE}" = "FILE" ] ; then
mkdir -p "${FAIL2BAN_LOG_PATH}"
touch "${FAIL2BAN_LOG_PATH}"/"${FAIL2BAN_LOG_FILE}"
create_logrotate fail2ban "${FAIL2BAN_LOG_PATH}"/"${FAIL2BAN_LOG_FILE}"
fi
}
fail2ban_create_data_dir() {
print_debug "Fail2ban: Creating Socket Directory"
mkdir -p /var/run/fail2ban
print_debug "Fail2ban: Configuring Filesystem"
if [ ! -f ${FAIL2BAN_CONFIG_PATH} ] ; then
if [ ! -f "${FAIL2BAN_CONFIG_PATH}" ] ; then
print_debug "Fail2ban: Creating Config Dir"
mkdir -p ${FAIL2BAN_CONFIG_PATH}
cp -R /etc/fail2ban/* ${FAIL2BAN_CONFIG_PATH}
mkdir -p "${FAIL2BAN_CONFIG_PATH}"
cp -R /etc/fail2ban/* "${FAIL2BAN_CONFIG_PATH}"
fi
print_debug "Fail2ban: Linking Config to Persistent Storage"
rm -rf /etc/fail2ban
ln -sf ${FAIL2BAN_CONFIG_PATH} /etc/fail2ban
ln -sf "${FAIL2BAN_CONFIG_PATH}" /etc/fail2ban
print_debug "Fail2ban: Creating Data Dir"
mkdir -p ${FAIL2BAN_DB_PATH}
if [ "$FAIL2BAN_LOG_TYPE" = "FILE" ] ; then
print_debug "Fail2ban: Creating Log Directory"
mkdir -p $(dirname ${FAIL2BAN_LOG_FILE})
sed -i "s|<FAIL2BAN_LOG_PATH>|$(dirname ${FAIL2BAN_LOG_FILE})|g" /etc/logrotate.d/fail2ban
else
rm -rf /etc/logrotate.d/fail2ban
fi
mkdir -p "${FAIL2BAN_DB_PATH}"
}
fail2ban_create_config_jail() {
@ -95,6 +89,7 @@ EOF
fail2ban_create_config_main(){
if [ "$SETUP_TYPE" = "AUTO" ]; then
if [ "$FAIL2BAN_LOG_TYPE" = "CONSOLE" ] ; then
unset FAIL2BAN_LOG_PATH
FAIL2BAN_LOG_FILE="STDOUT"
fi
print_debug "Fail2ban: Configuring main config file"
@ -106,7 +101,7 @@ fail2ban_create_config_main(){
[Definition]
loglevel = ${FAIL2BAN_LOG_LEVEL}
# Values: [ STDOUT | STDERR | SYSLOG | SYSOUT | FILE ] Default: STDERR
logtarget = ${FAIL2BAN_LOG_FILE}
logtarget = ${FAIL2BAN_LOG_PATH}${FAIL2BAN_LOG_FILE}
syslogsocket = auto
socket = /var/run/fail2ban/fail2ban.sock
pidfile = /var/run/fail2ban/fail2ban.pid
@ -159,7 +154,7 @@ fail2ban_jail_create() {
cat <<EOF >> ${FAIL2BAN_CONFIG_PATH}jail.local
[postal]
enabled = true
logpath = ${LOG_LOCATION}/smtp_server.log
logpath = ${LOG_PATH}/smtp_server.log
bantime = 86400
findtime = 86400
maxretry = 3

View file

@ -1,27 +1,36 @@
#!/usr/bin/with-contenv /bin/bash
bootstrap() {
mkdir -p ${CONFIG_PATH}
if [ ! -f "${CONFIG_PATH}"/"${SIGNING_KEY_FILE}" ]; then
print_notice "Creating Signing Private Key"
silent openssl genrsa -out $"${CONFIG_PATH}"/"${SIGNING_KEY_FILE}" ${SIGNING_KEY_BITS}
chmod 644 "${CONFIG_PATH}"/"${SIGNING_KEY_FILE}"
fi
}
certificates() {
CA_NAME=postal-selfsigned-ca
CA_SUBJECT=${CA_SUBJECT:-"/C=XX/ST=Postal/L=Postal/O=Postal/CN="}
CA_CERT_SUBJECT=${CA_CERT_SUBJECT:-${CA_SUBJECT}${CA_NAME}}
CA_CERT_FILE=${CA_CERT_FILE:-"/certs/${CA_NAME}/${CA_NAME}.crt"}
CA_KEY_FILE=${CA_KEY_FILE:-"`dirname ${CA_CERT_FILE}`/${CA_NAME}.key"}
CA_KEY_FILE=${CA_KEY_FILE:-"$(dirname ${CA_CERT_FILE})/${CA_NAME}.key"}
CREATE_CA=${CREATE_CA:-"TRUE"}
certificates_create_certificate_authority() {
if [ ! -f ${CA_CERT_FILE} ] ; then
print_debug "Certificates: Creating Self Signed Certificate Authority"
mkdir -p `dirname ${CA_CERT_FILE}`
echo "000a" > `dirname ${CA_CERT_FILE}`/serial
touch `dirname ${CA_CERT_FILE}`/certindex
mkdir -p $(dirname ${CA_CERT_FILE})
echo "000a" > $(dirname ${CA_CERT_FILE})/serial
touch $(dirname ${CA_CERT_FILE})/certindex
silent eval "openssl req \
-newkey rsa:4096 -keyout ${CA_KEY_FILE} \
-x509 -days 3650 -nodes -out ${CA_CERT_FILE} \
-subj \"${CA_CERT_SUBJECT}\""
cat > `dirname ${CA_CERT_FILE}`/$CA_NAME.conf << EOF
cat > $(dirname ${CA_CERT_FILE})/$CA_NAME.conf << EOF
[ ca ]
t_ca = $CA_NAME
@ -29,9 +38,9 @@ certificates() {
unique_subject = no
new_certs_dir = .
certificate = ${CA_CERT_FILE}
database = `dirname ${CA_CERT_FILE}`/certindex
database = $(dirname ${CA_CERT_FILE})/certindex
private_key = ${CA_KEY_FILE}
serial = `dirname ${CA_CERT_FILE}`/serial
serial = $(dirname ${CA_CERT_FILE})/serial
default_days = 3650
default_md = default
policy = ${CA_NAME}_policy
@ -74,7 +83,7 @@ EOF
certificates_create_certificate() {
if [ "$1" != "" ] ; then
if var_true $CREATE_CA ; then
if var_true "${CREATE_CA}" ; then
if [ ! -f ${CA_CERT_FILE} ] || [ ! -f ${CA_KEY_FILE} ] ; then
print_debug "Certificates: No CA Found - Creating before generating certificates"
certificates_create_certificate_authority
@ -104,7 +113,7 @@ EOF
if var_true $CREATE_CA ; then
if [ ! -f ${1%%.*}.cert ] ; then
print_debug "Certificates: Signing Certificate: ${1}"
silent eval "openssl ca -batch -config `dirname ${CA_CERT_FILE}`/${CA_NAME}.conf -notext -in ${1%%.*}.csr -out ${1%%.*}.crt"
silent eval "openssl ca -batch -config $(dirname ${CA_CERT_FILE})/${CA_NAME}.conf -notext -in ${1%%.*}.csr -out ${1%%.*}.crt"
rm -rf $(tail -n 1 $(dirname ${CA_CERT_FILE})/certindex | awk '{print $3}').pem
rm -rf ${1%%.*}.csr
fi
@ -132,15 +141,15 @@ EOF
certificates_check_certificates() {
print_debug "Certificates: Checking Existence of ${1}"
if [ ! -f ${1} ] ; then
mkdir -p `dirname ${1}`
mkdir -p $(dirname ${1})
certificates_create_certificate ${1}
fi
}
certificates_trust_ca() {
if var_true $CREATE_CA ; then
if var_true "${CREATE_CA}" ; then
if [ -f ${CA_CERT_FILE} ]; then
if [ ! -L /usr/local/share/ca-certificates/`basename ${CA_CERT_FILE}` ] ; then
if [ ! -L /usr/local/share/ca-certificates/$(basename ${CA_CERT_FILE}) ] ; then
print_debug "Certificates: Trusting CA ${CA_NAME}"
ln -sf ${CA_CERT_FILE} /usr/local/share/ca-certificates/
silent update-ca-certificates
@ -161,7 +170,7 @@ EOF
check_clamav(){
print_debug "Checking Clam Antivirus"
if var_true $ENABLE_CLAMAV ; then
if var_true "${ENABLE_CLAMAV}" ; then
sanity_var CLAMAV_HOST "ClamAV Host"
COUNTER=0
while ! (silent nc -z ${CLAMAV_HOST} ${CLAMAV_PORT}) ; do
@ -172,9 +181,22 @@ check_clamav(){
fi
}
check_rspamd() {
print_debug "Checking RSpamD"
if var_true "${ENABLE_RSPAMD}" ; then
sanity_var RSPAMD_HOST "RSpamd Host"
COUNTER=0
while ! (silent nc -z ${RSPAMD_HOST} ${RSPAMD_PORT}) ; do
sleep 5
let COUNTER+=5
print_warn "RSpamD Host '${RSPAMD_HOST}' is not accessible, retrying.. ($COUNTER seconds so far)"
done
fi
}
check_spamassassin() {
print_debug "Checking Spamassassin"
if var_true $ENABLE_SPAMASSASSIN ; then
if var_true "${ENABLE_SPAMASSASSIN}" ; then
sanity_var SPAMASSASSIN_HOST "SpamAssassin Host"
COUNTER=0
while ! (silent nc -z ${SPAMASSASSIN_HOST} ${SPAMASSASSIN_PORT}) ; do
@ -185,35 +207,49 @@ check_spamassassin() {
fi
}
compile_assets() {
print_info "Compiling Assets"
cd /app/
silent sudo -HEu postal POSTAL_SKIP_CONFIG_CHECK=1 RAILS_GROUPS=assets bundle exec rake assets:precompile
silent sudo -HEu postal touch /app/public/assets/.prebuilt
}
custom_assets() {
if [ -d /assets/custom ] ; then
print_warn "Custom Assets Found, Copying over top of Master"
silent cp -R /assets/custom/* "/app/"
chown -R postal:postal /app/
fi
## Execute Custom Scripts
if [ -d /assets/custom-scripts/ ] ; then
print_warn "Found Custom Scripts to Execute"
for f in $(find /assets/custom-scripts/ -name \*.sh -type f); do
print_warn "Running Script ${f}"
chmod +x "${f}"
${f}
done
fi
}
configure_logging() {
print_debug "Configuring Logging"
mkdir -p ${LOG_LOCATION}
chown -R postal: ${LOG_LOCATION}
sed -i "s|<LOG_LOCATION>|${LOG_LOCATION}|g" /etc/logrotate.d/postal
}
configure_nginx(){
print_debug "Configuring Nginx"
sed -i "s|server_name localhost|server_name ${WEB_HOST}|g" /etc/nginx/conf.d/default.conf
if var_true "${ENABLE_TRACKING}" ; then
sed -i "s|<LISTEN_PORT>|${NGINX_LISTEN_PORT}|g" /etc/nginx/conf.available/tracking.conf
sed -i "s|<DNS_TRACK_DOMAIN>|${DNS_TRACK_DOMAIN}|g" /etc/nginx/conf.available/tracking.conf
if [ "${FAST_SERVER_BIND_IP}" = "0.0.0.0" ]; then
fast_server_bind_ip="127.0.0.1"
else
fast_server_bind_ip="${FAST_SERVER_BIND_IP}"
fi
sed -i "s|<FAST_SERVER_BIND_IP>|${fast_server_bind_ip}|g" /etc/nginx/conf.available/tracking.conf
sed -i "s|<FAST_SERVER_BIND_PORT>|${FAST_SERVER_BIND_PORT}|g" /etc/nginx/conf.available/tracking.conf
ln -s /etc/nginx/conf.available/tracking.conf /etc/nginx/conf.d/
mkdir -p "${LOG_PATH}"
chown -R postal: "${LOG_PATH}"
ln -sf "${LOG_PATH}" /app/log
create_logrotate postal-production ${LOG_PATH}/production.log none postal postal
if [ "${LOG_CONSOLE,,}" = "false" ] ; then
create_logrotate postal-cron ${LOG_PATH}/cron.log none postal postal
create_logrotate postal-requeuer ${LOG_PATH}/message_requeuer.log none postal postal
create_logrotate postal-puma-access ${LOG_PATH}/puma-access.log none postal postal
create_logrotate postal-puma-error ${LOG_PATH}/puma-error.log none postal postal
create_logrotate postal-smtp ${LOG_PATH}/smtp_server.log none postal postal
create_logrotate postal-worker ${LOG_PATH}/worker.log none postal postal
fi
}
configure_postal() {
silent /app/bin/postal initialize-config
### Create Configuration
### Create Configuration
if [ "$SETUP_TYPE" = "AUTO" ]; then
print_notice "Configuring Postal"
mx_array=$(echo $DNS_MX | tr "," "\n")
@ -225,8 +261,15 @@ configure_postal() {
EOF
)
done
print_debug "Writing Configuration to ${CONFIG_LOCATION}"
cat <<EOF > ${CONFIG_LOCATION}
if [ -z "${APP_SECRET}" ] ; then
rails_secret_key=$(openssl rand -hex 128 | tr -d '\n')
else
rails_secret_key=${APP_SECRET}
fi
print_debug "Writing Configuration to ${CONFIG_PATH}/${CONFIG_FILE}"
cat <<EOF > "${CONFIG_PATH}"/"${CONFIG_FILE}"
web:
host: ${WEB_HOST}
protocol: ${WEB_PROTOCOL}
@ -238,15 +281,8 @@ general:
maximum_hold_expiry_days: ${MAX_HOLD_EXPIRY_DAYS}
suppression_list_removal_delay: ${SUPPRESSION_LIST_EXPIRY}
use_local_ns_for_domains: false
fast_server:
enabled: ${ENABLE_FAST_SERVER}
bind_address: ${FAST_SERVER_BIND_ADDRESS}
port: ${FAST_SERVER_BIND_PORT}
ssl_port: ${FAST_SERVER_BIND_PORT_TLS}
proxy_protocol: ${FAST_SERVER_ENABLE_PROXY_PROTOCOL}
default_private_key_path: # Defaults to config/fast_server.key
default_tls_certificate_path: # Defaults to config/fast_server.cert
default_spam_threshold: ${SPAM_THRESHOLD}
default_spam_failure_threshold: ${SPAM_FAILURE_THRESHOLD}
web_server:
bind_address: ${WEB_BIND_IP}
@ -263,7 +299,7 @@ main_db:
logging:
stdout: ${LOG_CONSOLE}
root: ${LOG_LOCATION}
root: ${LOG_PATH}
max_log_file_size: ${LOG_SIZE_MAX}
message_db:
@ -286,6 +322,7 @@ workers:
smtp_server:
port: ${SMTP_SERVER_PORT}
bind_adress: '::'
tls_enabled: ${SMTP_SERVER_ENABLE_TLS}
tls_certificate_path: ${SMTP_SERVER_TLS_CERT}
tls_private_key_path: ${SMTP_SERVER_TLS_KEY}
@ -324,7 +361,7 @@ smtp:
rails:
environment: production
secret_key:
secret_key: ${rails_secret_key}
spamd:
enabled: ${ENABLE_SPAMASSASSIN}
@ -336,20 +373,27 @@ clamav:
host: ${CLAMAV_HOST}
port: ${CLAMAV_PORT}
rspamd:
enabled: ${ENABLE_RSPAMD}
host: ${RSPAMD_HOST}
port: ${RSPAMD_PORT}
ssl: ${RSPAMD_SSL}
password: ${RSPAMD_PASS}
flags: ${RSPAMD_FLAGS}
smtp_client:
open_timeout: ${SMTP_CLIENT_OPEN_TIMEOUT}
read_timeout: ${SMTP_CLIENT_READ_TIMEOUT}
EOF
fi
if [ "${CONFIG_LOCATION}" != "/app/config/postal.yml" ] ; then
ln -sf ${CONFIG_LOCATION} /app/config/postal.yml
fi
if var_true ${LOG_AUTH_FAILURE} ; then
gawk -i inplace '/535 Invalid credential/ && !x {print " log \"\\e[33m WARN: AUTH failure for #{@ip_address}\\e[0m\""; x=1} 1' /app/lib/postal/smtp_server/client.rb
fi
if [ "${CONFIG_PATH}"/"${CONFIG_FILE}" != "/app/config/postal.yml" ] ; then
ln -sf "${CONFIG_PATH}"/"${CONFIG_FILE}" /app/config/postal.yml
fi
if [ -f "${CONFIG_PATH}"/"${SIGNING_KEY_FILE}" ] && [ ! -f "/app/config/signing.key" ] ; then
ln -sf "${CONFIG_PATH}"/"${SIGNING_KEY_FILE}" /app/config/signing.key
fi
}
check_rabbitmq() {
@ -369,24 +413,25 @@ check_rabbitmq() {
configure_tls() {
print_debug "Configuring TLS"
if var_true $SMTP_SERVER_ENABLE_TLS ; then
if var_true "$SMTP_SERVER_ENABLE_TLS" ; then
certificates ${SMTP_SERVER_TLS_CERT}
fi
}
initialize_database() {
print_debug "Initializing Database"
silent /app/bin/postal initialize
cd /app/
silent sudo -HEu postal bundle exec rake db:create db:schema:load db:seed
mysql -uroot -p$DB_ROOT_PASS -h$DB_HOST -e 'GRANT ALL PRIVILEGES ON `'$DB_NAME'-%` . * to `'$DB_USER'`@`%` IDENTIFIED BY "'$DB_PASS'";'
print_notice "Creating Administrative User"
print_notice "Creating Administrative User"
if [ ! -n "${ADMIN_EMAIL}" ]; then
print_warn "No Admin Email entered, setting default email login to 'postal@example.com'"
ADMIN_EMAIL="postal@example.com"
fi
if [ ! -n "${ADMIN_PASS}" ]; then
print_warn "WARNING: No Admin Pass entered, setting default password to 'postal'"
ADMIN_PASS="postal"
print_warn "WARNING: No Admin Pass entered, setting default password to 'PostalMailServer'"
ADMIN_PASS="PostalMailServer"
fi
if [ ! -n "${ADMIN_FNAME}" ]; then
print_warn "No Admin First Name entered, setting default to 'Postal'"

View file

@ -7,10 +7,14 @@ sanity_db
db_ready mariadb
check_clamav
check_rabbitmq
check_rspamd
check_spamassassin
bootstrap
configure_logging
configure_tls
configure_postal
custom_assets
compile_assets
if [[ $(mysql -h ${DB_HOST} -u${DB_USER} -p${DB_PASS} -s --skip-column-names -e "SELECT COUNT(DISTINCT table_name) FROM information_schema.columns WHERE table_schema = '"$DB_NAME"'") == 0 ]]; then
print_warn "Detecting new Install. Initializing Database"
@ -20,7 +24,8 @@ if [[ $(mysql -h ${DB_HOST} -u${DB_USER} -p${DB_PASS} -s --skip-column-names -e
fi
initialize_database
else
silent /app/bin/postal upgrade
cd /app/
silent sudo -HEu postal bundle exec rake db:migrate
fi
chown -R postal: /app/

View file

@ -1,9 +0,0 @@
<FAIL2BAN_LOG_LOCATION>/*.log {
daily
ifempty
rotate 7
missingok
copytruncate
compress
dateext
}

View file

@ -1,9 +0,0 @@
<LOG_LOCATION>/*.log {
daily
ifempty
rotate 7
missingok
copytruncate
compress
dateext
}

View file

@ -1,21 +0,0 @@
server {
### Don't Touch This
listen <LISTEN_PORT>;
server_name ${DNS_TRACK_DOMAIN};
###
### Populate your custom directives here
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_pass http://<FAST_SERVER_BIND_ADDRESS>:<FAST_SERVER_BIND_PORT>;
}
### Don't edit past here
include /etc/nginx/nginx.conf.d/site_optimization.conf;
include /etc/nginx/nginx.conf.d/exploit_protection.conf;
}

View file

@ -1,31 +0,0 @@
server {
### Don't Touch This
listen <LISTEN_PORT>;
server_name localhost;
root <WEBROOT>;
###
### Populate your custom directives here
index index.html index.htm;
location / {
client_max_body_size 50M;
try_files $uri $uri/index.html $uri.html @puma;
}
location /assets {
add_header Cache-Control max-age=3600;
}
location @puma {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_pass http://127.0.0.1:5000;
}
### Don't edit past here
include /etc/nginx/nginx.conf.d/site_optimization.conf;
include /etc/nginx/nginx.conf.d/exploit_protection.conf;
}

View file

@ -13,5 +13,5 @@ if [ "$FAIL2BAN_LOG_TYPE" = "FILE" ] ; then
fi
sleep 180
print_info "Starting Fail2ban"
print_start "Starting Fail2ban"
${silent_arg} fail2ban-server -f

View file

@ -0,0 +1,17 @@
#!/usr/bin/with-contenv bash
source /assets/functions/00-container
prepare_service defaults 20-postal
PROCESS_NAME=postal-web
check_container_initialized
check_service_initialized init 20-postal
liftoff
if [ "${LOG_CONSOLE,,}" = "false" ]; then
log_redirect="--redirect-stdout ${LOG_PATH}/puma-access.log --redirect-stderr ${LOG_PATH}/puma-error.log"
fi
print_start "Starting postal ${POSTAL_VERSION} Web Server"
cd /app/
sudo -HEu postal bundle exec puma -C config/puma.rb ${log_redirect}

View file

@ -1,21 +0,0 @@
#!/usr/bin/with-contenv bash
source /assets/functions/00-container
prepare_service defaults single
check_container_initialized
check_service_initialized init
liftoff
if var_false $LOG_CONSOLE ; then
console="silent"
fi
print_info "Starting postal"
${console} /app/bin/postal start
while :
do
/app/bin/postal status
sleep 86400
done

View file

@ -0,0 +1,13 @@
#!/usr/bin/with-contenv bash
source /assets/functions/00-container
prepare_service defaults 20-postal
PROCESS_NAME=postal-smtp
check_container_initialized
check_service_initialized init 20-postal
liftoff
print_start "Starting postal ${POSTAL_VERSION} SMTP Server"
cd /app/
sudo -HEu postal bundle exec rake postal:smtp_server

View file

@ -0,0 +1,13 @@
#!/usr/bin/with-contenv bash
source /assets/functions/00-container
prepare_service defaults 20-postal
PROCESS_NAME=postal-worker
check_container_initialized
check_service_initialized init 20-postal
liftoff
print_start "Starting postal ${POSTAL_VERSION} Worker"
cd /app/
sudo -HEu postal bundle exec ruby script/worker.rb

View file

@ -0,0 +1,13 @@
#!/usr/bin/with-contenv bash
source /assets/functions/00-container
prepare_service defaults 20-postal
PROCESS_NAME=postal-cron
check_container_initialized
check_service_initialized init 20-postal
liftoff
print_start "Starting postal ${POSTAL_VERSION} Cron"
cd /app/
sudo -HEu postal bundle exec rake postal:cron

View file

@ -0,0 +1,13 @@
#!/usr/bin/with-contenv bash
source /assets/functions/00-container
prepare_service defaults 20-postal
PROCESS_NAME=postal-requeuer
check_container_initialized
check_service_initialized init 20-postal
liftoff
print_start "Starting postal ${POSTAL_VERSION} Requeuer"
cd /app/
sudo -HEu postal bundle exec rake postal:requeuer