A definition names no host path for its own data

Twenty-eight modules' data directories are placed: the root as place ".", a sub-directory named by
its id, and every host-side reference — binds, secrets, own secrets, grants, receives, file paths,
mounts, env-files — as ${dir:<id>}. Resolved on the default root every path is the one the manifest
named before, which the controller's TestPlacedDirectoriesKeepTheirPaths proves over both checkouts;
so no data moves and no machine sees a change. Five directories whose id is not their last segment
keep their path as a placement (novox/hq issue 119, ADR 0112, design 27).
This commit is contained in:
2026-09-30 21:10:18 +02:00
parent 12bbcafacf
commit eed5e8958a
28 changed files with 210 additions and 223 deletions
+18 -19
View File
@@ -19,14 +19,14 @@
}
},
"binds": {
"postgres-database": "/var/lib/umami/database.json",
"route": "/var/lib/umami/route.json"
"postgres-database": "${dir:state}/database.json",
"route": "${dir:state}/route.json"
},
"secrets": {
"postgres-database": "/var/lib/umami/database.secret",
"postgres-database": "${dir:state}/database.secret",
"secret": {
"app-secret": "/var/lib/umami/app.secret",
"admin": "/var/lib/umami/admin.secret"
"app-secret": "${dir:state}/app.secret",
"admin": "${dir:state}/admin.secret"
}
},
"provides": [
@@ -39,10 +39,10 @@
"analytics": {}
},
"receives": {
"analytics": "/var/lib/umami/grants/mesh.json"
"analytics": "${dir:grants}/mesh.json"
},
"grants": {
"analytics": "/var/lib/umami/grants"
"analytics": "${dir:grants}"
},
"own-secrets": {
"broker": "/var/lib/mesh/umami/broker"
@@ -53,7 +53,7 @@
"port": 3000,
"protocol": "tcp",
"from": "mesh",
"why": "one port serves two surfaces \u2014 the dashboard and the collection endpoint that the browsers of every tracked site POST to. Both are reached through the proxy, by name, so the port is how the proxy reaches this module and nothing else (novox/hq ADR 0045). It said \"anywhere\" and gave the reason that the collection endpoint must be public, which is true of the name and not of the port: opened, the machine-side port served the dashboard over plain HTTP to the internet, bypassing every rule the proxy applies by path"
"why": "one port serves two surfaces — the dashboard and the collection endpoint that the browsers of every tracked site POST to. Both are reached through the proxy, by name, so the port is how the proxy reaches this module and nothing else (novox/hq ADR 0045). It said \"anywhere\" and gave the reason that the collection endpoint must be public, which is true of the name and not of the port: opened, the machine-side port served the dashboard over plain HTTP to the internet, bypassing every rule the proxy applies by path"
}
],
"resources": [
@@ -66,28 +66,27 @@
{
"id": "state",
"type": "directory",
"path": "/var/lib/umami",
"mode": "0700"
"mode": "0700",
"place": "."
},
{
"id": "grants",
"type": "directory",
"path": "/var/lib/umami/grants",
"mode": "0700"
},
{
"id": "server-env",
"type": "file",
"path": "/var/lib/umami/server.env",
"path": "${dir:state}/server.env",
"mode": "0600",
"content": "DATABASE_URL=postgresql://${bound:postgres-database:as}:${secret:postgres-database}@${bound:postgres-database:at}:${bound:postgres-database:port}/${bound:postgres-database:as}\nDATABASE_TYPE=postgresql\nAPP_SECRET=${secret:app-secret}\n"
},
{
"id": "provisioner-env",
"type": "file",
"path": "/var/lib/umami/provisioner.env",
"path": "${dir:state}/provisioner.env",
"mode": "0600",
"content": "MESH_PROVISION_UMAMI_URL=http://umami:3000\nGRANTS=/var/lib/umami/grants\n"
"content": "MESH_PROVISION_UMAMI_URL=http://umami:3000\nGRANTS=${dir:grants}\n"
},
{
"id": "net",
@@ -101,7 +100,7 @@
"image": "ghcr.io/umami-software/umami@sha256:85909afc45bdcda1917394594a087421fdbb05610fded0fa9f6fb861abb2f367",
"network": "umami",
"env-file": [
"/var/lib/umami/server.env"
"${dir:state}/server.env"
],
"ports": [
"3000"
@@ -115,16 +114,16 @@
"network": "umami",
"volumes": [
"/var/lib/mesh/umami/broker:/run/secrets/broker:ro",
"/var/lib/umami/grants:/var/lib/umami/grants",
"/var/lib/umami/admin.secret:/run/secrets/admin:ro"
"${dir:grants}:${dir:grants}",
"${dir:state}/admin.secret:/run/secrets/admin:ro"
],
"env": {
"MESH_BROKER_FILE": "/run/secrets/broker",
"MESH_RECEIVES": "/var/lib/umami/grants/mesh.json",
"MESH_RECEIVES": "${dir:grants}/mesh.json",
"MESH_UMAMI_ADMIN_PASSWORD_FILE": "/run/secrets/admin"
},
"env-file": [
"/var/lib/umami/provisioner.env"
"${dir:state}/provisioner.env"
],
"artifact": "runtime"
}