maj readme

This commit is contained in:
Grégory Lebreton 2025-03-23 14:17:45 +01:00
parent 25f7168e1b
commit e8daf6bae4
2 changed files with 51 additions and 221 deletions

View File

@ -5,43 +5,66 @@ Héberger sa boîte mail sur son serveur grâce à [Docker Mail Server](https://
## PRE REQUIS :paperclip: ## PRE REQUIS :paperclip:
- Docker + compose plugin - Docker + compose plugin
- Certbot
- Nom de domaine (ici exemple.com) - Nom de domaine (ici exemple.com)
- Le port 25 ouvert par son FAI (pas Free !) - Les ports 25, 143, 465, 587 et 993 ouverts
- Le port 25 ouvert en traffic sortant (Voir avec son FAI)
:warning: **Les FAIs ferme le port 25 sortant sur les boxs**
## CONFIGURER :wrench: ## CONFIGURER :wrench:
#### DNS #### CREATION DES DNS RECORDS
- mailserver.env
```env
MAIL_DNS=mail.exemple.com
POSTMASTER_ADDRESS=
```
- Créer les DNS suivant: - Créer les DNS suivant:
- A record: 1. `A` record:
``` ```
# mail.exemple.com point sur <IP_SERVER> # mail.exemple.com point sur <IP_SERVER>
mail 10800 IN A <IP_SERVER> mail 10800 IN A <IP_SERVER>
``` ```
- MX record: 2. `MX` record:
``` ```
# ne pas oublier le point à la fin !!! # ne pas oublier le point à la fin !!!
@ 10800 IN MX 10 mail.exemple.com. @ 10800 IN MX 10 mail.exemple.com.
``` ```
- TXT record (ancien SPF deprécié): 3. `TXT` record (ancien SPF deprécié):
``` ```
@ 10800 IN TXT "v=spf1 ip4:<IP_SERVER> ~all" @ 10800 IN TXT "v=spf1 ip4:<IP_SERVER> ~all"
``` ```
- TXT record (DMARC) 4. `TXT` record (DMARC)
``` ```
_dmarc 10800 IN TXT "v=DMARC1; p=quarantine; sp=reject; rua=mailto:reports@exemple.com; ruf=mailto:forensics@xemple.com; fo=1" _dmarc 10800 IN TXT "v=DMARC1; p=quarantine; sp=reject; rua=mailto:reports@exemple.com; ruf=mailto:forensics@xemple.com; fo=1"
``` ```
- CNAME record (autodiscover conf du server) 5. `CNAME` record (autodiscover conf du server)
``` ```
autodiscover 10800 IN CNAME mail.exemple.com autodiscover 10800 IN CNAME mail.exemple.com
``` ```
#### ENVS 6. `TXT` record for DKIM (pour mail.example.com après création de clefs DKIM):
```
mail._domainkey 10800 IN TXT "v=DKIM1; h=sha256; k=rsa; p=<DKIM_KEYS>"
```
#### ENVS :mag:
- mailserver.env:
```env
MAIL_DNS=mail.exemple.com
POSTMASTER_ADDRESS=postmaster@exemple.com
```
#### CREATION DES CERTIFICATS SSL ::page_with_curl:
- Création des certifs via certbot:
```bash
sudo certbot certonly -d mail.exemple.com
```
- Copie des certificats pour DMS:
```bash
mkdir -p docker-data/certbot/certs/
sudo cp -r /etc/letsencrypt/live/exemple.com/ docker-data/certbot/certs/
```
#### CREATION BOITE MAIL + CLEFS DKIM :email: :key:
- Lancer la stack: - Lancer la stack:
```bash ```bash
@ -50,15 +73,20 @@ docker compose up -d
- Créer une adresse mail: - Créer une adresse mail:
```bash ```bash
docker exec -it <CONTAINER NAME> setup email add user@exemple.com <PASSWORD>
``` ```
- Créer les clefs DKIM: - Créer un alias:
```bash ```bash
docker exec -ti <CONTAINER NAME> setup alias add postmaster@exemple.com user@exemple.com
``` ```
- Reporter les datas dans un - Créer les clefs `DKIM`:
```bash
docker exec -it <CONTAINER NAME> setup config dkim keysize 1024
```
- Reporter les datas entre () au niveau de `p=""` dans un `TXT` record (**voir étape 6 de la création des DNS records**)
Relancer la stack pour valider l'usage des clefs DKIM: Relancer la stack pour valider l'usage des clefs DKIM:
```bash ```bash
@ -67,5 +95,8 @@ docker compose down && docker compose up -d
## DOCUMENTATION :books: ## DOCUMENTATION :books:
- [DNS]() - [DMS](https://docker-mailserver.github.io/docker-mailserver/latest/usage/)
- [DMS](https://docker-mailserver.github.io/docker-mailserver/latest/usage/)
## TO DO :bookmark_tabs:
- [ ] Automate certbot renew

201
setup.sh
View File

@ -1,201 +0,0 @@
#!/bin/bash
# version v1.0.0
# executed manually / via Make
# task wrapper for various setup scripts
CONFIG_PATH=
CONTAINER_NAME=
CRI=
DEFAULT_CONFIG_PATH=
DESIRED_CONFIG_PATH=
DIR=$(pwd)
DMS_CONFIG='/tmp/docker-mailserver'
IMAGE_NAME=
DEFAULT_IMAGE_NAME='ghcr.io/docker-mailserver/docker-mailserver:latest'
INFO=
PODMAN_ROOTLESS=false
USE_SELINUX=
USE_TTY=
VOLUME=
WHITE=$(echo -ne '\e[37m')
ORANGE=$(echo -ne '\e[38;5;214m')
LBLUE=$(echo -ne '\e[94m')
RESET=$(echo -ne '\e[0m')
set -euEo pipefail
shopt -s inherit_errexit 2>/dev/null || true
function _show_local_usage() {
# shellcheck disable=SC2059
printf '%s' "${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}${DEFAULT_IMAGE_NAME}${RESET}'
-c CONTAINER_NAME
Provides the name of the running container.
-p PATH
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
Allows container access to the bind mount content that is shared among
multiple containers on a SELinux-enabled host.
-Z
Allows container access to the bind mount content that is private and
unshared with other containers on a SELinux-enabled host.
${LBLUE}Podman${RESET}
-R
Accept running in Podman rootless mode. Ignored when using Docker / Docker Compose.
"
[[ ${1:-} == 'no-exit' ]] && return 0
# shellcheck disable=SC2059
printf '%s' "${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.
"
}
function _get_absolute_script_directory() {
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
}
function _set_default_config_path() {
if [[ -d "${DIR}/config" ]]; then
# legacy path (pre v10.2.0)
DEFAULT_CONFIG_PATH="${DIR}/config"
else
DEFAULT_CONFIG_PATH="${DIR}/docker-data/dms/config"
fi
}
function _handle_config_path() {
if [[ -z ${DESIRED_CONFIG_PATH} ]]; then
# no desired config path
if [[ -n ${CONTAINER_NAME} ]]; then
VOLUME=$(${CRI} inspect "${CONTAINER_NAME}" \
--format="{{range .Mounts}}{{ println .Source .Destination}}{{end}}" | \
grep "${DMS_CONFIG}$" 2>/dev/null || :)
fi
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 _run_in_new_container() {
# start temporary container with specified image
if ! ${CRI} history -q "${IMAGE_NAME}" &>/dev/null; then
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
_set_default_config_path
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
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 1
fi
INFO=$(${CRI} ps --no-trunc --format "{{.Image}};{{.Names}}" --filter \
label=org.opencontainers.image.title="docker-mailserver" | tail -1)
[[ -z ${CONTAINER_NAME} ]] && CONTAINER_NAME=${INFO#*;}
[[ -z ${IMAGE_NAME} ]] && IMAGE_NAME=${INFO%;*}
if [[ -z ${IMAGE_NAME} ]]; then
IMAGE_NAME=${NAME:-${DEFAULT_IMAGE_NAME}}
fi
if test -t 0; then
USE_TTY="-it"
else
# GitHub Actions will fail (or really anything else
# lacking an interactive tty) if we don't set a
# value here; "-t" alone works for these cases.
USE_TTY="-t"
fi
_handle_config_path
if [[ -n ${CONTAINER_NAME} ]]; then
${CRI} exec "${USE_TTY}" "${CONTAINER_NAME}" setup "${@}"
else
_run_in_new_container setup "${@}"
fi
[[ ${1:-} == 'help' ]] && _show_local_usage
return 0
}
[[ -z ${1:-} ]] && set 'help'
_main "${@}"