fixing #1602; variable-brace-policy changed;

This commit is contained in:
Georg Lauterbach 2020-09-06 12:27:40 +02:00
parent 67e1e586c7
commit f7ca406ec9
No known key found for this signature in database
GPG key ID: 386D76E7AD496709
7 changed files with 169 additions and 169 deletions

View file

@ -119,21 +119,14 @@ var="bad"
##### braces ##### braces
We use braces in the following way: We always use braces.
``` BASH ``` BASH
# when it's clear and unambiguous,
# you do not have to use braces,
# but you might, see shellcheck SC2248
$VAR
# or
${VAR} ${VAR}
# when the variable is used
# in a bigger context
echo "/some/dir/${VAR}/to/destination/"
``` ```
If you forgot this and want to change it later, you can use [this link](https://regex101.com/r/ikzJpF/4), which points to <https://regex101.com>. The used regex is `\$([^{("\\'\/])([a-zA-Z0-9_]*)([^}\/ \t'"\n.\]:]*)`, where you should in practice be able to replace all variable occurrences without braces with occurrences with braces.
##### loops ##### loops
Like `if-else`, loops look like this Like `if-else`, loops look like this

View file

@ -161,14 +161,14 @@ clean:
sudo rm -rf test/config ;\ sudo rm -rf test/config ;\
mv testconfig.bak test/config ;\ mv testconfig.bak test/config ;\
fi fi
-@ sudo rm -rf test/onedir test/alias test/quota test/relay test/config/dovecot-lmtp/userdb test/config/key* test/config/opendkim/keys/domain.tld/ test/config/opendkim/keys/example.com/ test/config/opendkim/keys/localdomain2.com/ test/config/postfix-aliases.cf test/config/postfix-receive-access.cf test/config/postfix-receive-access.cfe test/config/dovecot-quotas.cf test/config/postfix-send-access.cf test/config/postfix-send-access.cfe test/config/relay-hosts/chksum test/config/relay-hosts/postfix-aliases.cf test/config/dhparams.pem test/config/dovecot-lmtp/dh.pem test/config/relay-hosts/dovecot-quotas.cf test/config/user-patches.sh -@ sudo rm -rf test/onedir test/alias test/quota test/relay test/config/dovecot-lmtp/userdb test/config/key* test/config/opendkim/keys/domain.tld/ test/config/opendkim/keys/example.com/ test/config/opendkim/keys/localdomain2.com/ test/config/postfix-aliases.cf test/config/postfix-receive-access.cf test/config/postfix-receive-access.cfe test/config/dovecot-quotas.cf test/config/postfix-send-access.cf test/config/postfix-send-access.cfe test/config/relay-hosts/chksum test/config/relay-hosts/postfix-aliases.cf test/config/dhparams.pem test/config/dovecot-lmtp/dh.pem test/config/relay-hosts/dovecot-quotas.cf test/config/user-patches.sh test/alias/config/postfix-virtual.cf test/quota/config/dovecot-quotas.cf test/quota/config/postfix-accounts.cf test/relay/config/postfix-relaymap.cf test/relay/config/postfix-sasl-password.cf
shellcheck: shellcheck:
@ echo -e "Testing shell / bash scripts with shellcheck\n" @ echo -e "Testing shell / bash scripts with shellcheck\n"
@ shellcheck --version @ shellcheck --version
@ echo '' @ echo ''
# currently without `start-mailserver` as this is to be merged separately # currently without `start-mailserver` as this is to be merged separately
@ if find -iname "*.sh" -not -path "./test/*" -not -path "./target/docker-configomat/*" -not -wholename ./target/start-mailserver.sh -exec shellcheck -S style -Cauto -e SC2250,SC2154,SC2248 -W 50 {} \; | grep .; then\ @ if find -iname "*.sh" -not -path "./test/*" -not -path "./target/docker-configomat/*" -not -wholename ./target/start-mailserver.sh -exec shellcheck -S style -Cauto -e SC2250,SC2154 -W 50 {} \; | grep .; then\
echo -e "\nError" ;\ echo -e "\nError" ;\
exit 1 ;\ exit 1 ;\
else\ else\

View file

@ -21,7 +21,7 @@ Easy to deploy and upgrade.
Why I created this image: [Simple mail server with Docker](http://tvi.al/simple-mail-server-with-docker/) Why I created this image: [Simple mail server with Docker](http://tvi.al/simple-mail-server-with-docker/)
## ANNOUNCEMENT ## Announcement
At this point we have merged the next branch based on Debian Buster into master. At this point we have merged the next branch based on Debian Buster into master.
That means the docker image latest uses Buster. The change may break things! That means the docker image latest uses Buster. The change may break things!
@ -144,8 +144,6 @@ If you got any problems with SPF and/or forwarding mails, give [SRS](https://git
#### For informational purposes #### For informational purposes
Your config folder will be mounted in `/tmp/docker-mailserver/`. To understand how things work on boot, please have a look at [start-mailserver.sh](https://github.com/tomav/docker-mailserver/blob/master/target/start-mailserver.sh)
`restart: always` ensures that the mail server container (and Filebeat/ELK containers when using the mail server together with ELK stack) is automatically restarted by Docker in cases like a Docker service or host restart or container exit. `restart: always` ensures that the mail server container (and Filebeat/ELK containers when using the mail server together with ELK stack) is automatically restarted by Docker in cases like a Docker service or host restart or container exit.
#### Exposed ports #### Exposed ports

181
setup.sh
View file

@ -4,11 +4,11 @@
# included in the docker-mailserver # included in the docker-mailserver
set -euEo pipefail set -euEo pipefail
trap '_report_err $_ $LINENO $?' ERR trap '_report_err ${_} ${LINENO} ${?}' ERR
function _report_err() function _report_err()
{ {
echo "ERROR occured :: source (hint) $1 ; line $2 ; exit code $3 ;;" >&2 echo "ERROR occured :: source ${1} ; line ${2} ; exit code ${3} ;;" >&2
_unset_vars _unset_vars
} }
@ -18,12 +18,24 @@ function _unset_vars()
unset USE_CONTAINER WISHED_CONFIG_PATH CONFIG_PATH VOLUME USE_TTY unset USE_CONTAINER WISHED_CONFIG_PATH CONFIG_PATH VOLUME USE_TTY
} }
CDIR="$(cd "$(dirname "$(readlink -f "$0")")" && pwd)" function _get_current_directory()
{
if dirname "$(readlink -f "${0}")" &>/dev/null
then
CDIR="$(cd "$(dirname "$(readlink -f "${0}")")" && pwd)"
elif realpath -e -L "${0}" &>/dev/null
then
CDIR="$(realpath -e -L "${0}")"
CDIR="${CDIR%/setup.sh}"
fi
}
CDIR="$(pwd)" ; _get_current_directory
CRI= CRI=
INFO= INFO=
IMAGE_NAME= IMAGE_NAME=
CONTAINER_NAME='mail' CONTAINER_NAME='mail'
DEFAULT_CONFIG_PATH="$CDIR/config" DEFAULT_CONFIG_PATH="${CDIR}/config"
USE_CONTAINER=false USE_CONTAINER=false
WISHED_CONFIG_PATH= WISHED_CONFIG_PATH=
CONFIG_PATH= CONFIG_PATH=
@ -32,7 +44,7 @@ USE_TTY=
function _check_root() function _check_root()
{ {
if [[ $EUID -ne 0 ]] if [[ ${EUID} -ne 0 ]]
then then
echo "Curently docker-mailserver doesn't support podman's rootless mode, please run this script as root user." echo "Curently docker-mailserver doesn't support podman's rootless mode, please run this script as root user."
return 1 return 1
@ -41,32 +53,32 @@ function _check_root()
function _update_config_path() function _update_config_path()
{ {
if [[ -n $CONTAINER_NAME ]] if [[ -n ${CONTAINER_NAME} ]]
then then
VOLUME=$(docker inspect "$CONTAINER_NAME" \ VOLUME=$(docker inspect "${CONTAINER_NAME}" \
--format="{{range .Mounts}}{{ println .Source .Destination}}{{end}}" | \ --format="{{range .Mounts}}{{ println .Source .Destination}}{{end}}" | \
grep "/tmp/docker-mailserver$" 2>/dev/null) grep "/tmp/docker-mailserver$" 2>/dev/null)
fi fi
if [[ -n $VOLUME ]] if [[ -n ${VOLUME} ]]
then then
CONFIG_PATH=$(echo "$VOLUME" | awk '{print $1}') CONFIG_PATH=$(echo "${VOLUME}" | awk '{print $1}')
fi fi
} }
function _inspect() function _inspect()
{ {
if _docker_image_exists "$IMAGE_NAME" if _docker_image_exists "${IMAGE_NAME}"
then then
echo "Image: $IMAGE_NAME" echo "Image: ${IMAGE_NAME}"
else else
echo "Image: '$IMAGE_NAME' cant be found." echo "Image: '${IMAGE_NAME}' cant be found."
fi fi
if [[ -n $CONTAINER_NAME ]] if [[ -n ${CONTAINER_NAME} ]]
then then
echo "Container: $CONTAINER_NAME" echo "Container: ${CONTAINER_NAME}"
echo "Config mount: $CONFIG_PATH" echo "Config mount: ${CONFIG_PATH}"
else else
echo "Container: Not running, please start docker-mailserver." echo "Container: Not running, please start docker-mailserver."
fi fi
@ -74,7 +86,7 @@ function _inspect()
function _usage() function _usage()
{ {
echo "Usage: $0 [-i IMAGE_NAME] [-c CONTAINER_NAME] <subcommand> <subcommand> [args] echo "Usage: ${0} [-i IMAGE_NAME] [-c CONTAINER_NAME] <subcommand> <subcommand> [args]
OPTIONS: OPTIONS:
@ -84,53 +96,52 @@ OPTIONS:
-c CONTAINER_NAME The name of the running container. -c CONTAINER_NAME The name of the running container.
-p PATH config folder path (default: $(pwd)/config) -p PATH config folder path (default: ${CDIR}/config)
SUBCOMMANDS: SUBCOMMANDS:
email: email:
$0 email add <email> [<password>] ${0} email add <email> [<password>]
$0 email update <email> [<password>] ${0} email update <email> [<password>]
$0 email del <email> ${0} email del <email>
$0 email restrict <add|del|list> <send|receive> [<email>] ${0} email restrict <add|del|list> <send|receive> [<email>]
$0 email list ${0} email list
alias: alias:
$0 alias add <email> <recipient> ${0} alias add <email> <recipient>
$0 alias del <email> <recipient> ${0} alias del <email> <recipient>
$0 alias list ${0} alias list
quota: quota:
$0 quota set <email> [<quota>] ${0} quota set <email> [<quota>]
$0 quota del <email> ${0} quota del <email>
config: config:
$0 config dkim <keysize> (default: 2048) ${0} config dkim <keysize> (default: 2048)
$0 config ssl <fqdn> ${0} config ssl <fqdn>
relay: relay:
$0 relay add-domain <domain> <host> [<port>] ${0} relay add-domain <domain> <host> [<port>]
$0 relay add-auth <domain> <username> [<password>] ${0} relay add-auth <domain> <username> [<password>]
$0 relay exclude-domain <domain> ${0} relay exclude-domain <domain>
debug: debug:
$0 debug fetchmail ${0} debug fetchmail
$0 debug fail2ban [<unban> <ip-address>] ${0} debug fail2ban [<unban> <ip-address>]
$0 debug show-mail-logs ${0} debug show-mail-logs
$0 debug inspect ${0} debug inspect
$0 debug login <commands> ${0} debug login <commands>
"
return 1 "
} }
function _docker_image_exists() function _docker_image_exists()
{ {
if $CRI history -q "$1" >/dev/null 2>&1 if ${CRI} history -q "${1}" >/dev/null 2>&1
then then
return 0 return 0
else else
@ -140,32 +151,32 @@ function _docker_image_exists()
function _docker_image() function _docker_image()
{ {
if $USE_CONTAINER if ${USE_CONTAINER}
then then
# reuse existing container specified on command line # reuse existing container specified on command line
$CRI exec "$USE_TTY" "$CONTAINER_NAME" "$@" ${CRI} exec "${USE_TTY}" "${CONTAINER_NAME}" "${@}"
else else
# start temporary container with specified image # start temporary container with specified image
if ! _docker_image_exists "$IMAGE_NAME" if ! _docker_image_exists "${IMAGE_NAME}"
then then
echo "Image '$IMAGE_NAME' not found. Pulling ..." echo "Image '${IMAGE_NAME}' not found. Pulling ..."
$CRI pull "$IMAGE_NAME" ${CRI} pull "${IMAGE_NAME}"
fi fi
${CRI} run --rm \ ${CRI} run --rm \
-v "$CONFIG_PATH":/tmp/docker-mailserver \ -v "${CONFIG_PATH}":/tmp/docker-mailserver \
"$USE_TTY" "$IMAGE_NAME" "$@" "${USE_TTY}" "${IMAGE_NAME}" "${@}"
fi fi
} }
function _docker_container() function _docker_container()
{ {
if [[ -n $CONTAINER_NAME ]] if [[ -n ${CONTAINER_NAME} ]]
then then
$CRI exec "$USE_TTY" "$CONTAINER_NAME" "$@" ${CRI} exec "${USE_TTY}" "${CONTAINER_NAME}" "${@}"
else else
echo "The docker-mailserver is not running!" echo "The docker-mailserver is not running!"
exit 1 exit 5
fi fi
} }
@ -183,7 +194,7 @@ function _main()
exit 10 exit 10
fi fi
INFO=$($CRI ps \ INFO=$(${CRI} ps \
--no-trunc \ --no-trunc \
--format "{{.Image}};{{.Names}}" \ --format "{{.Image}};{{.Names}}" \
--filter label=org.label-schema.name="docker-mailserver" | \ --filter label=org.label-schema.name="docker-mailserver" | \
@ -192,12 +203,12 @@ function _main()
IMAGE_NAME=${INFO%;*} IMAGE_NAME=${INFO%;*}
CONTAINER_NAME=${INFO#*;} CONTAINER_NAME=${INFO#*;}
if [[ -z $IMAGE_NAME ]] if [[ -z ${IMAGE_NAME} ]]
then then
if [[ $CRI == "docker" ]] if [[ ${CRI} == "docker" ]]
then then
IMAGE_NAME=tvial/docker-mailserver:latest IMAGE_NAME=tvial/docker-mailserver:latest
elif [[ $CRI == "podman" ]] elif [[ ${CRI} == "podman" ]]
then then
IMAGE_NAME=docker.io/tvial/docker-mailserver:latest IMAGE_NAME=docker.io/tvial/docker-mailserver:latest
fi fi
@ -211,38 +222,38 @@ function _main()
local OPTIND local OPTIND
while getopts ":c:i:p:" OPT while getopts ":c:i:p:" OPT
do do
case $OPT in case ${OPT} in
c) CONTAINER_NAME="$OPTARG" ; USE_CONTAINER=true ;; # container specified, connect to running instance c) CONTAINER_NAME="${OPTARG}" ; USE_CONTAINER=true ;; # container specified, connect to running instance
i) IMAGE_NAME="$OPTARG" ;; i) IMAGE_NAME="${OPTARG}" ;;
p) p)
case "$OPTARG" in case "${OPTARG}" in
/*) WISHED_CONFIG_PATH="$OPTARG" ;; /*) WISHED_CONFIG_PATH="${OPTARG}" ;;
* ) WISHED_CONFIG_PATH="$CDIR/$OPTARG" ;; * ) WISHED_CONFIG_PATH="${CDIR}/${OPTARG}" ;;
esac esac
if [[ ! -d $WISHED_CONFIG_PATH ]] if [[ ! -d ${WISHED_CONFIG_PATH} ]]
then then
echo "Directory doesn't exist" echo "Directory doesn't exist"
_usage _usage
exit 1 exit 40
fi fi
;; ;;
*) echo "Invalid option: -$OPTARG" >&2 ;; *) echo "Invalid option: -${OPTARG}" >&2 ;;
esac esac
done done
shift $((OPTIND-1)) shift $((OPTIND-1))
if [[ -z $WISHED_CONFIG_PATH ]] if [[ -z ${WISHED_CONFIG_PATH} ]]
then then
# no wished config path # no wished config path
_update_config_path _update_config_path
if [[ -z $CONFIG_PATH ]] if [[ -z ${CONFIG_PATH} ]]
then then
CONFIG_PATH=$DEFAULT_CONFIG_PATH CONFIG_PATH=${DEFAULT_CONFIG_PATH}
fi fi
else else
CONFIG_PATH=$WISHED_CONFIG_PATH CONFIG_PATH=${WISHED_CONFIG_PATH}
fi fi
@ -250,10 +261,10 @@ function _main()
email) email)
shift ; case ${1:-} in shift ; case ${1:-} in
add ) shift ; _docker_image addmailuser "$@" ;; add ) shift ; _docker_image addmailuser "${@}" ;;
update ) shift ; _docker_image updatemailuser "$@" ;; update ) shift ; _docker_image updatemailuser "${@}" ;;
del ) shift ; _docker_image delmailuser "$@" ;; del ) shift ; _docker_image delmailuser "${@}" ;;
restrict ) shift ; _docker_container restrict-access "$@" ;; restrict ) shift ; _docker_container restrict-access "${@}" ;;
list ) _docker_image listmailuser ;; list ) _docker_image listmailuser ;;
* ) _usage ;; * ) _usage ;;
esac esac
@ -261,17 +272,17 @@ function _main()
alias) alias)
shift ; case ${1:-} in shift ; case ${1:-} in
add ) shift ; _docker_image addalias "$@" ;; add ) shift ; _docker_image addalias "${@}" ;;
del ) shift ; _docker_image delalias "$@" ;; del ) shift ; _docker_image delalias "${@}" ;;
list ) shift ; _docker_image listalias "$@" ;; list ) shift ; _docker_image listalias "${@}" ;;
* ) _usage ;; * ) _usage ;;
esac esac
;; ;;
quota) quota)
shift ; case ${1:-} in shift ; case ${1:-} in
set ) shift ; _docker_image setquota "$@" ;; set ) shift ; _docker_image setquota "${@}" ;;
del ) shift ; _docker_image delquota "$@" ;; del ) shift ; _docker_image delquota "${@}" ;;
* ) _usage ;; * ) _usage ;;
esac esac
;; ;;
@ -279,16 +290,16 @@ function _main()
config) config)
shift ; case ${1:-} in shift ; case ${1:-} in
dkim ) _docker_image generate-dkim-config "${2:-2048}" ;; dkim ) _docker_image generate-dkim-config "${2:-2048}" ;;
ssl ) _docker_image generate-ssl-certificate "$2" ;; ssl ) _docker_image generate-ssl-certificate "${2}" ;;
* ) _usage ;; * ) _usage ;;
esac esac
;; ;;
relay) relay)
shift ; case ${1:-} in shift ; case ${1:-} in
add-domain ) shift ; _docker_image addrelayhost "$@" ;; add-domain ) shift ; _docker_image addrelayhost "${@}" ;;
add-auth ) shift ; _docker_image addsaslpassword "$@" ;; add-auth ) shift ; _docker_image addsaslpassword "${@}" ;;
exclude-domain ) shift ; _docker_image excluderelaydomain "$@" ;; exclude-domain ) shift ; _docker_image excluderelaydomain "${@}" ;;
* ) _usage ;; * ) _usage ;;
esac esac
;; ;;
@ -296,7 +307,7 @@ function _main()
debug) debug)
shift ; case ${1:-} in shift ; case ${1:-} in
fetchmail ) _docker_image debug-fetchmail ;; fetchmail ) _docker_image debug-fetchmail ;;
fail2ban ) shift ; _docker_container fail2ban "$@" ;; fail2ban ) shift ; _docker_container fail2ban "${@}" ;;
show-mail-logs ) _docker_container cat /var/log/mail/mail.log ;; show-mail-logs ) _docker_container cat /var/log/mail/mail.log ;;
inspect ) _inspect ;; inspect ) _inspect ;;
login ) login )
@ -305,16 +316,16 @@ function _main()
then then
_docker_container /bin/bash _docker_container /bin/bash
else else
_docker_container /bin/bash -c "$@" _docker_container /bin/bash -c "${@}"
fi fi
;; ;;
* ) _usage ;; * ) _usage ; exit 1 ;;
esac esac
;; ;;
* ) _usage ;; * ) _usage ; exit 1 ;;
esac esac
} }
_main "$@" _main "${@}"
_unset_vars _unset_vars

View file

@ -8,7 +8,7 @@
. /usr/local/bin/helper_functions.sh . /usr/local/bin/helper_functions.sh
LOG_DATE=$(date +"%Y-%m-%d %H:%M:%S ") LOG_DATE=$(date +"%Y-%m-%d %H:%M:%S ")
echo "$LOG_DATE Start check-for-changes script." echo "${LOG_DATE} Start check-for-changes script."
# ? Checks ------------------------------------------------ # ? Checks ------------------------------------------------
@ -17,14 +17,14 @@ cd /tmp/docker-mailserver || exit 1
# Check postfix-accounts.cf exist else break # Check postfix-accounts.cf exist else break
if [[ ! -f postfix-accounts.cf ]] if [[ ! -f postfix-accounts.cf ]]
then then
echo "$LOG_DATE postfix-accounts.cf is missing! This should not run! Exit!" echo "${LOG_DATE} postfix-accounts.cf is missing! This should not run! Exit!"
exit exit
fi fi
# Verify checksum file exists; must be prepared by start-mailserver.sh # Verify checksum file exists; must be prepared by start-mailserver.sh
if [[ ! -f $CHKSUM_FILE ]] if [[ ! -f ${CHKSUM_FILE} ]]
then then
echo "$LOG_DATE $CHKSUM_FILE is missing! Start script failed? Exit!" echo "${LOG_DATE} ${CHKSUM_FILE} is missing! Start script failed? Exit!"
exit exit
fi fi
@ -32,14 +32,14 @@ fi
# Determine postmaster address, duplicated from start-mailserver.sh # Determine postmaster address, duplicated from start-mailserver.sh
# This script previously didn't work when POSTMASTER_ADDRESS was empty # This script previously didn't work when POSTMASTER_ADDRESS was empty
if [[ -n $OVERRIDE_HOSTNAME ]] if [[ -n ${OVERRIDE_HOSTNAME} ]]
then then
DOMAINNAME="${OVERRIDE_HOSTNAME#*.}" DOMAINNAME="${OVERRIDE_HOSTNAME#*.}"
else else
DOMAINNAME="$(hostname -d)" DOMAINNAME="$(hostname -d)"
fi fi
PM_ADDRESS="${POSTMASTER_ADDRESS:=postmaster@${DOMAINNAME}}" PM_ADDRESS="${POSTMASTER_ADDRESS:=postmaster@${DOMAINNAME}}"
echo "$LOG_DATE Using postmaster address $PM_ADDRESS" echo "${LOG_DATE} Using postmaster address ${PM_ADDRESS}"
sleep 10 sleep 10
while true while true
@ -49,32 +49,32 @@ do
# get chksum and check it, no need to lock config yet # get chksum and check it, no need to lock config yet
_monitored_files_checksums >"${CHKSUM_FILE}.new" _monitored_files_checksums >"${CHKSUM_FILE}.new"
if ! cmp --silent -- "$CHKSUM_FILE" "$CHKSUM_FILE.new" if ! cmp --silent -- "${CHKSUM_FILE}" "${CHKSUM_FILE}.new"
then then
echo "${LOG_DATE} Change detected" echo "${LOG_DATE} Change detected"
changed=$(grep -Fxvf "$CHKSUM_FILE" "$CHKSUM_FILE.new" | sed 's/^[^ ]\+ //') changed=$(grep -Fxvf "${CHKSUM_FILE}" "${CHKSUM_FILE}.new" | sed 's/^[^ ]\+ //')
mv "$CHKSUM_FILE.new" "$CHKSUM_FILE" mv "${CHKSUM_FILE}.new" "${CHKSUM_FILE}"
# Bug alert! This overwrites the alias set by start-mailserver.sh # Bug alert! This overwrites the alias set by start-mailserver.sh
# Take care that changes in one script are propagated to the other # Take care that changes in one script are propagated to the other
# ! NEEDS FIX ----------------------------------------- # ! NEEDS FIX -----------------------------------------
# TODO FIX -------------------------------------------- # TODO FIX --------------------------------------------
# ! NEEDS EXTENSIONS ---------------------------- # ! NEEDS EXTENSIONS ----------------------------------
# TODO Perform updates below conditionally too -- # TODO Perform updates below conditionally too --------
# Also note that changes are performed in place and are not atomic # Also note that changes are performed in place and are not atomic
# We should fix that and write to temporary files, stop, swap and start # We should fix that and write to temporary files, stop, swap and start
# Lock configuration while working # Lock configuration while working
( (
flock -e 200 flock -e 200
for file in $changed for file in ${changed}
do do
case $file in case ${file} in
/etc/letsencrypt/acme.json) /etc/letsencrypt/acme.json)
for certdomain in $SSL_DOMAIN $HOSTNAME $DOMAINNAME for certdomain in ${SSL_DOMAIN} ${HOSTNAME} ${DOMAINNAME}
do do
if _extract_certs_from_acme "$certdomain" if _extract_certs_from_acme "${certdomain}"
then then
break break
fi fi
@ -96,7 +96,7 @@ do
echo -n >/etc/postfix/vmailbox echo -n >/etc/postfix/vmailbox
echo -n >/etc/dovecot/userdb echo -n >/etc/dovecot/userdb
if [[ -f /tmp/docker-mailserver/postfix-accounts.cf ]] && [[ $ENABLE_LDAP -ne 1 ]] if [[ -f /tmp/docker-mailserver/postfix-accounts.cf ]] && [[ ${ENABLE_LDAP} -ne 1 ]]
then then
sed -i 's/\r//g' /tmp/docker-mailserver/postfix-accounts.cf sed -i 's/\r//g' /tmp/docker-mailserver/postfix-accounts.cf
echo "# WARNING: this file is auto-generated. Modify config/postfix-accounts.cf to edit user list." >/etc/postfix/vmailbox echo "# WARNING: this file is auto-generated. Modify config/postfix-accounts.cf to edit user list." >/etc/postfix/vmailbox
@ -110,13 +110,13 @@ do
sed -i -e '/\!include auth-passwdfile\.inc/s/^#//' /etc/dovecot/conf.d/10-auth.conf sed -i -e '/\!include auth-passwdfile\.inc/s/^#//' /etc/dovecot/conf.d/10-auth.conf
# rebuild relay host # rebuild relay host
if [[ -n $RELAY_HOST ]] if [[ -n ${RELAY_HOST} ]]
then then
# keep old config # keep old config
echo -n >/etc/postfix/sasl_passwd echo -n >/etc/postfix/sasl_passwd
if [[ -n $SASL_PASSWD ]] if [[ -n ${SASL_PASSWD} ]]
then then
echo "$SASL_PASSWD" >>/etc/postfix/sasl_passwd echo "${SASL_PASSWD}" >>/etc/postfix/sasl_passwd
fi fi
# add domain-specific auth from config file # add domain-specific auth from config file
@ -124,17 +124,17 @@ do
then then
(grep -v "^\s*$\|^\s*\#" /tmp/docker-mailserver/postfix-sasl-password.cf || true) | while read -r line (grep -v "^\s*$\|^\s*\#" /tmp/docker-mailserver/postfix-sasl-password.cf || true) | while read -r line
do do
if ! echo "$line" | grep -q -e "\s*#" if ! echo "${line}" | grep -q -e "\s*#"
then then
echo "$line" >>/etc/postfix/sasl_passwd echo "${line}" >>/etc/postfix/sasl_passwd
fi fi
done done
fi fi
# add default relay # add default relay
if [[ -n "$RELAY_USER" ]] && [[ -n "$RELAY_PASSWORD" ]] if [[ -n "${RELAY_USER}" ]] && [[ -n "${RELAY_PASSWORD}" ]]
then then
echo "[$RELAY_HOST]:$RELAY_PORT $RELAY_USER:$RELAY_PASSWORD" >>/etc/postfix/sasl_passwd echo "[${RELAY_HOST}]:${RELAY_PORT} ${RELAY_USER}:${RELAY_PASSWORD}" >>/etc/postfix/sasl_passwd
fi fi
fi fi
@ -142,8 +142,8 @@ do
# comments and empty lines are ignored # comments and empty lines are ignored
grep -v "^\s*$\|^\s*\#" /tmp/docker-mailserver/postfix-accounts.cf | while IFS=$'|' read -r login pass grep -v "^\s*$\|^\s*\#" /tmp/docker-mailserver/postfix-accounts.cf | while IFS=$'|' read -r login pass
do do
user=$(echo "$login" | cut -d @ -f1) user=$(echo "${login}" | cut -d @ -f1)
domain=$(echo "$login" | cut -d @ -f2) domain=$(echo "${login}" | cut -d @ -f2)
user_attributes="" user_attributes=""
# test if user has a defined quota # test if user has a defined quota
@ -156,7 +156,7 @@ do
[[ ${#user_quota[@]} -eq 2 ]] && user_attributes="${user_attributes}userdb_quota_rule=*:bytes=${user_quota[1]}" [[ ${#user_quota[@]} -eq 2 ]] && user_attributes="${user_attributes}userdb_quota_rule=*:bytes=${user_quota[1]}"
fi fi
echo "$login ${domain}/${user}/" >>/etc/postfix/vmailbox echo "${login} ${domain}/${user}/" >>/etc/postfix/vmailbox
# user database for dovecot has the following format: # user database for dovecot has the following format:
# user:password:uid:gid:(gecos):home:(shell):extra_fields # user:password:uid:gid:(gecos):home:(shell):extra_fields
@ -170,11 +170,11 @@ do
cp "/tmp/docker-mailserver/${login}.dovecot.sieve" "/var/mail/${domain}/${user}/.dovecot.sieve" cp "/tmp/docker-mailserver/${login}.dovecot.sieve" "/var/mail/${domain}/${user}/.dovecot.sieve"
fi fi
echo "$domain" >>/tmp/vhost.tmp echo "${domain}" >>/tmp/vhost.tmp
done done
fi fi
[[ -n $RELAY_HOST ]] && _populate_relayhost_map [[ -n ${RELAY_HOST} ]] && _populate_relayhost_map
if [[ -f /etc/postfix/sasl_passwd ]] if [[ -f /etc/postfix/sasl_passwd ]]
@ -197,11 +197,11 @@ do
# shellcheck disable=SC2034 # shellcheck disable=SC2034
(grep -v "^\s*$\|^\s*\#" /tmp/docker-mailserver/postfix-virtual.cf || true) | while read -r from to (grep -v "^\s*$\|^\s*\#" /tmp/docker-mailserver/postfix-virtual.cf || true) | while read -r from to
do do
uname=$(echo "$from" | cut -d @ -f1) uname=$(echo "${from}" | cut -d @ -f1)
domain=$(echo "$from" | cut -d @ -f2) domain=$(echo "${from}" | cut -d @ -f2)
# if they are equal it means the line looks like: "user1 other@domain.tld" # if they are equal it means the line looks like: "user1 other@domain.tld"
[ "$uname" != "$domain" ] && echo "$domain" >>/tmp/vhost.tmp [ "${uname}" != "${domain}" ] && echo "${domain}" >>/tmp/vhost.tmp
done done
fi fi
@ -229,7 +229,7 @@ s/$/ regexp:\/etc\/postfix\/regexp/
supervisorctl restart postfix supervisorctl restart postfix
# prevent restart of dovecot when smtp_only=1 # prevent restart of dovecot when smtp_only=1
[[ $SMTP_ONLY -ne 1 ]] && supervisorctl restart dovecot [[ ${SMTP_ONLY} -ne 1 ]] && supervisorctl restart dovecot
) 200<postfix-accounts.cf # end lock ) 200<postfix-accounts.cf # end lock
fi fi

View file

@ -18,13 +18,13 @@ function _mask_ip_digit()
MASK=0 MASK=0
else else
VALUES=(0 128 192 224 240 248 252 254 255) VALUES=(0 128 192 224 240 248 252 254 255)
MASK=${VALUES[$1]} MASK=${VALUES[${1}]}
fi fi
local DVAL=${2} local DVAL=${2}
((DVAL&=MASK)) ((DVAL&=MASK))
echo "$DVAL" echo "${DVAL}"
} }
# Transforms a specific IP with CIDR suffix # Transforms a specific IP with CIDR suffix
@ -35,15 +35,13 @@ function _sanitize_ipv4_to_subnet_cidr()
{ {
local DIGIT_PREFIX_LENGTH="${1#*/}" local DIGIT_PREFIX_LENGTH="${1#*/}"
declare -a DIGITS
IFS='.' ; read -r -a DIGITS < <(echo "${1%%/*}")
unset IFS
declare -a MASKED_DIGITS declare -a MASKED_DIGITS
declare -a DIGITS
IFS='.' ; read -r -a DIGITS < <(echo "${1%%/*}") ; unset IFS
for ((i = 0 ; i < 4 ; i++)) for ((i = 0 ; i < 4 ; i++))
do do
MASKED_DIGITS[i]=$(_mask_ip_digit "$DIGIT_PREFIX_LENGTH" "${DIGITS[i]}") MASKED_DIGITS[i]=$(_mask_ip_digit "${DIGIT_PREFIX_LENGTH}" "${DIGITS[i]}")
DIGIT_PREFIX_LENGTH=$((DIGIT_PREFIX_LENGTH - 8)) DIGIT_PREFIX_LENGTH=$((DIGIT_PREFIX_LENGTH - 8))
done done
@ -66,7 +64,7 @@ for key, value in acme.items():
certs = value['Certificates'] certs = value['Certificates']
for cert in certs: for cert in certs:
if 'domain' in cert and 'key' in cert: if 'domain' in cert and 'key' in cert:
if 'main' in cert['domain'] and cert['domain']['main'] == '$1' or 'sans' in cert['domain'] and '$1' in cert['domain']['sans']: if 'main' in cert['domain'] and cert['domain']['main'] == '${1}' or 'sans' in cert['domain'] and '${1}' in cert['domain']['sans']:
print cert['key'] print cert['key']
break break
") ")
@ -80,7 +78,7 @@ for key, value in acme.items():
certs = value['Certificates'] certs = value['Certificates']
for cert in certs: for cert in certs:
if 'domain' in cert and 'certificate' in cert: if 'domain' in cert and 'certificate' in cert:
if 'main' in cert['domain'] and cert['domain']['main'] == '$1' or 'sans' in cert['domain'] and '$1' in cert['domain']['sans']: if 'main' in cert['domain'] and cert['domain']['main'] == '${1}' or 'sans' in cert['domain'] and '${1}' in cert['domain']['sans']:
print cert['certificate'] print cert['certificate']
break break
") ")
@ -89,9 +87,9 @@ for key, value in acme.items():
then then
mkdir -p "/etc/letsencrypt/live/${HOSTNAME}/" mkdir -p "/etc/letsencrypt/live/${HOSTNAME}/"
echo "$KEY" | base64 -d >/etc/letsencrypt/live/"$HOSTNAME"/key.pem || exit 1 echo "${KEY}" | base64 -d >/etc/letsencrypt/live/"${HOSTNAME}"/key.pem || exit 1
echo "$CERT" | base64 -d >/etc/letsencrypt/live/"$HOSTNAME"/fullchain.pem || exit 1 echo "${CERT}" | base64 -d >/etc/letsencrypt/live/"${HOSTNAME}"/fullchain.pem || exit 1
echo "Cert found in /etc/letsencrypt/acme.json for $1" echo "Cert found in /etc/letsencrypt/acme.json for ${1}"
return 0 return 0
else else
@ -116,9 +114,9 @@ function _notify()
c_bold="\033[1m" c_bold="\033[1m"
c_reset="\e[0m" c_reset="\e[0m"
notification_type=$1 notification_type=${1}
notification_msg=$2 notification_msg=${2}
notification_format=$3 notification_format=${3}
msg="" msg=""
case "${notification_type}" in case "${notification_type}" in
@ -147,7 +145,7 @@ function _notify()
* ) options="-e" ;; * ) options="-e" ;;
esac esac
[[ -n "${msg}" ]] && echo $options "${msg}" [[ -n "${msg}" ]] && echo ${options} "${msg}"
} }
export -f _notify export -f _notify
@ -184,7 +182,7 @@ function _populate_relayhost_map()
if ! grep -q -e "^@${domain}\b" /etc/postfix/relayhost_map && ! grep -qs -e "^\s*@${domain}\s*$" /tmp/docker-mailserver/postfix-relaymap.cf if ! grep -q -e "^@${domain}\b" /etc/postfix/relayhost_map && ! grep -qs -e "^\s*@${domain}\s*$" /tmp/docker-mailserver/postfix-relaymap.cf
then then
_notify 'inf' "Adding relay mapping for ${domain}" _notify 'inf' "Adding relay mapping for ${domain}"
echo "@${domain} [$RELAY_HOST]:$RELAY_PORT" >> /etc/postfix/relayhost_map echo "@${domain} [${RELAY_HOST}]:${RELAY_PORT}" >> /etc/postfix/relayhost_map
fi fi
done done
} }
@ -209,8 +207,8 @@ function _monitored_files_checksums()
postfix-aliases.cf \ postfix-aliases.cf \
dovecot-quotas.cf \ dovecot-quotas.cf \
/etc/letsencrypt/acme.json \ /etc/letsencrypt/acme.json \
"/etc/letsencrypt/live/$HOSTNAME/key.pem" \ "/etc/letsencrypt/live/${HOSTNAME}/key.pem" \
"/etc/letsencrypt/live/$HOSTNAME/fullchain.pem" "/etc/letsencrypt/live/${HOSTNAME}/fullchain.pem"
) )
} }
export -f _monitored_files_checksums export -f _monitored_files_checksums

View file

@ -2,20 +2,20 @@
# version 0.1.0 # version 0.1.0
function generate_secret() function _generate_secret()
{ {
( umask 0077 ; dd if=/dev/urandom bs=24 count=1 2>/dev/null | base64 -w0 > "$1" ) ( umask 0077 ; dd if=/dev/urandom bs=24 count=1 2>/dev/null | base64 -w0 > "${1}" )
} }
if [[ -n $SRS_DOMAINNAME ]] if [[ -n ${SRS_DOMAINNAME} ]]
then then
NEW_DOMAIN_NAME="$SRS_DOMAINNAME" NEW_DOMAIN_NAME="${SRS_DOMAINNAME}"
elif [[ -n $OVERRIDE_HOSTNAME ]] elif [[ -n ${OVERRIDE_HOSTNAME} ]]
then then
NEW_DOMAIN_NAME="${OVERRIDE_HOSTNAME#*.}" NEW_DOMAIN_NAME="${OVERRIDE_HOSTNAME#*.}"
elif [[ -n $DOMAINNAME ]] elif [[ -n ${DOMAINNAME} ]]
then then
NEW_DOMAIN_NAME="$DOMAINNAME" NEW_DOMAIN_NAME="${DOMAINNAME}"
else else
NEW_DOMAIN_NAME=$(hostname -d) NEW_DOMAIN_NAME=$(hostname -d)
fi fi
@ -26,28 +26,28 @@ POSTSRSD_SECRET_FILE='/etc/postsrsd.secret'
POSTSRSD_STATE_DIR='/var/mail-state/etc-postsrsd' POSTSRSD_STATE_DIR='/var/mail-state/etc-postsrsd'
POSTSRSD_STATE_SECRET_FILE="${POSTSRSD_STATE_DIR}/postsrsd.secret" POSTSRSD_STATE_SECRET_FILE="${POSTSRSD_STATE_DIR}/postsrsd.secret"
if [[ -n $SRS_SECRET ]] if [[ -n ${SRS_SECRET} ]]
then then
( umask 0077 ; echo "$SRS_SECRET" | tr ',' '\n' > "$POSTSRSD_SECRET_FILE" ) ( umask 0077 ; echo "${SRS_SECRET}" | tr ',' '\n' > "${POSTSRSD_SECRET_FILE}" )
else else
if [[ $ONE_DIR -eq 1 ]] if [[ ${ONE_DIR} -eq 1 ]]
then then
if [[ ! -f $POSTSRSD_STATE_SECRET_FILE ]] if [[ ! -f ${POSTSRSD_STATE_SECRET_FILE} ]]
then then
install -d -m 0775 "$POSTSRSD_STATE_DIR" install -d -m 0775 "${POSTSRSD_STATE_DIR}"
generate_secret "$POSTSRSD_STATE_SECRET_FILE" _generate_secret "${POSTSRSD_STATE_SECRET_FILE}"
fi fi
install -m 0400 "$POSTSRSD_STATE_SECRET_FILE" "$POSTSRSD_SECRET_FILE" install -m 0400 "${POSTSRSD_STATE_SECRET_FILE}" "${POSTSRSD_SECRET_FILE}"
elif [[ ! -f $POSTSRSD_SECRET_FILE ]] elif [[ ! -f ${POSTSRSD_SECRET_FILE} ]]
then then
generate_secret "$POSTSRSD_SECRET_FILE" _generate_secret "${POSTSRSD_SECRET_FILE}"
fi fi
fi fi
if [[ -n $SRS_EXCLUDE_DOMAINS ]] if [[ -n ${SRS_EXCLUDE_DOMAINS} ]]
then then
sed -i -e "s/^#\?SRS_EXCLUDE_DOMAINS=.*$/SRS_EXCLUDE_DOMAINS=$SRS_EXCLUDE_DOMAINS/g" /etc/default/postsrsd sed -i -e "s/^#\?SRS_EXCLUDE_DOMAINS=.*$/SRS_EXCLUDE_DOMAINS=${SRS_EXCLUDE_DOMAINS}/g" /etc/default/postsrsd
fi fi
/etc/init.d/postsrsd start /etc/init.d/postsrsd start