Add snnapymail and stalwart
This commit is contained in:
parent
88206b6bde
commit
a962db73c8
529
MAIL_STACK_README.md
Normal file
529
MAIL_STACK_README.md
Normal file
@ -0,0 +1,529 @@
|
|||||||
|
# Lightweight Mail Stack for k3s GitOps Lab
|
||||||
|
|
||||||
|
Complete deployment of **Stalwart Mail Server** + **SnappyMail** webmail using GitOps with ArgoCD.
|
||||||
|
|
||||||
|
## 📋 Overview
|
||||||
|
|
||||||
|
This repository deploys a lightweight, modern mail stack designed for self-hosting and lab environments:
|
||||||
|
|
||||||
|
- **Stalwart Mail Server**: All-in-one mail server (SMTP, IMAP, Admin UI)
|
||||||
|
- **SnappyMail**: Modern, lightweight webmail client
|
||||||
|
- **GitOps**: Managed by ArgoCD
|
||||||
|
- **Storage**: NFS-based persistent volumes
|
||||||
|
- **Ingress**: Traefik for web UI access
|
||||||
|
|
||||||
|
## 🏗️ Architecture
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────────┐
|
||||||
|
│ Traefik Ingress │
|
||||||
|
│ mail.dvirlabs.com webmail.dvirlabs.com │
|
||||||
|
└───────────┬──────────────────────┬──────────────┘
|
||||||
|
│ │
|
||||||
|
│ │
|
||||||
|
┌───────▼────────┐ ┌────────▼────────┐
|
||||||
|
│ Stalwart │◄───│ SnappyMail │
|
||||||
|
│ Mail Server │ │ Webmail │
|
||||||
|
│ │ │ │
|
||||||
|
│ • SMTP │ │ Connects via: │
|
||||||
|
│ • IMAP │ │ • IMAP:993 │
|
||||||
|
│ • Admin UI │ │ • SMTP:587 │
|
||||||
|
└────────┬───────┘ └─────────────────┘
|
||||||
|
│
|
||||||
|
│
|
||||||
|
┌────────▼───────┐
|
||||||
|
│ NFS Storage │
|
||||||
|
│ Mail Data │
|
||||||
|
└────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📁 Repository Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
mail-services/
|
||||||
|
├── argocd-apps/
|
||||||
|
│ ├── stalwart.yaml # ArgoCD Application for Stalwart
|
||||||
|
│ └── snappymail.yaml # ArgoCD Application for SnappyMail
|
||||||
|
├── charts/
|
||||||
|
│ ├── stalwart/ # Local Helm chart for Stalwart
|
||||||
|
│ │ ├── Chart.yaml
|
||||||
|
│ │ ├── values.yaml # Default values
|
||||||
|
│ │ └── templates/
|
||||||
|
│ │ ├── namespace.yaml
|
||||||
|
│ │ ├── secret.yaml
|
||||||
|
│ │ ├── statefulset.yaml
|
||||||
|
│ │ ├── service.yaml
|
||||||
|
│ │ └── ingress.yaml
|
||||||
|
│ └── snappymail/ # Local Helm chart for SnappyMail
|
||||||
|
│ ├── Chart.yaml
|
||||||
|
│ ├── values.yaml # Default values
|
||||||
|
│ └── templates/
|
||||||
|
│ ├── deployment.yaml
|
||||||
|
│ ├── pvc.yaml
|
||||||
|
│ ├── service.yaml
|
||||||
|
│ ├── ingress.yaml
|
||||||
|
│ └── configmap.yaml
|
||||||
|
└── manifests/
|
||||||
|
├── stalwart/
|
||||||
|
│ └── values.yaml # Custom values for dvirlabs.com
|
||||||
|
└── snappymail/
|
||||||
|
└── values.yaml # Custom values for dvirlabs.com
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🚀 Quick Start
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
|
||||||
|
- k3s cluster running
|
||||||
|
- ArgoCD installed and configured
|
||||||
|
- Traefik ingress controller
|
||||||
|
- NFS storage class (`nfs-client`)
|
||||||
|
- DNS records pointing to your cluster
|
||||||
|
|
||||||
|
### Step 1: Update Configuration
|
||||||
|
|
||||||
|
1. **Update ArgoCD Application manifests** with your Git repository URL:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Edit both files and replace YOUR_USERNAME with your actual repo
|
||||||
|
vim argocd-apps/stalwart.yaml
|
||||||
|
vim argocd-apps/snappymail.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Change the Stalwart admin password**:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Edit and set a strong password
|
||||||
|
vim manifests/stalwart/values.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
Find this section and change `CHANGE_ME_PLEASE_USE_STRONG_PASSWORD`:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
secret:
|
||||||
|
create: true
|
||||||
|
name: stalwart-credentials
|
||||||
|
adminPassword: "YOUR_STRONG_PASSWORD_HERE"
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Update domain names** (if not using dvirlabs.com):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Update in both files
|
||||||
|
vim manifests/stalwart/values.yaml
|
||||||
|
vim manifests/snappymail/values.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 2: Deploy with ArgoCD
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Apply ArgoCD Applications
|
||||||
|
kubectl apply -f argocd-apps/stalwart.yaml
|
||||||
|
kubectl apply -f argocd-apps/snappymail.yaml
|
||||||
|
|
||||||
|
# Check deployment status
|
||||||
|
kubectl get applications -n argocd
|
||||||
|
|
||||||
|
# Watch pods come up
|
||||||
|
kubectl get pods -n mail -w
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 3: Verify Deployment
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check all resources in mail namespace
|
||||||
|
kubectl get all -n mail
|
||||||
|
|
||||||
|
# Check PVCs
|
||||||
|
kubectl get pvc -n mail
|
||||||
|
|
||||||
|
# Check ingresses
|
||||||
|
kubectl get ingress -n mail
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected output:
|
||||||
|
```
|
||||||
|
NAME READY STATUS RESTARTS AGE
|
||||||
|
pod/stalwart-0 1/1 Running 0 2m
|
||||||
|
pod/snappymail-xxx-xxx 1/1 Running 0 2m
|
||||||
|
|
||||||
|
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S)
|
||||||
|
service/stalwart ClusterIP 10.43.x.x <none> 8080/TCP,25/TCP,587/TCP,993/TCP
|
||||||
|
service/snappymail ClusterIP 10.43.x.x <none> 8888/TCP
|
||||||
|
|
||||||
|
NAME CLASS HOSTS
|
||||||
|
ingress.networking.k8s.io/stalwart traefik mail.dvirlabs.com
|
||||||
|
ingress.networking.k8s.io/snappymail traefik webmail.dvirlabs.com
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🌐 Access the Services
|
||||||
|
|
||||||
|
### Stalwart Admin UI
|
||||||
|
|
||||||
|
URL: `https://mail.dvirlabs.com`
|
||||||
|
|
||||||
|
Default credentials:
|
||||||
|
- Username: `admin@dvirlabs.com`
|
||||||
|
- Password: (the one you set in manifests/stalwart/values.yaml)
|
||||||
|
|
||||||
|
### SnappyMail Webmail
|
||||||
|
|
||||||
|
URL: `https://webmail.dvirlabs.com`
|
||||||
|
|
||||||
|
First-time setup:
|
||||||
|
1. Access the admin panel: `https://webmail.dvirlabs.com/?admin`
|
||||||
|
2. Default admin password: `12345` (change immediately!)
|
||||||
|
3. Configure mail server connection:
|
||||||
|
- **IMAP Server**: `stalwart.mail.svc.cluster.local`
|
||||||
|
- **IMAP Port**: `993`
|
||||||
|
- **IMAP Security**: SSL/TLS
|
||||||
|
- **SMTP Server**: `stalwart.mail.svc.cluster.local`
|
||||||
|
- **SMTP Port**: `587`
|
||||||
|
- **SMTP Security**: STARTTLS
|
||||||
|
|
||||||
|
## 📧 Configuring Real Mail Service
|
||||||
|
|
||||||
|
### Important: Cloudflare Tunnel Limitations
|
||||||
|
|
||||||
|
⚠️ **WARNING**: While Cloudflare Tunnel works fine for web UIs (admin panel and webmail), it **CANNOT** be used for actual email protocols (SMTP/IMAP).
|
||||||
|
|
||||||
|
**What works through Cloudflare Tunnel:**
|
||||||
|
- ✅ Stalwart admin UI (HTTPS)
|
||||||
|
- ✅ SnappyMail webmail (HTTPS)
|
||||||
|
|
||||||
|
**What does NOT work through Cloudflare Tunnel:**
|
||||||
|
- ❌ Receiving mail from other servers (SMTP port 25)
|
||||||
|
- ❌ Sending mail to other servers (SMTP port 25)
|
||||||
|
- ❌ External email clients (IMAP/SMTP)
|
||||||
|
|
||||||
|
### Required for Real Email
|
||||||
|
|
||||||
|
To receive and send real email, you need:
|
||||||
|
|
||||||
|
#### 1. DNS Records
|
||||||
|
|
||||||
|
```dns
|
||||||
|
; MX Record (Mail Exchange)
|
||||||
|
@ IN MX 10 mail.dvirlabs.com.
|
||||||
|
|
||||||
|
; A Record (pointing to your public IP - NOT Cloudflare Tunnel)
|
||||||
|
mail IN A YOUR_PUBLIC_IP
|
||||||
|
|
||||||
|
; SPF Record (Sender Policy Framework)
|
||||||
|
@ IN TXT "v=spf1 mx ~all"
|
||||||
|
|
||||||
|
; DMARC Record
|
||||||
|
_dmarc IN TXT "v=DMARC1; p=quarantine; rua=mailto:admin@dvirlabs.com"
|
||||||
|
|
||||||
|
; DKIM Record (generated by Stalwart)
|
||||||
|
; Get this from Stalwart admin UI after setup
|
||||||
|
default._domainkey IN TXT "v=DKIM1; k=rsa; p=YOUR_PUBLIC_KEY_HERE"
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 2. Port Forwarding
|
||||||
|
|
||||||
|
You need to expose these ports directly (NOT through Cloudflare):
|
||||||
|
|
||||||
|
```
|
||||||
|
Port 25 (SMTP) - Required for receiving mail from other servers
|
||||||
|
Port 587 (SMTP) - Required for sending mail (submission)
|
||||||
|
Port 465 (SMTPS) - Optional, secure SMTP submission
|
||||||
|
Port 993 (IMAPS) - Required for IMAP access
|
||||||
|
Port 143 (IMAP) - Optional, plaintext IMAP
|
||||||
|
```
|
||||||
|
|
||||||
|
**Option A: NodePort Service**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl apply -f - <<EOF
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: stalwart-external
|
||||||
|
namespace: mail
|
||||||
|
spec:
|
||||||
|
type: NodePort
|
||||||
|
ports:
|
||||||
|
- name: smtp
|
||||||
|
port: 25
|
||||||
|
targetPort: 25
|
||||||
|
nodePort: 30025
|
||||||
|
- name: submission
|
||||||
|
port: 587
|
||||||
|
targetPort: 587
|
||||||
|
nodePort: 30587
|
||||||
|
- name: imaps
|
||||||
|
port: 993
|
||||||
|
targetPort: 993
|
||||||
|
nodePort: 30993
|
||||||
|
selector:
|
||||||
|
app.kubernetes.io/name: stalwart
|
||||||
|
EOF
|
||||||
|
```
|
||||||
|
|
||||||
|
Then forward ports 25, 587, 993 from your router to your k3s node on ports 30025, 30587, 30993.
|
||||||
|
|
||||||
|
**Option B: LoadBalancer with MetalLB**
|
||||||
|
|
||||||
|
If you have MetalLB configured:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl apply -f - <<EOF
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: stalwart-lb
|
||||||
|
namespace: mail
|
||||||
|
spec:
|
||||||
|
type: LoadBalancer
|
||||||
|
loadBalancerIP: YOUR_LB_IP
|
||||||
|
ports:
|
||||||
|
- name: smtp
|
||||||
|
port: 25
|
||||||
|
targetPort: 25
|
||||||
|
- name: submission
|
||||||
|
port: 587
|
||||||
|
targetPort: 587
|
||||||
|
- name: imaps
|
||||||
|
port: 993
|
||||||
|
targetPort: 993
|
||||||
|
selector:
|
||||||
|
app.kubernetes.io/name: stalwart
|
||||||
|
EOF
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 3. PTR (Reverse DNS) Record
|
||||||
|
|
||||||
|
Contact your ISP or VPS provider to set a PTR record:
|
||||||
|
|
||||||
|
```
|
||||||
|
YOUR_PUBLIC_IP -> mail.dvirlabs.com
|
||||||
|
```
|
||||||
|
|
||||||
|
This is **critical** for email deliverability. Without it, many servers will reject your mail.
|
||||||
|
|
||||||
|
## 🔧 Configuration Management
|
||||||
|
|
||||||
|
### Using External Secrets (Recommended for Production)
|
||||||
|
|
||||||
|
Instead of storing passwords in Git, use External Secrets Operator:
|
||||||
|
|
||||||
|
1. Install External Secrets Operator
|
||||||
|
2. Create a secret in your secret backend (Vault, AWS Secrets Manager, etc.)
|
||||||
|
3. Update manifests/stalwart/values.yaml:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
secret:
|
||||||
|
create: false # Don't create the secret
|
||||||
|
name: stalwart-credentials # Reference external secret
|
||||||
|
```
|
||||||
|
|
||||||
|
4. Create an ExternalSecret:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
apiVersion: external-secrets.io/v1beta1
|
||||||
|
kind: ExternalSecret
|
||||||
|
metadata:
|
||||||
|
name: stalwart-credentials
|
||||||
|
namespace: mail
|
||||||
|
spec:
|
||||||
|
refreshInterval: 1h
|
||||||
|
secretStoreRef:
|
||||||
|
name: your-secret-store
|
||||||
|
kind: SecretStore
|
||||||
|
target:
|
||||||
|
name: stalwart-credentials
|
||||||
|
data:
|
||||||
|
- secretKey: STALWART_ADMIN_PASSWORD
|
||||||
|
remoteRef:
|
||||||
|
key: mail/stalwart/admin-password
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🛠️ Maintenance
|
||||||
|
|
||||||
|
### View Stalwart Logs
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl logs -n mail stalwart-0 -f
|
||||||
|
```
|
||||||
|
|
||||||
|
### View SnappyMail Logs
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl logs -n mail -l app.kubernetes.io/name=snappymail -f
|
||||||
|
```
|
||||||
|
|
||||||
|
### Access Stalwart Shell
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl exec -it -n mail stalwart-0 -- /bin/sh
|
||||||
|
```
|
||||||
|
|
||||||
|
### Backup Mail Data
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Backup Stalwart data
|
||||||
|
kubectl exec -n mail stalwart-0 -- tar czf /tmp/mail-backup.tar.gz /opt/stalwart-mail
|
||||||
|
kubectl cp mail/stalwart-0:/tmp/mail-backup.tar.gz ./mail-backup-$(date +%Y%m%d).tar.gz
|
||||||
|
|
||||||
|
# Backup SnappyMail config
|
||||||
|
kubectl exec -n mail -l app.kubernetes.io/name=snappymail -- tar czf /tmp/snappymail-backup.tar.gz /var/lib/snappymail
|
||||||
|
kubectl cp mail/snappymail-xxx:/tmp/snappymail-backup.tar.gz ./snappymail-backup-$(date +%Y%m%d).tar.gz
|
||||||
|
```
|
||||||
|
|
||||||
|
### Restore from Backup
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Restore Stalwart
|
||||||
|
kubectl cp ./mail-backup.tar.gz mail/stalwart-0:/tmp/mail-backup.tar.gz
|
||||||
|
kubectl exec -n mail stalwart-0 -- tar xzf /tmp/mail-backup.tar.gz -C /
|
||||||
|
kubectl rollout restart statefulset -n mail stalwart
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔍 Troubleshooting
|
||||||
|
|
||||||
|
### Pods Not Starting
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check pod events
|
||||||
|
kubectl describe pod -n mail stalwart-0
|
||||||
|
kubectl describe pod -n mail -l app.kubernetes.io/name=snappymail
|
||||||
|
|
||||||
|
# Check PVC status
|
||||||
|
kubectl get pvc -n mail
|
||||||
|
```
|
||||||
|
|
||||||
|
### Ingress Not Working
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check ingress status
|
||||||
|
kubectl describe ingress -n mail
|
||||||
|
|
||||||
|
# Check Traefik logs
|
||||||
|
kubectl logs -n kube-system -l app.kubernetes.io/name=traefik
|
||||||
|
|
||||||
|
# Test internal connectivity
|
||||||
|
kubectl run -it --rm debug --image=busybox -n mail -- wget -O- http://stalwart:8080
|
||||||
|
```
|
||||||
|
|
||||||
|
### SnappyMail Can't Connect to Stalwart
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Test IMAP connectivity from SnappyMail pod
|
||||||
|
kubectl exec -it -n mail -l app.kubernetes.io/name=snappymail -- nc -zv stalwart.mail.svc.cluster.local 993
|
||||||
|
|
||||||
|
# Check Stalwart service
|
||||||
|
kubectl get svc -n mail stalwart
|
||||||
|
```
|
||||||
|
|
||||||
|
### Email Not Being Delivered
|
||||||
|
|
||||||
|
Common issues:
|
||||||
|
1. **No PTR record**: Check reverse DNS
|
||||||
|
2. **Port 25 blocked**: Many ISPs block outbound port 25
|
||||||
|
3. **Missing SPF/DKIM/DMARC**: Check DNS records
|
||||||
|
4. **IP on blacklist**: Check https://mxtoolbox.com/blacklists.aspx
|
||||||
|
|
||||||
|
## 📊 Monitoring
|
||||||
|
|
||||||
|
### Check Mail Queue
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Access Stalwart admin UI
|
||||||
|
# https://mail.dvirlabs.com
|
||||||
|
# Navigate to Queue section
|
||||||
|
```
|
||||||
|
|
||||||
|
### Resource Usage
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check pod resource usage
|
||||||
|
kubectl top pods -n mail
|
||||||
|
|
||||||
|
# Check PVC usage
|
||||||
|
kubectl exec -n mail stalwart-0 -- df -h /opt/stalwart-mail
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔐 Security Hardening
|
||||||
|
|
||||||
|
### Recommended Post-Deployment Steps
|
||||||
|
|
||||||
|
1. **Change SnappyMail admin password** immediately
|
||||||
|
2. **Enable fail2ban** for brute force protection
|
||||||
|
3. **Set up TLS certificates** with cert-manager (if not using Cloudflare)
|
||||||
|
4. **Enable DKIM signing** in Stalwart
|
||||||
|
5. **Configure rate limiting** in Stalwart
|
||||||
|
6. **Regular backups** of mail data
|
||||||
|
7. **Monitor logs** for suspicious activity
|
||||||
|
|
||||||
|
### TLS Certificates with cert-manager
|
||||||
|
|
||||||
|
If you want Let's Encrypt certificates instead of Cloudflare:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# Add to ingress annotations
|
||||||
|
cert-manager.io/cluster-issuer: letsencrypt-prod
|
||||||
|
```
|
||||||
|
|
||||||
|
And configure TLS:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
tls:
|
||||||
|
- hosts:
|
||||||
|
- mail.dvirlabs.com
|
||||||
|
secretName: stalwart-tls
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📚 Additional Resources
|
||||||
|
|
||||||
|
- [Stalwart Documentation](https://stalw.art/docs)
|
||||||
|
- [SnappyMail Documentation](https://snappymail.eu/)
|
||||||
|
- [Email Deliverability Best Practices](https://www.mail-tester.com/)
|
||||||
|
- [DKIM Setup Guide](https://www.cloudflare.com/learning/dns/dns-records/dns-dkim-record/)
|
||||||
|
|
||||||
|
## ⚙️ Customization
|
||||||
|
|
||||||
|
### Adjust Storage Size
|
||||||
|
|
||||||
|
Edit `manifests/stalwart/values.yaml` or `manifests/snappymail/values.yaml`:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
persistence:
|
||||||
|
size: 50Gi # Increase as needed
|
||||||
|
```
|
||||||
|
|
||||||
|
### Change Resource Limits
|
||||||
|
|
||||||
|
Edit `manifests/*/values.yaml`:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
memory: "2Gi"
|
||||||
|
cpu: "1000m"
|
||||||
|
limits:
|
||||||
|
memory: "8Gi"
|
||||||
|
cpu: "4000m"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Add Multiple Domains
|
||||||
|
|
||||||
|
Configure in Stalwart admin UI after deployment.
|
||||||
|
|
||||||
|
## 🤝 Contributing
|
||||||
|
|
||||||
|
This is a personal lab setup, but feel free to fork and adapt for your needs!
|
||||||
|
|
||||||
|
## 📝 License
|
||||||
|
|
||||||
|
MIT License - Use at your own risk
|
||||||
|
|
||||||
|
## ⚠️ Disclaimer
|
||||||
|
|
||||||
|
This setup is designed for lab/self-hosting environments. For production use:
|
||||||
|
- Use External Secrets for credentials
|
||||||
|
- Set up proper TLS certificates
|
||||||
|
- Configure backup automation
|
||||||
|
- Enable monitoring and alerting
|
||||||
|
- Review security best practices
|
||||||
|
- Test email deliverability thoroughly
|
||||||
298
QUICKSTART.md
Normal file
298
QUICKSTART.md
Normal file
@ -0,0 +1,298 @@
|
|||||||
|
# Quick Start Guide - Stalwart + SnappyMail Mail Stack
|
||||||
|
|
||||||
|
## 📋 What Was Created
|
||||||
|
|
||||||
|
A complete GitOps-ready mail stack with:
|
||||||
|
- ✅ Stalwart Mail Server (all-in-one: SMTP, IMAP, Admin UI)
|
||||||
|
- ✅ SnappyMail webmail client
|
||||||
|
- ✅ Local Helm charts for both applications
|
||||||
|
- ✅ ArgoCD Application manifests
|
||||||
|
- ✅ Custom values files for dvirlabs.com
|
||||||
|
- ✅ All manifests validated successfully
|
||||||
|
|
||||||
|
## 📁 File Structure Created
|
||||||
|
|
||||||
|
```
|
||||||
|
mail-services/
|
||||||
|
├── argocd-apps/
|
||||||
|
│ ├── stalwart.yaml # ⚠️ UPDATE: Change repo URL
|
||||||
|
│ └── snappymail.yaml # ⚠️ UPDATE: Change repo URL
|
||||||
|
│
|
||||||
|
├── charts/
|
||||||
|
│ ├── stalwart/ # Local Helm chart for Stalwart
|
||||||
|
│ │ ├── Chart.yaml
|
||||||
|
│ │ ├── values.yaml
|
||||||
|
│ │ └── templates/
|
||||||
|
│ │ ├── _helpers.tpl
|
||||||
|
│ │ ├── namespace.yaml
|
||||||
|
│ │ ├── secret.yaml
|
||||||
|
│ │ ├── statefulset.yaml
|
||||||
|
│ │ ├── service.yaml
|
||||||
|
│ │ └── ingress.yaml
|
||||||
|
│ │
|
||||||
|
│ └── snappymail/ # Local Helm chart for SnappyMail
|
||||||
|
│ ├── Chart.yaml
|
||||||
|
│ ├── values.yaml
|
||||||
|
│ └── templates/
|
||||||
|
│ ├── _helpers.tpl
|
||||||
|
│ ├── deployment.yaml
|
||||||
|
│ ├── pvc.yaml
|
||||||
|
│ ├── service.yaml
|
||||||
|
│ ├── ingress.yaml
|
||||||
|
│ └── configmap.yaml
|
||||||
|
│
|
||||||
|
├── manifests/
|
||||||
|
│ ├── stalwart/
|
||||||
|
│ │ └── values.yaml # ⚠️ UPDATE: Change admin password
|
||||||
|
│ └── snappymail/
|
||||||
|
│ └── values.yaml
|
||||||
|
│
|
||||||
|
├── MAIL_STACK_README.md # 📖 Full documentation
|
||||||
|
└── QUICKSTART.md # 👈 This file
|
||||||
|
```
|
||||||
|
|
||||||
|
## ⚠️ REQUIRED CHANGES Before Deployment
|
||||||
|
|
||||||
|
### 1. Update Git Repository URL
|
||||||
|
|
||||||
|
Edit these files and replace `YOUR_USERNAME` with your actual Git username/organization:
|
||||||
|
|
||||||
|
**File: `argocd-apps/stalwart.yaml`**
|
||||||
|
```yaml
|
||||||
|
source:
|
||||||
|
repoURL: https://github.com/YOUR_USERNAME/mail-services.git # ← CHANGE THIS
|
||||||
|
```
|
||||||
|
|
||||||
|
**File: `argocd-apps/snappymail.yaml`**
|
||||||
|
```yaml
|
||||||
|
source:
|
||||||
|
repoURL: https://github.com/YOUR_USERNAME/mail-services.git # ← CHANGE THIS
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Change Admin Password (CRITICAL!)
|
||||||
|
|
||||||
|
Edit `manifests/stalwart/values.yaml`:
|
||||||
|
|
||||||
|
Find this section:
|
||||||
|
```yaml
|
||||||
|
secret:
|
||||||
|
create: true
|
||||||
|
name: stalwart-credentials
|
||||||
|
adminPassword: "CHANGE_ME_PLEASE_USE_STRONG_PASSWORD" # ← CHANGE THIS!
|
||||||
|
```
|
||||||
|
|
||||||
|
Replace with a strong password:
|
||||||
|
```yaml
|
||||||
|
adminPassword: "MyStr0ng!P@ssw0rd#2024"
|
||||||
|
```
|
||||||
|
|
||||||
|
**⚠️ DO NOT commit this file with the default password!**
|
||||||
|
|
||||||
|
### 3. (Optional) Update Domain Names
|
||||||
|
|
||||||
|
If you're not using `dvirlabs.com`, update these files:
|
||||||
|
|
||||||
|
**`manifests/stalwart/values.yaml`:**
|
||||||
|
```yaml
|
||||||
|
ingress:
|
||||||
|
hosts:
|
||||||
|
- host: mail.YOUR-DOMAIN.com # ← Update
|
||||||
|
```
|
||||||
|
|
||||||
|
**`manifests/snappymail/values.yaml`:**
|
||||||
|
```yaml
|
||||||
|
ingress:
|
||||||
|
hosts:
|
||||||
|
- host: webmail.YOUR-DOMAIN.com # ← Update
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🚀 Deployment Steps
|
||||||
|
|
||||||
|
### Step 1: Commit and Push to Git
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd c:\Users\dvirl\OneDrive\Desktop\gitea\mail-services
|
||||||
|
|
||||||
|
# Review changes
|
||||||
|
git status
|
||||||
|
|
||||||
|
# Add new files
|
||||||
|
git add argocd-apps/stalwart.yaml
|
||||||
|
git add argocd-apps/snappymail.yaml
|
||||||
|
git add charts/stalwart/
|
||||||
|
git add charts/snappymail/
|
||||||
|
git add manifests/stalwart/
|
||||||
|
git add manifests/snappymail/
|
||||||
|
git add MAIL_STACK_README.md
|
||||||
|
git add QUICKSTART.md
|
||||||
|
|
||||||
|
# Commit
|
||||||
|
git commit -m "Add Stalwart Mail Server + SnappyMail stack"
|
||||||
|
|
||||||
|
# Push to your Git server
|
||||||
|
git push origin main
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 2: Deploy with ArgoCD
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Apply ArgoCD Applications
|
||||||
|
kubectl apply -f argocd-apps/stalwart.yaml
|
||||||
|
kubectl apply -f argocd-apps/snappymail.yaml
|
||||||
|
|
||||||
|
# Watch ArgoCD sync
|
||||||
|
kubectl get applications -n argocd -w
|
||||||
|
|
||||||
|
# Watch pods come up
|
||||||
|
kubectl get pods -n mail -w
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 3: Verify Deployment
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check all resources
|
||||||
|
kubectl get all -n mail
|
||||||
|
|
||||||
|
# Expected output:
|
||||||
|
# - statefulset.apps/stalwart (1/1)
|
||||||
|
# - deployment.apps/snappymail (1/1)
|
||||||
|
# - service/stalwart
|
||||||
|
# - service/snappymail
|
||||||
|
# - ingress.networking.k8s.io/stalwart
|
||||||
|
# - ingress.networking.k8s.io/snappymail
|
||||||
|
|
||||||
|
# Check PVCs
|
||||||
|
kubectl get pvc -n mail
|
||||||
|
|
||||||
|
# Check logs
|
||||||
|
kubectl logs -n mail stalwart-0
|
||||||
|
kubectl logs -n mail -l app.kubernetes.io/name=snappymail
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🌐 Access the Services
|
||||||
|
|
||||||
|
### Stalwart Admin UI
|
||||||
|
- URL: `https://mail.dvirlabs.com`
|
||||||
|
- Username: `admin@dvirlabs.com`
|
||||||
|
- Password: (what you set in manifests/stalwart/values.yaml)
|
||||||
|
|
||||||
|
### SnappyMail Webmail
|
||||||
|
- URL: `https://webmail.dvirlabs.com`
|
||||||
|
- First access: Admin panel at `https://webmail.dvirlabs.com/?admin`
|
||||||
|
- Default admin password: `12345` (CHANGE IMMEDIATELY!)
|
||||||
|
|
||||||
|
## ⚙️ SnappyMail Configuration
|
||||||
|
|
||||||
|
After deployment, configure SnappyMail to connect to Stalwart:
|
||||||
|
|
||||||
|
1. Go to `https://webmail.dvirlabs.com/?admin`
|
||||||
|
2. Login with default password `12345`
|
||||||
|
3. Change admin password immediately
|
||||||
|
4. Go to **Domains** → **Add Domain**
|
||||||
|
5. Configure:
|
||||||
|
- **IMAP Server:** `stalwart.mail.svc.cluster.local`
|
||||||
|
- **IMAP Port:** `993`
|
||||||
|
- **IMAP Secure:** `SSL/TLS`
|
||||||
|
- **SMTP Server:** `stalwart.mail.svc.cluster.local`
|
||||||
|
- **SMTP Port:** `587`
|
||||||
|
- **SMTP Secure:** `STARTTLS`
|
||||||
|
|
||||||
|
## 📧 Setting Up Real Email
|
||||||
|
|
||||||
|
### DNS Records Needed
|
||||||
|
|
||||||
|
```dns
|
||||||
|
; MX Record
|
||||||
|
@ IN MX 10 mail.dvirlabs.com.
|
||||||
|
|
||||||
|
; A Record (use your public IP, NOT Cloudflare proxy)
|
||||||
|
mail IN A YOUR_PUBLIC_IP
|
||||||
|
|
||||||
|
; SPF Record
|
||||||
|
@ IN TXT "v=spf1 mx ~all"
|
||||||
|
|
||||||
|
; DMARC Record
|
||||||
|
_dmarc IN TXT "v=DMARC1; p=quarantine; rua=mailto:admin@dvirlabs.com"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Port Forwarding Required
|
||||||
|
|
||||||
|
For real email (not just webmail), you need to expose these ports directly:
|
||||||
|
|
||||||
|
```
|
||||||
|
Port 25 (SMTP) - Receiving mail
|
||||||
|
Port 587 (SMTP) - Sending mail
|
||||||
|
Port 993 (IMAPS) - IMAP access
|
||||||
|
```
|
||||||
|
|
||||||
|
**⚠️ Important:** These ports CANNOT go through Cloudflare Tunnel!
|
||||||
|
|
||||||
|
## 🔍 Troubleshooting
|
||||||
|
|
||||||
|
### Pods stuck in Pending
|
||||||
|
```bash
|
||||||
|
# Check PVC status
|
||||||
|
kubectl describe pvc -n mail
|
||||||
|
|
||||||
|
# Check if nfs-client storage class exists
|
||||||
|
kubectl get storageclass
|
||||||
|
```
|
||||||
|
|
||||||
|
### Can't access web UIs
|
||||||
|
```bash
|
||||||
|
# Check ingress
|
||||||
|
kubectl describe ingress -n mail
|
||||||
|
|
||||||
|
# Check if DNS resolves to your cluster
|
||||||
|
nslookup mail.dvirlabs.com
|
||||||
|
nslookup webmail.dvirlabs.com
|
||||||
|
```
|
||||||
|
|
||||||
|
### SnappyMail can't connect to Stalwart
|
||||||
|
```bash
|
||||||
|
# Test connectivity from SnappyMail pod
|
||||||
|
kubectl exec -it -n mail deploy/snappymail -- nc -zv stalwart.mail.svc.cluster.local 993
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📖 Full Documentation
|
||||||
|
|
||||||
|
See [MAIL_STACK_README.md](MAIL_STACK_README.md) for:
|
||||||
|
- Complete architecture overview
|
||||||
|
- External mail setup instructions
|
||||||
|
- Security hardening guide
|
||||||
|
- Backup and restore procedures
|
||||||
|
- Advanced configuration options
|
||||||
|
- External Secrets integration
|
||||||
|
|
||||||
|
## ✅ Validation Results
|
||||||
|
|
||||||
|
All manifests have been validated:
|
||||||
|
- ✅ Stalwart Helm chart renders correctly
|
||||||
|
- ✅ SnappyMail Helm chart renders correctly
|
||||||
|
- ✅ ArgoCD Application manifests are valid
|
||||||
|
- ✅ All Kubernetes resources are syntactically correct
|
||||||
|
|
||||||
|
## 🎯 Next Steps
|
||||||
|
|
||||||
|
1. **Update repo URL** in ArgoCD manifests ← DO THIS FIRST!
|
||||||
|
2. **Change admin password** in manifests/stalwart/values.yaml
|
||||||
|
3. **Commit and push** to Git
|
||||||
|
4. **Apply ArgoCD applications**
|
||||||
|
5. **Wait for deployment** (2-3 minutes)
|
||||||
|
6. **Access Stalwart admin UI** and configure mail settings
|
||||||
|
7. **Configure SnappyMail** to connect to Stalwart
|
||||||
|
8. **Set up DNS records** for real email
|
||||||
|
9. **Configure port forwarding** for mail protocols
|
||||||
|
|
||||||
|
## 💡 Pro Tips
|
||||||
|
|
||||||
|
- Start with web UIs only, add real mail later
|
||||||
|
- Use External Secrets for production passwords
|
||||||
|
- Enable DKIM in Stalwart for better deliverability
|
||||||
|
- Monitor logs during first email tests
|
||||||
|
- Test with mail-tester.com for deliverability score
|
||||||
|
- Backup mail data regularly
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Need help?** Check [MAIL_STACK_README.md](MAIL_STACK_README.md) for detailed documentation.
|
||||||
36
argocd-apps/snappymail.yaml
Normal file
36
argocd-apps/snappymail.yaml
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
apiVersion: argoproj.io/v1alpha1
|
||||||
|
kind: Application
|
||||||
|
metadata:
|
||||||
|
name: snappymail
|
||||||
|
namespace: argocd
|
||||||
|
finalizers:
|
||||||
|
- resources-finalizer.argocd.argoproj.io
|
||||||
|
spec:
|
||||||
|
project: default
|
||||||
|
|
||||||
|
source:
|
||||||
|
repoURL: https://github.com/YOUR_USERNAME/mail-services.git # TODO: Update with your repo URL
|
||||||
|
targetRevision: HEAD
|
||||||
|
path: charts/snappymail
|
||||||
|
helm:
|
||||||
|
valueFiles:
|
||||||
|
- ../../manifests/snappymail/values.yaml
|
||||||
|
|
||||||
|
destination:
|
||||||
|
server: https://kubernetes.default.svc
|
||||||
|
namespace: mail
|
||||||
|
|
||||||
|
syncPolicy:
|
||||||
|
automated:
|
||||||
|
prune: true
|
||||||
|
selfHeal: true
|
||||||
|
allowEmpty: false
|
||||||
|
syncOptions:
|
||||||
|
- CreateNamespace=true
|
||||||
|
- ServerSideApply=true
|
||||||
|
retry:
|
||||||
|
limit: 5
|
||||||
|
backoff:
|
||||||
|
duration: 5s
|
||||||
|
factor: 2
|
||||||
|
maxDuration: 3m
|
||||||
36
argocd-apps/stalwart.yaml
Normal file
36
argocd-apps/stalwart.yaml
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
apiVersion: argoproj.io/v1alpha1
|
||||||
|
kind: Application
|
||||||
|
metadata:
|
||||||
|
name: stalwart
|
||||||
|
namespace: argocd
|
||||||
|
finalizers:
|
||||||
|
- resources-finalizer.argocd.argoproj.io
|
||||||
|
spec:
|
||||||
|
project: default
|
||||||
|
|
||||||
|
source:
|
||||||
|
repoURL: https://github.com/YOUR_USERNAME/mail-services.git # TODO: Update with your repo URL
|
||||||
|
targetRevision: HEAD
|
||||||
|
path: charts/stalwart
|
||||||
|
helm:
|
||||||
|
valueFiles:
|
||||||
|
- ../../manifests/stalwart/values.yaml
|
||||||
|
|
||||||
|
destination:
|
||||||
|
server: https://kubernetes.default.svc
|
||||||
|
namespace: mail
|
||||||
|
|
||||||
|
syncPolicy:
|
||||||
|
automated:
|
||||||
|
prune: true
|
||||||
|
selfHeal: true
|
||||||
|
allowEmpty: false
|
||||||
|
syncOptions:
|
||||||
|
- CreateNamespace=true
|
||||||
|
- ServerSideApply=true
|
||||||
|
retry:
|
||||||
|
limit: 5
|
||||||
|
backoff:
|
||||||
|
duration: 5s
|
||||||
|
factor: 2
|
||||||
|
maxDuration: 3m
|
||||||
15
charts/snappymail/Chart.yaml
Normal file
15
charts/snappymail/Chart.yaml
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
apiVersion: v2
|
||||||
|
name: snappymail
|
||||||
|
description: SnappyMail - Simple, modern, lightweight webmail client
|
||||||
|
type: application
|
||||||
|
version: 1.0.0
|
||||||
|
appVersion: "2.39.1"
|
||||||
|
keywords:
|
||||||
|
- webmail
|
||||||
|
- mail
|
||||||
|
- snappymail
|
||||||
|
home: https://snappymail.eu
|
||||||
|
sources:
|
||||||
|
- https://github.com/the-djmaze/snappymail
|
||||||
|
maintainers:
|
||||||
|
- name: dvirlabs
|
||||||
49
charts/snappymail/templates/_helpers.tpl
Normal file
49
charts/snappymail/templates/_helpers.tpl
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
{{/*
|
||||||
|
Expand the name of the chart.
|
||||||
|
*/}}
|
||||||
|
{{- define "snappymail.name" -}}
|
||||||
|
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{/*
|
||||||
|
Create a default fully qualified app name.
|
||||||
|
*/}}
|
||||||
|
{{- define "snappymail.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 "snappymail.chart" -}}
|
||||||
|
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{/*
|
||||||
|
Common labels
|
||||||
|
*/}}
|
||||||
|
{{- define "snappymail.labels" -}}
|
||||||
|
helm.sh/chart: {{ include "snappymail.chart" . }}
|
||||||
|
{{ include "snappymail.selectorLabels" . }}
|
||||||
|
{{- if .Chart.AppVersion }}
|
||||||
|
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
|
||||||
|
{{- end }}
|
||||||
|
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{/*
|
||||||
|
Selector labels
|
||||||
|
*/}}
|
||||||
|
{{- define "snappymail.selectorLabels" -}}
|
||||||
|
app.kubernetes.io/name: {{ include "snappymail.name" . }}
|
||||||
|
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||||
|
{{- end }}
|
||||||
15
charts/snappymail/templates/configmap.yaml
Normal file
15
charts/snappymail/templates/configmap.yaml
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: {{ include "snappymail.fullname" . }}-config
|
||||||
|
namespace: {{ .Values.namespace }}
|
||||||
|
labels:
|
||||||
|
{{- include "snappymail.labels" . | nindent 4 }}
|
||||||
|
data:
|
||||||
|
# Stalwart mail server connection info
|
||||||
|
# This can be used for documentation or manual configuration
|
||||||
|
# SnappyMail is configured through its web UI
|
||||||
|
IMAP_HOST: {{ .Values.stalwart.imap.host | quote }}
|
||||||
|
IMAP_PORT: {{ .Values.stalwart.imap.port | quote }}
|
||||||
|
SMTP_HOST: {{ .Values.stalwart.smtp.host | quote }}
|
||||||
|
SMTP_PORT: {{ .Values.stalwart.smtp.port | quote }}
|
||||||
69
charts/snappymail/templates/deployment.yaml
Normal file
69
charts/snappymail/templates/deployment.yaml
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: {{ include "snappymail.fullname" . }}
|
||||||
|
namespace: {{ .Values.namespace }}
|
||||||
|
labels:
|
||||||
|
{{- include "snappymail.labels" . | nindent 4 }}
|
||||||
|
spec:
|
||||||
|
replicas: {{ .Values.replicaCount }}
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
{{- include "snappymail.selectorLabels" . | nindent 6 }}
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
{{- include "snappymail.selectorLabels" . | nindent 8 }}
|
||||||
|
spec:
|
||||||
|
securityContext:
|
||||||
|
{{- toYaml .Values.securityContext | nindent 8 }}
|
||||||
|
containers:
|
||||||
|
- name: snappymail
|
||||||
|
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
|
||||||
|
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
containerPort: {{ .Values.service.targetPort }}
|
||||||
|
protocol: TCP
|
||||||
|
volumeMounts:
|
||||||
|
- name: data
|
||||||
|
mountPath: {{ .Values.persistence.mountPath }}
|
||||||
|
resources:
|
||||||
|
{{- toYaml .Values.resources | nindent 10 }}
|
||||||
|
livenessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /
|
||||||
|
port: http
|
||||||
|
initialDelaySeconds: 30
|
||||||
|
periodSeconds: 10
|
||||||
|
readinessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /
|
||||||
|
port: http
|
||||||
|
initialDelaySeconds: 10
|
||||||
|
periodSeconds: 5
|
||||||
|
{{- with .Values.env }}
|
||||||
|
env:
|
||||||
|
{{- toYaml . | nindent 10 }}
|
||||||
|
{{- end }}
|
||||||
|
volumes:
|
||||||
|
{{- if .Values.persistence.enabled }}
|
||||||
|
- name: data
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: {{ include "snappymail.fullname" . }}
|
||||||
|
{{- else }}
|
||||||
|
- name: data
|
||||||
|
emptyDir: {}
|
||||||
|
{{- end }}
|
||||||
|
{{- with .Values.nodeSelector }}
|
||||||
|
nodeSelector:
|
||||||
|
{{- toYaml . | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- with .Values.affinity }}
|
||||||
|
affinity:
|
||||||
|
{{- toYaml . | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- with .Values.tolerations }}
|
||||||
|
tolerations:
|
||||||
|
{{- toYaml . | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
42
charts/snappymail/templates/ingress.yaml
Normal file
42
charts/snappymail/templates/ingress.yaml
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
{{- if .Values.ingress.enabled -}}
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: Ingress
|
||||||
|
metadata:
|
||||||
|
name: {{ include "snappymail.fullname" . }}
|
||||||
|
namespace: {{ .Values.namespace }}
|
||||||
|
labels:
|
||||||
|
{{- include "snappymail.labels" . | nindent 4 }}
|
||||||
|
{{- with .Values.ingress.annotations }}
|
||||||
|
annotations:
|
||||||
|
{{- toYaml . | nindent 4 }}
|
||||||
|
{{- end }}
|
||||||
|
spec:
|
||||||
|
{{- if .Values.ingress.className }}
|
||||||
|
ingressClassName: {{ .Values.ingress.className }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if .Values.ingress.tls }}
|
||||||
|
tls:
|
||||||
|
{{- range .Values.ingress.tls }}
|
||||||
|
- hosts:
|
||||||
|
{{- range .hosts }}
|
||||||
|
- {{ . | quote }}
|
||||||
|
{{- end }}
|
||||||
|
secretName: {{ .secretName }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
rules:
|
||||||
|
{{- range .Values.ingress.hosts }}
|
||||||
|
- host: {{ .host | quote }}
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
{{- range .paths }}
|
||||||
|
- path: {{ .path }}
|
||||||
|
pathType: {{ .pathType }}
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: {{ include "snappymail.fullname" $ }}
|
||||||
|
port:
|
||||||
|
number: {{ $.Values.service.port }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
16
charts/snappymail/templates/pvc.yaml
Normal file
16
charts/snappymail/templates/pvc.yaml
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
{{- if .Values.persistence.enabled }}
|
||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: {{ include "snappymail.fullname" . }}
|
||||||
|
namespace: {{ .Values.namespace }}
|
||||||
|
labels:
|
||||||
|
{{- include "snappymail.labels" . | nindent 4 }}
|
||||||
|
spec:
|
||||||
|
accessModes:
|
||||||
|
- {{ .Values.persistence.accessMode }}
|
||||||
|
storageClassName: {{ .Values.persistence.storageClass }}
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: {{ .Values.persistence.size }}
|
||||||
|
{{- end }}
|
||||||
16
charts/snappymail/templates/service.yaml
Normal file
16
charts/snappymail/templates/service.yaml
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: {{ include "snappymail.fullname" . }}
|
||||||
|
namespace: {{ .Values.namespace }}
|
||||||
|
labels:
|
||||||
|
{{- include "snappymail.labels" . | nindent 4 }}
|
||||||
|
spec:
|
||||||
|
type: {{ .Values.service.type }}
|
||||||
|
ports:
|
||||||
|
- port: {{ .Values.service.port }}
|
||||||
|
targetPort: {{ .Values.service.targetPort }}
|
||||||
|
protocol: TCP
|
||||||
|
name: http
|
||||||
|
selector:
|
||||||
|
{{- include "snappymail.selectorLabels" . | nindent 4 }}
|
||||||
86
charts/snappymail/values.yaml
Normal file
86
charts/snappymail/values.yaml
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
## SnappyMail webmail configuration
|
||||||
|
## Default values for snappymail chart
|
||||||
|
|
||||||
|
## Image configuration
|
||||||
|
image:
|
||||||
|
repository: djmaze/snappymail
|
||||||
|
tag: "2.39"
|
||||||
|
pullPolicy: IfNotPresent
|
||||||
|
|
||||||
|
## Namespace
|
||||||
|
namespace: mail
|
||||||
|
|
||||||
|
## Replica count
|
||||||
|
replicaCount: 1
|
||||||
|
|
||||||
|
## Service configuration
|
||||||
|
service:
|
||||||
|
type: ClusterIP
|
||||||
|
port: 8888
|
||||||
|
targetPort: 8888
|
||||||
|
|
||||||
|
## Ingress configuration
|
||||||
|
ingress:
|
||||||
|
enabled: true
|
||||||
|
className: traefik
|
||||||
|
annotations:
|
||||||
|
traefik.ingress.kubernetes.io/router.entrypoints: websecure
|
||||||
|
traefik.ingress.kubernetes.io/router.tls: "true"
|
||||||
|
hosts:
|
||||||
|
- host: webmail.dvirlabs.com
|
||||||
|
paths:
|
||||||
|
- path: /
|
||||||
|
pathType: Prefix
|
||||||
|
tls: []
|
||||||
|
|
||||||
|
## Persistence configuration for SnappyMail data
|
||||||
|
persistence:
|
||||||
|
enabled: true
|
||||||
|
storageClass: nfs-client
|
||||||
|
accessMode: ReadWriteOnce
|
||||||
|
size: 1Gi
|
||||||
|
# Where SnappyMail stores its data
|
||||||
|
mountPath: /var/lib/snappymail
|
||||||
|
|
||||||
|
## Resource limits
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
memory: "128Mi"
|
||||||
|
cpu: "100m"
|
||||||
|
limits:
|
||||||
|
memory: "512Mi"
|
||||||
|
cpu: "500m"
|
||||||
|
|
||||||
|
## Stalwart mail server configuration
|
||||||
|
## SnappyMail will connect to Stalwart internally
|
||||||
|
stalwart:
|
||||||
|
# Service name of Stalwart in the same namespace
|
||||||
|
serviceName: stalwart
|
||||||
|
# IMAP configuration
|
||||||
|
imap:
|
||||||
|
host: stalwart.mail.svc.cluster.local
|
||||||
|
port: 993
|
||||||
|
secure: true
|
||||||
|
# SMTP configuration
|
||||||
|
smtp:
|
||||||
|
host: stalwart.mail.svc.cluster.local
|
||||||
|
port: 587
|
||||||
|
secure: true
|
||||||
|
|
||||||
|
## Environment variables
|
||||||
|
env: {}
|
||||||
|
|
||||||
|
## Pod Security Context
|
||||||
|
securityContext:
|
||||||
|
fsGroup: 82 # www-data group in Alpine
|
||||||
|
runAsUser: 82
|
||||||
|
runAsNonRoot: true
|
||||||
|
|
||||||
|
## Node selector
|
||||||
|
nodeSelector: {}
|
||||||
|
|
||||||
|
## Tolerations
|
||||||
|
tolerations: []
|
||||||
|
|
||||||
|
## Affinity
|
||||||
|
affinity: {}
|
||||||
16
charts/stalwart/Chart.yaml
Normal file
16
charts/stalwart/Chart.yaml
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
apiVersion: v2
|
||||||
|
name: stalwart
|
||||||
|
description: Stalwart Mail Server - Modern all-in-one mail server
|
||||||
|
type: application
|
||||||
|
version: 1.0.0
|
||||||
|
appVersion: "0.10.8"
|
||||||
|
keywords:
|
||||||
|
- mail
|
||||||
|
- smtp
|
||||||
|
- imap
|
||||||
|
- stalwart
|
||||||
|
home: https://stalw.art
|
||||||
|
sources:
|
||||||
|
- https://github.com/stalwartlabs/mail-server
|
||||||
|
maintainers:
|
||||||
|
- name: dvirlabs
|
||||||
60
charts/stalwart/templates/_helpers.tpl
Normal file
60
charts/stalwart/templates/_helpers.tpl
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
{{/*
|
||||||
|
Expand the name of the chart.
|
||||||
|
*/}}
|
||||||
|
{{- define "stalwart.name" -}}
|
||||||
|
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{/*
|
||||||
|
Create a default fully qualified app name.
|
||||||
|
*/}}
|
||||||
|
{{- define "stalwart.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 "stalwart.chart" -}}
|
||||||
|
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{/*
|
||||||
|
Common labels
|
||||||
|
*/}}
|
||||||
|
{{- define "stalwart.labels" -}}
|
||||||
|
helm.sh/chart: {{ include "stalwart.chart" . }}
|
||||||
|
{{ include "stalwart.selectorLabels" . }}
|
||||||
|
{{- if .Chart.AppVersion }}
|
||||||
|
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
|
||||||
|
{{- end }}
|
||||||
|
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{/*
|
||||||
|
Selector labels
|
||||||
|
*/}}
|
||||||
|
{{- define "stalwart.selectorLabels" -}}
|
||||||
|
app.kubernetes.io/name: {{ include "stalwart.name" . }}
|
||||||
|
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{/*
|
||||||
|
Create the name of the service account to use
|
||||||
|
*/}}
|
||||||
|
{{- define "stalwart.serviceAccountName" -}}
|
||||||
|
{{- if .Values.serviceAccount.create }}
|
||||||
|
{{- default (include "stalwart.fullname" .) .Values.serviceAccount.name }}
|
||||||
|
{{- else }}
|
||||||
|
{{- default "default" .Values.serviceAccount.name }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
42
charts/stalwart/templates/ingress.yaml
Normal file
42
charts/stalwart/templates/ingress.yaml
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
{{- if .Values.ingress.enabled -}}
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: Ingress
|
||||||
|
metadata:
|
||||||
|
name: {{ include "stalwart.fullname" . }}
|
||||||
|
namespace: {{ .Values.namespace }}
|
||||||
|
labels:
|
||||||
|
{{- include "stalwart.labels" . | nindent 4 }}
|
||||||
|
{{- with .Values.ingress.annotations }}
|
||||||
|
annotations:
|
||||||
|
{{- toYaml . | nindent 4 }}
|
||||||
|
{{- end }}
|
||||||
|
spec:
|
||||||
|
{{- if .Values.ingress.className }}
|
||||||
|
ingressClassName: {{ .Values.ingress.className }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if .Values.ingress.tls }}
|
||||||
|
tls:
|
||||||
|
{{- range .Values.ingress.tls }}
|
||||||
|
- hosts:
|
||||||
|
{{- range .hosts }}
|
||||||
|
- {{ . | quote }}
|
||||||
|
{{- end }}
|
||||||
|
secretName: {{ .secretName }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
rules:
|
||||||
|
{{- range .Values.ingress.hosts }}
|
||||||
|
- host: {{ .host | quote }}
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
{{- range .paths }}
|
||||||
|
- path: {{ .path }}
|
||||||
|
pathType: {{ .pathType }}
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: {{ include "stalwart.fullname" $ }}
|
||||||
|
port:
|
||||||
|
number: {{ .servicePort }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
6
charts/stalwart/templates/namespace.yaml
Normal file
6
charts/stalwart/templates/namespace.yaml
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: {{ .Values.namespace }}
|
||||||
|
labels:
|
||||||
|
{{- include "stalwart.labels" . | nindent 4 }}
|
||||||
12
charts/stalwart/templates/secret.yaml
Normal file
12
charts/stalwart/templates/secret.yaml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{{- if .Values.secret.create }}
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: {{ .Values.secret.name }}
|
||||||
|
namespace: {{ .Values.namespace }}
|
||||||
|
labels:
|
||||||
|
{{- include "stalwart.labels" . | nindent 4 }}
|
||||||
|
type: Opaque
|
||||||
|
stringData:
|
||||||
|
STALWART_ADMIN_PASSWORD: {{ .Values.secret.adminPassword | quote }}
|
||||||
|
{{- end }}
|
||||||
36
charts/stalwart/templates/service.yaml
Normal file
36
charts/stalwart/templates/service.yaml
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: {{ include "stalwart.fullname" . }}
|
||||||
|
namespace: {{ .Values.namespace }}
|
||||||
|
labels:
|
||||||
|
{{- include "stalwart.labels" . | nindent 4 }}
|
||||||
|
spec:
|
||||||
|
type: {{ .Values.service.type }}
|
||||||
|
ports:
|
||||||
|
- port: {{ .Values.service.web.port }}
|
||||||
|
targetPort: {{ .Values.service.web.targetPort }}
|
||||||
|
protocol: TCP
|
||||||
|
name: web
|
||||||
|
- port: {{ .Values.service.smtp.port }}
|
||||||
|
targetPort: {{ .Values.service.smtp.targetPort }}
|
||||||
|
protocol: TCP
|
||||||
|
name: smtp
|
||||||
|
- port: {{ .Values.service.smtps.port }}
|
||||||
|
targetPort: {{ .Values.service.smtps.targetPort }}
|
||||||
|
protocol: TCP
|
||||||
|
name: smtps
|
||||||
|
- port: {{ .Values.service.submission.port }}
|
||||||
|
targetPort: {{ .Values.service.submission.targetPort }}
|
||||||
|
protocol: TCP
|
||||||
|
name: submission
|
||||||
|
- port: {{ .Values.service.imap.port }}
|
||||||
|
targetPort: {{ .Values.service.imap.targetPort }}
|
||||||
|
protocol: TCP
|
||||||
|
name: imap
|
||||||
|
- port: {{ .Values.service.imaps.port }}
|
||||||
|
targetPort: {{ .Values.service.imaps.targetPort }}
|
||||||
|
protocol: TCP
|
||||||
|
name: imaps
|
||||||
|
selector:
|
||||||
|
{{- include "stalwart.selectorLabels" . | nindent 4 }}
|
||||||
94
charts/stalwart/templates/statefulset.yaml
Normal file
94
charts/stalwart/templates/statefulset.yaml
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: StatefulSet
|
||||||
|
metadata:
|
||||||
|
name: {{ include "stalwart.fullname" . }}
|
||||||
|
namespace: {{ .Values.namespace }}
|
||||||
|
labels:
|
||||||
|
{{- include "stalwart.labels" . | nindent 4 }}
|
||||||
|
spec:
|
||||||
|
serviceName: {{ include "stalwart.fullname" . }}
|
||||||
|
replicas: {{ .Values.replicaCount }}
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
{{- include "stalwart.selectorLabels" . | nindent 6 }}
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
{{- include "stalwart.selectorLabels" . | nindent 8 }}
|
||||||
|
spec:
|
||||||
|
securityContext:
|
||||||
|
{{- toYaml .Values.securityContext | nindent 8 }}
|
||||||
|
containers:
|
||||||
|
- name: stalwart
|
||||||
|
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
|
||||||
|
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
||||||
|
ports:
|
||||||
|
- name: web
|
||||||
|
containerPort: {{ .Values.service.web.targetPort }}
|
||||||
|
protocol: TCP
|
||||||
|
- name: smtp
|
||||||
|
containerPort: {{ .Values.service.smtp.targetPort }}
|
||||||
|
protocol: TCP
|
||||||
|
- name: smtps
|
||||||
|
containerPort: {{ .Values.service.smtps.targetPort }}
|
||||||
|
protocol: TCP
|
||||||
|
- name: submission
|
||||||
|
containerPort: {{ .Values.service.submission.targetPort }}
|
||||||
|
protocol: TCP
|
||||||
|
- name: imap
|
||||||
|
containerPort: {{ .Values.service.imap.targetPort }}
|
||||||
|
protocol: TCP
|
||||||
|
- name: imaps
|
||||||
|
containerPort: {{ .Values.service.imaps.targetPort }}
|
||||||
|
protocol: TCP
|
||||||
|
env:
|
||||||
|
- name: STALWART_ADMIN_USER
|
||||||
|
value: {{ .Values.env.STALWART_ADMIN_USER | quote }}
|
||||||
|
- name: STALWART_ADMIN_PASSWORD
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: {{ .Values.secret.name }}
|
||||||
|
key: STALWART_ADMIN_PASSWORD
|
||||||
|
volumeMounts:
|
||||||
|
- name: data
|
||||||
|
mountPath: {{ .Values.persistence.mountPath }}
|
||||||
|
resources:
|
||||||
|
{{- toYaml .Values.resources | nindent 10 }}
|
||||||
|
livenessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /
|
||||||
|
port: web
|
||||||
|
initialDelaySeconds: 30
|
||||||
|
periodSeconds: 10
|
||||||
|
readinessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /
|
||||||
|
port: web
|
||||||
|
initialDelaySeconds: 10
|
||||||
|
periodSeconds: 5
|
||||||
|
{{- with .Values.nodeSelector }}
|
||||||
|
nodeSelector:
|
||||||
|
{{- toYaml . | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- with .Values.affinity }}
|
||||||
|
affinity:
|
||||||
|
{{- toYaml . | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- with .Values.tolerations }}
|
||||||
|
tolerations:
|
||||||
|
{{- toYaml . | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if .Values.persistence.enabled }}
|
||||||
|
volumeClaimTemplates:
|
||||||
|
- metadata:
|
||||||
|
name: data
|
||||||
|
labels:
|
||||||
|
{{- include "stalwart.labels" . | nindent 8 }}
|
||||||
|
spec:
|
||||||
|
accessModes:
|
||||||
|
- {{ .Values.persistence.accessMode }}
|
||||||
|
storageClassName: {{ .Values.persistence.storageClass }}
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: {{ .Values.persistence.size }}
|
||||||
|
{{- end }}
|
||||||
104
charts/stalwart/values.yaml
Normal file
104
charts/stalwart/values.yaml
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
## Stalwart Mail Server configuration
|
||||||
|
## Default values for stalwart chart
|
||||||
|
|
||||||
|
## Image configuration
|
||||||
|
image:
|
||||||
|
repository: stalwartlabs/mail-server
|
||||||
|
tag: v0.10.8
|
||||||
|
pullPolicy: IfNotPresent
|
||||||
|
|
||||||
|
## Namespace
|
||||||
|
namespace: mail
|
||||||
|
|
||||||
|
## Replica count (should be 1 for StatefulSet with persistent data)
|
||||||
|
replicaCount: 1
|
||||||
|
|
||||||
|
## Service configuration
|
||||||
|
service:
|
||||||
|
type: ClusterIP
|
||||||
|
# Admin/Web UI port
|
||||||
|
web:
|
||||||
|
port: 8080
|
||||||
|
targetPort: 8080
|
||||||
|
# SMTP ports
|
||||||
|
smtp:
|
||||||
|
port: 25
|
||||||
|
targetPort: 25
|
||||||
|
smtps:
|
||||||
|
port: 465
|
||||||
|
targetPort: 465
|
||||||
|
submission:
|
||||||
|
port: 587
|
||||||
|
targetPort: 587
|
||||||
|
# IMAP ports
|
||||||
|
imap:
|
||||||
|
port: 143
|
||||||
|
targetPort: 143
|
||||||
|
imaps:
|
||||||
|
port: 993
|
||||||
|
targetPort: 993
|
||||||
|
|
||||||
|
## Ingress configuration for admin UI
|
||||||
|
ingress:
|
||||||
|
enabled: true
|
||||||
|
className: traefik
|
||||||
|
annotations:
|
||||||
|
traefik.ingress.kubernetes.io/router.entrypoints: websecure
|
||||||
|
traefik.ingress.kubernetes.io/router.tls: "true"
|
||||||
|
hosts:
|
||||||
|
- host: mail.dvirlabs.com
|
||||||
|
paths:
|
||||||
|
- path: /
|
||||||
|
pathType: Prefix
|
||||||
|
servicePort: 8080
|
||||||
|
tls: []
|
||||||
|
|
||||||
|
## Persistence configuration
|
||||||
|
persistence:
|
||||||
|
enabled: true
|
||||||
|
storageClass: nfs-client
|
||||||
|
accessMode: ReadWriteOnce
|
||||||
|
size: 10Gi
|
||||||
|
# Where Stalwart stores mail data
|
||||||
|
mountPath: /opt/stalwart-mail
|
||||||
|
|
||||||
|
## Resource limits
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
memory: "512Mi"
|
||||||
|
cpu: "250m"
|
||||||
|
limits:
|
||||||
|
memory: "2Gi"
|
||||||
|
cpu: "1000m"
|
||||||
|
|
||||||
|
## Environment variables for Stalwart configuration
|
||||||
|
env:
|
||||||
|
# Admin credentials - CHANGE THESE!
|
||||||
|
# Or reference a secret using envFrom
|
||||||
|
STALWART_ADMIN_USER: "admin@dvirlabs.com"
|
||||||
|
# Password should come from a secret
|
||||||
|
# STALWART_ADMIN_PASSWORD: defined in secret
|
||||||
|
|
||||||
|
## Secret configuration
|
||||||
|
secret:
|
||||||
|
# Set to true to create a secret
|
||||||
|
create: true
|
||||||
|
# Name of the secret (if create: false, this should reference an existing secret)
|
||||||
|
name: stalwart-credentials
|
||||||
|
# Admin password - CHANGE THIS or use external secrets later
|
||||||
|
adminPassword: "CHANGE_ME_PLEASE"
|
||||||
|
|
||||||
|
## Pod Security Context
|
||||||
|
securityContext:
|
||||||
|
fsGroup: 1000
|
||||||
|
runAsUser: 1000
|
||||||
|
runAsNonRoot: true
|
||||||
|
|
||||||
|
## Node selector
|
||||||
|
nodeSelector: {}
|
||||||
|
|
||||||
|
## Tolerations
|
||||||
|
tolerations: []
|
||||||
|
|
||||||
|
## Affinity
|
||||||
|
affinity: {}
|
||||||
54
manifests/snappymail/values.yaml
Normal file
54
manifests/snappymail/values.yaml
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
## SnappyMail - Custom values for dvirlabs.com
|
||||||
|
## Override default chart values here
|
||||||
|
|
||||||
|
## Namespace
|
||||||
|
namespace: mail
|
||||||
|
|
||||||
|
## Image configuration
|
||||||
|
image:
|
||||||
|
repository: djmaze/snappymail
|
||||||
|
tag: "2.39"
|
||||||
|
pullPolicy: IfNotPresent
|
||||||
|
|
||||||
|
## Persistence - using NFS storage
|
||||||
|
persistence:
|
||||||
|
enabled: true
|
||||||
|
storageClass: nfs-client
|
||||||
|
accessMode: ReadWriteOnce
|
||||||
|
size: 2Gi
|
||||||
|
mountPath: /var/lib/snappymail
|
||||||
|
|
||||||
|
## Ingress for webmail UI
|
||||||
|
ingress:
|
||||||
|
enabled: true
|
||||||
|
className: traefik
|
||||||
|
annotations:
|
||||||
|
traefik.ingress.kubernetes.io/router.entrypoints: websecure
|
||||||
|
traefik.ingress.kubernetes.io/router.tls: "true"
|
||||||
|
hosts:
|
||||||
|
- host: webmail.dvirlabs.com
|
||||||
|
paths:
|
||||||
|
- path: /
|
||||||
|
pathType: Prefix
|
||||||
|
|
||||||
|
## Stalwart mail server connection
|
||||||
|
## SnappyMail will connect to Stalwart internally
|
||||||
|
stalwart:
|
||||||
|
serviceName: stalwart
|
||||||
|
imap:
|
||||||
|
host: stalwart.mail.svc.cluster.local
|
||||||
|
port: 993
|
||||||
|
secure: true
|
||||||
|
smtp:
|
||||||
|
host: stalwart.mail.svc.cluster.local
|
||||||
|
port: 587
|
||||||
|
secure: true
|
||||||
|
|
||||||
|
## Resource allocation
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
memory: "256Mi"
|
||||||
|
cpu: "200m"
|
||||||
|
limits:
|
||||||
|
memory: "1Gi"
|
||||||
|
cpu: "1000m"
|
||||||
54
manifests/stalwart/values.yaml
Normal file
54
manifests/stalwart/values.yaml
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
## Stalwart Mail Server - Custom values for dvirlabs.com
|
||||||
|
## Override default chart values here
|
||||||
|
|
||||||
|
## Namespace
|
||||||
|
namespace: mail
|
||||||
|
|
||||||
|
## Image configuration
|
||||||
|
image:
|
||||||
|
repository: stalwartlabs/mail-server
|
||||||
|
tag: v0.10.8
|
||||||
|
pullPolicy: IfNotPresent
|
||||||
|
|
||||||
|
## Persistence - using NFS storage
|
||||||
|
persistence:
|
||||||
|
enabled: true
|
||||||
|
storageClass: nfs-client
|
||||||
|
accessMode: ReadWriteOnce
|
||||||
|
size: 20Gi # Increased for production mail storage
|
||||||
|
mountPath: /opt/stalwart-mail
|
||||||
|
|
||||||
|
## Ingress for admin UI only
|
||||||
|
ingress:
|
||||||
|
enabled: true
|
||||||
|
className: traefik
|
||||||
|
annotations:
|
||||||
|
traefik.ingress.kubernetes.io/router.entrypoints: websecure
|
||||||
|
traefik.ingress.kubernetes.io/router.tls: "true"
|
||||||
|
hosts:
|
||||||
|
- host: mail.dvirlabs.com
|
||||||
|
paths:
|
||||||
|
- path: /
|
||||||
|
pathType: Prefix
|
||||||
|
servicePort: 8080
|
||||||
|
|
||||||
|
## Admin credentials
|
||||||
|
env:
|
||||||
|
STALWART_ADMIN_USER: "admin@dvirlabs.com"
|
||||||
|
|
||||||
|
## Secret configuration
|
||||||
|
## IMPORTANT: Change the adminPassword before deploying!
|
||||||
|
secret:
|
||||||
|
create: true
|
||||||
|
name: stalwart-credentials
|
||||||
|
# TODO: Replace with a strong password or use External Secrets
|
||||||
|
adminPassword: "CHANGE_ME_PLEASE_USE_STRONG_PASSWORD"
|
||||||
|
|
||||||
|
## Resource allocation
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
memory: "1Gi"
|
||||||
|
cpu: "500m"
|
||||||
|
limits:
|
||||||
|
memory: "4Gi"
|
||||||
|
cpu: "2000m"
|
||||||
Loading…
x
Reference in New Issue
Block a user