Step-by-step guide for deploying Mailroom to a Kubernetes cluster. Assumes familiarity with kubectl and container registries.
- Docker installed locally
kubectlconfigured with access to your cluster- A Fastmail account with:
- JMAP API token (Settings > Privacy & Security > API tokens)
- App password with CardDAV access (Settings > Privacy & Security > Integrations > New app password)
docker build -t ghcr.io/hellothisisflo/mailroom:latest .docker push ghcr.io/hellothisisflo/mailroom:latestIf using a different registry, update the image reference in
k8s/deployment.yamlto match.
kubectl apply -f k8s/namespace.yamlCopy the example and fill in your real Fastmail credentials:
cp k8s/secret.yaml.example k8s/secret.yamlEdit k8s/secret.yaml and replace the placeholder values with your actual credentials. The file uses stringData, so you enter plaintext values directly -- no base64 encoding needed.
kubectl apply -f k8s/secret.yaml
k8s/secret.yamlis in.gitignore-- never commit real credentials.
kubectl apply -f k8s/configmap.yamlThe ConfigMap contains all non-secret configuration (poll interval, label names, contact group names). See config.md for the full configuration reference.
kubectl apply -f k8s/deployment.yamlCheck the pod is running:
kubectl -n mailroom get podsWatch the logs:
kubectl -n mailroom logs -f deploy/mailroomYou should see service_started with the configured poll interval.
Mailroom exposes a /healthz endpoint on port 8080 inside the container. The Kubernetes deployment is already configured with liveness and readiness probes pointing to this endpoint.
To check health manually:
kubectl -n mailroom port-forward deploy/mailroom 8080:8080
curl http://localhost:8080/healthzReturns {"status": "ok", "last_poll_age_seconds": ...} with HTTP 200 when healthy, or HTTP 503 when the last successful poll is too old.
Build and push a new image, then restart the deployment:
docker build -t ghcr.io/hellothisisflo/mailroom:latest .
docker push ghcr.io/hellothisisflo/mailroom:latest
kubectl -n mailroom rollout restart deploy/mailroomWatch the rollout:
kubectl -n mailroom rollout status deploy/mailroomMissing credentials: Mailroom requires MAILROOM_JMAP_TOKEN, MAILROOM_CARDDAV_USERNAME, and MAILROOM_CARDDAV_PASSWORD to start. Check that the secret was applied:
kubectl -n mailroom get secret mailroom-secretsWrong credentials: Check logs for authentication errors:
kubectl -n mailroom logs deploy/mailroom --previousMissing Fastmail labels: Mailroom validates that all triage labels (@ToImbox, @ToFeed, @ToPaperTrail, @ToJail, @ToPerson) and system labels (@MailroomError, @MailroomWarning) exist as Fastmail mailboxes/labels at startup. Create them in Fastmail before deploying.
Missing contact groups: The four contact groups (Imbox, Feed, Paper Trail, Jail) must exist in Fastmail Contacts. Create them manually in Fastmail before deploying.
Poll interval: By default, Mailroom polls every 300 seconds (5 minutes). Check the ConfigMap if you want to adjust this.
JMAP errors: Verify your JMAP token is valid and has the required scopes.
CardDAV errors: Verify the app password has CardDAV access. The username should be your full Fastmail email address.