k8_apps.communication.stalwart #
Stalwart Mail Server K8s Installer
Deploy Stalwart Mail (SMTP/IMAP/POP3/Sieve) + JMAP/CalDAV/CardDAV/UI on a k3s cluster.
Architecture
(Internet) ── HTTPS ──▶ TFGW ── HTTP ──▶ Traefik Ingress ──▶ Service (stalwart-http:80) ─▶ Pod (JMAP/DAV/UI :8080)
Mail clients ── Mycelium IPv6 TCP ──▶ ServiceLB (stalwart-mail: 25/465/587/143/993/110/995/4190 DNAT) ─▶ Pod (Stalwart)
Features
- TFGW generates an HTTPS FQDN (
https://<hostname>.gent01.grid.tf) for web access - Traefik Ingress for all web protocols (JMAP/DAV/UI on :8080 inside the pod)
- k3s ServiceLB (klipper-lb) as a dual-stack LoadBalancer for mail TCP ports
- ConfigMap with embedded
config.tomland PVC for Stalwart data/logs
Usage
import incubaid.herolib.k8_apps.communication.stalwart
// Create installer instance
mut installer := stalwart.get(
name: 'mymail'
create: true
)!
// Optional: customize settings
installer.hostname = 'mymail' // TFGW hostname
installer.admin_user = 'admin' // Admin username
installer.admin_password = 'secure123' // Admin password
installer.storage_size = '50Gi' // PVC storage size
installer.log_level = 'info' // Log level
// Install
installer.install()!
// Destroy when done
// installer.destroy()!
Configuration Options
| Option | Default | Description |
|---|---|---|
name |
stalwart |
Instance name |
hostname |
{name}mail |
TFGW hostname |
namespace |
{name}stalwartns |
Kubernetes namespace |
admin_user |
admin |
Admin username |
admin_password |
changeme123 |
Admin password |
storage_size |
20Gi |
PVC storage size |
http_port |
8080 |
HTTP port for web UI |
log_level |
info |
Log level (info, debug, warn, error) |
Mail Ports
The LoadBalancer service exposes these ports:
| Port | Protocol | Description |
|---|---|---|
| 25 | SMTP | Mail submission |
| 465 | SMTPS | SMTP over TLS |
| 587 | Submission | Mail submission (STARTTLS) |
| 143 | IMAP | IMAP access |
| 993 | IMAPS | IMAP over TLS |
| 110 | POP3 | POP3 access |
| 995 | POP3S | POP3 over TLS |
| 4190 | ManageSieve | Sieve filter management |
Constants #
const version = '0.0.0'
fn delete #
fn delete(args ArgsGet) !
fn exists #
fn exists(args ArgsGet) !bool
does the config exists?
fn get #
fn get(args ArgsGet) !&Stalwart
fn heroscript_loads #
fn heroscript_loads(heroscript string) !Stalwart
///////////NORMALLY NO NEED TO TOUCH
fn installed #
fn installed() !bool
checks if a certain version or above is installed
fn list #
fn list(args ArgsList) ![]&Stalwart
if fromdb set: load from filesystem, and not from mem, will also reset what is in mem
fn new #
fn new(args ArgsGet) !&Stalwart
fn play #
fn play(mut plbook PlayBook) !
fn set #
fn set(o Stalwart) !
register the config for the future
fn switch #
fn switch(name string)
switch instance to be used for stalwart
struct ArgsGet #
@[params]
struct ArgsGet {
pub mut:
name string = stalwart_default
fromdb bool // will load from filesystem
create bool // default will not create if not exist
}
///////FACTORY
struct ArgsList #
@[params]
struct ArgsList {
pub mut:
fromdb bool // will load from filesystem
}
struct InstallArgs #
@[params]
struct InstallArgs {
pub mut:
reset bool
}
struct Stalwart #
@[heap]
struct Stalwart {
pub mut:
name string = 'stalwart'
hostname string
namespace string
// Stalwart configuration
http_port int = 8080
data_path string = '/opt/stalwart'
log_level string = 'info'
admin_user string = 'admin'
admin_password string = 'changeme123' @[secret]
storage_size string = '20Gi'
// Internal paths
stalwart_app_path string = '/tmp/stalwart/stalwart-app.yaml'
tfgw_path string = '/tmp/stalwart/tfgw-stalwart.yaml'
// K8App instance for kubernetes operations
k8app ?core.K8App @[skip]
}
fn (Stalwart) destroy #
fn (mut self Stalwart) destroy() !
fn (Stalwart) install #
fn (mut self Stalwart) install(args InstallArgs) !
fn (Stalwart) reload #
fn (mut self Stalwart) reload() !
load from disk and make sure is properly intialized