--- apiVersion: v1 kind: Namespace metadata: name: mail --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: stalwart-data namespace: mail spec: accessModes: - ReadWriteOnce storageClassName: hcloud-volumes-encrypted resources: requests: storage: 20Gi --- # OAuth Configuration ConfigMap apiVersion: v1 kind: ConfigMap metadata: name: stalwart-oauth-config namespace: mail data: oauth-config.json: | { "oauth": { "providers": [ { "id": "pocket-id", "name": "Pocket ID", "issuer": "https://auth.basicstack.de", "authorization-url": "https://auth.basicstack.de/api/oidc/authorize", "token-url": "https://auth.basicstack.de/api/oidc/token", "userinfo-url": "https://auth.basicstack.de/api/oidc/userinfo", "client-id": "REPLACED_BY_SECRET", "client-secret": "REPLACED_BY_SECRET", "scopes": ["openid", "profile", "email"], "redirect-url": "https://mail.basicstack.de/login/oauth", "user-mapping": { "username": "preferred_username", "email": "email", "name": "name" } } ], "enabled": true, "allow-password-auth": false } } --- # Secret managed via SealedSecrets # See: stalwart-oidc-sealed.yaml --- apiVersion: v1 kind: Service metadata: name: stalwart-smtp namespace: mail spec: type: LoadBalancer selector: app: stalwart ports: - name: smtp port: 25 targetPort: 25 protocol: TCP - name: submission port: 587 targetPort: 587 protocol: TCP - name: submissions port: 465 targetPort: 465 protocol: TCP --- apiVersion: v1 kind: Service metadata: name: stalwart-imap namespace: mail spec: type: LoadBalancer selector: app: stalwart ports: - name: imap port: 143 targetPort: 143 protocol: TCP - name: imaps port: 993 targetPort: 993 protocol: TCP --- apiVersion: v1 kind: Service metadata: name: stalwart-http namespace: mail spec: type: ClusterIP selector: app: stalwart ports: - name: http port: 8080 targetPort: 8080 protocol: TCP --- apiVersion: apps/v1 kind: Deployment metadata: name: stalwart namespace: mail spec: replicas: 1 strategy: type: Recreate selector: matchLabels: app: stalwart template: metadata: labels: app: stalwart spec: initContainers: - name: fix-permissions image: busybox command: ["sh", "-c", "chown -R 2000:2000 /opt/stalwart-mail && chmod -R 755 /opt/stalwart-mail"] volumeMounts: - name: data mountPath: /opt/stalwart-mail containers: - name: stalwart image: stalwartlabs/stalwart:v0.16 command: ["/usr/local/bin/stalwart"] args: ["--config", "/etc/stalwart/config.json"] ports: - containerPort: 25 name: smtp - containerPort: 587 name: submission - containerPort: 465 name: submissions - containerPort: 143 name: imap - containerPort: 993 name: imaps - containerPort: 8080 name: http env: # Emergency recovery admin (can be disabled after OIDC is working) - name: STALWART_RECOVERY_ADMIN value: "admin@basicstack.de:***REMOVED***" # OAuth configuration - name: STALWART_OAUTH_ENABLED value: "true" - name: STALWART_OAUTH_PROVIDER value: "pocket-id" - name: STALWART_OAUTH_CLIENT_ID valueFrom: secretKeyRef: name: stalwart-oidc-secret key: client-id - name: STALWART_OAUTH_CLIENT_SECRET valueFrom: secretKeyRef: name: stalwart-oidc-secret key: client-secret # Disable password authentication (except recovery admin) - name: STALWART_PASSWORD_AUTH_ENABLED value: "false" volumeMounts: - name: data mountPath: /var/lib/stalwart - name: data mountPath: /etc/stalwart subPath: etc - name: oauth-config mountPath: /etc/stalwart/oauth readOnly: true resources: requests: memory: "512Mi" cpu: "250m" limits: memory: "1Gi" cpu: "1000m" volumes: - name: data persistentVolumeClaim: claimName: stalwart-data - name: oauth-config configMap: name: stalwart-oauth-config --- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: stalwart-web namespace: mail annotations: cert-manager.io/cluster-issuer: "letsencrypt-prod" traefik.ingress.kubernetes.io/router.entrypoints: websecure spec: ingressClassName: traefik tls: - hosts: - mail.basicstack.de secretName: stalwart-tls rules: - host: mail.basicstack.de http: paths: - path: / pathType: Prefix backend: service: name: stalwart-http port: number: 8080