Compare commits

...
Sign in to create a new pull request.

2 commits

Author SHA1 Message Date
27f5dd4b44
WIP 2025-01-01 12:39:10 +01:00
3443452cf7
feat(mycloud-stalwart-mail): init - WIP 2024-12-22 11:59:17 +01:00
8 changed files with 522 additions and 0 deletions

View file

@ -0,0 +1,17 @@
##
# commons are from mycloud-core
##
components:
mycloud-services:
# patch mycloud-core to get another database
values:
databases:
mycloud-mail-stalwart:
type: postgresql
mycloud-stalwart-mail:
enabled: true
namespace:
# current namespace
name:

View file

@ -0,0 +1,23 @@
# Patterns to ignore when building packages.
# This supports shell glob matching, relative path matching, and
# negation (prefixed with !). Only one pattern per line.
.DS_Store
# Common VCS dirs
.git/
.gitignore
.bzr/
.bzrignore
.hg/
.hgignore
.svn/
# Common backup files
*.swp
*.bak
*.tmp
*.orig
*~
# Various IDEs
.project
.idea/
*.tmproj
.vscode/

View file

@ -0,0 +1,9 @@
apiVersion: v2
name: mycloud-mail-stalwart
description: myCloud component to setup stalwart mail-server
type: application
maintainers:
- name: WrenIX
url: https://wrenix.eu
version: 0.1.0

View file

@ -0,0 +1,62 @@
---
apiVersion: source.toolkit.fluxcd.io/v1
kind: GitRepository
metadata:
name: wrenix-helm-charts
spec:
url: https://codeberg.org/wrenix/helm-charts.git
ref:
branch: "authentik-application/ldap"
interval: 10m
---
apiVersion: helm.toolkit.fluxcd.io/v2beta2
kind: HelmRelease
metadata:
name: {{ .Release.Name }}-auth
spec:
chart:
spec:
sourceRef:
kind: GitRepository
name: "wrenix-helm-charts"
# namespace: "flux-system"
chart: "./authentik-application"
reconcileStrategy: "Revision"
install:
{{- toYaml .Values.commons.helm.release.install | nindent 4 }}
test:
{{- toYaml .Values.commons.helm.release.test | nindent 4 }}
upgrade:
{{- toYaml .Values.commons.helm.release.upgrade | nindent 4 }}
driftDetection:
{{- toYaml .Values.commons.helm.release.driftDetection | nindent 4 }}
interval: 10m
values:
{{- $host := .Values.ingress.host | default (printf "mail.%s" .Values.commons.ingress.domain) }}
blueprint:
authentik:
domain: "https://{{ .Values.commons.auth.host | default (printf "auth.%s" .Values.commons.ingress.domain) }}"
provider:
type: "ldap"
name: "Mail-Stalwart"
ldap:
token: {{ .Values.auth.ldap.token | default (derivePassword 1 "long" .Values.commons.masterPassword "stalwart-mail" "auth.token") | quote }}
groups:
- slug: "mycloud - users"
bindID: "4525d9a3-1853-45dc-adc0-6d411a3a907e"
users:
- username: {{ .Values.auth.ldap.bind.username | default (printf "%s-ldap" .Release.Name) | quote }}
groups:
- "mycloud - users"
application:
policyEngineMode: "any"
openInNewTab: true
publisher: "WrenIX's myCloud"
slug: "mycloud-mail-stalwart"
group: "Communication"
name: "Mail Stalwart"
launchURL: "https://{{ $host }}/"
icon: "https://{{ $host }}/logo.svg"
description: "Unlock the future of email with Stalwart (Management)"

View file

@ -0,0 +1,13 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-init
namespace: "{{ .Values.init.namespace }}"
data:
{{- if and
(.Capabilities.APIVersions.Has "v1/ConfigMap")
}}
init: "-1"
{{- else }}
init: "{{ add1 .Values.init.version }}"
{{- end }}

View file

@ -0,0 +1,258 @@
---
apiVersion: helm.toolkit.fluxcd.io/v2beta2
kind: HelmRelease
metadata:
name: "{{ .Release.Name }}-hr"
spec:
chart:
spec:
sourceRef:
kind: GitRepository
name: "wrenix-helm-charts"
namespace: "flux-system"
chart: "./stalwart-mail"
reconcileStrategy: "Revision"
install:
{{- toYaml .Values.commons.helm.release.install | nindent 4 }}
test:
{{- toYaml .Values.commons.helm.release.test | nindent 4 }}
upgrade:
{{- toYaml .Values.commons.helm.release.upgrade | nindent 4 }}
driftDetection:
{{- toYaml .Values.commons.helm.release.driftDetection | nindent 4 }}
interval: 10m
valuesFrom:
- kind: Secret
name: {{ .Release.Name | quote }}
valuesKey: admin_password
targetPath: "secrets.env.FALLBACK_ADMIN_SECRET"
- kind: Secret
name: {{ .Release.Name | quote }}
valuesKey: "database_password"
targetPath: "secrets.env.STORE_PGSQL_PASSWORD"
- kind: Secret
name: {{ .Release.Name | quote }}
valuesKey: "metrics_secret"
targetPath: "secrets.env.METRICS_SECRET"
values:
{{- $host := .Values.ingress.host | default (printf "mail.%s" .Values.commons.ingress.domain) }}
config:
lookup:
default:
hostname: {{ $host | quote }}
server:
listener:
smtp:
proxy:
trusted-networks:
{{- toYaml .Values.networks.trustedNetworks | nindent 16 }}
submission:
submissions:
proxy:
trusted-networks:
{{- toYaml .Values.networks.trustedNetworks | nindent 16 }}
imap:
imaptls:
proxy:
trusted-networks:
{{- toYaml .Values.networks.trustedNetworks | nindent 16 }}
pop3:
pop3s:
proxy:
trusted-networks:
{{- toYaml .Values.networks.trustedNetworks | nindent 16 }}
sieve:
proxy:
trusted-networks:
{{- toYaml .Values.networks.trustedNetworks | nindent 16 }}
# without proxy and tls for ingress
http:
protocol: "http"
bind: [ "[::]:8080" ]
https:
url: {{ printf "https://%s" $host | quote }}
bind: [ "[::]:443" ]
proxy:
trusted-networks:
{{- toYaml .Values.networks.trustedNetworks | nindent 16 }}
tls:
implicit: true
storage:
data: "pgsql"
fts: "pgsql"
full-text:
default-language: "en"
blob: "filesystem"
lookup: "pgsql"
directory: "ldap"
store:
rocksdb: null
pgsql:
type: "postgresql"
host: {{ .Values.database.host | quote }}
database: {{ .Values.database.name | quote }}
user: {{ .Values.database.username | quote }}
password: "%{env:STORE_PGSQL_PASSWORD}%"
filesystem:
type: "fs"
path: "/data/blobs"
depth: 2
directory:
internal:
ldap:
type: "ldap"
url: "ldap://{{ .Release.Name }}-auth-authentik-application-ldap:389"
base-dn: "dc=ldap,dc=goauthentik,dc=io"
timeout: "30s"
tls:
enable: false
allow-invalid-certs: false
bind:
dn: "cn=ldap-mail,ou=users,dc=ldap,dc=goauthentik,dc=io"
secret: "oJyh5W3P50glb8fWDdlDABUJlJPIMHp4dGBl14g9aLxv1SNbLudvfBWFMrFJ"
auth:
enable: false
dn: "cn=?,ou=users,dc=ldap,dc=goauthentik,dc=io"
search: true
filter:
name: "(&(|(objectClass=posixAccount)(ak-active=TRUE))(cn=?))"
email: "(&(|(objectClass=posixAccount)(ak-active=TRUE))(|(mail=?)(mailAlias=?)(mailList=?)))"
verify: "(&(|(objectClass=posixAccount)(ak-active=TRUE))(|(mail=*?*)(mailAlias=*?*)))"
expand: "(&(|(objectClass=posixAccount)(ak-active=TRUE))(mailList=?))"
domains: "(&(|(objectClass=posixAccount)(ak-active=TRUE))(|(mail=*@?)(mailAlias=*@?)))"
attributes:
name: "cn"
class: "ak-superuser"
description: "displayName"
# secret: "userPassword"
groups: "memberOf"
email: "mail"
email-alias: "mailAlias"
# quota: "diskQuota"
tracer:
stdout:
level: info
# TODO cleanup
# level: warn
{{- with .Values.commons.tracing }}
{{- if .enabled }}
otel:
enable:
span-exporter: true
log-exporter: false
level: "debug"
{{- if .grpc.enabled }}
transport: "grpc"
endpoint: {{ printf "%s://%s" (.grpc.insecure | ternary "http" "https") .grpc.endpoint }}
{{- else }}
transport: "http"
endpoint: {{ .hrrp.endpoint }}
{{- end }}
{{- end }}
{{- end }}
certificate:
default:
cert: "%{file:/opt/stalwart-mail/etc/certs/tls.crt}%"
private-key: "%{file:/opt/stalwart-mail/etc/certs/tls.key}%"
service:
{{- if .Values.networks.ipv6 }}
ipFamilies: [ "IPv6", "IPv4" ]
ipFamilyPolicy: "RequireDualStack"
{{- end }}
ports:
submission:
imap:
pop3:
http: 8080
ingress:
enabled: true
annotations:
{{- with .Values.commons.ingress.annotations }}
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.ingress.annotations }}
{{- toYaml . | nindent 8 }}
{{- end }}
hosts:
- host: "{{ .Values.commons.ingress.domain }}"
paths:
- path: /.well-known/jmap
pathType: Prefix
- path: /.well-known/mta-sts.txt
pathType: Exact
- path: /.well-known/mail-v1.xml
pathType: Exact
- path: /.well-known/autoconfig
pathType: Prefix
- path: /autodiscover
pathType: Prefix
- host: "autoconfig.{{ .Values.commons.ingress.domain }}"
paths:
- path: /mail
pathType: Prefix
- host: "autodiscover.{{ .Values.commons.ingress.domain }}"
paths:
- path: /autodiscover
pathType: Prefix
- host: "mta-sts.{{ .Values.commons.ingress.domain }}"
paths:
- path: /
pathType: Prefix
{{- if .Values.commons.ingress.tls.enabled }}
tls:
{{- with .Values.commons.ingress.tls.override }}
{{- toYaml . | nindent 8 }}
{{- else }}
- secretName: "{{ .Release.Name }}-cert"
hosts:
- "{{ .Values.commons.ingress.domain }}"
- "autoconfig.{{ .Values.commons.ingress.domain }}"
- "autodiscover.{{ .Values.commons.ingress.domain }}"
- "mta-sts.{{ .Values.commons.ingress.domain }}"
{{- end }}
{{- end }}
traefik:
enabled: true
host: {{ $host | quote }}
ports:
smtp:
match: 'HostSNI(`*`)'
submission:
imap:
pop3:
https:
entrypoint: websecure
certificate:
certmanager:
dnsNames:
- {{ $host | quote }}
prometheus:
servicemonitor:
enabled: {{ (.Capabilities.APIVersions.Has "monitoring.coreos.com/v1/ServiceMonitor") }}
labels:
{{- toYaml .Values.commons.prometheus.monitor.labels | nindent 10 }}
persistence:
enabled: true
size: {{ .Values.persistence.size }}
{{- with .Values.persistence.storageClass | default .Values.commons.persistence.storageClass }}
storageClass: {{ . }}
{{- end }}
{{- if .Values.commons.persistence.hostPath.enabled }}
hostPath: "{{ .Values.commons.persistence.hostPath.prefix }}/mail-stalwart"
{{- end }}

View file

@ -0,0 +1,9 @@
---
apiVersion: v1
kind: Secret
metadata:
name: "{{ .Release.Name }}"
data:
admin_password: {{ .Values.admin.password | default (derivePassword 1 "long" .Values.commons.masterPassword "mail-stalwart" "admin_password" | b64enc) | b64enc }}
database_password: {{ .Values.database.password | default (derivePassword 1 "long" .Values.commons.masterPassword "mail-stalwart" "database_password" | b64enc) | b64enc }}
metrics_secret: {{ derivePassword 1 "long" .Values.commons.masterPassword "stalwart-mail" "metrics_secret" | b64enc }}

View file

@ -0,0 +1,131 @@
init:
version: 0
namespace: "bases"
commons:
# -- masterPassword to generate secrets
# @section -- Commons
masterPassword: "CHANGEME"
auth:
# -- default auth.(.Values.commons.ingress.domain)
# @section -- Commons
host:
theme:
# -- title everywhere
# @section -- Commons theme
title: myCloud
# -- logo everywhere
# @section -- Commons theme
logo: /static/dist/assets/icons/icon_left_brand.svg
# -- favicon everywhere
# @section -- Commons theme
favicon: /static/dist/assets/icons/icon.png
persistence:
# -- storageClass of PVC
# @section -- Commons Persistence
storageClass:
hostPath:
# -- use hostPath instatt of PVC
# @section -- Commons Persistence
enabled: false
# -- use hostPath under the following path
# @section -- Commons Persistence
prefix: "/var/lib/mycloud"
helm:
release:
# -- install of FluxCD HelmRelease
# @section -- Commons helm release
install: {}
# -- test of FluxCD HelmRelease
# @section -- Commons helm release
test: {}
# -- upgrade of FluxCD HelmRelease
# @section -- Commons helm release
upgrade: {}
# -- driftDetection of FluxCD HelmRelease
# @section -- Commons helm release
driftDetection: {}
ingress:
# -- top domain for all services
# @section -- Commons Ingress
domain: "wrenix.eu"
# -- annotations for all ingress objects
# @section -- Commons Ingress
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
tls:
# -- tls on every ingress
# @section -- Commons Ingress
enabled: true
# -- use own definition of tls (e.g. for own or wildcard certificate)
# @section -- Commons Ingress
override: []
prometheus:
monitor:
# -- labels on Pod- and Service-Monitor
# @section -- Commons Monitoring
labels: {}
rules:
# -- labels on PrometheusRules
# @section -- Commons Monitoring
labels: {}
tracing:
# -- enable tracing on all components
# @section -- Commons Tracing
enabled: false
http:
# -- http endpoint
# @section -- Commons Tracing
endpoint: "http://tempo.monitoring.svc:4318/v1/traces"
grpc:
# -- prefer grpc over http
# @section -- Commons Tracing
enabled: true
# -- allow insecure connection per grpc
# @section -- Commons Tracing
insecure: true
# -- grpc endpoint
# @section -- Commons Tracing
endpoint: "tempo.monitoring.svc:4317"
auth:
ldap:
# -- WARNING must be set after generated in Artifactory(generated by .Values.commons.masterPassword)
token:
bind:
username:
password:
admin:
# -- fallback admin password (default: generated by .Values.commons.masterPassword)
password:
networks:
ipv6: false
trustedNetworks:
- "127.0.0.0/8"
- "::1"
- "10.0.0.0/8"
ingress:
# -- used for main domain
host:
database:
# -- default is from mysql-services
host: mycloud-services-postgresql
name: mail-stalwart
username: mail-stalwart
# -- generated by .Values.commons.masterPassword (equal to mycloud-services)
password:
persistence:
storageClass:
size: 16Gi