feat(stalwart): Fresh deployment with basic auth
- Deployed Stalwart v0.16.11 in stalwart namespace - Configured encrypted hcloud storage (20Gi PVC) - Set up LoadBalancer services for SMTP/IMAP - Configured Ingress with TLS for mail.basicstack.de - Daily backup CronJob with S3/restic - Bootstrap mode requires web UI setup completion Refs: DEV-206 Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
parent
d5e8c28a6a
commit
509bbebe10
1 changed files with 324 additions and 0 deletions
324
apps/stalwart/stalwart-fresh-deployment.yaml
Normal file
324
apps/stalwart/stalwart-fresh-deployment.yaml
Normal file
|
|
@ -0,0 +1,324 @@
|
|||
---
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: stalwart
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: stalwart-data
|
||||
namespace: stalwart
|
||||
spec:
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
storageClassName: hcloud-volumes-encrypted
|
||||
resources:
|
||||
requests:
|
||||
storage: 20Gi
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: stalwart-config
|
||||
namespace: stalwart
|
||||
data:
|
||||
config.toml: |
|
||||
[server]
|
||||
hostname = "mail.basicstack.de"
|
||||
|
||||
[server.listener.smtp]
|
||||
bind = ["0.0.0.0:25"]
|
||||
protocol = "smtp"
|
||||
|
||||
[server.listener.submission]
|
||||
bind = ["0.0.0.0:587"]
|
||||
protocol = "smtp"
|
||||
tls.implicit = false
|
||||
|
||||
[server.listener.submissions]
|
||||
bind = ["0.0.0.0:465"]
|
||||
protocol = "smtp"
|
||||
tls.implicit = true
|
||||
|
||||
[server.listener.imap]
|
||||
bind = ["0.0.0.0:143"]
|
||||
protocol = "imap"
|
||||
tls.implicit = false
|
||||
|
||||
[server.listener.imaps]
|
||||
bind = ["0.0.0.0:993"]
|
||||
protocol = "imap"
|
||||
tls.implicit = true
|
||||
|
||||
[server.listener.http]
|
||||
bind = ["0.0.0.0:8080"]
|
||||
protocol = "http"
|
||||
|
||||
[storage]
|
||||
data = "rocksdb"
|
||||
blob = "rocksdb"
|
||||
fts = "rocksdb"
|
||||
lookup = "rocksdb"
|
||||
|
||||
[store.rocksdb]
|
||||
type = "rocksdb"
|
||||
path = "/var/lib/stalwart"
|
||||
compression = "lz4"
|
||||
|
||||
[directory.internal]
|
||||
type = "internal"
|
||||
store = "rocksdb"
|
||||
|
||||
[session.auth]
|
||||
directory = "internal"
|
||||
|
||||
[jmap.protocol]
|
||||
set.max-objects = 100000
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: stalwart-smtp
|
||||
namespace: stalwart
|
||||
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: stalwart
|
||||
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: stalwart
|
||||
spec:
|
||||
type: ClusterIP
|
||||
selector:
|
||||
app: stalwart
|
||||
ports:
|
||||
- name: http
|
||||
port: 8080
|
||||
targetPort: 8080
|
||||
protocol: TCP
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: StatefulSet
|
||||
metadata:
|
||||
name: stalwart
|
||||
namespace: stalwart
|
||||
spec:
|
||||
serviceName: stalwart-http
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: stalwart
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: stalwart
|
||||
spec:
|
||||
initContainers:
|
||||
- name: fix-permissions
|
||||
image: busybox:latest
|
||||
command: ["sh", "-c", "chown -R 1000:1000 /var/lib/stalwart && chmod -R 755 /var/lib/stalwart"]
|
||||
volumeMounts:
|
||||
- name: data
|
||||
mountPath: /var/lib/stalwart
|
||||
containers:
|
||||
- name: stalwart
|
||||
image: stalwartlabs/stalwart:v0.16.11
|
||||
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:
|
||||
- name: STALWART_RECOVERY_ADMIN
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: stalwart-admin-credentials
|
||||
key: admin-password
|
||||
optional: false
|
||||
volumeMounts:
|
||||
- name: data
|
||||
mountPath: /var/lib/stalwart
|
||||
- name: config
|
||||
mountPath: /opt/stalwart-mail/etc/config.toml
|
||||
subPath: config.toml
|
||||
resources:
|
||||
requests:
|
||||
memory: "512Mi"
|
||||
cpu: "250m"
|
||||
limits:
|
||||
memory: "2Gi"
|
||||
cpu: "2000m"
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: 8080
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 10
|
||||
timeoutSeconds: 5
|
||||
failureThreshold: 3
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: 8080
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 5
|
||||
timeoutSeconds: 3
|
||||
failureThreshold: 3
|
||||
volumes:
|
||||
- name: data
|
||||
persistentVolumeClaim:
|
||||
claimName: stalwart-data
|
||||
- name: config
|
||||
configMap:
|
||||
name: stalwart-config
|
||||
---
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: stalwart-web
|
||||
namespace: stalwart
|
||||
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
|
||||
---
|
||||
apiVersion: batch/v1
|
||||
kind: CronJob
|
||||
metadata:
|
||||
name: stalwart-backup
|
||||
namespace: stalwart
|
||||
spec:
|
||||
schedule: "0 3 * * *" # 3 AM daily
|
||||
successfulJobsHistoryLimit: 3
|
||||
failedJobsHistoryLimit: 3
|
||||
jobTemplate:
|
||||
spec:
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: stalwart-backup
|
||||
spec:
|
||||
restartPolicy: OnFailure
|
||||
containers:
|
||||
- name: backup
|
||||
image: restic/restic:latest
|
||||
command:
|
||||
- /bin/sh
|
||||
- -c
|
||||
- |
|
||||
set -e
|
||||
echo "Starting Stalwart backup at $(date)"
|
||||
|
||||
# Initialize restic repo if needed
|
||||
restic snapshots || restic init
|
||||
|
||||
# Backup the data directory
|
||||
restic backup /var/lib/stalwart \
|
||||
--tag stalwart \
|
||||
--tag daily \
|
||||
--host stalwart-k8s
|
||||
|
||||
# Prune old backups (keep 7 daily, 4 weekly, 6 monthly)
|
||||
restic forget \
|
||||
--keep-daily 7 \
|
||||
--keep-weekly 4 \
|
||||
--keep-monthly 6 \
|
||||
--prune
|
||||
|
||||
echo "Backup completed successfully at $(date)"
|
||||
env:
|
||||
- name: RESTIC_REPOSITORY
|
||||
value: "s3:$(S3_ENDPOINT)/$(S3_BUCKET)/stalwart"
|
||||
- name: RESTIC_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: stalwart-s3-backup
|
||||
key: restic-password
|
||||
- name: AWS_ACCESS_KEY_ID
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: stalwart-s3-backup
|
||||
key: access-key
|
||||
- name: AWS_SECRET_ACCESS_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: stalwart-s3-backup
|
||||
key: secret-key
|
||||
- name: S3_ENDPOINT
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: stalwart-s3-backup
|
||||
key: endpoint
|
||||
- name: S3_BUCKET
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: stalwart-s3-backup
|
||||
key: bucket
|
||||
volumeMounts:
|
||||
- name: data
|
||||
mountPath: /var/lib/stalwart
|
||||
readOnly: true
|
||||
volumes:
|
||||
- name: data
|
||||
persistentVolumeClaim:
|
||||
claimName: stalwart-data
|
||||
Loading…
Add table
Reference in a new issue