Quick Start: Deploy Your First Mailu Instance¶
Learn how to deploy a basic Mailu mail server using cdk8s-mailu in under 30 minutes.
What you’ll build¶
By the end of this tutorial, you’ll have:
A working Mailu deployment on Kubernetes
Basic understanding of the MailuChart construct
Knowledge of essential configuration options
A functional mail server ready for testing
Prerequisites¶
Kubernetes cluster (minikube, kind, or cloud provider)
kubectl configured and working
Node.js 16+ installed
npm or yarn package manager
Basic familiarity with TypeScript
Overview¶
This tutorial will guide you through:
Setting up a new CDK8S project
Installing cdk8s-mailu
Creating a basic MailuChart
Synthesizing Kubernetes manifests
Deploying to your cluster
Testing the deployment
Step 1: Create a new CDK8S project¶
mkdir my-mailu-deployment
cd my-mailu-deployment
cdk8s init typescript-app
Step 2: Install cdk8s-mailu¶
npm install cdk8s-mailu
Step 3: Create your Mailu chart¶
Replace the contents of main.ts with a basic Mailu configuration:
import { App } from 'cdk8s';
import { MailuChart } from 'cdk8s-mailu';
const app = new App();
new MailuChart(app, 'mailu', {
// Basic domain configuration
namespace: 'mailu',
domain: 'example.com',
hostnames: ['mail.example.com'],
subnet: '10.42.0.0/16', // Your Kubernetes pod CIDR
timezone: 'UTC',
// Database configuration (PostgreSQL recommended)
database: {
type: 'postgresql',
postgresql: {
host: 'postgres-rw', // Your PostgreSQL service
port: 5432,
database: 'mailu',
secretName: 'postgres-app', // Secret with DB credentials
secretKeys: {
username: 'username',
password: 'password',
},
},
},
// Redis configuration
redis: {
host: 'redis',
port: 6379,
},
// Secrets (create these in Kubernetes first!)
secrets: {
mailuSecretKey: 'mailu-secrets', // Secret with 'secret-key' field
initialAdminPassword: 'mailu-secrets', // Secret with 'password' field
},
// Optional: Enable/disable components
components: {
webmail: true, // Roundcube webmail (enabled by default)
clamav: false, // Antivirus (disabled, requires ~1GB RAM)
fetchmail: false, // External account fetching
webdav: false, // CalDAV/CardDAV
},
// Optional: Customize storage
storage: {
storageClass: 'longhorn', // Your storage class
dovecot: {
size: '50Gi', // Mailbox storage (adjust based on users)
},
},
});
app.synth();
What this configuration does:
Sets up Mailu for
example.comdomainUses PostgreSQL for database (more reliable than SQLite)
Connects to Redis for caching
Enables webmail (Roundcube)
Disables optional heavy components (ClamAV, etc.)
Allocates 50Gi for mailbox storage
Step 4: Synthesize manifests¶
npm run synth
This generates Kubernetes manifests in the dist/ directory.
Step 5: Deploy to Kubernetes¶
kubectl apply -f dist/
Step 6: Verify deployment¶
Check that all pods are running:
kubectl get pods -n mailu
What’s next?¶
Configuration & Customization:
Scale Resources - Adjust CPU and memory for your workload
Customize Storage - Increase mailbox storage
Enable Optional Components - Add webmail, antivirus, CalDAV
Configure TLS - Set up Traefik ingress with Let’s Encrypt
Operations:
Backup and Restore - Protect your mail data
Upgrade Mailu - Update to newer versions
Understanding:
Architecture Overview - How components work together
Dovecot Submission Service - Webmail email sending
Troubleshooting¶
Pods not starting?
Check secrets exist:
kubectl get secrets -n mailuVerify PostgreSQL is accessible:
kubectl get svc postgres-rwCheck pod logs:
kubectl logs -n mailu -l app.kubernetes.io/part-of=mailu
Storage issues?
Verify storage class exists:
kubectl get storageclassCheck PVC status:
kubectl get pvc -n mailu
Service discovery issues?
Check ConfigMap:
kubectl get configmap -n mailu -o yaml | grep ADDRESS