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", "d53-a imap.deuxfleurs.fr", ] 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 = "{{ with $d := key \"tricot/certs/imap.deuxfleurs.fr\" | parseJSON }}{{ $d.cert_pem }}{{ end }}" destination = "secrets/ssl/certs/dovecot.crt" perms = "400" } template { 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))", "d53-a email-in.deuxfleurs.fr", "d53-a smtp.deuxfleurs.fr", # ipv6 is commented for now as port is not open in firewall (TODO) # "d53-aaaa email-in.deuxfleurs.fr" ] 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 = "{{ with $d := key \"tricot/certs/smtp.deuxfleurs.fr\" | parseJSON }}{{ $d.cert_pem }}{{ end }}" destination = "secrets/ssl/postfix.crt" perms = "400" } template { 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/amd64_alps:v4" 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 = 500 memory_max = 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 } } } } } }