Files
mesh-controller/examples/modules/gitea.json
T
jschoubben ee3cc1b6f4 Pin the example modules to images that exist
novox/hq 04-ISSUES/025. Every image reference in every example module
was sixty-four zeros — eighteen of them across five modules. Each
parsed, resolved, and composed into a declaration a host accepts, and
none could ever have started: the machine reaches `docker pull` and
stops. That is why those modules were written and not running, and no
check saw it because every check passed.

The host validates the shape of a reference and nothing more, which is
correct: verifying a digest exists means reaching a registry, and that
is the one thing a host must never have to do. So the last place that
could catch this is the wrong place to try.

The guard therefore sits where a declaration is composed, not where a
manifest is parsed. A file in a repository is allowed to await a pin —
the design already says the manifest in a repository names artifacts
while the manifest the mesh holds names digests, and the bundle works
exactly that way. What must never happen is a placeholder reaching a
machine, and composing is the last moment before one does.

Twelve third-party images resolved to real digests without pulling
anything, which is also the mechanism the open issue needs. Two
discoveries came free: mailu publishes to ghcr rather than Docker Hub,
so seven references named repositories that do not exist at all; and it
renamed roundcube to webmail, so that one would have failed even with
the right registry.

What stays a placeholder is the mesh's own provisioner images, which
genuinely have no digest until built and pushed — the bundle's problem,
legitimately unresolved here. The stand-in consumer now stands in with
a real image rather than an invented one.
2026-09-01 15:13:33 +02:00

37 lines
1.6 KiB
JSON

{
"module": "gitea",
"version": "1",
"requires": ["postgres-database"],
"contributes": {
"postgres-database": {"name": "gitea"}
},
"binds": {"postgres-database": "/var/lib/gitea/database.json"},
"secrets": {"postgres-database": "/var/lib/gitea/database.secret"},
"capabilities": ["container-runtime"],
"listens": [
{"port": 3000, "protocol": "tcp", "from": "mesh", "why": "the forge, over http"},
{"port": 2222, "protocol": "tcp", "from": "mesh",
"why": "git over ssh. Not 22: the machine's own daemon holds that, and a module does not take it"}
],
"own-secrets": {"internal-token": "/var/lib/gitea/internal-token.secret"},
"resources": [
{"id": "state", "type": "directory", "path": "/var/lib/gitea", "mode": "0700"},
{"id": "server-env", "type": "file", "path": "/var/lib/gitea/server.env", "mode": "0600",
"content": "GITEA__security__INTERNAL_TOKEN=${secret:internal-token}\nGITEA__database__DB_TYPE=postgres\nGITEA__database__HOST=${bound:postgres-database:at}:${bound:postgres-database:port}\nGITEA__database__NAME=gitea\nGITEA__database__USER=${bound:postgres-database:as}\nGITEA__database__PASSWD=${secret:postgres-database}\n"},
{"id": "server", "type": "container", "name": "gitea",
"image": "gitea/gitea@sha256:dfc61e347c8b582df918f4556401bf2cecdfbdb56c5282ae9488dd76fca3e41c",
"env": {"DB_TYPE": "postgres", "USER_UID": "1000", "USER_GID": "1000"},
"env-file": ["/var/lib/gitea/server.env"],
"ports": ["3000:3000", "2222:22"],
"volumes": ["/services/gitea/gitea:/data"],
"restart-on": ["server-env"]}
]
}