From 1fe65ef19fd74f1742769ec44c84cd90b77a1056 Mon Sep 17 00:00:00 2001 From: Jade Ellis Date: Fri, 25 Oct 2024 20:00:48 +0100 Subject: [PATCH] Stalwart mail --- servers/ansible/playbook.yaml | 8 ++ servers/containers/stalwart.container | 109 ++++++++++++++++++++++++++ servers/stalwart/config.toml | 89 +++++++++++++++++++++ 3 files changed, 206 insertions(+) create mode 100644 servers/containers/stalwart.container create mode 100644 servers/stalwart/config.toml diff --git a/servers/ansible/playbook.yaml b/servers/ansible/playbook.yaml index 1677726c..64305baf 100644 --- a/servers/ansible/playbook.yaml +++ b/servers/ansible/playbook.yaml @@ -45,6 +45,14 @@ ansible.posix.synchronize: src: ../sentry-relay/ dest: /etc/sentry-relay + - name: Creates stalwart mail data directory + file: + path: /var/opt/stalwart-mail + state: directory + - name: Copy stalwart config + ansible.posix.synchronize: + src: ../stalwart/ + dest: /etc/stalwart # - name: install linux-system-roles # package: # name: linux-system-roles diff --git a/servers/containers/stalwart.container b/servers/containers/stalwart.container new file mode 100644 index 00000000..5ec33929 --- /dev/null +++ b/servers/containers/stalwart.container @@ -0,0 +1,109 @@ + + +[Unit] +Description=Stalwart Mail +Wants=network-online.target +Wants=traefik.service +After=network-online.target +Documentation=https://conduwuit.puppyirl.gay/ + +[Container] +ContainerName=stalwart-mail +Image=docker.io/stalwartlabs/mail-server:latest +Entrypoint=["/usr/local/bin/stalwart-mail", "--config", "/etc/stalwart/config.toml"] +Volume=/etc/localtime:/etc/localtime:ro +Volume=traefik-certs.volume:/data/certs:ro +Volume=/var/opt/stalwart-mail:/opt/stalwart-mail:z,U +Volume=/etc/stalwart:/etc/stalwart:ro +AutoUpdate=registry +Network=web.network + +# allow many file descriptors for rocksdb +Ulimit=nofile=1048567:1048567 + +Label="traefik.enable=true" +Label="traefik.http.routers.stalwart-mail.rule=(Host(`mail.ellis.link`) || Host(`autodiscover.ellis.link`) || Host(`autoconfig.ellis.link`) || Host(`mta-sts.ellis.link`))" +Label="traefik.http.services.stalwart-mail.loadbalancer.server.port=8080" + +Label="traefik.http.routers.stalwart-mail.service=stalwart-mail" +Label="traefik.http.routers.stalwart-mail.entrypoints=https" + +Label="traefik.http.routers.stalwart-mail.middlewares=default@file" + +Label="homepage.group=Public" +Label="homepage.name=Stalwart Mail" +Label="homepage.href=https://mail.ellis.link/" + +# Label="homepage.siteMonitor=" +Label="homepage.description=AIO mail server" + + + +Label="traefik.tcp.routers.smtp.rule=HostSNI(`*`)" +Label="traefik.tcp.routers.smtp.entrypoints=smtp" +Label="traefik.tcp.routers.smtp.service=smtp" +Label="traefik.tcp.services.smtp.loadbalancer.server.port=25" +Label="traefik.tcp.services.smtp.loadbalancer.proxyProtocol.version=2" + +Label="traefik.tcp.routers.pop.rule=HostSNI(`*`)" +Label="traefik.tcp.routers.pop.entrypoints=pop" +Label="traefik.tcp.routers.pop.service=pop" +Label="traefik.tcp.services.pop.loadbalancer.server.port=110" +Label="traefik.tcp.services.pop.loadbalancer.proxyProtocol.version=2" + +Label="traefik.tcp.routers.managesieve.rule=HostSNI(`*`)" +Label="traefik.tcp.routers.managesieve.tls.passthrough=true" +Label="traefik.tcp.routers.managesieve.entrypoints=managesieve" +Label="traefik.tcp.routers.managesieve.service=managesieve" +Label="traefik.tcp.services.managesieve.loadbalancer.server.port=4190" +Label="traefik.tcp.services.managesieve.loadbalancer.proxyProtocol.version=2" + +Label="traefik.tcp.routers.jmap.rule=HostSNI(`*`)" +Label="traefik.tcp.routers.jmap.tls.passthrough=true" +Label="traefik.tcp.routers.jmap.entrypoints=https" +Label="traefik.tcp.routers.jmap.service=jmap" +Label="traefik.tcp.services.jmap.loadbalancer.server.port=443" +Label="traefik.tcp.services.jmap.loadbalancer.proxyProtocol.version=2" + +Label="traefik.tcp.routers.smtpstarttls.rule=HostSNI(`*`)" +Label="traefik.tcp.routers.smtpstarttls.entrypoints=smtpstarttls" +Label="traefik.tcp.routers.smtpstarttls.service=smtpstarttls" +Label="traefik.tcp.services.smtpstarttls.loadbalancer.server.port=587" +Label="traefik.tcp.services.smtpstarttls.loadbalancer.proxyProtocol.version=2" + +Label="traefik.tcp.routers.smtps.rule=HostSNI(`*`)" +Label="traefik.tcp.routers.smtps.tls.passthrough=true" +Label="traefik.tcp.routers.smtps.entrypoints=smtps" +Label="traefik.tcp.routers.smtps.service=smtps" +Label="traefik.tcp.services.smtps.loadbalancer.server.port=465" +Label="traefik.tcp.services.smtps.loadbalancer.proxyProtocol.version=2" + +Label="traefik.tcp.routers.imaps.rule=HostSNI(`*`)" +Label="traefik.tcp.routers.imaps.tls.passthrough=true" +Label="traefik.tcp.routers.imaps.entrypoints=imaps" +Label="traefik.tcp.routers.imaps.service=imaps" +Label="traefik.tcp.services.imaps.loadbalancer.server.port=993" +Label="traefik.tcp.services.imaps.loadbalancer.proxyProtocol.version=2" + +Label="traefik.tcp.routers.pops.rule=HostSNI(`*`)" +Label="traefik.tcp.routers.pops.tls.passthrough=true" +Label="traefik.tcp.routers.pops.entrypoints=pops" +Label="traefik.tcp.routers.pops.service=pops" +Label="traefik.tcp.services.pops.loadbalancer.server.port=995" +Label="traefik.tcp.services.pops.loadbalancer.proxyProtocol.version=2" + +StopTimeout=100 + +[Service] + +Restart=on-failure +RestartSec=5 + +TimeoutStopSec=2m +TimeoutStartSec=2m + +# StartLimitInterval=1m +StartLimitBurst=5 + +[Install] +WantedBy=default.target \ No newline at end of file diff --git a/servers/stalwart/config.toml b/servers/stalwart/config.toml new file mode 100644 index 00000000..57bf015d --- /dev/null +++ b/servers/stalwart/config.toml @@ -0,0 +1,89 @@ +authentication.fallback-admin.secret = "$6$iGpfCci4xpCUIq1a$j8Zdj7OynBNUcc1OPwJ8n/vyhG1hE9gLeiHYQ7Ymp6HyjzqbfDvO/xwRa1no37ZGQewwaySYz/k8peabKxIrn1" +authentication.fallback-admin.user = "admin" +directory.internal.store = "rocksdb" +directory.internal.type = "internal" + +certificate.default.cert = "%{file:/data/certs/*.ellis.link/cert.pem}%" +certificate.default.default = true +certificate.default.private-key = "%{file:/data/certs/*.ellis.link/key.pem}%" +lookup.default.hostname = "mail.ellis.link" +server.http.hsts = true +server.http.permissive-cors = false +server.http.url = "protocol + '://' + key_get('default', 'hostname') + ':' + local_port" +server.http.use-x-forwarded = true +server.listener.http.bind = "[::]:8080" +server.listener.http.protocol = "http" +server.listener.https.bind = "[::]:443" +server.listener.https.protocol = "http" +server.listener.https.tls.implicit = true +# Do we need proxy config for http? +server.listener.imaptls.bind = "[::]:993" +server.listener.imaptls.protocol = "imap" +server.listener.imaptls.proxy.override = true +server.listener.imaptls.proxy.trusted-networks.0 = "10.89.0.0/24" +server.listener.imaptls.proxy.trusted-networks.1 = "fd76:6f6d:f45e:ea1a::/64" +server.listener.imaptls.tls.implicit = true +server.listener.pop3s.bind = "[::]:995" +server.listener.pop3s.protocol = "pop3" +server.listener.pop3s.proxy.override = true +server.listener.pop3s.proxy.trusted-networks.0 = "10.89.0.0/24" +server.listener.pop3s.proxy.trusted-networks.1 = "fd76:6f6d:f45e:ea1a::/64" +server.listener.pop3s.tls.implicit = true +server.listener.smtp.bind = "[::]:25" +server.listener.smtp.protocol = "smtp" +server.listener.smtp.proxy.override = true +server.listener.smtp.proxy.trusted-networks.0 = "10.89.0.0/24" +server.listener.smtp.proxy.trusted-networks.1 = "fd76:6f6d:f45e:ea1a::/64" +server.listener.submission.bind = "[::]:587" +server.listener.submission.protocol = "smtp" +server.listener.submission.proxy.override = true +server.listener.submission.proxy.trusted-networks.0 = "10.89.0.0/24" +server.listener.submission.proxy.trusted-networks.1 = "fd76:6f6d:f45e:ea1a::/64" +server.listener.submissions.bind = "[::]:465" +server.listener.submissions.protocol = "smtp" +server.listener.submissions.proxy.override = true +server.listener.submissions.proxy.trusted-networks.0 = "10.89.0.0/24" +server.listener.submissions.proxy.trusted-networks.1 = "fd76:6f6d:f45e:ea1a::/64" +server.listener.submissions.tls.implicit = true + +server.listener.imap.bind = "[::]:143" +server.listener.imap.protocol = "imap" +server.listener.imap.proxy.override = true +server.listener.imap.proxy.trusted-networks.0 = "10.89.0.0/24" +server.listener.imap.proxy.trusted-networks.1 = "fd76:6f6d:f45e:ea1a::/64" +server.listener.pop3.bind = "[::]:110" +server.listener.pop3.protocol = "pop3" +server.listener.pop3.proxy.override = true +server.listener.pop3.proxy.trusted-networks.0 = "10.89.0.0/24" +server.listener.pop3.proxy.trusted-networks.1 = "fd76:6f6d:f45e:ea1a::/64" +server.listener.sieve.bind = "[::]:4190" +server.listener.sieve.protocol = "managesieve" +server.listener.sieve.proxy.override = true +server.listener.sieve.proxy.trusted-networks.0 = "10.89.0.0/24" +server.listener.sieve.proxy.trusted-networks.1 = "fd76:6f6d:f45e:ea1a::/64" + +storage.blob = "cloudflare-r2" +storage.data = "rocksdb" +storage.directory = "internal" +storage.fts = "rocksdb" +storage.lookup = "rocksdb" +store.rocksdb.compression = "lz4" +store.rocksdb.path = "/opt/stalwart-mail/data" +store.rocksdb.type = "rocksdb" +tracer.log.ansi = false +tracer.log.enable = true +tracer.log.level = "info" +tracer.log.path = "/opt/stalwart-mail/logs" +tracer.log.prefix = "stalwart.log" +tracer.log.rotate = "daily" +tracer.log.type = "log" + +[store."cloudflare-r2"] +type = "s3" +bucket = "mail-blobs" +region = "auto" +access-key = "a264c5fb57677f6edca2f09e70891cc4" +secret-key = "dff812b5027eef16d57f2ff6865e3f4235663d88aaf3cf066348ca6f1841099c" +endpoint = "https://ad1e593a824b98c89c76cade5db18036.r2.cloudflarestorage.com" +timeout = "30s" +key-prefix = "stalwart/"