The split the controller now makes, from this side. The module's own configuration — ports, TLS, JetStream — is a declared file resource, because those are properties of this container and change when its image does. `bus-users` names where the mesh writes every account and permission, in the same directory, and the module's configuration includes it. **Both files in one directory because they have to be.** An absolute include path is resolved relative to the including file's directory: nats-server given `include /etc/nats/accounts.conf` from /etc/nats-server/nats.conf looks for /etc/nats-server/etc/nats/accounts.conf and refuses to start. Verified against the server, and recorded in the configuration itself where somebody moving a file will read it. **`verify: true` is gone, and it was refusing every connection in the mesh.** It makes the server demand a client certificate; a host pins this server's exact certificate and authenticates with the password the mesh minted, and presents none. Found by building this image and connecting to it as a host would. The entrypoint now waits for both files and watches the mesh's half: the module's own does not change without a new declaration, and that recreates the container anyway. Verified end to end against this image — the mesh's user list rewritten, the module noticing and reloading the server itself with no signal from outside, and the connection the mesh already had still working afterwards.
85 lines
3.6 KiB
JSON
85 lines
3.6 KiB
JSON
{
|
|
"module": "nats",
|
|
"version": "1",
|
|
"provides": [
|
|
{
|
|
"name": "mesh-bus",
|
|
"scope": "mesh"
|
|
}
|
|
],
|
|
"claims": [
|
|
{
|
|
"name": "mesh-broker",
|
|
"scope": "mesh"
|
|
}
|
|
],
|
|
"bus-users": "/var/lib/nats-module/conf/accounts.conf",
|
|
"capabilities": [
|
|
"container-runtime"
|
|
],
|
|
"emits": [],
|
|
"consumes": [],
|
|
"listens": [
|
|
{
|
|
"port": 4222,
|
|
"protocol": "tcp",
|
|
"from": "mesh",
|
|
"why": "the mesh bus \u2014 every link the mesh has, over TLS, reached across the overlay"
|
|
}
|
|
],
|
|
"guards": [
|
|
8222
|
|
],
|
|
"resources": [
|
|
{
|
|
"id": "jetstream-data",
|
|
"type": "directory",
|
|
"path": "/var/lib/mesh-broker-nats",
|
|
"mode": "0700"
|
|
},
|
|
{
|
|
"id": "conf-dir",
|
|
"type": "directory",
|
|
"path": "/var/lib/nats-module/conf",
|
|
"mode": "0700"
|
|
},
|
|
{
|
|
"id": "server-conf",
|
|
"type": "file",
|
|
"path": "/var/lib/nats-module/conf/nats.conf",
|
|
"content": "# The nats module's own server settings. Declared by the module, because a port, a TLS path\n# and a store directory are properties of the container this module raises: they live in its\n# image and its mounts and change when it does.\n#\n# The mesh writes accounts.conf beside this one and nothing else. A controller that wrote the\n# whole file would have to be kept in step with a Dockerfile it never sees.\n\nport: 4222\nhttp: 127.0.0.1:8222\n\ntls {\n cert_file: \"/tls/tls.crt\"\n key_file: \"/tls/tls.key\"\n ca_file: \"/tls/ca.crt\"\n}\n\n# **No `verify`, deliberately, and it was `verify: true` until a probe ran this image.** That\n# setting makes the server demand a *client* certificate, and nothing in the mesh presents one: a\n# host pins this server's exact certificate and authenticates with the password the mesh minted\n# (novox/hq ADR 0004, design 25 \u00a74), and so does a module's runtime. With it on, every connection\n# in the mesh is refused at the TLS handshake, before any password is looked at \u2014 and the error is\n# \"client didn't provide a certificate\", which reads as a client fault.\n#\n# TLS is still required: a tls block is what makes it required, and verify only decides whether\n# client certificates are checked. What is given up is a second factor the mesh has no machinery\n# to issue or rotate \u2014 a certificate per module per node \u2014 and what is kept is stronger than a\n# name check in both directions: an exact pin outward, a per-user password inward.\n\njetstream {\n store_dir: \"/data\"\n}\n\n# Every user of the mesh, composed by the controller and rewritten whenever a module is\n# assigned, a node enrols or a person's access changes.\n#\n# **Relative, and in this same directory, because it has to be.** An absolute include path is\n# resolved relative to the including file's directory, not from the root: nats-server given\n# `include /etc/nats/accounts.conf` from /etc/nats-server/nats.conf looks for\n# /etc/nats-server/etc/nats/accounts.conf and refuses to start. Verified against the server.\ninclude accounts.conf\n",
|
|
"mode": "0644"
|
|
},
|
|
{
|
|
"id": "server",
|
|
"type": "container",
|
|
"name": "mesh-broker-nats",
|
|
"ports": [
|
|
"4222:4222",
|
|
"127.0.0.1:8222:8222"
|
|
],
|
|
"volumes": [
|
|
"/var/lib/mesh-broker-nats:/data",
|
|
"/var/lib/nats-module/conf:/etc/nats:ro",
|
|
"/var/lib/mesh-broker-nats-tls:/tls:ro"
|
|
],
|
|
"artifact": "server"
|
|
}
|
|
],
|
|
"accesses": [
|
|
{
|
|
"path": "/var/lib/mesh-broker-nats-tls",
|
|
"mode": "read"
|
|
}
|
|
],
|
|
"build": {
|
|
"artifacts": [
|
|
{
|
|
"name": "server",
|
|
"kind": "image",
|
|
"from": "Dockerfile"
|
|
}
|
|
]
|
|
}
|
|
}
|