From 6343c1e7aa86902a8146c088d78c57862fa119ca Mon Sep 17 00:00:00 2001 From: polpetta Date: Wed, 10 Nov 2021 14:32:56 +0000 Subject: [PATCH 1/2] chore: bump mail server to 10.2.0 (#7) chore: bump mail server to 10.2.0 Co-authored-by: Davide Polonio Reviewed-on: https://git.poldebra.me/polpetta/server-dotfiles/pulls/7 --- mail/docker-compose.yml | 2 +- mail/setup.sh | 450 ++++++++++++---------------------------- 2 files changed, 136 insertions(+), 316 deletions(-) diff --git a/mail/docker-compose.yml b/mail/docker-compose.yml index ea9441d..2668c6d 100644 --- a/mail/docker-compose.yml +++ b/mail/docker-compose.yml @@ -2,7 +2,7 @@ version: '3.7' services: mail: - image: mailserver/docker-mailserver:10.1.2 + image: mailserver/docker-mailserver:10.2.0 hostname: ${HOSTNAME} domainname: ${DOMAINNAME} container_name: ${CONTAINER_NAME} diff --git a/mail/setup.sh b/mail/setup.sh index 0cffd32..100ecc4 100755 --- a/mail/setup.sh +++ b/mail/setup.sh @@ -1,162 +1,62 @@ #! /bin/bash -# version v0.3.0 stable +# version v1.0.0 # executed manually / via Make # task wrapper for various setup scripts -SCRIPT='setup.sh' +CONFIG_PATH= +CONTAINER_NAME= +CRI= +DEFAULT_CONFIG_PATH= +DESIRED_CONFIG_PATH= +DIR="$(pwd)" +DMS_CONFIG='/tmp/docker-mailserver' +IMAGE_NAME= +INFO= +PODMAN_ROOTLESS=false +USE_SELINUX= +USE_TTY= +VOLUME= +RED="\e[31m\e[1m" WHITE="\e[37m" -RED="\e[31m" -PURPLE="\e[35m" -YELLOW="\e[93m" ORANGE="\e[38;5;214m" -CYAN="\e[96m" -BLUE="\e[34m" LBLUE="\e[94m" -BOLD="\e[1m" RESET="\e[0m" set -euEo pipefail -trap '__log_err "${FUNCNAME[0]:-?}" "${BASH_COMMAND:-?}" "${LINENO:-?}" "${?:-?}"' ERR +trap '__err "${BASH_SOURCE}" "${FUNCNAME[0]:-?}" "${BASH_COMMAND:-?}" "${LINENO:-?}" "${?:-?}"' ERR -function __log_err +function __err { - printf "\n--- ${BOLD}${RED}UNCHECKED ERROR${RESET}\n%s\n%s\n%s\n%s\n\n" \ - " - script = ${SCRIPT:-${0}}" \ - " - function = ${1} / ${2}" \ - " - line = ${3}" \ - " - exit code = ${4}" >&2 + [[ ${5} -gt 1 ]] && exit 1 - printf "Make sure you use a version of this script that matches -the version / tag of docker-mailserver. Please read the -'Get the tools' section in the README on GitHub careful- -ly and use ./setup.sh help and read the VERSION section.\n" >&2 + local ERR_MSG="\n--- ${RED}UNCHECKED ERROR${RESET}" + ERR_MSG+="\n - script = ${1}" + ERR_MSG+="\n - function = ${2}" + ERR_MSG+="\n - command = ${3}" + ERR_MSG+="\n - line = ${4}" + ERR_MSG+="\n - exit code = ${5}" + ERR_MSG+='\n\nThis should not have happened. Please file a bug report.\n' + + echo -e "${ERR_MSG}" } -function _get_absolute_script_directory -{ - if [[ "$(uname)" == "Darwin" ]] - then - readlink() { - greadlink "${@:+$@}" # Requires coreutils - } - fi - if dirname "$(readlink -f "${0}")" &>/dev/null - then - DIR="$(dirname "$(readlink -f "${0}")")" - elif realpath -e -L "${0}" &>/dev/null - then - DIR="$(realpath -e -L "${0}")" - DIR="${DIR%/setup.sh}" - fi -} - -DIR="$(pwd)" -_get_absolute_script_directory - -CRI= -CONFIG_PATH= -CONTAINER_NAME= -DEFAULT_CONFIG_PATH="${DIR}/config" -IMAGE_NAME= -INFO= -USE_CONTAINER=false -USE_TTY= -USE_SELINUX= -VOLUME= -WISHED_CONFIG_PATH= - -function _check_root -{ - if [[ ${EUID} -ne 0 ]] - then - echo "Curently docker-mailserver doesn't support podman's rootless mode, please run this script as root user." - exit 1 - fi -} - -function _update_config_path -{ - if [[ -n ${CONTAINER_NAME} ]] - then - VOLUME=$(${CRI} inspect "${CONTAINER_NAME}" \ - --format="{{range .Mounts}}{{ println .Source .Destination}}{{end}}" | \ - grep "/tmp/docker-mailserver$" 2>/dev/null) - fi - - if [[ -n ${VOLUME} ]] - then - CONFIG_PATH=$(echo "${VOLUME}" | awk '{print $1}') - fi -} - -function _inspect -{ - if _docker_image_exists "${IMAGE_NAME}" - then - echo "Image: ${IMAGE_NAME}" - else - echo "Image: '${IMAGE_NAME}' can’t be found." - fi - - if [[ -n ${CONTAINER_NAME} ]] - then - echo "Container: ${CONTAINER_NAME}" - echo "Config mount: ${CONFIG_PATH}" - else - echo "Container: Not running, please start docker-mailserver." - fi -} - -function _usage +function _show_local_usage { # shellcheck disable=SC2059 - printf "${PURPLE}SETUP${RED}(${YELLOW}1${RED}) - -${ORANGE}NAME${RESET} - ${SCRIPT:-${0}} - docker-mailserver administration script - -${ORANGE}SYNOPSIS${RESET} - ./${SCRIPT:-${0}} [ OPTIONS${RED}...${RESET} ] COMMAND [ help ${RED}|${RESET} ARGUMENTS${RED}...${RESET} ] - - COMMAND ${RED}:=${RESET} { email ${RED}|${RESET} alias ${RED}|${RESET} quota ${RED}|${RESET} config ${RED}|${RESET} relay ${RED}|${RESET} debug } SUBCOMMAND - -${ORANGE}DESCRIPTION${RESET} - This is the main administration script that you use for all interactions with your - mail server. Setup, configuration and much more is done with this script. - - Please note that the script executes most of the commands inside the container itself. - If the image was not found, this script will pull the ${WHITE}:latest${RESET} tag of - ${WHITE}mailserver/docker-mailserver${RESET}. This tag refers to the latest release, - see the tagging convention in the README under - ${BLUE}https://github.com/docker-mailserver/docker-mailserver/blob/master/README.md${RESET} - - You will be able to see detailed information about the script you're invoking and - its arguments by appending ${WHITE}help${RESET} after your command. Currently, this - does not work with all scripts. - -${ORANGE}VERSION${RESET} - The current version of this script is backwards compatible with versions of - ${WHITE}docker-mailserver${RESET} ${BOLD}after${RESET} ${BLUE}8.0.1${RESET}. In case that there is not a more recent release, - this script is currently only working with the ${WHITE}:edge${RESET} tag. - - You can download the script for your release by substituting TAG from the - following URL, where TAG looks like 'vX.X.X': - https://raw.githubusercontent.com/docker-mailserver/docker-mailserver/TAG/setup.sh - -${ORANGE}OPTIONS${RESET} + printf "${ORANGE}OPTIONS${RESET} ${LBLUE}Config path, container or image adjustments${RESET} -i IMAGE_NAME - Provides the name of the docker-mailserver image. The default value is - ${WHITE}docker.io/mailserver/docker-mailserver:latest${RESET} + Provides the name of the 'docker-mailserver' image. The default value is + '${WHITE}docker.io/mailserver/docker-mailserver:latest${RESET}' -c CONTAINER_NAME Provides the name of the running container. -p PATH - Provides the config folder path. The default is - ${WHITE}${DIR}/config/${RESET} + Provides the local path of the config folder to the temporary container instance. + Does not work if an existing a 'docker-mailserver' container is already running. ${LBLUE}SELinux${RESET} -z @@ -167,52 +67,16 @@ ${ORANGE}OPTIONS${RESET} Allows container access to the bind mount content that is private and unshared with other containers on a SELinux-enabled host. -${RED}[${ORANGE}SUB${RED}]${ORANGE}COMMANDS${RESET} - ${LBLUE}COMMAND${RESET} email ${RED}:=${RESET} - ${0} email ${CYAN}add${RESET} [] - ${0} email ${CYAN}update${RESET} [] - ${0} email ${CYAN}del${RESET} [ OPTIONS${RED}...${RESET} ] [ ${RED}...${RESET} ] - ${0} email ${CYAN}restrict${RESET} [] - ${0} email ${CYAN}list${RESET} + ${LBLUE}Podman${RESET} + -R + Accept running in Podman rootless mode. Ignored when using Docker / Docker Compose. - ${LBLUE}COMMAND${RESET} alias ${RED}:=${RESET} - ${0} alias ${CYAN}add${RESET} - ${0} alias ${CYAN}del${RESET} - ${0} alias ${CYAN}list${RESET} +" - ${LBLUE}COMMAND${RESET} quota ${RED}:=${RESET} - ${0} quota ${CYAN}set${RESET} [] - ${0} quota ${CYAN}del${RESET} + [[ ${1:-} == 'no-exit' ]] && return 0 - ${LBLUE}COMMAND${RESET} config ${RED}:=${RESET} - ${0} config ${CYAN}dkim${RESET} [ ARGUMENTS${RED}...${RESET} ] - - ${LBLUE}COMMAND${RESET} relay ${RED}:=${RESET} - ${0} relay ${CYAN}add-domain${RESET} [] - ${0} relay ${CYAN}add-auth${RESET} [] - ${0} relay ${CYAN}exclude-domain${RESET} - - ${LBLUE}COMMAND${RESET} debug ${RED}:=${RESET} - ${0} debug ${CYAN}fetchmail${RESET} - ${0} debug ${CYAN}fail2ban${RESET} [unban ] - ${0} debug ${CYAN}show-mail-logs${RESET} - ${0} debug ${CYAN}inspect${RESET} - ${0} debug ${CYAN}login${RESET} - -${ORANGE}EXAMPLES${RESET} - ${WHITE}./setup.sh email add test@domain.tld${RESET} - Add the email account ${WHITE}test@domain.tld${RESET}. You will be prompted - to input a password afterwards since no password was supplied. - - ${WHITE}./setup.sh config dkim keysize 2048 domain 'whoami.com,whoareyou.org'${RESET} - Creates keys of length 2048 but in an LDAP setup where domains are not known to - Postfix by default, so you need to provide them yourself in a comma-separated list. - - ${WHITE}./setup.sh config dkim help${RESET} - This will provide you with a detailed explanation on how to use the ${WHITE} - config dkim${RESET} command, showing what arguments can be passed and what they do. - -${ORANGE}EXIT STATUS${RESET} + # shellcheck disable=SC2059 + printf "${ORANGE}EXIT STATUS${RESET} Exit status is 0 if the command was successful. If there was an unexpected error, an error message is shown describing the error. In case of an error, the script will exit with exit status 1. @@ -220,63 +84,125 @@ ${ORANGE}EXIT STATUS${RESET} " } -function _docker_image_exists +function _get_absolute_script_directory { - ${CRI} history -q "${1}" &>/dev/null - return ${?} + if [[ "$(uname)" == 'Darwin' ]] + then + readlink() { + # requires coreutils + greadlink "${@:+$@}" + } + fi + + if dirname "$(readlink -f "${0}")" &>/dev/null + then + DIR="$(dirname "$(readlink -f "${0}")")" + elif realpath -e -L "${0}" &>/dev/null + then + DIR="$(realpath -e -L "${0}")" + DIR="${DIR%/setup.sh}" + fi + + DEFAULT_CONFIG_PATH="${DIR}/config" } -function _docker_image +function _handle_config_path { - if ${USE_CONTAINER} + if [[ -z ${DESIRED_CONFIG_PATH} ]] then - # reuse existing container specified on command line - ${CRI} exec "${USE_TTY}" "${CONTAINER_NAME}" "${@:+$@}" - else - # start temporary container with specified image - if ! _docker_image_exists "${IMAGE_NAME}" + # no desired config path + if [[ -n ${CONTAINER_NAME} ]] then - echo "Image '${IMAGE_NAME}' not found. Pulling ..." - ${CRI} pull "${IMAGE_NAME}" + VOLUME=$(${CRI} inspect "${CONTAINER_NAME}" \ + --format="{{range .Mounts}}{{ println .Source .Destination}}{{end}}" | \ + grep "${DMS_CONFIG}$" 2>/dev/null || :) fi - ${CRI} run --rm \ - -v "${CONFIG_PATH}:/tmp/docker-mailserver${USE_SELINUX}" \ - "${USE_TTY}" "${IMAGE_NAME}" "${@:+$@}" + if [[ -n ${VOLUME} ]] + then + CONFIG_PATH=$(echo "${VOLUME}" | awk '{print $1}') + fi + + if [[ -z ${CONFIG_PATH} ]] + then + CONFIG_PATH=${DEFAULT_CONFIG_PATH} + fi + else + CONFIG_PATH=${DESIRED_CONFIG_PATH} fi } -function _docker_container +function _run_in_new_container { - if [[ -n ${CONTAINER_NAME} ]] + # start temporary container with specified image + if ! ${CRI} history -q "${IMAGE_NAME}" &>/dev/null then - ${CRI} exec "${USE_TTY}" "${CONTAINER_NAME}" "${@:+$@}" - else - echo "The mailserver is not running!" - exit 1 + echo "Image '${IMAGE_NAME}' not found. Pulling ..." + ${CRI} pull "${IMAGE_NAME}" fi + + ${CRI} run --rm "${USE_TTY}" \ + -v "${CONFIG_PATH}:${DMS_CONFIG}${USE_SELINUX}" \ + "${IMAGE_NAME}" "${@:+$@}" } function _main { + _get_absolute_script_directory + + local OPTIND + while getopts ":c:i:p:zZR" OPT + do + case ${OPT} in + ( i ) IMAGE_NAME="${OPTARG}" ;; + ( z | Z ) USE_SELINUX=":${OPT}" ;; + ( c ) CONTAINER_NAME="${OPTARG}" ;; + ( R ) PODMAN_ROOTLESS=true ;; + ( p ) + case "${OPTARG}" in + ( /* ) DESIRED_CONFIG_PATH="${OPTARG}" ;; + ( * ) DESIRED_CONFIG_PATH="${DIR}/${OPTARG}" ;; + esac + + if [[ ! -d ${DESIRED_CONFIG_PATH} ]] + then + echo "Specified directory '${DESIRED_CONFIG_PATH}' doesn't exist" >&2 + exit 1 + fi + ;; + + ( * ) + echo "Invalid option: '-${OPTARG}'" >&2 + echo -e "Use './setup.sh help' to get a complete overview.\n" >&2 + _show_local_usage 'no-exit' + exit 1 + ;; + + esac + done + shift $(( OPTIND - 1 )) + if command -v docker &>/dev/null then CRI=docker elif command -v podman &>/dev/null then CRI=podman - _check_root + if ! ${PODMAN_ROOTLESS} && [[ ${EUID} -ne 0 ]] + then + read -r -p "You are running Podman in rootless mode. Continue? [Y/n] " + [[ -n ${REPLY} ]] && [[ ${REPLY} =~ (n|N) ]] && exit 0 + fi else - echo "No supported Container Runtime Interface detected." - exit 10 + echo 'No supported Container Runtime Interface detected.' + exit 1 fi INFO=$(${CRI} ps --no-trunc --format "{{.Image}};{{.Names}}" --filter \ label=org.opencontainers.image.title="docker-mailserver" | tail -1) - IMAGE_NAME=${INFO%;*} CONTAINER_NAME=${INFO#*;} - + [[ -z ${IMAGE_NAME} ]] && IMAGE_NAME=${INFO%;*} if [[ -z ${IMAGE_NAME} ]] then IMAGE_NAME=${NAME:-docker.io/mailserver/docker-mailserver:latest} @@ -284,7 +210,7 @@ function _main if test -t 0 then - USE_TTY="-ti" + USE_TTY="-it" else # GitHub Actions will fail (or really anything else # lacking an interactive tty) if we don't set a @@ -292,124 +218,18 @@ function _main USE_TTY="-t" fi - local OPTIND - while getopts ":c:i:p:hzZ" OPT - do - case ${OPT} in - i ) IMAGE_NAME="${OPTARG}" ;; - z ) USE_SELINUX=":z" ;; - Z ) USE_SELINUX=":Z" ;; - c ) - # container specified, connect to running instance - CONTAINER_NAME="${OPTARG}" - USE_CONTAINER=true - ;; + _handle_config_path - p ) - case "${OPTARG}" in - /* ) WISHED_CONFIG_PATH="${OPTARG}" ;; - * ) WISHED_CONFIG_PATH="${DIR}/${OPTARG}" ;; - esac - - if [[ ! -d ${WISHED_CONFIG_PATH} ]] - then - echo "Directory doesn't exist" - _usage - exit 40 - fi - ;; - - * ) - echo "Invalid option: -${OPT}" >&2 - ;; - - esac - done - - shift $(( OPTIND - 1 )) - - if [[ -z ${WISHED_CONFIG_PATH} ]] + if [[ -n ${CONTAINER_NAME} ]] then - # no wished config path - _update_config_path - - if [[ -z ${CONFIG_PATH} ]] - then - CONFIG_PATH=${DEFAULT_CONFIG_PATH} - fi + ${CRI} exec "${USE_TTY}" "${CONTAINER_NAME}" setup "${@:+$@}" else - CONFIG_PATH=${WISHED_CONFIG_PATH} + _run_in_new_container setup "${@:+$@}" fi + [[ ${1} == 'help' ]] && _show_local_usage - case ${1:-} in - - email ) - case ${2:-} in - add ) shift 2 ; _docker_image addmailuser "${@:+$@}" ;; - update ) shift 2 ; _docker_image updatemailuser "${@:+$@}" ;; - del ) shift 2 ; _docker_container delmailuser "${@:+$@}" ;; - restrict ) shift 2 ; _docker_container restrict-access "${@:+$@}" ;; - list ) _docker_container listmailuser ;; - * ) _usage ;; - esac - ;; - - alias ) - case ${2:-} in - add ) shift 2 ; _docker_image addalias "${1}" "${2}" ;; - del ) shift 2 ; _docker_image delalias "${1}" "${2}" ;; - list ) shift 2 ; _docker_image listalias ;; - * ) _usage ;; - esac - ;; - - quota ) - case ${2:-} in - set ) shift 2 ; _docker_image setquota "${@:+$@}" ;; - del ) shift 2 ; _docker_image delquota "${@:+$@}" ;; - * ) _usage ;; - esac - ;; - - config ) - case ${2:-} in - dkim ) shift 2 ; _docker_image open-dkim "${@:+$@}" ;; - * ) _usage ;; - esac - ;; - - relay ) - case ${2:-} in - add-domain ) shift 2 ; _docker_image addrelayhost "${@:+$@}" ;; - add-auth ) shift 2 ; _docker_image addsaslpassword "${@:+$@}" ;; - exclude-domain ) shift 2 ; _docker_image excluderelaydomain "${@:+$@}" ;; - * ) _usage ;; - esac - ;; - - debug ) - case ${2:-} in - fetchmail ) _docker_image debug-fetchmail ;; - fail2ban ) shift 2 ; _docker_container fail2ban "${@:+$@}" ;; - show-mail-logs ) _docker_container cat /var/log/mail/mail.log ;; - inspect ) _inspect ;; - login ) - shift 2 - if [[ -z ${1:-} ]] - then - _docker_container /bin/bash - else - _docker_container /bin/bash -c "${@:+$@}" - fi - ;; - * ) _usage ; exit 1 ;; - esac - ;; - - help ) _usage ;; - * ) _usage ; exit 1 ;; - esac + return 0 } _main "${@:+$@}" From 92f5124a5871f2b08601959e6dc8db9df20840c4 Mon Sep 17 00:00:00 2001 From: polpetta Date: Wed, 10 Nov 2021 14:38:02 +0000 Subject: [PATCH 2/2] feat(songlify): upgrade to 0.2.1 (#8) Merge branch 'master' into songlify-0.2.1 feat(songlify): upgrade to 0.2.1 Co-authored-by: Davide Polonio Reviewed-on: https://git.poldebra.me/polpetta/server-dotfiles/pulls/8 --- songlify/docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/songlify/docker-compose.yml b/songlify/docker-compose.yml index 7a6ebb2..f7fa23b 100644 --- a/songlify/docker-compose.yml +++ b/songlify/docker-compose.yml @@ -2,7 +2,7 @@ version: '3.7' services: bot: - image: polpetta/songlify:0.2.0 + image: polpetta/songlify:0.2.1 restart: always entrypoint: /usr/bin/songlify env_file: