Customize Storage#
How to adjust PersistentVolumeClaim sizes and storage classes for Mailu components.
Problem#
You need to customize storage sizes for mailboxes, queues, and other persistent data based on your expected user count, email volume, or available storage classes.
Solution#
The MailuChart accepts a storage configuration object that controls PVC sizes and storage classes for each component. Configure a global storage class and override sizes per component.
Understanding Storage Requirements#
Different Mailu components have different storage needs:
Component |
Purpose |
Typical Size |
Growth Rate |
|---|---|---|---|
Dovecot |
User mailboxes (largest) |
50-500Gi |
1-5GB per active user |
Postfix |
Mail queue |
5-10Gi |
Temporary, self-cleaning |
Rspamd |
Spam learning data |
5Gi |
Slow growth |
Admin |
DKIM keys, config |
5Gi |
Minimal growth |
ClamAV |
Virus signatures |
5Gi |
Periodic updates |
Webdav |
Calendars, contacts |
5-20Gi |
50-200MB per user |
Set Global Storage Class#
Configure a default storage class for all components:
import { App } from 'cdk8s';
import { MailuChart } from 'cdk8s-mailu';
const app = new App();
new MailuChart(app, 'mailu', {
namespace: 'mailu',
domain: 'example.com',
hostnames: ['mail.example.com'],
subnet: '10.42.0.0/16',
// ... other config ...
storage: {
storageClass: 'longhorn', // Applied to all components
},
});
app.synth();
Common storage classes:
longhorn- Longhorn distributed storage (recommended for production)local-path- K3s default local storage (testing only)standard- Cloud provider defaultgp2,gp3- AWS EBSpd-standard,pd-ssd- GCP Persistent Disk
Customize Component Storage Sizes#
Small Deployment (< 50 users)#
Minimal storage footprint for personal or small team use:
storage: {
storageClass: 'longhorn',
admin: { size: '5Gi' }, // Default
postfix: { size: '5Gi' }, // Default
dovecot: { size: '50Gi' }, // ~1GB per user
rspamd: { size: '5Gi' }, // Default
},
Medium Deployment (50-500 users)#
Scale mailbox storage for more users:
storage: {
storageClass: 'longhorn',
admin: { size: '5Gi' },
postfix: { size: '10Gi' }, // Larger queue for volume
dovecot: { size: '200Gi' }, // ~4GB per user average
rspamd: { size: '10Gi' }, // More spam learning data
},
Large Deployment (500+ users)#
Production-scale storage with capacity planning:
storage: {
storageClass: 'longhorn',
admin: { size: '10Gi' },
postfix: { size: '20Gi' },
dovecot: { size: '1000Gi' }, // Plan for 2GB per user
rspamd: { size: '20Gi' },
},
Override Storage Class Per Component#
Use different storage classes for different performance tiers:
storage: {
// Default storage class (standard tier)
storageClass: 'longhorn',
// High-performance storage for mailboxes (SSD-backed)
dovecot: {
size: '200Gi',
storageClass: 'longhorn-fast', // Override with faster class
},
// Standard storage for queues and caches
postfix: { size: '10Gi' }, // Uses default 'longhorn'
rspamd: { size: '10Gi' }, // Uses default 'longhorn'
},
Use cases for per-component storage classes:
Fast SSDs for Dovecot mailboxes (high IOPS)
Standard disks for Postfix queue (temporary data)
Cheaper storage for backups
Enable Optional Component Storage#
When enabling optional components, configure their storage:
components: {
clamav: true,
webdav: true,
},
storage: {
storageClass: 'longhorn',
// Required for enabled optional components
clamav: { size: '10Gi' }, // Virus signature database
webdav: { size: '20Gi' }, // Calendars and contacts
},
Expand Existing PVCs#
Important: PVC sizes can be increased but never decreased. Shrinking requires deleting and recreating the PVC (data loss).
Step 1: Update configuration#
Increase the size in your CDK8S configuration:
storage: {
storageClass: 'longhorn',
dovecot: { size: '500Gi' }, // Increased from 200Gi
},
Step 2: Regenerate and apply#
# Regenerate manifests with new size
npm run synth
# Apply changes
kubectl apply -f dist/mailu.k8s.yaml
Step 3: Verify expansion#
# Check PVC status
kubectl get pvc -n mailu
# Verify new size (should show RESIZING or new size)
kubectl describe pvc -n mailu mailu-dovecot-pvc
Note: The storage class must support volume expansion (allowVolumeExpansion: true). Check with:
kubectl get storageclass <storage-class-name> -o yaml | grep allowVolumeExpansion
Storage Performance Optimization#
Longhorn Replica Configuration#
For Longhorn storage, consider replica settings based on data criticality:
High availability (mailboxes):
3 replicas across nodes
Use
longhornstorage class with 2-3 replicas
Standard reliability (queues, caches):
2 replicas
Use default
longhornstorage class
Single replica (temporary data):
1 replica
Lower storage overhead
Not recommended for mailboxes
Note: Replica configuration is set at the storage class level, not per-PVC.
Monitor Storage Usage#
Track storage consumption to plan capacity:
# Check PVC usage
kubectl get pvc -n mailu
# Detailed usage per pod
kubectl exec -n mailu <dovecot-pod-name> -- df -h /mail
# Check available capacity on nodes (Longhorn)
kubectl get nodes.longhorn.io -n longhorn-system
Set up monitoring alerts at 70% and 85% capacity thresholds.
Troubleshooting#
PVC stuck in Pending#
Symptom: PVC shows Pending status, pod cannot start.
Solution: Check storage class exists and has available capacity.
# Check PVC status
kubectl describe pvc -n mailu <pvc-name>
# Check storage class
kubectl get storageclass
# Check node storage capacity (Longhorn)
kubectl get nodes.longhorn.io -n longhorn-system
PVC expansion not working#
Symptom: PVC size unchanged after applying new configuration.
Solution: Verify storage class supports expansion:
# Check storage class expansion support
kubectl get storageclass <storage-class-name> -o jsonpath='{.allowVolumeExpansion}'
# If false, expansion is not supported
# Alternative: Create new PVC with larger size and migrate data
Out of storage space#
Symptom: Pods show disk pressure, writes failing.
Immediate fix: Increase PVC size (see expansion section above).
Long-term:
Set up storage monitoring and alerting
Review mailbox quotas in Mailu admin UI
Enable email compression in Dovecot
Implement email retention policies
Estimate Storage Requirements#
Calculating Dovecot mailbox storage#
Formula: Total Storage = (Active Users × Average MB per User × Growth Factor) + Buffer
Example (100 users):
Active users: 100
Average per user: 3GB (typical)
Growth factor: 1.5 (50% growth over 2 years)
Buffer: 20% (for spikes)
Calculation: (100 × 3GB × 1.5) + 20% = 450GB × 1.2 = 540GB
Recommended: 600Gi PVC
Monitoring actual usage#
Deploy with initial estimates, then adjust based on actual usage:
# Check current mailbox usage
kubectl exec -n mailu <dovecot-pod> -- du -sh /mail
# Per-user breakdown (if accessible)
kubectl exec -n mailu <dovecot-pod> -- du -sh /mail/*
See Also#
Component Specifications - Default storage sizes
Scale Resources - Adjust CPU/memory
Enable Optional Components - Add components requiring storage