mesh/delivery rejected: the gate failed or could not run, or the repository's own check failed
mesh/merge-gate out of date: judged against trunk a44d490d974c, the trunk is now b15846dd6e78; judged again on a recheck or when it is merged
mesh/repo-check out of date: judged against trunk a44d490d974c, the trunk is now b15846dd6e78; judged again on a recheck or when it is merged
A watch that panicked stopped for good, and one that could not read said so only to stderr, so a dead watch read as no slow consumers. A faulted look is now recovered and the loop goes on; every look ends with a bus.watch heartbeat saying whether the watch is healthy, which the controller raises when it stops or says it cannot see. The record is read newest first back to the last look, and closures that could not be published are forgotten after the hour.
168 lines
6.7 KiB
JSON
168 lines
6.7 KiB
JSON
{
|
|
"module": "nats",
|
|
"version": "1",
|
|
"upgrade": {
|
|
"policy": "record",
|
|
"why": "the bus: replaced only as a planned step a person starts (`bus upgrade`), its streams snapshotted first and checked after (hq ADR 0236); the controller holds this whatever is said here"
|
|
},
|
|
"provides": [
|
|
{
|
|
"name": "mesh-bus",
|
|
"scope": "mesh"
|
|
}
|
|
],
|
|
"claims": [
|
|
{
|
|
"name": "mesh-broker",
|
|
"scope": "mesh"
|
|
}
|
|
],
|
|
"bus-users": "/var/lib/nats-module/conf/accounts.conf",
|
|
"own-secrets": {
|
|
"broker": "${dir:mesh-state}/broker"
|
|
},
|
|
"capabilities": [
|
|
"container-runtime"
|
|
],
|
|
"emits": [
|
|
"bus.slow-consumer",
|
|
"bus.connection-closed",
|
|
"bus.watch"
|
|
],
|
|
"consumes": [],
|
|
"listens": [
|
|
{
|
|
"name": "bus",
|
|
"port": 4222,
|
|
"protocol": "tcp",
|
|
"from": "mesh",
|
|
"why": "the mesh bus — every link the mesh has, over TLS, reached across the overlay"
|
|
}
|
|
],
|
|
"tools": [
|
|
"nats_server",
|
|
"nats_connections",
|
|
"nats_closed_connections",
|
|
"nats_bus_watch",
|
|
"nats_subscriptions",
|
|
"nats_streams",
|
|
"nats_backlog",
|
|
"nats_buckets",
|
|
"nats_users",
|
|
"nats_user_can"
|
|
],
|
|
"guards": [
|
|
8222
|
|
],
|
|
"data": {
|
|
"own": [
|
|
{
|
|
"id": "jetstream",
|
|
"path": "${dir:jetstream-data}",
|
|
"class": "valuable",
|
|
"active": "1d",
|
|
"backup": {
|
|
"dump": "docker exec -i mesh-broker-nats mesh-nats-snapshot snapshot < ${dir:mesh-state}/broker > ${dir:snapshots}/bus.tar.partial && mv ${dir:snapshots}/bus.tar.partial ${dir:snapshots}/bus.tar || { rm -f ${dir:snapshots}/bus.tar.partial; exit 1; }",
|
|
"into": "snapshots"
|
|
},
|
|
"why": "the bus's streams and key-value buckets: the hand-act log, conditions, every module's state; written all the time, so copied by the server's own snapshot of each stream (novox/hq ADR 0235), never as live files"
|
|
},
|
|
{
|
|
"id": "snapshots",
|
|
"path": "${dir:snapshots}",
|
|
"class": "rebuildable",
|
|
"why": "last night's snapshot of every stream with its manifest, made again every night"
|
|
}
|
|
]
|
|
},
|
|
"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": "snapshots",
|
|
"type": "directory",
|
|
"mode": "0700"
|
|
},
|
|
{
|
|
"id": "mesh-state",
|
|
"type": "directory",
|
|
"mode": "0700",
|
|
"place": "mesh"
|
|
},
|
|
{
|
|
"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\n# Monitoring on every interface *inside* the container, so the publish below can reach it; the publish\n# is 127.0.0.1:8222 on the machine, so nothing beyond the machine reaches it, and the module guards 8222\n# too. Bound to the container's own loopback until 2026-10-04, the published port answered nothing\n# (connection reset), and the only way in was `docker exec`.\nhttp: 0.0.0.0:8222\n\n# The mesh's own broker certificate — the one every machine already pins by fingerprint and the\n# controller already trusts (MESH_BROKER_CERTIFICATE). Serving the new bus with it means no\n# machine's pin changes when it moves, and no second certificate exists to be wrong about.\ntls {\n cert_file: \"/tls/tls.crt\"\n key_file: \"/tls/tls.key\"\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 §4), 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 — 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 — a certificate per module per node — 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",
|
|
"${access:tls}:/tls:ro"
|
|
],
|
|
"artifact": "server"
|
|
}
|
|
],
|
|
"accesses": [
|
|
{
|
|
"id": "tls",
|
|
"path": "/var/lib/mesh-broker-tls",
|
|
"mode": "read"
|
|
}
|
|
],
|
|
"build": {
|
|
"on": [
|
|
{
|
|
"arg": "NATS_BASE",
|
|
"image": "nats@sha256:e4bf19f15fd3218814a4e3c9e0064e1334bd8aa20d5984b9f1a0afd084f8cc00"
|
|
},
|
|
{
|
|
"arg": "GO_BASE",
|
|
"image": "golang@sha256:8ac98ca534ac3f51e1f420a1dd2c15e74c75cfa0f23f3ad27eb5d7236c349a0c"
|
|
}
|
|
],
|
|
"artifacts": [
|
|
{
|
|
"name": "server",
|
|
"kind": "image",
|
|
"from": "Dockerfile"
|
|
},
|
|
{
|
|
"name": "tools",
|
|
"kind": "bundle",
|
|
"language": "go",
|
|
"system": "arch",
|
|
"from": "cmd/nats-tools",
|
|
"binary": "nats-tools",
|
|
"loads": [
|
|
"nats-tools"
|
|
],
|
|
"env": {
|
|
"MESH_NATS_MONITOR": "http://127.0.0.1:8222",
|
|
"MESH_NATS_CONTAINER": "mesh-broker-nats",
|
|
"MESH_NATS_USERS_FILE": "/etc/nats/accounts.conf"
|
|
}
|
|
}
|
|
]
|
|
}
|
|
}
|