The predecessor serves the registry under a public name, behind htpasswd basic auth, with a twenty-gigabyte body limit for layer pushes. The mesh's registry has no name, no lock and no limit — by design inside the mesh, where the private network is the boundary and every node pulls without an account (hq ADR 0082). Taking the name over must not change that. A route on `distribution` itself would: contributing a route is requiring one, and the store is raised at genesis on a node with no proxy. So the public door is `distribution-gate`, a second registry process on the same volume, behind the registry's own htpasswd (the predecessor's realm, the predecessor's file, carried in with `secret accept`), with the route and its limit. It requires the store's storage as a node-scoped provision, so it can only land beside the store. The store's own door is untouched — no auth, no htpasswd — which is what keeps the builder's pushes and every node's pulls working. Both processes read the predecessor's configuration where it changed behaviour: delete enabled, which tag retention depends on; no per-process descriptor cache, which two processes over one store cannot share; the CORS headers for the retired interface dropped. route-adapter writes the limit as the predecessor's own buffering middleware, named after the router, only when asked for — and skips a route whose limit it cannot read rather than carrying what the module said not to. hq ADR 0082/0104, the registry hand-over.
77 lines
2.6 KiB
JSON
77 lines
2.6 KiB
JSON
{
|
|
"module": "distribution",
|
|
"version": "1",
|
|
"provides": [
|
|
{
|
|
"name": "artifact-store",
|
|
"scope": "mesh"
|
|
},
|
|
{
|
|
"name": "artifact-storage",
|
|
"scope": "node"
|
|
}
|
|
],
|
|
"claims": [
|
|
{
|
|
"name": "the-artifact-store",
|
|
"scope": "node"
|
|
}
|
|
],
|
|
"capabilities": [
|
|
"container-runtime"
|
|
],
|
|
"emits": [
|
|
"module.registry.image.pushed"
|
|
],
|
|
"own-secrets": {
|
|
"broker": "/var/lib/mesh/registry/broker"
|
|
},
|
|
"serves": {
|
|
"artifact-store": {
|
|
"port": 5000
|
|
},
|
|
"artifact-storage": {
|
|
"volume": "mesh-registry-data"
|
|
}
|
|
},
|
|
"listens": [
|
|
{
|
|
"port": 5000,
|
|
"protocol": "tcp",
|
|
"from": "mesh",
|
|
"why": "every machine pulls images and artifacts from here"
|
|
}
|
|
],
|
|
"resources": [
|
|
{
|
|
"id": "state",
|
|
"type": "directory",
|
|
"path": "/var/lib/mesh/registry",
|
|
"mode": "0700"
|
|
},
|
|
{
|
|
"id": "config",
|
|
"type": "file",
|
|
"path": "/var/lib/mesh/registry/config.yml",
|
|
"mode": "0644",
|
|
"content": "# The registry's configuration, written by the mesh from the module's manifest.\n#\n# Carried over from the predecessor's registry.yml where it changed behaviour (novox/hq ADR 0082,\n# the registry hand-over):\n# - storage.delete.enabled: the image's default refuses DELETE on a manifest; the predecessor\n# enabled it, and tag retention and garbage collection depend on it.\n# - no storage.cache: the image's default keeps an in-memory blob-descriptor cache, which is\n# right for one process and wrong for two on one store — the mesh door and the public door\n# are two registry processes sharing this filesystem, and a descriptor cached by one and\n# deleted through the other would say a blob exists that does not.\n# Dropped: the CORS headers, which served the browser interface that is being retired.\nversion: 0.1\nlog:\n fields:\n service: registry\nstorage:\n delete:\n enabled: true\n filesystem:\n rootdirectory: /var/lib/registry\nhttp:\n addr: :5000\n headers:\n X-Content-Type-Options: [nosniff]\nhealth:\n storagedriver:\n enabled: true\n interval: 10s\n threshold: 3\n"
|
|
},
|
|
{
|
|
"id": "store",
|
|
"type": "container",
|
|
"name": "mesh-registry",
|
|
"image": "registry@sha256:a3d8aaa63ed8681a604f1dea0aa03f100d5895b6a58ace528858a7b332415373",
|
|
"ports": [
|
|
"5000:5000"
|
|
],
|
|
"volumes": [
|
|
"mesh-registry-data:/var/lib/registry",
|
|
"/var/lib/mesh/registry/config.yml:/etc/docker/registry/config.yml:ro"
|
|
],
|
|
"restart-on": [
|
|
"config"
|
|
]
|
|
}
|
|
]
|
|
}
|