mirror of
https://github.com/chatmail/relay.git
synced 2026-05-10 16:04:37 +00:00
docker: add traefik support
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -170,3 +170,4 @@ chatmail.zone
|
|||||||
/custom/
|
/custom/
|
||||||
docker-compose.yaml
|
docker-compose.yaml
|
||||||
.env
|
.env
|
||||||
|
/traefik/data/
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
- Add configuration parameters
|
- Add configuration parameters
|
||||||
([#614](https://github.com/chatmail/relay/pull/614)):
|
([#614](https://github.com/chatmail/relay/pull/614)):
|
||||||
|
- `use_foreign_cert_manager` - Use a third-party certificate manager instead of acmetool (default: `False`)
|
||||||
- `change_kernel_settings` - Whether to change kernel parameters during installation (default: `True`)
|
- `change_kernel_settings` - Whether to change kernel parameters during installation (default: `True`)
|
||||||
- `fs_inotify_max_user_instances_and_watchers` - Value for kernel parameters `fs.inotify.max_user_instances` and `fs.inotify.max_user_watches` (default: `65535`)
|
- `fs_inotify_max_user_instances_and_watchers` - Value for kernel parameters `fs.inotify.max_user_instances` and `fs.inotify.max_user_watches` (default: `65535`)
|
||||||
|
|
||||||
|
|||||||
@@ -44,6 +44,9 @@ class Config:
|
|||||||
)
|
)
|
||||||
self.mtail_address = params.get("mtail_address")
|
self.mtail_address = params.get("mtail_address")
|
||||||
self.disable_ipv6 = params.get("disable_ipv6", "false").lower() == "true"
|
self.disable_ipv6 = params.get("disable_ipv6", "false").lower() == "true"
|
||||||
|
self.use_foreign_cert_manager = (
|
||||||
|
params.get("use_foreign_cert_manager", "false").lower() == "true"
|
||||||
|
)
|
||||||
self.change_kernel_settings = (
|
self.change_kernel_settings = (
|
||||||
params.get("change_kernel_settings", "true").lower() == "true"
|
params.get("change_kernel_settings", "true").lower() == "true"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -60,6 +60,9 @@ postfix_reinject_port_incoming = 10026
|
|||||||
# if set to "True" IPv6 is disabled
|
# if set to "True" IPv6 is disabled
|
||||||
disable_ipv6 = False
|
disable_ipv6 = False
|
||||||
|
|
||||||
|
# if you set "True", acmetool will not be installed and you will have to manage certificates yourself.
|
||||||
|
use_foreign_cert_manager = False
|
||||||
|
|
||||||
#
|
#
|
||||||
# Kernel settings
|
# Kernel settings
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -726,10 +726,11 @@ def deploy_chatmail(config_path: Path, disable_mail: bool) -> None:
|
|||||||
deploy_iroh_relay(config)
|
deploy_iroh_relay(config)
|
||||||
|
|
||||||
# Deploy acmetool to have TLS certificates.
|
# Deploy acmetool to have TLS certificates.
|
||||||
tls_domains = [mail_domain, f"mta-sts.{mail_domain}", f"www.{mail_domain}"]
|
if not config.use_foreign_cert_manager:
|
||||||
deploy_acmetool(
|
tls_domains = [mail_domain, f"mta-sts.{mail_domain}", f"www.{mail_domain}"]
|
||||||
domains=tls_domains,
|
deploy_acmetool(
|
||||||
)
|
domains=tls_domains,
|
||||||
|
)
|
||||||
|
|
||||||
apt.packages(
|
apt.packages(
|
||||||
# required for setfacl for echobot
|
# required for setfacl for echobot
|
||||||
|
|||||||
136
docker/docker-compose-traefik.yaml
Normal file
136
docker/docker-compose-traefik.yaml
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
services:
|
||||||
|
chatmail:
|
||||||
|
build:
|
||||||
|
context: ./docker
|
||||||
|
dockerfile: chatmail_relay.dockerfile
|
||||||
|
tags:
|
||||||
|
- chatmail-relay:latest
|
||||||
|
image: chatmail-relay:latest
|
||||||
|
restart: unless-stopped
|
||||||
|
container_name: chatmail
|
||||||
|
depends_on:
|
||||||
|
- traefik-certs-dumper
|
||||||
|
cgroup: host # required for systemd
|
||||||
|
tty: true # required for logs
|
||||||
|
tmpfs: # required for systemd
|
||||||
|
- /tmp
|
||||||
|
- /run
|
||||||
|
- /run/lock
|
||||||
|
logging:
|
||||||
|
driver: json-file
|
||||||
|
options:
|
||||||
|
max-size: "10m"
|
||||||
|
max-file: "3"
|
||||||
|
environment: #all possible variables you can check inside README and /chatmaild/src/chatmaild/ini/chatmail.ini.f
|
||||||
|
MAIL_DOMAIN: $MAIL_DOMAIN
|
||||||
|
# MAX_MESSAGE_SIZE: "50M"
|
||||||
|
# DEBUG_COMMANDS_ENABLED: "true"
|
||||||
|
# FORCE_REINIT_INI_FILE: "true"
|
||||||
|
# RECREATE_VENV: "false"
|
||||||
|
USE_FOREIGN_CERT_MANAGER: "true"
|
||||||
|
CHANGE_KERNEL_SETTINGS: "false"
|
||||||
|
PATH_TO_SSL: "${CERTS_ROOT_DIR_CONTAINER}/${MAIL_DOMAIN}"
|
||||||
|
ENABLE_CERTS_MONITORING: "true"
|
||||||
|
# CERTS_MONITORING_TIMEOUT: 60
|
||||||
|
# IS_DEVELOPMENT_INSTANCE: "true"
|
||||||
|
ports:
|
||||||
|
- "25:25"
|
||||||
|
- "587:587"
|
||||||
|
- "143:143"
|
||||||
|
- "465:465"
|
||||||
|
- "993:993"
|
||||||
|
volumes:
|
||||||
|
## system
|
||||||
|
- /sys/fs/cgroup:/sys/fs/cgroup:rw # required for systemd
|
||||||
|
- ./:/opt/chatmail
|
||||||
|
- ${CERTS_ROOT_DIR_HOST}:${CERTS_ROOT_DIR_CONTAINER}:ro
|
||||||
|
|
||||||
|
## data
|
||||||
|
- ./data/chatmail:/home
|
||||||
|
# - ./data/chatmail-dkimkeys:/etc/dkimkeys
|
||||||
|
# - ./data/chatmail-echobot:/run/echobot
|
||||||
|
# - ./data/chatmail-acme:/var/lib/acme
|
||||||
|
|
||||||
|
## custom resources
|
||||||
|
# - ./custom/www/src/index.md:/opt/chatmail/www/src/index.md
|
||||||
|
|
||||||
|
## debug
|
||||||
|
# - ./docker/files/setup_chatmail_docker.sh:/setup_chatmail_docker.sh
|
||||||
|
# - ./docker/files/entrypoint.sh:/entrypoint.sh
|
||||||
|
# - ./docker/files/update_ini.sh:/update_ini.sh
|
||||||
|
|
||||||
|
labels:
|
||||||
|
- traefik.enable=true
|
||||||
|
- traefik.http.services.chatmail-relay.loadbalancer.server.scheme=https
|
||||||
|
- traefik.http.services.chatmail-relay.loadbalancer.server.port=443
|
||||||
|
- traefik.http.services.chatmail-relay.loadbalancer.serverstransport=insecure@file
|
||||||
|
- traefik.http.routers.chatmail-relay.rule=Host(`${MAIL_DOMAIN}`) || Host(`mta-sts.${MAIL_DOMAIN}`) || Host(`www.${MAIL_DOMAIN}`)
|
||||||
|
- traefik.http.routers.chatmail-relay.service=chatmail-relay
|
||||||
|
- traefik.http.routers.chatmail-relay.tls=true
|
||||||
|
- traefik.http.routers.chatmail-relay.tls.certresolver=letsEncrypt
|
||||||
|
|
||||||
|
traefik_init:
|
||||||
|
image: alpine:latest
|
||||||
|
restart: on-failure
|
||||||
|
logging:
|
||||||
|
driver: json-file
|
||||||
|
options:
|
||||||
|
max-size: "10m"
|
||||||
|
max-file: "3"
|
||||||
|
working_dir: /app
|
||||||
|
entrypoint: sh -c '
|
||||||
|
touch acme.json &&
|
||||||
|
chown 0:0 ./acme.json &&
|
||||||
|
chmod 600 ./acme.json'
|
||||||
|
volumes:
|
||||||
|
- ./traefik/data:/app
|
||||||
|
|
||||||
|
traefik:
|
||||||
|
image: traefik:v3.3
|
||||||
|
container_name: traefik
|
||||||
|
restart: unless-stopped
|
||||||
|
logging:
|
||||||
|
driver: json-file
|
||||||
|
options:
|
||||||
|
max-size: "10m"
|
||||||
|
max-file: "3"
|
||||||
|
command:
|
||||||
|
- "--configFile=/config.yaml"
|
||||||
|
- "--certificatesresolvers.letsEncrypt.acme.email=${ACME_EMAIL}"
|
||||||
|
# ports:
|
||||||
|
# - "80:80"
|
||||||
|
# - "443:443"
|
||||||
|
network_mode: host
|
||||||
|
depends_on:
|
||||||
|
traefik_init:
|
||||||
|
condition: service_completed_successfully
|
||||||
|
volumes:
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
|
- ./traefik/config.yaml:/config.yaml
|
||||||
|
- ./traefik/data/acme.json:/acme.json
|
||||||
|
- ./traefik/dynamic-configs:/dynamic/conf
|
||||||
|
|
||||||
|
traefik-certs-dumper:
|
||||||
|
image: ldez/traefik-certs-dumper:v2.10.0
|
||||||
|
restart: unless-stopped
|
||||||
|
logging:
|
||||||
|
driver: json-file
|
||||||
|
options:
|
||||||
|
max-size: "10m"
|
||||||
|
max-file: "3"
|
||||||
|
depends_on:
|
||||||
|
- traefik
|
||||||
|
entrypoint: sh -c '
|
||||||
|
apk add openssl &&
|
||||||
|
while ! [ -e /data/acme.json ]
|
||||||
|
|| ! [ `jq ".[] | .Certificates | length" /data/acme.json | jq -s "add" ` != 0 ]; do
|
||||||
|
sleep 1
|
||||||
|
; done
|
||||||
|
&& traefik-certs-dumper file --version v3 --watch --domain-subdir=true
|
||||||
|
--source /data/acme.json --dest /data/letsencrypt/certs --post-hook "sh /post-hook.sh"'
|
||||||
|
environment:
|
||||||
|
CERTS_DIR: /data/letsencrypt/certs
|
||||||
|
volumes:
|
||||||
|
- ./traefik/data/letsencrypt:/data/letsencrypt
|
||||||
|
- ./traefik/data/acme.json:/data/acme.json
|
||||||
|
- ./traefik/post-hook.sh:/post-hook.sh
|
||||||
@@ -1 +1,5 @@
|
|||||||
MAIL_DOMAIN="chat.example.com"
|
MAIL_DOMAIN="chat.example.com"
|
||||||
|
ACME_EMAIL="my.email@gmail.com"
|
||||||
|
|
||||||
|
CERTS_ROOT_DIR_HOST="./traefik/data/letsencrypt/certs"
|
||||||
|
CERTS_ROOT_DIR_CONTAINER="/var/lib/acme/live"
|
||||||
|
|||||||
@@ -3,6 +3,19 @@ set -eo pipefail
|
|||||||
|
|
||||||
unlink /etc/nginx/sites-enabled/default || true
|
unlink /etc/nginx/sites-enabled/default || true
|
||||||
|
|
||||||
|
if [ "${USE_FOREIGN_CERT_MANAGER,,}" == "true" ]; then
|
||||||
|
if [ ! -f "$PATH_TO_SSL/fullchain" ]; then
|
||||||
|
echo "Error: file '$PATH_TO_SSL/fullchain' does not exist. Exiting..." > /dev/stderr
|
||||||
|
sleep 2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if [ ! -f "$PATH_TO_SSL/privkey" ]; then
|
||||||
|
echo "Error: file '$PATH_TO_SSL/privkey' does not exist. Exiting..." > /dev/stderr
|
||||||
|
sleep 2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
SETUP_CHATMAIL_SERVICE_PATH="${SETUP_CHATMAIL_SERVICE_PATH:-/lib/systemd/system/setup_chatmail.service}"
|
SETUP_CHATMAIL_SERVICE_PATH="${SETUP_CHATMAIL_SERVICE_PATH:-/lib/systemd/system/setup_chatmail.service}"
|
||||||
|
|
||||||
env_vars=$(printenv | cut -d= -f1 | xargs)
|
env_vars=$(printenv | cut -d= -f1 | xargs)
|
||||||
|
|||||||
@@ -32,11 +32,25 @@ Please substitute it with your own domain.
|
|||||||
```
|
```
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
When installing via Docker, there are several options:
|
||||||
|
|
||||||
1. Copy the file `./docker/docker-compose-default.yaml` to `docker-compose.yaml`. This is necessary because `docker-compose.yaml` is in `.gitignore` and won’t cause conflicts when updating the git repository.
|
- Use the built-in nginx and acmetool in Chatmail container to host the chat and manage certificates.
|
||||||
|
- Use third-party tools for certificate management.
|
||||||
|
|
||||||
|
For the third-party certificate manager example, traefik will be used, but you can use whatever is more convenient for you.
|
||||||
|
|
||||||
|
1. Copy the file `./docker/docker-compose-default.yaml` or `./docker/docker-compose-traefik.yaml` and rename it to `docker-compose.yaml`. This is necessary because `docker-compose.yaml` is in `.gitignore` and won’t cause conflicts when updating the git repository.
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
cp ./docker/docker-compose-default.yaml docker-compose.yaml
|
cp ./docker/docker-compose-default.yaml docker-compose.yaml
|
||||||
|
## or
|
||||||
|
# cp ./docker/docker-compose-traefik.yaml docker-compose.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Copy `./docker/example.env` and rename it to `.env`. This file stores variables used in `docker-compose.yaml`.
|
||||||
|
|
||||||
|
```shell
|
||||||
|
cp ./docker/example.env .env
|
||||||
```
|
```
|
||||||
|
|
||||||
3. Configure environment variables in the `.env` file. These variables are used in the `docker-compose.yaml` file to pass repeated values.
|
3. Configure environment variables in the `.env` file. These variables are used in the `docker-compose.yaml` file to pass repeated values.
|
||||||
|
|||||||
@@ -29,10 +29,22 @@ Please substitute it with your own domain.
|
|||||||
```
|
```
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
При установке через docker есть несколько вариантов:
|
||||||
|
- использовать встроенный в chatmail контейнер nginx и acmetool для хостинга чата и управления сертификатами.
|
||||||
|
- использовать сторонние инструменты для менеджмента сертификатов
|
||||||
|
|
||||||
1. Скопировать файл `./docker/docker-compose-default.yaml` в `docker-compose.yaml`. Это нужно потому что `docker-compose.yaml` находится в `.gitignore` и не будет создавать конфликты при обновлении гит репозитория.
|
В качестве примера для стороннего менеджера сертификатов будет использоваться traefik, но вы можете использовать то что удобнее вам.
|
||||||
|
|
||||||
|
1. Скопировать файл `./docker/docker-compose-default.yaml` или `./docker/docker-compose-traefik.yaml` и переименовать в `docker-compose.yaml`. Это нужно потому что `docker-compose.yaml` находится в `.gitignore` и не будет создавать конфликты при обновлении гит репозитория.
|
||||||
```shell
|
```shell
|
||||||
cp ./docker/docker-compose-default.yaml docker-compose.yaml
|
cp ./docker/docker-compose-default.yaml docker-compose.yaml
|
||||||
|
## or
|
||||||
|
# cp ./docker/docker-compose-traefik.yaml docker-compose.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Скопировать `./docker/example.env` и переименовать в `.env`. Здесь хранятся переменные, которые используятся в `docker-compose.yaml`.
|
||||||
|
```shell
|
||||||
|
cp ./docker/example.env .env
|
||||||
```
|
```
|
||||||
|
|
||||||
3. Настроить переменные окружения в `.env` файле. Эти переменные используются в `docker-compose.yaml` файле, чтобы передавать повторяющиеся значения.
|
3. Настроить переменные окружения в `.env` файле. Эти переменные используются в `docker-compose.yaml` файле, чтобы передавать повторяющиеся значения.
|
||||||
|
|||||||
33
traefik/config.yaml
Normal file
33
traefik/config.yaml
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
log:
|
||||||
|
level: TRACE
|
||||||
|
|
||||||
|
entryPoints:
|
||||||
|
web:
|
||||||
|
address: ":80"
|
||||||
|
http:
|
||||||
|
redirections:
|
||||||
|
entryPoint:
|
||||||
|
to: websecure
|
||||||
|
permanent: true
|
||||||
|
websecure:
|
||||||
|
address: ":443"
|
||||||
|
|
||||||
|
providers:
|
||||||
|
docker:
|
||||||
|
endpoint: "unix:///var/run/docker.sock"
|
||||||
|
exposedByDefault: false
|
||||||
|
file:
|
||||||
|
directory: /dynamic/conf
|
||||||
|
watch: true
|
||||||
|
|
||||||
|
serverstransport:
|
||||||
|
insecureskipverify: true
|
||||||
|
|
||||||
|
certificatesResolvers:
|
||||||
|
letsEncrypt:
|
||||||
|
acme:
|
||||||
|
storage: /acme.json
|
||||||
|
caServer: "https://acme-v02.api.letsencrypt.org/directory"
|
||||||
|
tlschallenge: true
|
||||||
|
httpChallenge:
|
||||||
|
entryPoint: web
|
||||||
4
traefik/dynamic-configs/insecure.yaml
Normal file
4
traefik/dynamic-configs/insecure.yaml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
http:
|
||||||
|
serversTransports:
|
||||||
|
insecure:
|
||||||
|
insecureSkipVerify: true
|
||||||
15
traefik/post-hook.sh
Executable file
15
traefik/post-hook.sh
Executable file
@@ -0,0 +1,15 @@
|
|||||||
|
CERTS_DIR=${CERTS_DIR:-"/data/letsencrypt/certs"}
|
||||||
|
|
||||||
|
echo "CERTS_DIR: $CERTS_DIR"
|
||||||
|
|
||||||
|
for dir in "$CERTS_DIR"/*/; do
|
||||||
|
echo "Processing: $dir"
|
||||||
|
cd "$dir"
|
||||||
|
if [ -f "certificate.crt" ]; then
|
||||||
|
ln -sf certificate.crt fullchain
|
||||||
|
fi
|
||||||
|
if [ -f "privatekey.key" ]; then
|
||||||
|
ln -sf privatekey.key privkey
|
||||||
|
fi
|
||||||
|
cd -
|
||||||
|
done
|
||||||
Reference in New Issue
Block a user