Files
mesh-controller/examples/modules/umami.json
T
jschoubben 8c4a478b09 Four more of the catalogue: registry, redis, umami, grafana
Converted from the arrangement being replaced, in its shapes rather
than theirs.

The registry is the manifest the lab already proved, promoted: names
its image by digest and is never built (04-ISSUES/029), provides the
artifact store, claims it once per machine.

Redis is the third provision after a database and a bucket, and the
first whose tenancy is a pattern in a shared keyspace rather than a
namespace something else enforces. Its provisioner mirrors the postgres
one's contract line for line — the manifest, the sealed per-consumer
files, the mark, the withdrawal of orphans — and speaks RESP directly:
five commands are needed, and a client library large enough to hide
them would be most of the program's size. A prefix Redis would read as
a pattern is refused, because the grant must mean what the manifest
said; grants are persisted with ACL SAVE, or said loudly, because a
cache that forgets its tenants on restart reports success until then.

Umami asks the mesh for its database and a generated app secret, and
carries no state of its own — the arrangement being replaced ran a
bundled second postgres beside it. Grafana keeps its dashboards in a
declared directory with the image's own owner. Both listen on 3000, as
does the forge — which is the mesh's port assignment earning its keep.

Traefik is deliberately not converted: the mesh's route provider is
mesh-route-proxy, which speaks route grants natively, and a traefik
that consumed them would be an adapter nobody has written pretending
to be a conversion.

All images pinned by real digests, resolved on this workstation today.
2026-09-01 22:44:53 +02:00

60 lines
1.3 KiB
JSON

{
"module": "umami",
"version": "1",
"requires": [
"postgres-database"
],
"contributes": {
"postgres-database": {
"name": "umami"
}
},
"binds": {
"postgres-database": "/var/lib/umami/database.json"
},
"secrets": {
"postgres-database": "/var/lib/umami/database.secret"
},
"own-secrets": {
"app-secret": "/var/lib/umami/app.secret"
},
"capabilities": [
"container-runtime"
],
"listens": [
{
"port": 3000,
"protocol": "tcp",
"from": "mesh",
"why": "the analytics pages and the collection endpoint"
}
],
"resources": [
{
"id": "state",
"type": "directory",
"path": "/var/lib/umami",
"mode": "0700"
},
{
"id": "server-env",
"type": "file",
"path": "/var/lib/umami/server.env",
"mode": "0600",
"content": "DATABASE_URL=postgresql://${bound:postgres-database:as}:${secret:postgres-database}@${bound:postgres-database:at}:${bound:postgres-database:port}/umami\nAPP_SECRET=${secret:app-secret}\n"
},
{
"id": "server",
"type": "container",
"name": "umami",
"image": "ghcr.io/umami-software/umami@sha256:fa32d116cf20cad52cbc3fad9a63b46e7fa02299d8f967168eb453d49c476b4a",
"env-file": [
"/var/lib/umami/server.env"
],
"ports": [
"3000"
]
}
]
}