Files
mesh-controller/examples/modules/mailu.json
T
jschoubben a5d85266d0 A container does not take restart-on, and nine of them did
This is what stopped the forge. The host refused the whole declaration:

  resource "postgres.server": a container does not use "restart-on",
  and it is set. Refused rather than ignored

`restart-on` belongs to a service. I put it on containers this morning
so one would pick up a rotated credential — nine times across seven
modules — and nothing between the manifest and the machine said a word.
The control plane composed it happily; the parser accepted it; the
manifest tests passed. The only thing that knew was the host, five steps
downstream, and hearing from it cost a seventeen-minute run.

The host was right twice over. It refused, and it refused *everything*,
because applying the parts it understood would leave a machine that
looks configured and is not. One misplaced key therefore stops a module
dead, which is the correct severity and an argument for catching it
where it is written.

So the shapes and their keys are now written down here and checked. They
are duplicated from another repository deliberately — this is its wire
format, like the shape of a grant file — and a contract with two copies
and no check is a contract until somebody edits one.

What this does not fix is why I reached for it: a container cannot
follow a file. Filed separately.
2026-09-01 17:19:04 +02:00

271 lines
6.7 KiB
JSON

{
"module": "mailu",
"version": "1",
"capabilities": [
"container-runtime"
],
"listens": [
{
"port": 25,
"protocol": "tcp",
"from": "anywhere",
"why": "mail from other mail servers"
},
{
"port": 465,
"protocol": "tcp",
"from": "anywhere",
"why": "submission over TLS"
},
{
"port": 587,
"protocol": "tcp",
"from": "anywhere",
"why": "submission"
},
{
"port": 993,
"protocol": "tcp",
"from": "anywhere",
"why": "IMAP over TLS"
},
{
"port": 7080,
"protocol": "tcp",
"from": "mesh",
"why": "the web interface, behind a proxy"
}
],
"own-secrets": {
"secret-key": "/var/lib/mailu/secret-key.secret",
"database": "/var/lib/mailu/database.secret",
"admin": "/var/lib/mailu/admin.secret"
},
"resources": [
{
"id": "state",
"type": "directory",
"path": "/var/lib/mailu",
"mode": "0700"
},
{
"id": "secret-env",
"type": "file",
"path": "/var/lib/mailu/secret.env",
"mode": "0600",
"content": "SECRET_KEY=${secret:secret-key}\n"
},
{
"id": "database-env",
"type": "file",
"path": "/var/lib/mailu/database.env",
"mode": "0600",
"content": "POSTGRES_USER=mailu\nPOSTGRES_DB=mailu\nPOSTGRES_PASSWORD=${secret:database}\nDB_USER=mailu\nDB_NAME=mailu\nDB_PW=${secret:database}\n"
},
{
"id": "admin-env",
"type": "file",
"path": "/var/lib/mailu/admin.env",
"mode": "0600",
"content": "INITIAL_ADMIN_PW=${secret:admin}\n"
},
{
"id": "data-certs",
"type": "directory",
"path": "/services/mailu/data/certs",
"mode": "0700"
},
{
"id": "data-data",
"type": "directory",
"path": "/services/mailu/data/data",
"mode": "0700"
},
{
"id": "data-dkim",
"type": "directory",
"path": "/services/mailu/data/dkim",
"mode": "0700"
},
{
"id": "data-filter",
"type": "directory",
"path": "/services/mailu/data/filter",
"mode": "0700"
},
{
"id": "data-mail",
"type": "directory",
"path": "/services/mailu/data/mail",
"mode": "0700"
},
{
"id": "data-mailqueue",
"type": "directory",
"path": "/services/mailu/data/mailqueue",
"mode": "0700"
},
{
"id": "data-redis",
"type": "directory",
"path": "/services/mailu/data/redis",
"mode": "0700"
},
{
"id": "data-webmail",
"type": "directory",
"path": "/services/mailu/data/webmail",
"mode": "0700"
},
{
"id": "data-dovecot",
"type": "directory",
"path": "/services/mailu/data/overrides/dovecot",
"mode": "0700"
},
{
"id": "data-nginx",
"type": "directory",
"path": "/services/mailu/data/overrides/nginx",
"mode": "0700"
},
{
"id": "data-pgdata",
"type": "directory",
"path": "/services/mailu/data/data/psql_admindb/pgdata",
"mode": "0700"
},
{
"id": "net",
"type": "network",
"name": "mailu"
},
{
"id": "resolver",
"type": "container",
"name": "mailu-resolver",
"image": "ghcr.io/mailu/unbound@sha256:142aaad82ad1b0d5b59a5f1303778dba61a3e0a540f5d969c48862bcc99f6f5d",
"network": "mailu",
"env-file": [
"/var/lib/mailu/secret.env"
]
},
{
"id": "redis",
"type": "container",
"name": "mailu-redis",
"image": "redis@sha256:1db42ccef14898aa29bae778452d567534b59c107129cbc1163fb552de184d3c",
"network": "mailu",
"volumes": [
"/services/mailu/data/redis:/data"
]
},
{
"id": "admindb",
"type": "container",
"name": "mailu-admindb",
"image": "postgres@sha256:7456ef82e5f5bc43d997f4781bbd7c0d6389bff397564649a356e206ba473aee",
"network": "mailu",
"env": {
"PGDATA": "/var/lib/postgresql/data/pgdata"
},
"env-file": [
"/var/lib/mailu/database.env"
],
"volumes": [
"/services/mailu/data/data/psql_admindb/pgdata:/var/lib/postgresql/data/pgdata"
]
},
{
"id": "admin",
"type": "container",
"name": "mailu-admin",
"image": "ghcr.io/mailu/admin@sha256:dcac20e9cbdad560faef9653b1b5ac0d9266f4098dc00f0e7f0d35f4e70ed8f1",
"network": "mailu",
"env-file": [
"/var/lib/mailu/secret.env",
"/var/lib/mailu/database.env",
"/var/lib/mailu/admin.env"
],
"volumes": [
"/services/mailu/data/data:/data",
"/services/mailu/data/dkim:/dkim"
]
},
{
"id": "imap",
"type": "container",
"name": "mailu-imap",
"image": "ghcr.io/mailu/dovecot@sha256:46d18ba51032be8ebd6841aa49c1ef8762c729038c5fd86a081b5b884d478af9",
"network": "mailu",
"env-file": [
"/var/lib/mailu/secret.env"
],
"volumes": [
"/services/mailu/data/mail:/mail",
"/services/mailu/data/overrides/dovecot:/overrides:ro"
]
},
{
"id": "smtp",
"type": "container",
"name": "mailu-smtp",
"image": "ghcr.io/mailu/postfix@sha256:bbf882880f68849511710b35237a933f3fe80c4b28bf48ff20205dbd1f1433d7",
"network": "mailu",
"env-file": [
"/var/lib/mailu/secret.env"
],
"volumes": [
"/services/mailu/data/mailqueue:/queue"
]
},
{
"id": "antispam",
"type": "container",
"name": "mailu-antispam",
"image": "ghcr.io/mailu/rspamd@sha256:e87ab93dd252cc69499caa5317dd10d445fd4291a7ecf6bca09793c7d475a0c8",
"network": "mailu",
"env-file": [
"/var/lib/mailu/secret.env"
],
"volumes": [
"/services/mailu/data/filter:/var/lib/rspamd"
]
},
{
"id": "webmail",
"type": "container",
"name": "mailu-webmail",
"image": "ghcr.io/mailu/webmail@sha256:076b720fc766e58a97321cdb700e887c2008d6d323685fe59f323088333059dc",
"network": "mailu",
"env-file": [
"/var/lib/mailu/secret.env"
],
"volumes": [
"/services/mailu/data/webmail:/data"
]
},
{
"id": "front",
"type": "container",
"name": "mailu-front",
"image": "ghcr.io/mailu/nginx@sha256:09f28ab6d36367fcacc7994f7021f132ac845bdc05f04bf80906102d11aaa057",
"network": "mailu",
"env-file": [
"/var/lib/mailu/secret.env"
],
"ports": [
"25:25",
"465:465",
"587:587",
"993:993",
"7080:80"
],
"volumes": [
"/services/mailu/data/certs:/certs",
"/services/mailu/data/overrides/nginx:/overrides:ro"
]
}
]
}