umami declared its port reachable from anywhere, reasoning that the collection endpoint tracked browsers POST to must be public. That is true of the name and not of the port: both its surfaces are served through the proxy by name, so the port is how the proxy reaches it and nothing else (ADR 0045). Measured, which is how this was found: with the port open to the internet, the dashboard's login page was served over plain HTTP directly on the machine's port, bypassing every rule the proxy applies by path. The route stays exactly as it was, so the collection endpoint keeps working.
153 lines
4.0 KiB
JSON
153 lines
4.0 KiB
JSON
{
|
|
"module": "umami",
|
|
"version": "1",
|
|
"capabilities": [
|
|
"container-runtime"
|
|
],
|
|
"requires": [
|
|
"postgres-database",
|
|
"route",
|
|
"secret"
|
|
],
|
|
"contributes": {
|
|
"postgres-database": {
|
|
"name": "umami"
|
|
},
|
|
"route": {
|
|
"label": "umami",
|
|
"port": 3000
|
|
}
|
|
},
|
|
"binds": {
|
|
"postgres-database": "/var/lib/umami/database.json",
|
|
"route": "/var/lib/umami/route.json"
|
|
},
|
|
"secrets": {
|
|
"postgres-database": "/var/lib/umami/database.secret",
|
|
"secret": {
|
|
"app-secret": "/var/lib/umami/app.secret",
|
|
"admin": "/var/lib/umami/admin.secret"
|
|
}
|
|
},
|
|
"provides": [
|
|
{
|
|
"name": "analytics",
|
|
"scope": "mesh"
|
|
}
|
|
],
|
|
"serves": {
|
|
"analytics": {}
|
|
},
|
|
"receives": {
|
|
"analytics": "/var/lib/umami/grants/mesh.json"
|
|
},
|
|
"grants": {
|
|
"analytics": "/var/lib/umami/grants"
|
|
},
|
|
"own-secrets": {
|
|
"broker": "/var/lib/mesh/umami/broker"
|
|
},
|
|
"listens": [
|
|
{
|
|
"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"
|
|
}
|
|
],
|
|
"resources": [
|
|
{
|
|
"id": "mesh-state",
|
|
"type": "directory",
|
|
"path": "/var/lib/mesh/umami",
|
|
"mode": "0700"
|
|
},
|
|
{
|
|
"id": "state",
|
|
"type": "directory",
|
|
"path": "/var/lib/umami",
|
|
"mode": "0700"
|
|
},
|
|
{
|
|
"id": "grants",
|
|
"type": "directory",
|
|
"path": "/var/lib/umami/grants",
|
|
"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}/${bound:postgres-database:as}\nDATABASE_TYPE=postgresql\nAPP_SECRET=${secret:app-secret}\n"
|
|
},
|
|
{
|
|
"id": "provisioner-env",
|
|
"type": "file",
|
|
"path": "/var/lib/umami/provisioner.env",
|
|
"mode": "0600",
|
|
"content": "MESH_PROVISION_UMAMI_URL=http://umami:3000\nGRANTS=/var/lib/umami/grants\n"
|
|
},
|
|
{
|
|
"id": "net",
|
|
"type": "network",
|
|
"name": "umami"
|
|
},
|
|
{
|
|
"id": "server",
|
|
"type": "container",
|
|
"name": "umami",
|
|
"image": "ghcr.io/umami-software/umami@sha256:85909afc45bdcda1917394594a087421fdbb05610fded0fa9f6fb861abb2f367",
|
|
"network": "umami",
|
|
"env-file": [
|
|
"/var/lib/umami/server.env"
|
|
],
|
|
"ports": [
|
|
"3000"
|
|
],
|
|
"secrets-in-environment": "a Next.js/Prisma application: DATABASE_URL and APP_SECRET are read from the environment only; not convertible"
|
|
},
|
|
{
|
|
"id": "runtime",
|
|
"type": "container",
|
|
"name": "mesh-umami",
|
|
"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"
|
|
],
|
|
"env": {
|
|
"MESH_BROKER_FILE": "/run/secrets/broker",
|
|
"MESH_RECEIVES": "/var/lib/umami/grants/mesh.json",
|
|
"MESH_UMAMI_ADMIN_PASSWORD_FILE": "/run/secrets/admin"
|
|
},
|
|
"env-file": [
|
|
"/var/lib/umami/provisioner.env"
|
|
],
|
|
"artifact": "runtime"
|
|
}
|
|
],
|
|
"build": {
|
|
"on": [
|
|
{
|
|
"arg": "BUILD_BASE",
|
|
"module": "mesh-tools",
|
|
"artifact": "build"
|
|
},
|
|
{
|
|
"arg": "RUNTIME_BASE",
|
|
"module": "mesh-tools",
|
|
"artifact": "runtime"
|
|
}
|
|
],
|
|
"artifacts": [
|
|
{
|
|
"name": "runtime",
|
|
"kind": "image",
|
|
"from": "Dockerfile"
|
|
}
|
|
]
|
|
}
|
|
}
|