Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • justJanne/helm
1 result
Show changes
Commits on Source (2)
Showing
with 13 additions and 1292 deletions
......@@ -7,17 +7,16 @@ stages:
- lint
- release
include:
- /actual/pipeline.yml
- /flood/pipeline.yml
- /imghost/pipeline.yml
- /jellyfin/pipeline.yml
- /languagetool/pipeline.yml
- /mailu/pipeline.yml
- /mastodon/pipeline.yml
- /oauth2-proxy/pipeline.yml
- /powerdns/pipeline.yml
- /postgresql/pipeline.yml
- /quassel/pipeline.yml
- /restic/pipeline.yml
- /rtorrent/pipeline.yml
- /seafile/pipeline.yml
- /actual/pipeline.yml
- /flood/pipeline.yml
- /imghost/pipeline.yml
- /jellyfin/pipeline.yml
- /languagetool/pipeline.yml
- /mastodon/pipeline.yml
- /oauth2-proxy/pipeline.yml
- /powerdns/pipeline.yml
- /postgresql/pipeline.yml
- /quassel/pipeline.yml
- /restic/pipeline.yml
- /rtorrent/pipeline.yml
- /seafile/pipeline.yml
apiVersion: v2
name: mailu
description: Helm Chart for Mailu
type: application
version: 1.3.7
appVersion: "1.9.28"
lint-mailu:
stage: lint
rules:
- changes:
- mailu/**/*
script:
- helm lint mailu
release-mailu:
stage: release
needs:
- lint-mailu
rules:
- if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
changes:
- mailu/**/*
script:
- apk add --no-cache git
- helm plugin install https://github.com/chartmuseum/helm-push.git
- helm repo add --username gitlab-ci-token --password $CI_JOB_TOKEN repo ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/helm/stable
- helm cm-push mailu repo
{{/*
Expand the name of the chart.
*/}}
{{- define "mailu-helm.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
If release name contains chart name it will be used as a full name.
*/}}
{{- define "mailu-helm.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- if contains $name .Release.Name }}
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{- end }}
{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "mailu-helm.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Common labels
*/}}
{{- define "mailu-helm.labels" -}}
helm.sh/chart: {{ include "mailu-helm.chart" . }}
{{ include "mailu-helm.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
{{/*
Selector labels
*/}}
{{- define "mailu-helm.selectorLabels" -}}
app.kubernetes.io/name: {{ include "mailu-helm.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: {{ include "mailu-helm.fullname" . }}-tls
spec:
commonName: {{ .Values.certificate.commonName }}
dnsNames:
{{- toYaml .Values.certificate.hostnames | nindent 4 }}
issuerRef:
kind: ClusterIssuer
name: {{ .Values.certificate.issuer }}
secretName: {{ include "mailu-helm.fullname" . }}-tls
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "mailu-helm.fullname" . }}-admin
labels:
component: admin
{{- include "mailu-helm.labels" . | nindent 4 }}
data:
start.py: |-
#!/usr/bin/python3
import os
import logging as log
import sys
log.basicConfig(stream=sys.stderr, level=os.environ.get("LOG_LEVEL", "INFO"))
os.system("flask db upgrade")
account = os.environ.get("INITIAL_ADMIN_ACCOUNT")
domain = os.environ.get("INITIAL_ADMIN_DOMAIN")
password = os.environ.get("INITIAL_ADMIN_PW")
if account is not None and domain is not None and password is not None:
mode = os.environ.get("INITIAL_ADMIN_MODE", default="ifmissing")
log.info("Creating initial admin accout %s@%s with mode %s", account, domain, mode)
os.system("flask mailu admin %s %s '%s' --mode %s" % (account, domain, password, mode))
def test_DNS():
import dns.resolver
import dns.exception
import dns.flags
import dns.rdtypes
import dns.rdatatype
import dns.rdataclass
import time
# DNS stub configured to do DNSSEC enabled queries
resolver = dns.resolver.Resolver()
resolver.use_edns(0, dns.flags.DO, 1232)
resolver.flags = dns.flags.AD | dns.flags.RD
nameservers = resolver.nameservers
for ns in nameservers:
resolver.nameservers = [ns]
while True:
try:
result = resolver.resolve('example.org', dns.rdatatype.A, dns.rdataclass.IN, lifetime=10)
except Exception as e:
log.critical(
"Your DNS resolver at %s is not working (%s). Please see https://mailu.io/master/faq.html#the-admin-container-won-t-start-and-its-log-says-critical-your-dns-resolver-isn-t-doing-dnssec-validation",
ns, e);
else:
if result.response.flags & dns.flags.AD:
break
log.critical(
"Your DNS resolver at %s isn't doing DNSSEC validation; Please see https://mailu.io/master/faq.html#the-admin-container-won-t-start-and-its-log-says-critical-your-dns-resolver-isn-t-doing-dnssec-validation.",
ns)
time.sleep(5)
test_DNS()
start_command = "".join([
"gunicorn --threads ", str(os.cpu_count()),
" -b :80 ",
"--access-logfile - " if (log.root.level <= log.INFO) else "",
"--error-logfile - ",
"--preload ",
"'mailu:create_app()'"])
os.system(start_command)
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "mailu-helm.fullname" . }}-autodiscover
labels:
{{- include "mailu-helm.labels" . | nindent 4 }}
component: autodiscover
data:
config-v1.1.xml: |-
<?xml version="1.0" encoding="UTF-8"?>
<clientConfig version="1.1">
<emailProvider id="{{ .Values.config.domain }}">
<domain>{{ .Values.config.domain }}</domain>
<displayName>{{ .Values.config.siteName }}</displayName>
<displayShortName>{{ .Values.config.domain }}</displayShortName>
<incomingServer type="imap">
<hostname>{{ .Values.config.domain }}</hostname>
<port>993</port>
<socketType>SSL</socketType>
<authentication>password-cleartext</authentication>
<username>%EMAILADDRESS%</username>
</incomingServer>
<outgoingServer type="smtp">
<hostname>kuschku.de</hostname>
<port>465</port>
<socketType>SSL</socketType>
<authentication>password-cleartext</authentication>
<username>%EMAILADDRESS%</username>
</outgoingServer>
<documentation url="{{ .Values.admin.host }}{{ .Values.admin.path }}/ui/client">
<descr lang="en">Configure your email client</descr>
</documentation>
</emailProvider>
</clientConfig>
autodiscover.xml: |-
<?xml version="1.0" encoding="utf-8" ?>
<Autodiscover xmlns="http://schemas.microsoft.com/exchange/autodiscover/responseschema/2006">
<Response xmlns="http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a">
<User>
<DisplayName>{{ .Values.config.siteName }}</DisplayName>
</User>
<Account>
<AccountType>email</AccountType>
<Action>settings</Action>
<ServiceHome>{{ .Values.admin.host }}{{ .Values.admin.path }}</ServiceHome>
<Protocol>
<Type>IMAP</Type>
<Server>{{ .Values.config.domain }}</Server>
<Port>993</Port>
<DomainRequired>true</DomainRequired>
<SPA>off</SPA>
<SSL>on</SSL>
<AuthRequired>on</AuthRequired>
<SMTPLast>off</SMTPLast>
</Protocol>
<Protocol>
<Type>SMTP</Type>
<Server>{{ .Values.config.domain }}</Server>
<Port>465</Port>
<DomainRequired>true</DomainRequired>
<SPA>off</SPA>
<SSL>on</SSL>
<AuthRequired>on</AuthRequired>
<SMTPLast>off</SMTPLast>
</Protocol>
<Protocol>
<Type>DAV</Type>
<Server>{{ .Values.webdav.host }}{{ .Values.webdav.path }}</Server>
<DomainRequired>true</DomainRequired>
<SPA>off</SPA>
<SSL>on</SSL>
<AuthRequired>on</AuthRequired>
</Protocol>
</Account>
</Response>
</Autodiscover>
mta-sts.txt: |-
version: STSv1
mode: enforce
{{ range .Values.config.hostnames -}}
mx: {{ . }}
{{ end -}}
max_age: 1209600
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "mailu-helm.fullname" . }}-front
labels:
component: front
{{- include "mailu-helm.labels" . | nindent 4 }}
data:
nginx.conf: |-
# Basic configuration
user nginx;
worker_processes auto;
error_log /dev/stderr notice;
pid /var/run/nginx.pid;
load_module "modules/ngx_mail_module.so";
events {
worker_connections 1024;
}
http {
# Standard HTTP configuration with slight hardening
include /etc/nginx/mime.types;
default_type application/octet-stream;
access_log /dev/stdout;
sendfile on;
keepalive_timeout 65;
server_tokens off;
absolute_redirect off;
resolver {{ "{{" }} RESOLVER }} valid=30s;
{% if REAL_IP_HEADER %}
real_ip_header {{ "{{" }} REAL_IP_HEADER }};
{% endif %}
{% if REAL_IP_FROM %}{% for from_ip in REAL_IP_FROM.split(',') %}
set_real_ip_from {{ "{{" }} from_ip }};
{% endfor %}{% endif %}
# Header maps
map $http_x_forwarded_proto $proxy_x_forwarded_proto {
default $http_x_forwarded_proto;
'' $scheme;
}
}
mail {
server_name "{{ .Values.config.domain }}";
auth_http http://{{ include "mailu-helm.fullname" . }}-admin.{{ .Release.Namespace }}.svc.{{ .Values.clusterSuffix }}/internal/auth/email;
proxy_pass_error_message on;
resolver {{ "{{" }} RESOLVER }} valid=30s;
{% if TLS and not TLS_ERROR %}
include /etc/nginx/tls.conf;
ssl_session_cache shared:SSLMAIL:50m;
{% endif %}
# Advertise real capabilites of backends (postfix/dovecot)
smtp_capabilities PIPELINING SIZE {{ "{{" }} MESSAGE_SIZE_LIMIT }} ETRN ENHANCEDSTATUSCODES 8BITMIME DSN;
pop3_capabilities TOP UIDL RESP-CODES PIPELINING AUTH-RESP-CODE USER;
imap_capabilities IMAP4 IMAP4rev1 UIDPLUS SASL-IR LOGIN-REFERRALS ID ENABLE IDLE LITERAL+;
# Default SMTP server for the webmail (no encryption, but authentication)
server {
listen 10025;
protocol smtp;
smtp_auth plain;
auth_http_header Auth-Port 10025;
}
# Default IMAP server for the webmail (no encryption, but authentication)
server {
listen 10143;
protocol imap;
smtp_auth plain;
auth_http_header Auth-Port 10143;
}
# All other protocols are disabled if TLS is failing
{% if not TLS_ERROR %}
server {
listen 143;
listen [::]:143;
{% if TLS %}
starttls only;
{% endif %}
protocol imap;
imap_auth plain;
auth_http_header Auth-Port 143;
}
server {
listen 110;
listen [::]:110;
{% if TLS %}
starttls only;
{% endif %}
protocol pop3;
pop3_auth plain;
auth_http_header Auth-Port 110;
}
server {
listen 587;
listen [::]:587;
{% if TLS %}
starttls only;
{% endif %}
protocol smtp;
smtp_auth plain login;
auth_http_header Auth-Port 587;
}
{% if TLS %}
server {
listen 465 ssl;
listen [::]:465 ssl;
protocol smtp;
smtp_auth plain login;
auth_http_header Auth-Port 465;
}
server {
listen 993 ssl;
listen [::]:993 ssl;
protocol imap;
imap_auth plain;
auth_http_header Auth-Port 993;
}
server {
listen 995 ssl;
listen [::]:995 ssl;
protocol pop3;
pop3_auth plain;
auth_http_header Auth-Port 995;
}
{% endif %}
{% endif %}
}
tls.conf: |-
ssl_protocols TLSv1.3 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:EECDH+AESGCM:EDH+AESGCM:DHE-RSA-CHACHA20-POLY1305:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!RC4:!SEED:!CAMELLIA;
ssl_ecdh_curve secp384r1;
ssl_session_timeout 10m;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
ssl_certificate {{ "{{" }} TLS[0] }};
ssl_certificate_key {{ "{{" }} TLS[1] }};
ssl_dhparam /conf/dhparam.pem;
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "mailu-helm.fullname" . }}
labels:
{{- include "mailu-helm.labels" . | nindent 4 }}
data:
ADMIN: "{{ .Values.admin.enabled }}"
ANTIVIRUS: "none"
AUTH_RATELIMIT: "10/minute;1000/hour"
BIND_ADDRESS4: "127.0.0.1"
BIND_ADDRESS6: "::1"
DB_FLAVOR: "{{ .Values.database.flavor }}"
DB_HOST: "{{ .Values.database.host }}"
DB_NAME: "{{ .Values.database.database }}"
DMARC_RUA: "{{ .Values.dmarc.rua }}"
DMARC_RUF: "{{ .Values.dmarc.ruf }}"
DOMAIN: "{{ .Values.config.domain }}"
FETCHMAIL_DELAY: "600"
HOSTNAMES: "{{ join "," .Values.config.hostnames }}"
KUBERNETES_INGRESS: "true"
MESSAGE_SIZE_LIMIT: "{{ .Values.config.messageSizeLimit }}"
PASSWORD_SCHEME: "{{ .Values.config.passwordScheme }}"
POD_ADDRESS_RANGE: "{{ .Values.config.realIpFrom }}"
POSTMASTER: "{{ .Values.config.postmaster }}"
REAL_IP_FROM: "{{ .Values.config.realIpFrom }}"
REAL_IP_HEADER: "{{ .Values.config.realIpHeader }}"
RECIPIENT_DELIMITER: "{{ .Values.config.recipientDelimiter }}"
SITENAME: "{{ .Values.config.siteName }}"
SUBNET: "{{ .Values.config.subnet }}"
SUBNET_EXTERNAL: "{{ .Values.config.subnet_external }}"
TLS_FLAVOR: "mail"
VERSION: "{{ .Values.image.tag | default .Chart.AppVersion }}"
WEBDAV: "radicale"
WEBMAIL: "roundcube"
WEBSITE: "https://{{ .Values.config.domain }}/"
WEB_ADMIN: "{{ .Values.admin.path }}"
WEB_WEBMAIL: "{{ .Values.webmail.path }}"
WELCOME: "{{ .Values.welcome.enabled }}"
WELCOME_SUBJECT: "{{ .Values.welcome.subject }}"
WELCOME_BODY: "{{ .Values.welcome.body }}"
HOST_ADMIN: "{{ include "mailu-helm.fullname" . }}-admin.{{.Release.Namespace}}.svc.{{.Values.clusterSuffix}}"
ADMIN_ADDRESS: "{{ include "mailu-helm.fullname" . }}-admin.{{.Release.Namespace}}.svc.{{.Values.clusterSuffix}}"
HOST_FRONT: "{{ include "mailu-helm.fullname" . }}-front.{{.Release.Namespace}}.svc.{{.Values.clusterSuffix}}"
FRONT_ADDRESS: "{{ include "mailu-helm.fullname" . }}-front.{{.Release.Namespace}}.svc.{{.Values.clusterSuffix}}"
HOST_ANTISPAM_MILTER: "{{ include "mailu-helm.fullname" . }}-antispam.{{.Release.Namespace}}.svc.{{.Values.clusterSuffix}}"
ANTISPAM_MILTER_ADDRESS: "{{ include "mailu-helm.fullname" . }}-antispam.{{.Release.Namespace}}.svc.{{.Values.clusterSuffix}}:11332"
HOST_ANTISPAM_WEBUI: "{{ include "mailu-helm.fullname" . }}-antispam.{{.Release.Namespace}}.svc.{{.Values.clusterSuffix}}"
ANTISPAM_WEBUI_ADDRESS: "{{ include "mailu-helm.fullname" . }}-antispam.{{.Release.Namespace}}.svc.{{.Values.clusterSuffix}}:11334"
HOST_ANTIVIRUS: "{{ include "mailu-helm.fullname" . }}-antivirus.{{.Release.Namespace}}.svc.{{.Values.clusterSuffix}}"
ADDRESS_ANTIVIRUS: "{{ include "mailu-helm.fullname" . }}-antivirus.{{.Release.Namespace}}.svc.{{.Values.clusterSuffix}}:3310"
HOST_AUTHSMTP: "{{ include "mailu-helm.fullname" . }}-smtp.{{.Release.Namespace}}.svc.{{.Values.clusterSuffix}}"
AUTHSMTP_ADDRESS: "{{ include "mailu-helm.fullname" . }}-smtp.{{.Release.Namespace}}.svc.{{.Values.clusterSuffix}}"
HOST_IMAP: "{{ include "mailu-helm.fullname" . }}-imap.{{.Release.Namespace}}.svc.{{.Values.clusterSuffix}}"
IMAP_ADDRESS: "{{ include "mailu-helm.fullname" . }}-imap.{{.Release.Namespace}}.svc.{{.Values.clusterSuffix}}"
LMTP_ADDRESS: "{{ include "mailu-helm.fullname" . }}-imap.{{.Release.Namespace}}.svc.{{.Values.clusterSuffix}}:2525"
HOST_POP3: "{{ include "mailu-helm.fullname" . }}-imap.{{.Release.Namespace}}.svc.{{.Values.clusterSuffix}}"
POP3_ADDRESS: "{{ include "mailu-helm.fullname" . }}-imap.{{.Release.Namespace}}.svc.{{.Values.clusterSuffix}}"
HOST_REDIS: "{{ .Values.redis.host }}"
REDIS_ADDRESS: "{{ .Values.redis.host }}"
HOST_SMTP: "{{ include "mailu-helm.fullname" . }}-smtp.{{.Release.Namespace}}.svc.{{.Values.clusterSuffix}}"
SMTP_ADDRESS: "{{ include "mailu-helm.fullname" . }}-smtp.{{.Release.Namespace}}.svc.{{.Values.clusterSuffix}}"
HOST_WEBDAV: "{{ include "mailu-helm.fullname" . }}-webdav.{{.Release.Namespace}}.svc.{{.Values.clusterSuffix}}:5232"
WEBDAV_ADDRESS: "{{ include "mailu-helm.fullname" . }}-webmail.{{.Release.Namespace}}.svc.{{.Values.clusterSuffix}}:5232"
HOST_WEBMAIL: "{{ include "mailu-helm.fullname" . }}-webmail.{{.Release.Namespace}}.svc.{{.Values.clusterSuffix}}"
WEBMAIL_ADDRESS: "{{ include "mailu-helm.fullname" . }}-webmail.{{.Release.Namespace}}.svc.{{.Values.clusterSuffix}}"
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "mailu-helm.fullname" . }}-smtp
labels:
component: smtp
{{- include "mailu-helm.labels" . | nindent 4 }}
data:
postfix.cf: |-
# General TLS configuration
tls_high_cipherlist=ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:EECDH+AESGCM:EDH+AESGCM:DHE-RSA-CHACHA20-POLY1305:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS:!RC4:!SEED:!CAMELLIA
tls_preempt_cipherlist=yes
tls_ssl_options=NO_COMPRESSION
# Outgoing TLS is more flexible because 1. not all receiving servers will
# support TLS, 2. not all will have and up-to-date TLS stack.
smtp_tls_security_level=may
smtp_tls_mandatory_protocols=!SSLv2,!SSLv3,!TLSv1
smtp_tls_protocols=!SSLv2,!SSLv3,!TLSv1
smtpd_tls_security_level=may
smtpd_tls_mandatory_protocols=!SSLv2,!SSLv3,!TLSv1
smtpd_tls_protocols=!SSLv2,!SSLv3,!TLSv1
lmtp_tls_ciphers = high
lmtp_tls_mandatory_ciphers = high
smtp_tls_ciphers = high
smtp_tls_mandatory_ciphers = high
smtpd_tls_ciphers = high
smtpd_tls_mandatory_ciphers = high
# Relayed networks
mynetworks=127.0.0.1/32 [::1]/128 {{ .Values.config.subnet }} {{ .Values.config.subnet_external }}/32
smtpd_authorized_xclient_hosts={{ .Values.config.subnet }} {{ .Values.config.subnet_external }}/32
postscreen_upstream_proxy_protocol = haproxy
postscreen_upstream_proxy_protocol = haproxy
smtpd_tls_key_file=/certs/tls.key
smtpd_tls_cert_file=/certs/tls.crt
smtpd_use_tls = yes
smtp_use_tls = yes
postfix.master: |-
# expose proxy protocol support
10024/inet=10024 inet n - n - 1 postscreen
smtpd/pass=smtpd pass - - n - - smtpd
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: {{ include "mailu-helm.fullname" . }}-front
labels:
component: front
{{- include "mailu-helm.labels" . | nindent 4 }}
spec:
selector:
matchLabels:
component: front
{{- include "mailu-helm.selectorLabels" . | nindent 6 }}
template:
metadata:
{{- with .Values.podAnnotations }}
annotations:
{{- toYaml . | nindent 8 }}
{{- end }}
labels:
component: front
{{- include "mailu-helm.selectorLabels" . | nindent 8 }}
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
# securityContext: Not supported by mailu-nginx for now
volumes:
- name: tls
secret:
secretName: {{ include "mailu-helm.fullname" . }}-tls
items:
- key: tls.crt
path: cert.pem
- key: tls.key
path: key.pem
- name: config
configMap:
name: {{ include "mailu-helm.fullname" . }}-front
containers:
- name: front
# securityContext: Not supported by mailu-nginx for now
image: "mailu/nginx:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
envFrom:
- configMapRef:
name: {{ include "mailu-helm.fullname" . }}
- secretRef:
name: {{ include "mailu-helm.fullname" . }}
ports:
- containerPort: 110
hostPort: 110
name: pop3
protocol: "TCP"
- containerPort: 995
hostPort: 995
name: pop3s
protocol: "TCP"
- containerPort: 143
hostPort: 143
name: imap
protocol: "TCP"
- containerPort: 993
hostPort: 993
name: imaps
protocol: "TCP"
- containerPort: 25
hostPort: 25
name: smtp
protocol: "TCP"
- containerPort: 10025
hostPort: 10025
name: smtp-auth
protocol: "TCP"
- containerPort: 10143
hostPort: 10143
name: imap-auth
protocol: "TCP"
- containerPort: 465
hostPort: 465
name: smtps
protocol: "TCP"
- containerPort: 587
hostPort: 587
name: smtpd
protocol: "TCP"
- containerPort: 8000
hostPort: 8000
name: auth
protocol: "TCP"
resources:
{{- toYaml .Values.front.resources | nindent 12 }}
volumeMounts:
- name: tls
mountPath: "/certs"
- name: config
mountPath: /conf/tls.conf
subPath: tls.conf
- name: config
mountPath: /conf/nginx.conf
subPath: nginx.conf
hostNetwork: true
dnsPolicy: ClusterFirstWithHostNet
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "mailu-helm.fullname" . }}-admin
labels:
component: admin
{{- include "mailu-helm.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
component: admin
{{- include "mailu-helm.selectorLabels" . | nindent 6 }}
template:
metadata:
{{- with .Values.podAnnotations }}
annotations:
{{- toYaml . | nindent 8 }}
{{- end }}
labels:
component: admin
{{- include "mailu-helm.selectorLabels" . | nindent 8 }}
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
securityContext:
{{- toYaml .Values.podSecurityContext | nindent 8 }}
volumes:
- name: data
{{- .Values.volumes.data | nindent 10 }}
- name: dkim
{{- .Values.volumes.dkim | nindent 10 }}
- name: config
configMap:
name: {{ include "mailu-helm.fullname" . }}-admin
defaultMode: 0755
containers:
- name: admin
securityContext:
{{- toYaml .Values.securityContext | nindent 12 }}
image: "mailu/admin:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
envFrom:
- configMapRef:
name: {{ include "mailu-helm.fullname" . }}
- secretRef:
name: {{ include "mailu-helm.fullname" . }}
env:
- name: SUBNET
valueFrom:
configMapKeyRef:
name: {{ include "mailu-helm.fullname" . }}
key: SUBNET_EXTERNAL
ports:
- name: "http"
containerPort: 80
protocol: "TCP"
resources:
{{- toYaml .Values.admin.resources | nindent 12 }}
volumeMounts:
- name: data
mountPath: "/data"
- name: dkim
mountPath: "/dkim"
- name: config
mountPath: "/start.py"
subPath: "start.py"
startupProbe:
httpGet:
path: /sso/login
port: http
periodSeconds: 10
failureThreshold: 30
timeoutSeconds: 5
livenessProbe:
httpGet:
path: /sso/login
port: http
periodSeconds: 10
failureThreshold: 3
timeoutSeconds: 5
readinessProbe:
httpGet:
path: /sso/login
port: http
periodSeconds: 10
failureThreshold: 1
timeoutSeconds: 5
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "mailu-helm.fullname" . }}-antispam
labels:
component: antispam
{{- include "mailu-helm.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
component: antispam
{{- include "mailu-helm.selectorLabels" . | nindent 6 }}
template:
metadata:
{{- with .Values.podAnnotations }}
annotations:
{{- toYaml . | nindent 8 }}
{{- end }}
labels:
component: antispam
{{- include "mailu-helm.selectorLabels" . | nindent 8 }}
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
securityContext:
{{- toYaml .Values.podSecurityContext | nindent 8 }}
volumes:
- name: filter
{{- .Values.volumes.filter | nindent 10 }}
- name: dkim
{{- .Values.volumes.dkim | nindent 10 }}
- name: local-config
emptyDir: {}
containers:
- name: antispam
securityContext:
{{- toYaml .Values.securityContext | nindent 12 }}
image: "mailu/rspamd:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
envFrom:
- configMapRef:
name: {{ include "mailu-helm.fullname" . }}
- secretRef:
name: {{ include "mailu-helm.fullname" . }}
ports:
- name: antispam
containerPort: 11332
protocol: "TCP"
- name: antispam-http
containerPort: 11334
protocol: "TCP"
resources:
{{- toYaml .Values.antispam.resources | nindent 12 }}
volumeMounts:
- name: filter
mountPath: "/var/lib/rspamd"
- name: dkim
mountPath: "/dkim"
- name: local-config
mountPath: "/etc/rspamd/local.d"
startupProbe:
httpGet:
path: /
port: antispam-http
periodSeconds: 10
failureThreshold: 90
timeoutSeconds: 5
livenessProbe:
httpGet:
path: /
port: antispam-http
periodSeconds: 10
failureThreshold: 90
timeoutSeconds: 5
readinessProbe:
httpGet:
path: /
port: antispam-http
periodSeconds: 10
failureThreshold: 90
timeoutSeconds: 5
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "mailu-helm.fullname" . }}-autodiscover
labels:
component: autodiscover
{{- include "mailu-helm.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
component: autodiscover
{{- include "mailu-helm.selectorLabels" . | nindent 6 }}
template:
metadata:
{{- with .Values.podAnnotations }}
annotations:
{{- toYaml . | nindent 8 }}
{{- end }}
labels:
component: autodiscover
{{- include "mailu-helm.selectorLabels" . | nindent 8 }}
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
securityContext:
{{- toYaml .Values.podSecurityContext | nindent 8 }}
volumes:
- name: config
configMap:
name: {{ include "mailu-helm.fullname" . }}-autodiscover
items:
- key: mta-sts.txt
path: ".well-known/mta-sts.txt"
- key: config-v1.1.xml
path: config-v1.1.xml
- key: autodiscover.xml
path: autodiscover.xml
containers:
- name: autodiscover
securityContext:
{{- toYaml .Values.securityContext | nindent 12 }}
image: "nginx:stable-alpine"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- name: "http"
containerPort: 80
protocol: "TCP"
resources:
{{- toYaml .Values.admin.resources | nindent 12 }}
volumeMounts:
- name: config
mountPath: "/usr/share/nginx/html"
startupProbe:
httpGet:
path: /config-v1.1.xml
port: http
periodSeconds: 10
failureThreshold: 30
timeoutSeconds: 5
livenessProbe:
httpGet:
path: /config-v1.1.xml
port: http
periodSeconds: 10
failureThreshold: 3
timeoutSeconds: 5
readinessProbe:
httpGet:
path: /config-v1.1.xml
port: http
periodSeconds: 10
failureThreshold: 1
timeoutSeconds: 5
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "mailu-helm.fullname" . }}-imap
labels:
component: imap
{{- include "mailu-helm.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
component: imap
{{- include "mailu-helm.selectorLabels" . | nindent 6 }}
template:
metadata:
{{- with .Values.podAnnotations }}
annotations:
{{- toYaml . | nindent 8 }}
{{- end }}
labels:
component: imap
{{- include "mailu-helm.selectorLabels" . | nindent 8 }}
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
securityContext:
{{- toYaml .Values.podSecurityContext | nindent 8 }}
volumes:
- name: data
{{- .Values.volumes.data | nindent 10 }}
- name: mail
{{- .Values.volumes.mail | nindent 10 }}
containers:
- name: imap
securityContext:
{{- toYaml .Values.securityContext | nindent 12 }}
image: "mailu/dovecot:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
envFrom:
- configMapRef:
name: {{ include "mailu-helm.fullname" . }}
- secretRef:
name: {{ include "mailu-helm.fullname" . }}
ports:
- name: imap-auth
containerPort: 2102
protocol: "TCP"
- name: imap-transport
containerPort: 2525
protocol: "TCP"
- name: pop3
containerPort: 110
protocol: "TCP"
- name: imap-default
containerPort: 143
protocol: "TCP"
- name: sieve
containerPort: 4190
protocol: "TCP"
resources:
{{- toYaml .Values.imap.resources | nindent 12 }}
volumeMounts:
- name: data
mountPath: "/data"
- name: mail
mountPath: "/mail"
startupProbe:
exec:
command:
- sh
- -c
- 'echo QUIT|nc localhost 110|grep "Dovecot ready."'
periodSeconds: 10
failureThreshold: 30
timeoutSeconds: 5
livenessProbe:
exec:
command:
- sh
- -c
- 'echo QUIT|nc localhost 110|grep "Dovecot ready."'
periodSeconds: 10
failureThreshold: 3
timeoutSeconds: 5
readinessProbe:
exec:
command:
- sh
- -c
- 'echo QUIT|nc localhost 110|grep "Dovecot ready."'
periodSeconds: 10
failureThreshold: 1
timeoutSeconds: 5
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "mailu-helm.fullname" . }}-smtp
labels:
component: smtp
{{- include "mailu-helm.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
component: smtp
{{- include "mailu-helm.selectorLabels" . | nindent 6 }}
template:
metadata:
{{- with .Values.podAnnotations }}
annotations:
{{- toYaml . | nindent 8 }}
{{- end }}
labels:
component: smtp
{{- include "mailu-helm.selectorLabels" . | nindent 8 }}
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
securityContext:
{{- toYaml .Values.podSecurityContext | nindent 8 }}
volumes:
- name: data
{{- .Values.volumes.data | nindent 10 }}
- name: certs
secret:
secretName: {{ include "mailu-helm.fullname" . }}-tls
- name: config
configMap:
name: {{ include "mailu-helm.fullname" . }}-smtp
containers:
- name: smtp
securityContext:
{{- toYaml .Values.securityContext | nindent 12 }}
image: "mailu/postfix:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
envFrom:
- configMapRef:
name: {{ include "mailu-helm.fullname" . }}
- secretRef:
name: {{ include "mailu-helm.fullname" . }}
ports:
- name: smtp
containerPort: 25
protocol: "TCP"
- name: smtp-ssl
containerPort: 465
protocol: "TCP"
- name: smtp-starttls
containerPort: 587
protocol: "TCP"
- name: smtp-proxy
containerPort: 10024
protocol: "TCP"
- name: smtp-auth
containerPort: 10025
protocol: "TCP"
resources:
{{- toYaml .Values.smtp.resources | nindent 12 }}
volumeMounts:
- name: data
mountPath: "/data"
- name: certs
mountPath: "/certs"
- name: config
mountPath: "/overrides"
startupProbe:
exec:
command:
- sh
- -c
- 'echo QUIT|nc localhost 25|grep "220 .* ESMTP Postfix"'
periodSeconds: 10
failureThreshold: 30
timeoutSeconds: 5
livenessProbe:
exec:
command:
- sh
- -c
- 'echo QUIT|nc localhost 25|grep "220 .* ESMTP Postfix"'
periodSeconds: 10
failureThreshold: 3
timeoutSeconds: 5
readinessProbe:
exec:
command:
- sh
- -c
- 'echo QUIT|nc localhost 25|grep "220 .* ESMTP Postfix"'
periodSeconds: 10
failureThreshold: 1
timeoutSeconds: 5
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "mailu-helm.fullname" . }}-webdav
labels:
component: webdav
{{- include "mailu-helm.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
component: webdav
{{- include "mailu-helm.selectorLabels" . | nindent 6 }}
template:
metadata:
{{- with .Values.podAnnotations }}
annotations:
{{- toYaml . | nindent 8 }}
{{- end }}
labels:
component: webdav
{{- include "mailu-helm.selectorLabels" . | nindent 8 }}
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
securityContext:
{{- toYaml .Values.podSecurityContext | nindent 8 }}
volumes:
- name: webdav
{{- .Values.volumes.webdav | nindent 10 }}
containers:
- name: webdav
securityContext:
{{- toYaml .Values.securityContext | nindent 12 }}
image: "mailu/radicale:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
envFrom:
- configMapRef:
name: {{ include "mailu-helm.fullname" . }}
- secretRef:
name: {{ include "mailu-helm.fullname" . }}
ports:
- name: "http"
containerPort: 5232
protocol: "TCP"
resources:
{{- toYaml .Values.webdav.resources | nindent 12 }}
volumeMounts:
- name: webdav
mountPath: "/data"
startupProbe:
httpGet:
path: /
port: http
periodSeconds: 10
failureThreshold: 30
timeoutSeconds: 5
livenessProbe:
httpGet:
path: /
port: http
periodSeconds: 10
failureThreshold: 3
timeoutSeconds: 5
readinessProbe:
httpGet:
path: /
port: http
periodSeconds: 10
failureThreshold: 1
timeoutSeconds: 5
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "mailu-helm.fullname" . }}-webmail
labels:
component: webmail
{{- include "mailu-helm.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
component: webmail
{{- include "mailu-helm.selectorLabels" . | nindent 6 }}
template:
metadata:
{{- with .Values.podAnnotations }}
annotations:
{{- toYaml . | nindent 8 }}
{{- end }}
labels:
component: webmail
{{- include "mailu-helm.selectorLabels" . | nindent 8 }}
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
securityContext:
{{- toYaml .Values.podSecurityContext | nindent 8 }}
volumes:
- name: webmail
{{- .Values.volumes.webmail | nindent 10 }}
containers:
- name: webmail
securityContext:
{{- toYaml .Values.securityContext | nindent 12 }}
image: "k8r.eu/justjanne/mailu-snappymail:{{ .Values.webmail.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
envFrom:
- configMapRef:
name: {{ include "mailu-helm.fullname" . }}
- secretRef:
name: {{ include "mailu-helm.fullname" . }}
env:
- name: HOST_FRONT
valueFrom:
configMapKeyRef:
key: FRONT_ADDRESS
name: {{ include "mailu-helm.fullname" . }}
ports:
- name: "http"
containerPort: 80
protocol: "TCP"
resources:
{{- toYaml .Values.webmail.resources | nindent 12 }}
volumeMounts:
- name: webmail
mountPath: "/data"
startupProbe:
httpGet:
path: /healthz
port: http
periodSeconds: 10
failureThreshold: 30
timeoutSeconds: 5
livenessProbe:
httpGet:
path: /healthz
port: http
periodSeconds: 10
failureThreshold: 3
timeoutSeconds: 5
readinessProbe:
httpGet:
path: /healthz
port: http
periodSeconds: 10
failureThreshold: 1
timeoutSeconds: 5
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{ include "mailu-helm.fullname" . }}-admin
labels:
{{- include "mailu-helm.labels" . | nindent 4 }}
component: admin
annotations:
nginx.ingress.kubernetes.io/server-snippet: |-
location @login {
return 302 "/sso/login";
}
{{- range $key, $value := .Values.ingress.annotations }}
{{- printf "%s: %s" $key (tpl $value $ | quote) | nindent 4 }}
{{- end }}
spec:
rules:
- host: "{{ .Values.admin.host }}"
http:
paths:
- path: "{{ .Values.admin.path }}"
backend:
service:
name: {{ include "mailu-helm.fullname" . }}-admin
port:
name: http
pathType: Prefix
- path: "/sso/"
backend:
service:
name: {{ include "mailu-helm.fullname" . }}-admin
port:
name: http
pathType: Prefix
- path: "/static"
backend:
service:
name: {{ include "mailu-helm.fullname" . }}-admin
port:
name: http
pathType: Prefix
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{ include "mailu-helm.fullname" . }}-antispam
labels:
{{- include "mailu-helm.labels" . | nindent 4 }}
component: antispam
annotations:
nginx.ingress.kubernetes.io/auth-url:
"http://{{ include "mailu-helm.fullname" . }}-admin.{{ .Release.Namespace }}.svc.{{ .Values.clusterSuffix }}/internal/auth/admin"
nginx.ingress.kubernetes.io/rewrite-target: "/$2"
nginx.ingress.kubernetes.io/configuration-snippet: |
proxy_set_header X-Real-IP "";
proxy_set_header X-Forwarded-For "";
proxy_set_header Password "mailu";
{{- range $key, $value := .Values.ingress.annotations }}
{{- printf "%s: %s" $key (tpl $value $ | quote) | nindent 4 }}
{{- end }}
spec:
rules:
- host: "{{ .Values.admin.host }}"
http:
paths:
- path: "{{ .Values.admin.path }}/antispam($|/)(.*)"
backend:
service:
name: {{ include "mailu-helm.fullname" . }}-antispam
port:
name: antispam-http
pathType: Prefix