| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384 |
- #!/usr/bin/env bash
- set -euo pipefail
- project_dir="${MAILHUB_PROJECT_DIR:-$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd -P)}"
- data_dir="${MAILHUB_DATA_DIR:-${project_dir}/data}"
- fail() {
- echo "Dovecot preparation failed: $*" >&2
- exit 1
- }
- command -v openssl >/dev/null 2>&1 || fail "openssl is required."
- [[ ! -L "${data_dir}" ]] || fail "data directory must not be a symbolic link."
- mkdir -p "${data_dir}"
- data_dir="$(cd "${data_dir}" && pwd -P)"
- secret_file="${MAILHUB_DOVECOT_SECRET_FILE:-${data_dir}/secrets/dovecot_auth_secret}"
- webmail_secret_file="${MAILHUB_WEBMAIL_SSO_SECRET_FILE:-${data_dir}/secrets/webmail_sso_secret}"
- maildir_root="${MAILHUB_MAILDIR_ROOT:-${data_dir}/maildir}"
- host_uid="$(id -u)"
- if [[ "$(uname -s)" == "Linux" && "${host_uid}" != "0" && "${host_uid}" != "1000" ]]; then
- fail "Linux preparation must run as root or host uid 1000 so the rootless containers can read and write their bind mounts."
- fi
- case "${secret_file}" in
- "${data_dir}"/*) ;;
- *) fail "secret file must stay inside the MailHub data directory." ;;
- esac
- case "${webmail_secret_file}" in
- "${data_dir}"/*) ;;
- *) fail "Webmail SSO secret file must stay inside the MailHub data directory." ;;
- esac
- case "${maildir_root}" in
- "${data_dir}"/*) ;;
- *) fail "Maildir root must stay inside the MailHub data directory." ;;
- esac
- [[ ! -L "${secret_file}" ]] || fail "secret file must not be a symbolic link."
- [[ ! -L "${webmail_secret_file}" ]] || fail "Webmail SSO secret file must not be a symbolic link."
- [[ ! -L "${maildir_root}" ]] || fail "Maildir root must not be a symbolic link."
- mkdir -p "$(dirname "${secret_file}")" "$(dirname "${webmail_secret_file}")" "${maildir_root}"
- secret_dir="$(dirname "${secret_file}")"
- webmail_secret_dir="$(dirname "${webmail_secret_file}")"
- prepare_secret() {
- local file="$1"
- local prefix="$2"
- local temporary_secret
- if [[ ! -f "${file}" ]]; then
- umask 077
- temporary_secret="$(mktemp "$(dirname "${file}")/.${prefix}.XXXXXX")"
- if ! openssl rand -hex 32 >"${temporary_secret}"; then
- rm -f -- "${temporary_secret}"
- fail "unable to generate ${prefix} secret."
- fi
- chmod 0600 "${temporary_secret}"
- mv "${temporary_secret}" "${file}"
- fi
- [[ -f "${file}" ]] || fail "${prefix} secret path must be a regular file."
- local value
- value="$(tr -d '\r\n' <"${file}")"
- [[ "${value}" =~ ^[0-9a-fA-F]+$ ]] || fail "${prefix} secret must contain only hexadecimal characters."
- (( ${#value} >= 64 && ${#value} <= 512 )) || fail "${prefix} secret must contain 64-512 hexadecimal characters."
- }
- prepare_secret "${secret_file}" "dovecot-auth"
- prepare_secret "${webmail_secret_file}" "webmail-sso"
- if [[ "${host_uid}" == "0" ]]; then
- # MailHub runs as uid/gid 1000. The Webmail secret is group-readable so a
- # Roundcube container can join supplemental gid 1000 without making it public.
- chown 1000:1000 \
- "${secret_dir}" \
- "${webmail_secret_dir}" \
- "${secret_file}" \
- "${webmail_secret_file}" \
- "${maildir_root}"
- fi
- chmod 0700 "${maildir_root}"
- chmod 0750 "${secret_dir}" "${webmail_secret_dir}"
- chmod 0400 "${secret_file}"
- chmod 0440 "${webmail_secret_file}"
- echo "Dovecot storage and authentication secrets are ready."
|