Add email support

This commit is contained in:
Quentin 2022-08-25 04:39:44 +02:00
parent ea1b0e9d19
commit ec0e483d99
Signed by untrusted user: quentin
GPG key ID: E9602264D639FF68
53 changed files with 1382 additions and 0 deletions

View file

@ -0,0 +1,20 @@
FROM golang:1.15.6-buster as builder
ARG VERSION
ENV CGO_ENABLED=0 GOOS=linux GOARCH=amd64
WORKDIR /tmp/alps
RUN git init && \
git remote add origin https://git.deuxfleurs.fr/Deuxfleurs/alps.git && \
git fetch --depth 1 origin ${VERSION} && \
git checkout FETCH_HEAD
RUN go build -a -o /usr/local/bin/alps ./cmd/alps
FROM scratch
COPY --from=builder /usr/local/bin/alps /alps
COPY --from=builder /tmp/alps/themes /themes
COPY --from=builder /tmp/alps/plugins /plugins
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
ENTRYPOINT ["/alps"]

View file

@ -0,0 +1,36 @@
version: '3.4'
services:
# Email
sogo:
build:
context: ./sogo
args:
# fake for now
VERSION: 5.0.0
image: superboum/amd64_sogo:v7
alps:
build:
context: ./alps
args:
VERSION: 9bafa64b9d
image: superboum/amd64_alps:v1
dovecot:
build:
context: ./dovecot
image: superboum/amd64_dovecot:v6
postfix:
build:
context: ./postfix
args:
# https://packages.debian.org/fr/buster/postfix
VERSION: 3.4.14-0+deb10u1
image: superboum/amd64_postfix:v3
opendkim:
build:
context: ./opendkim
image: superboum/amd64_opendkim:v6

View file

@ -0,0 +1 @@
dovecot-ldap.conf

View file

@ -0,0 +1,16 @@
FROM amd64/debian:bullseye
RUN apt-get update && \
apt-get install -y \
dovecot-antispam \
dovecot-core \
dovecot-imapd \
dovecot-ldap \
dovecot-managesieved \
dovecot-sieve \
dovecot-lmtpd && \
rm -rf /etc/dovecot/*
RUN useradd mailstore
COPY entrypoint.sh /usr/local/bin/entrypoint
ENTRYPOINT ["/usr/local/bin/entrypoint"]

View file

@ -0,0 +1,18 @@
```
sudo docker build -t superboum/amd64_dovecot:v2 .
```
```
sudo docker run -t -i \
-e TLSINFO="/C=FR/ST=Bretagne/L=Rennes/O=Deuxfleurs/CN=www.deuxfleurs.fr" \
-p 993:993 \
-p 143:143 \
-p 24:24 \
-p 1337:1337 \
-v /mnt/glusterfs/email/ssl:/etc/ssl/ \
-v /mnt/glusterfs/email/mail:/var/mail \
-v `pwd`/dovecot-ldap.conf:/etc/dovecot/dovecot-ldap.conf \
superboum/amd64_dovecot:v1 \
dovecot -F
```

View file

@ -0,0 +1,27 @@
#!/bin/bash
if [[ ! -f /etc/ssl/certs/dovecot.crt || ! -f /etc/ssl/private/dovecot.key ]]; then
cd /root
openssl req \
-new \
-newkey rsa:4096 \
-days 3650 \
-nodes \
-x509 \
-subj ${TLSINFO} \
-keyout dovecot.key \
-out dovecot.crt
mkdir -p /etc/ssl/{certs,private}/
cp dovecot.crt /etc/ssl/certs/dovecot.crt
cp dovecot.key /etc/ssl/private/dovecot.key
chmod 400 /etc/ssl/certs/dovecot.crt
chmod 400 /etc/ssl/private/dovecot.key
fi
if [[ $(stat -c '%U' /var/mail/) != "mailstore" ]]; then
chown -R mailstore /var/mail
fi
exec "$@"

View file

@ -0,0 +1,5 @@
require ["fileinto", "mailbox"];
if header :contains "X-Spam-Flag" "YES" {
fileinto :create "Junk";
}

View file

@ -0,0 +1,8 @@
hosts = ldap.example.com
dn = cn=admin,dc=example,dc=com
dnpass = s3cr3t
base = dc=example,dc=com
scope = subtree
user_filter = (&(mail=%u)(&(objectClass=inetOrgPerson)(memberOf=cn=email,ou=groups,dc=example,dc=com)))
pass_filter = (&(mail=%u)(&(objectClass=inetOrgPerson)(memberOf=cn=email,ou=groups,dc=example,dc=com)))
user_attrs = mail=/var/mail/%{ldap:mail}

View file

@ -0,0 +1,17 @@
require ["vnd.dovecot.pipe", "copy", "imapsieve", "environment", "variables", "vnd.dovecot.debug"];
if environment :matches "imap.mailbox" "*" {
set "mailbox" "${1}";
}
if string "${mailbox}" "Trash" {
stop;
}
if environment :matches "imap.user" "*" {
set "username" "${1}";
}
pipe :copy "sa-learn" [ "--ham", "-u", "debian-spamd" ];
debug_log "ham reported by ${username}";

View file

@ -0,0 +1,9 @@
require ["vnd.dovecot.pipe", "copy", "imapsieve", "environment", "variables", "vnd.dovecot.debug"];
if environment :matches "imap.user" "*" {
set "username" "${1}";
}
pipe :copy "sa-learn" [ "--spam", "-u", "debian-spamd"];
debug_log "spam reported by ${username}";

View file

@ -0,0 +1,9 @@
FROM amd64/debian:bullseye
RUN apt-get update && \
apt-get dist-upgrade -y && \
apt-get install -y opendkim opendkim-tools
COPY ./opendkim.conf /etc/opendkim.conf
COPY ./entrypoint /entrypoint
CMD ["/entrypoint"]

View file

@ -0,0 +1,12 @@
```
sudo docker build -t superboum/amd64_opendkim:v1 .
```
```
sudo docker run -t -i \
-v `pwd`/conf:/etc/dkim \
-v /dev/log:/dev/log \
-p 8999:8999
superboum/amd64_opendkim:v1
opendkim -f -v -x /etc/opendkim.conf
```

View file

@ -0,0 +1,8 @@
#!/bin/bash
chown 0:0 /etc/dkim/*
chown 0:0 /etc/dkim
chmod 400 /etc/dkim/*
chmod 700 /etc/dkim
opendkim -f -v -x /etc/opendkim.conf

View file

@ -0,0 +1,12 @@
Syslog yes
SyslogSuccess yes
LogWhy yes
UMask 007
Mode sv
OversignHeaders From
TrustAnchorFile /usr/share/dns/root.key
KeyTable refile:/etc/dkim/keytable
SigningTable refile:/etc/dkim/signingtable
ExternalIgnoreList refile:/etc/dkim/trusted
InternalHosts refile:/etc/dkim/trusted
Socket inet:8999

View file

@ -0,0 +1,13 @@
FROM amd64/debian:buster
ARG VERSION
RUN apt-get update && \
apt-get install -y \
postfix=$VERSION \
postfix-ldap
COPY entrypoint.sh /usr/local/bin/entrypoint
ENTRYPOINT ["/usr/local/bin/entrypoint"]
CMD ["postfix", "start-fg"]

View file

@ -0,0 +1,18 @@
```
sudo docker build -t superboum/amd64_postfix:v1 .
```
```
sudo docker run -t -i \
-e TLSINFO="/C=FR/ST=Bretagne/L=Rennes/O=Deuxfleurs/CN=smtp.deuxfleurs.fr" \
-e MAILNAME="smtp.deuxfleurs.fr" \
-p 25:25 \
-p 465:465 \
-p 587:587 \
-v `pwd`/../../ansible/roles/container_conf/files/email/postfix-conf:/etc/postfix-conf \
-v /mnt/glusterfs/email/postfix-ssl/private:/etc/ssl/private \
-v /mnt/glusterfs/email/postfix-ssl/certs:/etc/ssl/certs \
superboum/amd64_postfix:v1 \
bash
```

View file

@ -0,0 +1,31 @@
#!/bin/bash
if [[ ! -f /etc/ssl/certs/postfix.crt || ! -f /etc/ssl/private/postfix.key ]]; then
cd /root
openssl req \
-new \
-newkey rsa:4096 \
-days 3650 \
-nodes \
-x509 \
-subj ${TLSINFO} \
-keyout postfix.key \
-out postfix.crt
mkdir -p /etc/ssl/{certs,private}/
cp postfix.crt /etc/ssl/certs/postfix.crt
cp postfix.key /etc/ssl/private/postfix.key
chmod 400 /etc/ssl/certs/postfix.crt
chmod 400 /etc/ssl/private/postfix.key
fi
# A way to map files inside the postfix folder :s
for file in $(ls /etc/postfix-conf); do
cp /etc/postfix-conf/${file} /etc/postfix/${file}
done
echo ${MAILNAME} > /etc/mailname
postmap /etc/postfix/transport
exec "$@"

View file

@ -0,0 +1,17 @@
#FROM amd64/debian:stretch as builder
FROM amd64/debian:buster
RUN mkdir ~/.gnupg && echo "disable-ipv6" >> ~/.gnupg/dirmngr.conf
RUN apt-get update && \
apt-get install -y apt-transport-https gnupg2 sudo nginx && \
rm -rf /etc/nginx/sites-enabled/* && \
apt-key adv --keyserver keys.gnupg.net --recv-key 0x810273C4 && \
echo "deb http://packages.inverse.ca/SOGo/nightly/5/debian/ buster buster" > /etc/apt/sources.list.d/sogo.list && \
apt-get update && \
apt-get install -y sogo sogo-activesync sope4.9-gdl1-postgresql postgresql-client
COPY sogo.nginx.conf /etc/nginx/sites-enabled/sogo.conf
COPY entrypoint /usr/sbin/entrypoint
ENTRYPOINT ["/usr/sbin/entrypoint"]

View file

@ -0,0 +1,20 @@
```
docker build -t superboum/amd64_sogo:v6 .
# privileged is only for debug
docker run --rm -ti \
--privileged \
-p 8080:8080 \
-v /tmp/sogo/log:/var/log/sogo \
-v /tmp/sogo/run:/var/run/sogo \
-v /tmp/sogo/spool:/var/spool/sogo \
-v /tmp/sogo/tmp:/tmp \
-v `pwd`/sogo:/etc/sogo:ro \
superboum/amd64_sogo:v1
```
Password must be url encoded in sogo.conf for postgres
Will need a nginx instance: http://wiki.sogo.nu/nginxSettings
Might (or might not) be needed:
traefik.frontend.headers.customRequestHeaders=x-webobjects-server-port:443||x-webobjects-server-name=sogo.deuxfleurs.fr||x-webobjects-server-url:https://sogo.deuxfleurs.fr

View file

@ -0,0 +1,13 @@
#!/bin/bash
mkdir -p /var/log/sogo
mkdir -p /var/run/sogo
mkdir -p /var/spool/sogo
chown sogo /var/log/sogo
chown sogo /var/run/sogo
chown sogo /var/spool/sogo
nginx -g 'daemon on; master_process on;'
sudo -u sogo memcached -d
sudo -u sogo sogod
sleep 10
tail -n200 -f /var/log/sogo/sogo.log

View file

@ -0,0 +1,83 @@
server {
listen 8080;
server_name default_server;
root /usr/lib/GNUstep/SOGo/WebServerResources/;
## requirement to create new calendars in Thunderbird ##
proxy_http_version 1.1;
# Message size limit
client_max_body_size 50m;
client_body_buffer_size 128k;
location = / {
rewrite ^ '/SOGo';
allow all;
}
location = /principals/ {
rewrite ^ '/SOGo/dav';
allow all;
}
location ^~/SOGo {
proxy_pass 'http://127.0.0.1:20000';
proxy_redirect 'http://127.0.0.1:20000' default;
# forward user's IP address
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_set_header x-webobjects-server-protocol HTTP/1.0;
proxy_set_header x-webobjects-remote-host 127.0.0.1;
proxy_set_header x-webobjects-server-name $server_name;
proxy_set_header x-webobjects-server-url $scheme://$host;
proxy_set_header x-webobjects-server-port $server_port;
proxy_connect_timeout 90;
proxy_send_timeout 90;
proxy_read_timeout 90;
proxy_buffer_size 4k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;
break;
}
location /SOGo.woa/WebServerResources/ {
alias /usr/lib/GNUstep/SOGo/WebServerResources/;
allow all;
expires max;
}
location /SOGo/WebServerResources/ {
alias /usr/lib/GNUstep/SOGo/WebServerResources/;
allow all;
expires max;
}
location (^/SOGo/so/ControlPanel/Products/([^/]*)/Resources/(.*)$) {
alias /usr/lib/GNUstep/SOGo/$1.SOGo/Resources/$2;
expires max;
}
location (^/SOGo/so/ControlPanel/Products/[^/]*UI/Resources/.*\.(jpg|png|gif|css|js)$) {
alias /usr/lib/GNUstep/SOGo/$1.SOGo/Resources/$2;
expires max;
}
location ^~ /Microsoft-Server-ActiveSync {
access_log /var/log/nginx/activesync.log;
error_log /var/log/nginx/activesync-error.log;
proxy_connect_timeout 75;
proxy_send_timeout 3600;
proxy_read_timeout 3600;
proxy_buffers 64 256k;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://127.0.0.1:20000/SOGo/Microsoft-Server-ActiveSync;
proxy_redirect http://127.0.0.1:20000/SOGo/Microsoft-Server-ActiveSync /;
}
}

View file

@ -0,0 +1 @@
smtp._domainkey.deuxfleurs.fr deuxfleurs.fr:smtp:/etc/dkim/smtp.private

View file

@ -0,0 +1,2 @@
*@deuxfleurs.fr smtp._domainkey.deuxfleurs.fr
*@dufour.io smtp._domainkey.deuxfleurs.fr

View file

@ -0,0 +1,4 @@
127.0.0.1
localhost
192.168.1.0/24
172.16.0.0/12

View file

@ -0,0 +1,13 @@
#!/bin/bash
TLSINFO="/C=FR/ST=Bretagne/L=Rennes/O=Deuxfleurs/CN=imap.deuxfleurs.fr"
openssl req \
-new \
-newkey rsa:4096 \
-days 3650 \
-nodes \
-x509 \
-subj ${TLSINFO} \
-keyout dovecot.key \
-out dovecot.crt

View file

@ -0,0 +1,12 @@
hosts = {{ env "meta.site" }}.bottin.service.prod.consul
dn = {{ key "secrets/email/dovecot/ldap_binddn" | trimSpace }}
dnpass = {{ key "secrets/email/dovecot/ldap_bindpwd" | trimSpace }}
base = dc=deuxfleurs,dc=fr
scope = subtree
user_filter = (&(mail=%u)(&(objectClass=inetOrgPerson)(memberOf=cn=email,ou=groups,dc=deuxfleurs,dc=fr)))
pass_filter = (&(mail=%u)(&(objectClass=inetOrgPerson)(memberOf=cn=email,ou=groups,dc=deuxfleurs,dc=fr)))
user_attrs = \
=user=%{ldap:cn}, \
=mail=maildir:/var/mail/%{ldap:cn}, \
=uid=1000, \
=gid=1000

View file

@ -0,0 +1,87 @@
auth_mechanisms = plain login
auth_username_format = %u
log_timestamp = "%Y-%m-%d %H:%M:%S "
mail_location = maildir:/var/mail/%u
mail_privileged_group = mail
log_path = /dev/stderr
info_log_path = /dev/stdout
debug_log_path = /dev/stdout
protocols = imap sieve lmtp
ssl_cert = < /etc/ssl/certs/dovecot.crt
ssl_key = < /etc/ssl/private/dovecot.key
service auth {
inet_listener {
port = 1337
}
}
service lmtp {
inet_listener lmtp {
address = 0.0.0.0
port = 24
}
}
# https://doc.dovecot.org/configuration_manual/authentication/ldap_authentication/
passdb {
args = /etc/dovecot/dovecot-ldap.conf
driver = ldap
}
userdb {
driver = prefetch
}
userdb {
args = /etc/dovecot/dovecot-ldap.conf
driver = ldap
}
service imap-login {
service_count = 0 # performance mode. set to 1 for secure mode
process_min_avail = 1
inet_listener imap {
port = 143
}
inet_listener imaps {
port = 993
}
}
protocol imap {
mail_plugins = $mail_plugins imap_sieve
}
protocol lda {
auth_socket_path = /var/run/dovecot/auth-master
info_log_path = /var/log/dovecot-deliver.log
log_path = /var/log/dovecot-deliver-errors.log
postmaster_address = postmaster@deuxfleurs.fr
mail_plugins = $mail_plugins sieve
}
plugin {
sieve = file:~/sieve;active=~/dovecot.sieve
sieve_before = /etc/dovecot/all_before.sieve
# antispam learn
sieve_plugins = sieve_imapsieve sieve_extprograms
sieve_global_extensions = +vnd.dovecot.pipe +vnd.dovecot.environment +vnd.dovecot.debug
sieve_pipe_bin_dir = /usr/bin
imapsieve_mailbox1_name = Junk
imapsieve_mailbox1_causes = COPY FLAG APPEND
imapsieve_mailbox1_before = file:/etc/dovecot/report-spam.sieve
imapsieve_mailbox2_name = *
imapsieve_mailbox2_from = Spam
imapsieve_mailbox2_causes = COPY APPEND
imapsieve_mailbox2_before = file:/etc/dovecot/report-ham.sieve
}

View file

@ -0,0 +1,13 @@
#!/bin/bash
TLSINFO="/C=FR/ST=Bretagne/L=Rennes/O=Deuxfleurs/CN=smtp.deuxfleurs.fr"
openssl req \
-new \
-newkey rsa:4096 \
-days 3650 \
-nodes \
-x509 \
-subj ${TLSINFO} \
-keyout postfix.key \
-out postfix.crt

View file

@ -0,0 +1,9 @@
# Postfix dynamic maps configuration file.
#
# The first match found is the one that is used. Wildcards are not supported
# as of postfix 2.0.2
#
#type location of .so file open function (mkmap func)
#==== ================================ ============= ============
ldap postfix-ldap.so dict_ldap_open
sqlite postfix-sqlite.so dict_sqlite_open

View file

@ -0,0 +1,3 @@
/^Received:/ IGNORE
/^X-Originating-IP:/ IGNORE
/^X-Mailer:/ IGNORE

View file

@ -0,0 +1,12 @@
bind = yes
bind_dn = {{ key "secrets/email/postfix/ldap_binddn" | trimSpace }}
bind_pw = {{ key "secrets/email/postfix/ldap_bindpwd" | trimSpace }}
version = 3
timeout = 20
start_tls = no
tls_require_cert = no
server_host = ldap://{{ env "meta.site" }}.bottin.service.prod.consul
scope = sub
search_base = ou=users,dc=deuxfleurs,dc=fr
query_filter = mail=%s
result_attribute = mail

View file

@ -0,0 +1,9 @@
server_host = {{ env "meta.site" }}.bottin.service.prod.consul
server_port = 389
search_base = dc=deuxfleurs,dc=fr
query_filter = (&(objectClass=inetOrgPerson)(memberOf=cn=%s,ou=mailing_lists,ou=groups,dc=deuxfleurs,dc=fr))
result_attribute = mail
bind = yes
bind_dn = {{ key "secrets/email/postfix/ldap_binddn" | trimSpace }}
bind_pw = {{ key "secrets/email/postfix/ldap_bindpwd" | trimSpace }}
version = 3

View file

@ -0,0 +1,12 @@
bind = yes
bind_dn = {{ key "secrets/email/postfix/ldap_binddn" | trimSpace }}
bind_pw = {{ key "secrets/email/postfix/ldap_bindpwd" | trimSpace }}
version = 3
timeout = 20
start_tls = no
tls_require_cert = no
server_host = ldap://{{ env "meta.site" }}.bottin.service.prod.consul
scope = sub
search_base = ou=domains,ou=groups,dc=deuxfleurs,dc=fr
query_filter = (&(objectclass=dNSDomain)(domain=%s))
result_attribute = domain

View file

@ -0,0 +1,105 @@
#===
# Base configuration
#===
myhostname = smtp.deuxfleurs.fr
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
myorigin = /etc/mailname
mydestination = smtp.deuxfleurs.fr
mynetworks = 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128 192.168.1.0/24
mailbox_size_limit = 0
recipient_delimiter = +
inet_protocols = all
inet_interfaces = all
message_size_limit = 204800000
smtpd_banner = $myhostname
biff = no
append_dot_mydomain = no
readme_directory = no
compatibility_level = 2
#===
# TLS parameters
#===
smtpd_tls_cert_file=/etc/ssl/postfix.crt
smtpd_tls_key_file=/etc/ssl/postfix.key
smtpd_tls_dh1024_param_file=auto
smtpd_use_tls=yes
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
#smtp_tls_policy_maps = hash:/etc/postfix/tls_policy
smtp_tls_security_level = may
#===
# Remove privacy related content from emails
#===
mime_header_checks = regexp:/etc/postfix/header_checks
header_checks = regexp:/etc/postfix/header_checks
#===
# Handle user authentication (handled by dovecot)
#===
smtpd_sasl_auth_enable = yes
smtpd_sasl_path = inet:dovecot-auth.service.prod.consul:1337
smtpd_sasl_type = dovecot
#===
# Restrictions / Checks
#===
# -- Inspired by: http://www.postfix.org/SMTPD_ACCESS_README.html#lists
# Require a valid HELO
smtpd_helo_required = yes
# As we use the same postfix to send and receive,
# we can't enforce a valid HELO hostname...
#smtpd_helo_restrictions =
# reject_unknown_helo_hostname
# Require that sender email has a valid domain
smtpd_sender_restrictions =
reject_unknown_sender_domain
# Delivering email policy
# MyNetwork is required by sogo
smtpd_recipient_restrictions =
permit_sasl_authenticated
permit_mynetworks
reject_unauth_destination
reject_rbl_client zen.spamhaus.org
reject_rhsbl_reverse_client dbl.spamhaus.org
reject_rhsbl_helo dbl.spamhaus.org
reject_rhsbl_sender dbl.spamhaus.org
# Sending email policy
# MyNetwork is required by sogo
smtpd_relay_restrictions =
permit_sasl_authenticated
permit_mynetworks
reject_unauth_destination
smtpd_data_restrictions = reject_unauth_pipelining
smtpd_client_connection_rate_limit = 2
#===
# Rate limiting
#===
slow_destination_recipient_limit = 20
slow_destination_concurrency_limit = 2
#====
# Transport configuration
#====
transport_maps = hash:/etc/postfix/transport
virtual_mailbox_domains = ldap:/etc/postfix/ldap-virtual-domains.cf
virtual_mailbox_maps = ldap:/etc/postfix/ldap-account.cf
virtual_alias_maps = ldap:/etc/postfix/ldap-alias.cf
virtual_transport = lmtp:dovecot-lmtp.service.prod.consul:24
#===
# Mail filters
#===
milter_default_action = accept
milter_protocol = 6
smtpd_milters = inet:opendkim.service.prod.consul:8999
non_smtpd_milters = inet:opendkim.service.prod.consul:8999

View file

@ -0,0 +1,114 @@
#
# Postfix master process configuration file. For details on the format
# of the file, see the master(5) manual page (command: "man 5 master").
#
# Do not forget to execute "postfix reload" after editing this file.
#
# ==========================================================================
# service type private unpriv chroot wakeup maxproc command + args
# (yes) (yes) (yes) (never) (100)
# ==========================================================================
smtp inet n - n - - smtpd
submission inet n - n - - smtpd
-o smtpd_tls_security_level=encrypt
-o smtpd_sasl_auth_enable=yes
-o smtpd_client_restrictions=permit_sasl_authenticated,reject
-o milter_macro_daemon_name=ORIGINATING
smtps inet n - n - - smtpd
-o smtpd_tls_wrappermode=yes
-o smtpd_sasl_auth_enable=yes
-o smtpd_client_restrictions=permit_sasl_authenticated,reject
-o milter_macro_daemon_name=ORIGINATING
slow unix - - n - 5 smtp
-o syslog_name=postfix-slow
-o smtp_destination_concurrency_limit=3
-o slow_destination_rate_delay=1
#628 inet n - - - - qmqpd
pickup fifo n - n 60 1 pickup
cleanup unix n - n - 0 cleanup
qmgr fifo n - n 300 1 qmgr
#qmgr fifo n - - 300 1 oqmgr
tlsmgr unix - - n 1000? 1 tlsmgr
rewrite unix - - n - - trivial-rewrite
bounce unix - - n - 0 bounce
defer unix - - n - 0 bounce
trace unix - - n - 0 bounce
verify unix - - n - 1 verify
flush unix n - n 1000? 0 flush
proxymap unix - - n - - proxymap
proxywrite unix - - n - 1 proxymap
# When relaying mail as backup MX, disable fallback_relay to avoid MX loops
smtp unix - - n - - smtp
# -o smtp_helo_timeout=5 -o smtp_connect_timeout=5
relay unix - - n - - smtp
-o smtp_fallback_relay=
showq unix n - n - - showq
error unix - - n - - error
retry unix - - n - - error
discard unix - - n - - discard
local unix - n n - - local
virtual unix - n n - - virtual
lmtp unix - - n - - lmtp
anvil unix - - n - 1 anvil
#
# ====================================================================
# Interfaces to non-Postfix software. Be sure to examine the manual
# pages of the non-Postfix software to find out what options it wants.
#
# Many of the following services use the Postfix pipe(8) delivery
# agent. See the pipe(8) man page for information about ${recipient}
# and other message envelope options.
# ====================================================================
#
# maildrop. See the Postfix MAILDROP_README file for details.
# Also specify in main.cf: maildrop_destination_recipient_limit=1
#
scache unix - - n - 1 scache
maildrop unix - n n - - pipe
flags=DRhu user=vmail argv=/usr/bin/maildrop -d ${recipient}
#
# ====================================================================
#
# Recent Cyrus versions can use the existing "lmtp" master.cf entry.
#
# Specify in cyrus.conf:
# lmtp cmd="lmtpd -a" listen="localhost:lmtp" proto=tcp4
#
# Specify in main.cf one or more of the following:
# mailbox_transport = lmtp:inet:localhost
# virtual_transport = lmtp:inet:localhost
#
# ====================================================================
#
# Cyrus 2.1.5 (Amos Gouaux)
# Also specify in main.cf: cyrus_destination_recipient_limit=1
#
#cyrus unix - n n - - pipe
# user=cyrus argv=/cyrus/bin/deliver -e -r ${sender} -m ${extension} ${user}
#
# ====================================================================
# Old example of delivery via Cyrus.
#
#old-cyrus unix - n n - - pipe
# flags=R user=cyrus argv=/cyrus/bin/deliver -e -m ${extension} ${user}
#
# ====================================================================
#
# See the Postfix UUCP_README file for configuration details.
#
uucp unix - n n - - pipe
flags=Fqhu user=uucp argv=uux -r -n -z -a$sender - $nexthop!rmail ($recipient)
#
# Other external delivery methods.
#
ifmail unix - n n - - pipe
flags=F user=ftn argv=/usr/lib/ifmail/ifmail -r $nexthop ($recipient)
bsmtp unix - n n - - pipe
flags=Fq. user=bsmtp argv=/usr/lib/bsmtp/bsmtp -t$nexthop -f$sender $recipient
scalemail-backend unix - n n - 2 pipe
flags=R user=scalemail argv=/usr/lib/scalemail/bin/scalemail-store ${nexthop} ${user} ${extension}
mailman unix - n n - - pipe
flags=FR user=list argv=/usr/lib/mailman/bin/postfix-to-mailman.py
${nexthop} ${user}

View file

@ -0,0 +1,5 @@
#wanadoo.com slow:
#wanadoo.fr slow:
#orange.com slow:
#orange.fr slow:
#smtp.orange.fr slow:

Binary file not shown.

View file

@ -0,0 +1,69 @@
{
WONoDetach = NO;
WOWorkersCount = 3;
SxVMemLimit = 300;
WOPort = "127.0.0.1:20000";
SOGoProfileURL = "postgresql://{{ key "secrets/email/sogo/postgre_auth" | trimSpace }}@psql-proxy.service.prod.consul:5432/sogo/sogo_user_profile";
OCSFolderInfoURL = "postgresql://{{ key "secrets/email/sogo/postgre_auth" | trimSpace }}@psql-proxy.service.prod.consul:5432/sogo/sogo_folder_info";
OCSSessionsFolderURL = "postgresql://{{ key "secrets/email/sogo/postgre_auth" | trimSpace }}@psql-proxy.service.prod.consul:5432/sogo/sogo_sessions_folder";
OCSEMailAlarmsFolderURL = "postgresql://{{ key "secrets/email/sogo/postgre_auth" | trimSpace }}@psql-proxy.service.prod.consul:5432/sogo/sogo_alarms_folder";
OCSStoreURL = "postgresql://{{ key "secrets/email/sogo/postgre_auth" | trimSpace }}@psql-proxy.service.prod.consul:5432/sogo/sogo_store";
OCSAclURL = "postgresql://{{ key "secrets/email/sogo/postgre_auth" | trimSpace }}@psql-proxy.service.prod.consul:5432/sogo/sogo_acl";
OCSCacheFolderURL = "postgresql://{{ key "secrets/email/sogo/postgre_auth" | trimSpace }}@psql-proxy.service.prod.consul:5432/sogo/sogo_cache_folder";
SOGoTimeZone = "Europe/Paris";
SOGoMailDomain = "deuxfleurs.fr";
SOGoLanguage = French;
SOGoAppointmentSendEMailNotifications = YES;
SOGoEnablePublicAccess = YES;
SOGoMailingMechanism = smtp;
SOGoSMTPServer = postfix-smtp.service.prod.consul;
SOGoSMTPAuthenticationType = PLAIN;
SOGoForceExternalLoginWithEmail = YES;
SOGoIMAPAclConformsToIMAPExt = YES;
SOGoTimeZone = UTC;
SOGoSentFolderName = Sent;
SOGoTrashFolderName = Trash;
SOGoDraftsFolderName = Drafts;
SOGoIMAPServer = "imaps://dovecot-imaps.service.prod.consul:993/?tlsVerifyMode=none";
SOGoSieveServer = "sieve://sieve.service.prod.consul:4190/?tls=YES";
SOGoIMAPAclConformsToIMAPExt = YES;
SOGoVacationEnabled = NO;
SOGoForwardEnabled = NO;
SOGoSieveScriptsEnabled = NO;
SOGoFirstDayOfWeek = 1;
SOGoRefreshViewCheck = every_5_minutes;
SOGoMailAuxiliaryUserAccountsEnabled = NO;
SOGoPasswordChangeEnabled = YES;
SOGoPageTitle = "deuxfleurs.fr";
SOGoLoginModule = Mail;
SOGoMailAddOutgoingAddresses = YES;
SOGoSelectedAddressBook = autobook;
SOGoMailAuxiliaryUserAccountsEnabled = YES;
SOGoCalendarEventsDefaultClassification = PRIVATE;
SOGoMailReplyPlacement = above;
SOGoMailSignaturePlacement = above;
SOGoMailComposeMessageType = html;
SOGoLDAPContactInfoAttribute = "displayname";
SOGoUserSources = (
{
type = ldap;
CNFieldName = displayname;
IDFieldName = cn;
UIDFieldName = cn;
MailFieldNames = (mail, mailForwardingAddress);
SearchFieldNames = (displayname, cn, sn, mail, telephoneNumber);
IMAPLoginFieldName = mail;
baseDN = "ou=users,dc=deuxfleurs,dc=fr";
bindDN = "{{ key "secrets/email/sogo/ldap_binddn" | trimSpace }}";
bindPassword = "{{ key "secrets/email/sogo/ldap_bindpw" | trimSpace}}";
bindFields = (cn, mail);
canAuthenticate = YES;
displayName = "Bottin";
hostname = "ldap://{{ env "meta.site" }}.bottin.service.prod.consul:389";
id = bottin;
isAddressBook = NO;
}
);
}

View file

@ -0,0 +1,505 @@
job "email" {
datacenters = ["orion"]
type = "service"
priority = 65
group "dovecot" {
count = 1
network {
port "zauthentication_port" {
static = 1337
to = 1337
}
port "imaps_port" {
static = 993
to = 993
}
port "imap_port" {
static = 143
to = 143
}
port "lmtp_port" {
static = 24
to = 24
}
}
task "server" {
driver = "docker"
constraint {
attribute = "${attr.unique.hostname}"
operator = "="
value = "doradille"
}
config {
image = "superboum/amd64_dovecot:v6"
readonly_rootfs = false
network_mode = "host"
ports = [ "zauthentication_port", "imaps_port", "imap_port", "lmtp_port" ]
command = "dovecot"
args = [ "-F" ]
volumes = [
"secrets/ssl/certs:/etc/ssl/certs",
"secrets/ssl/private:/etc/ssl/private",
"secrets/conf/:/etc/dovecot/",
"/mnt/ssd/mail:/var/mail/",
]
}
env {
TLSINFO = "/C=FR/ST=Bretagne/L=Rennes/O=Deuxfleurs/CN=imap.deuxfleurs.fr"
}
resources {
cpu = 100
memory = 200
}
service {
name = "dovecot-imap"
port = "imap_port"
tags = [
"dovecot"
]
check {
type = "tcp"
port = "imap_port"
interval = "60s"
timeout = "5s"
check_restart {
limit = 3
grace = "90s"
ignore_warnings = false
}
}
}
service {
name = "dovecot-imaps"
port = "imaps_port"
tags = [
"dovecot",
"(diplonat (tcp_port 993))"
]
check {
type = "tcp"
port = "imaps_port"
interval = "60s"
timeout = "5s"
check_restart {
limit = 3
grace = "90s"
ignore_warnings = false
}
}
}
service {
name = "dovecot-lmtp"
port = "lmtp_port"
tags = [
"dovecot",
]
check {
type = "tcp"
port = "lmtp_port"
interval = "60s"
timeout = "5s"
check_restart {
limit = 3
grace = "90s"
ignore_warnings = false
}
}
}
service {
name = "dovecot-auth"
port = "zauthentication_port"
tags = [
"dovecot",
]
check {
type = "tcp"
port = "zauthentication_port"
interval = "60s"
timeout = "5s"
check_restart {
limit = 3
grace = "90s"
ignore_warnings = false
}
}
}
template {
data = file("../config/dovecot/dovecot-ldap.conf.tpl")
destination = "secrets/conf/dovecot-ldap.conf"
perms = "400"
}
template {
data = file("../config/dovecot/dovecot.conf")
destination = "secrets/conf/dovecot.conf"
perms = "400"
}
# ----- secrets ------
template {
# data = "{{ key \"secrets/email/dovecot/dovecot.crt\" }}"
data = "{{ with $d := key \"tricot/certs/imap.deuxfleurs.fr\" | parseJSON }}{{ $d.cert_pem }}{{ end }}"
destination = "secrets/ssl/certs/dovecot.crt"
perms = "400"
}
template {
# data = "{{ key \"secrets/email/dovecot/dovecot.key\" }}"
data = "{{ with $d := key \"tricot/certs/imap.deuxfleurs.fr\" | parseJSON }}{{ $d.key_pem }}{{ end }}"
destination = "secrets/ssl/private/dovecot.key"
perms = "400"
}
}
}
group "opendkim" {
count = 1
network {
port "dkim_port" {
static = 8999
to = 8999
}
}
task "server" {
driver = "docker"
config {
image = "superboum/amd64_opendkim:v6"
readonly_rootfs = false
ports = [ "dkim_port" ]
volumes = [
"/dev/log:/dev/log",
"secrets/dkim:/etc/dkim",
]
}
resources {
cpu = 100
memory = 50
}
service {
name = "opendkim"
port = "dkim_port"
address_mode = "host"
tags = [
"opendkim",
]
check {
type = "tcp"
port = "dkim_port"
interval = "60s"
timeout = "5s"
check_restart {
limit = 3
grace = "90s"
ignore_warnings = false
}
}
}
template {
data = file("../config/dkim/keytable")
destination = "secrets/dkim/keytable"
}
template {
data = file("../config/dkim/signingtable")
destination = "secrets/dkim/signingtable"
}
template {
data = file("../config/dkim/trusted")
destination = "secrets/dkim/trusted"
}
# --- secrets ---
template {
data = "{{ key \"secrets/email/dkim/smtp.private\" }}"
destination = "secrets/dkim/smtp.private"
}
}
}
group "postfix" {
count = 1
network {
port "smtp_port" {
static = 25
to = 25
}
port "smtps_port" {
static = 465
to = 465
}
port "submission_port" {
static = 587
to = 587
}
}
task "server" {
driver = "docker"
config {
image = "superboum/amd64_postfix:v3"
readonly_rootfs = false
network_mode = "host"
ports = [ "smtp_port", "smtps_port", "submission_port" ]
command = "postfix"
args = [ "start-fg" ]
volumes = [
"secrets/ssl:/etc/ssl",
"secrets/postfix:/etc/postfix-conf",
"/dev/log:/dev/log"
]
}
env {
TLSINFO = "/C=FR/ST=Bretagne/L=Rennes/O=Deuxfleurs/CN=smtp.deuxfleurs.fr"
MAILNAME = "smtp.deuxfleurs.fr"
}
resources {
cpu = 100
memory = 200
}
service {
name = "postfix-smtp"
port = "smtp_port"
address_mode = "host"
tags = [
"postfix",
"(diplonat (tcp_port 25 465 587))"
]
check {
type = "tcp"
port = "smtp_port"
interval = "60s"
timeout = "5s"
check_restart {
limit = 3
grace = "90s"
ignore_warnings = false
}
}
}
service {
name = "postfix-smtps"
port = "smtps_port"
address_mode = "host"
tags = [
"postfix",
]
check {
type = "tcp"
port = "smtps_port"
interval = "60s"
timeout = "5s"
check_restart {
limit = 3
grace = "90s"
ignore_warnings = false
}
}
}
service {
name = "postfix-submission"
port = "submission_port"
address_mode = "host"
tags = [
"postfix",
]
check {
type = "tcp"
port = "submission_port"
interval = "60s"
timeout = "5s"
check_restart {
limit = 3
grace = "90s"
ignore_warnings = false
}
}
}
template {
data = file("../config/postfix/ldap-account.cf.tpl")
destination = "secrets/postfix/ldap-account.cf"
}
template {
data = file("../config/postfix/ldap-alias.cf.tpl")
destination = "secrets/postfix/ldap-alias.cf"
}
template {
data = file("../config/postfix/ldap-virtual-domains.cf.tpl")
destination = "secrets/postfix/ldap-virtual-domains.cf"
}
template {
data = file("../config/postfix/dynamicmaps.cf")
destination = "secrets/postfix/dynamicmaps.cf"
}
template {
data = file("../config/postfix/header_checks")
destination = "secrets/postfix/header_checks"
}
template {
data = file("../config/postfix/main.cf")
destination = "secrets/postfix/main.cf"
}
template {
data = file("../config/postfix/master.cf")
destination = "secrets/postfix/master.cf"
}
template {
data = file("../config/postfix/transport")
destination = "secrets/postfix/transport"
}
# --- secrets ---
template {
# data = "{{ key \"secrets/email/postfix/postfix.crt\" }}"
data = "{{ with $d := key \"tricot/certs/smtp.deuxfleurs.fr\" | parseJSON }}{{ $d.cert_pem }}{{ end }}"
destination = "secrets/ssl/postfix.crt"
perms = "400"
}
template {
# data = "{{ key \"secrets/email/postfix/postfix.key\" }}"
data = "{{ with $d := key \"tricot/certs/smtp.deuxfleurs.fr\" | parseJSON }}{{ $d.key_pem }}{{ end }}"
destination = "secrets/ssl/postfix.key"
perms = "400"
}
}
}
group "alps" {
count = 1
network {
port "alps_web_port" { to = 1323 }
}
task "main" {
driver = "docker"
config {
image = "lxpz/alps_amd64:v2"
readonly_rootfs = true
ports = [ "alps_web_port" ]
args = [
"-skiptlsverification",
"-theme",
"alps",
"imaps://imap.deuxfleurs.fr:993",
"smtps://smtp.deuxfleurs.fr:465"
]
}
resources {
cpu = 100
memory = 100
}
service {
name = "alps"
port = "alps_web_port"
address_mode = "host"
tags = [
"alps",
"traefik.enable=true",
"traefik.frontend.entryPoints=https,http",
"traefik.frontend.rule=Host:alps.deuxfleurs.fr",
"tricot alps.deuxfleurs.fr",
]
check {
type = "tcp"
port = "alps_web_port"
interval = "60s"
timeout = "5s"
check_restart {
limit = 3
grace = "5m"
ignore_warnings = false
}
}
}
}
}
group "sogo" {
count = 1
network {
port "sogo_web_port" { to = 8080 }
}
task "bundle" {
driver = "docker"
config {
image = "superboum/amd64_sogo:v7"
readonly_rootfs = false
ports = [ "sogo_web_port" ]
volumes = [
"secrets/sogo.conf:/etc/sogo/sogo.conf",
]
}
template {
data = file("../config/sogo/sogo.conf.tpl")
destination = "secrets/sogo.conf"
}
resources {
cpu = 200
memory = 1000
}
service {
name = "sogo"
port = "sogo_web_port"
address_mode = "host"
tags = [
"sogo",
"tricot www.sogo.deuxfleurs.fr",
"tricot sogo.deuxfleurs.fr",
]
check {
type = "tcp"
port = "sogo_web_port"
interval = "60s"
timeout = "5s"
check_restart {
limit = 3
grace = "5m"
ignore_warnings = false
}
}
}
}
}
}

View file

@ -0,0 +1 @@
RSA_PRIVATE_KEY dkim

View file

@ -0,0 +1 @@
USER AWS Acces Key ID

View file

@ -0,0 +1 @@
USER AWS Secret Access key

View file

@ -0,0 +1 @@
USER Restic backup password to encrypt data

View file

@ -0,0 +1 @@
USER Restic Repository URL, check op_guide/backup-minio to see the format

View file

@ -0,0 +1 @@
SSL_CERT dovecot deuxfleurs.fr

View file

@ -0,0 +1 @@
SSL_KEY dovecot

View file

@ -0,0 +1 @@
SERVICE_DN dovecot Dovecot IMAP server

View file

@ -0,0 +1 @@
SERVICE_PASSWORD dovecot

View file

@ -0,0 +1 @@
SSL_CERT postfix deuxfleurs.fr

View file

@ -0,0 +1 @@
SSL_KEY postfix

View file

@ -0,0 +1 @@
SERVICE_DN sogo SoGo email frontend

View file

@ -0,0 +1 @@
SERVICE_PASSWORD sogo

View file

@ -0,0 +1 @@
USER SoGo postgres auth (format: sogo:<password>) (TODO: replace this with two separate files and change template)