The nats module, and every manifest's event names made local #115
+22
-14
@@ -3,9 +3,9 @@
|
||||
# configuration.
|
||||
#
|
||||
# **Why this exists inside the module** (novox/hq design 25 §5). The controller composes every
|
||||
# account and permission into one configuration file, and that file changes whenever a module is
|
||||
# added, reassigned, or a person's access is granted or revoked — which is often, and on the one
|
||||
# server everything else depends on. The host has no way to say "reload this container": a
|
||||
# account and permission into one file, and that file changes whenever a module is added,
|
||||
# reassigned, or a person's access is granted or revoked — which is often, and on the one server
|
||||
# everything else depends on. The host has no way to say "reload this container": a
|
||||
# container resource has `restart-on` and nothing else, and a container's `restart-on` means
|
||||
# *recreate* — every connection dropped and every in-flight JetStream ack lost, mid-flight, for a
|
||||
# permission change. `reload-on` is real but it is a *service* field, not a container's.
|
||||
@@ -19,21 +19,29 @@
|
||||
# here is declared `restart-on` or `reload-on`.
|
||||
set -eu
|
||||
|
||||
# **Two files, and only one of them is the mesh's** (novox/hq design 25 §4, task 1.7). CONF is this
|
||||
# module's own — ports, TLS, JetStream — declared in its manifest, because those are properties of
|
||||
# the container this module raises. USERS is every account and permission, composed by the
|
||||
# controller, and CONF includes it. So what is watched here is the mesh's half: the module's own
|
||||
# does not change without a new declaration, and that recreates the container anyway.
|
||||
CONF="${MESH_NATS_CONF:-/etc/nats/nats.conf}"
|
||||
USERS="${MESH_NATS_USERS:-/etc/nats/accounts.conf}"
|
||||
POLL="${MESH_NATS_CONF_POLL_SECONDS:-5}"
|
||||
|
||||
# The controller writes the configuration as part of the same declaration that creates this
|
||||
# container, but the two are not ordered against each other. Waiting is correct and starting
|
||||
# without one is not: nats-server would come up with its compiled-in defaults — no TLS, no
|
||||
# accounts, every subject open to anyone who can reach the port — and then be reloaded into
|
||||
# correctness a moment later. A bus that is briefly open to everything is not a bus that is
|
||||
# briefly wrong; it is an open bus.
|
||||
while [ ! -s "$CONF" ]; do
|
||||
echo "[nats] waiting for the mesh to compose $CONF"
|
||||
sleep 1
|
||||
# Both are written as part of the same declaration that creates this container, but none of the
|
||||
# three are ordered against each other. Waiting is correct and starting without them is not:
|
||||
# nats-server given a configuration whose include is missing refuses to start, and one given no
|
||||
# configuration at all comes up with its compiled-in defaults — no TLS, no accounts, every subject
|
||||
# open to anyone who can reach the port. A bus that is briefly open to everything is not a bus that
|
||||
# is briefly wrong; it is an open bus.
|
||||
for needed in "$CONF" "$USERS"; do
|
||||
while [ ! -s "$needed" ]; do
|
||||
echo "[nats] waiting for the mesh to write $needed"
|
||||
sleep 1
|
||||
done
|
||||
done
|
||||
|
||||
digest() { sha256sum "$CONF" 2>/dev/null | cut -d' ' -f1; }
|
||||
digest() { sha256sum "$USERS" 2>/dev/null | cut -d' ' -f1; }
|
||||
|
||||
nats-server --config "$CONF" "$@" &
|
||||
server=$!
|
||||
@@ -52,7 +60,7 @@ while kill -0 "$server" 2>/dev/null; do
|
||||
[ -n "$now" ] || continue
|
||||
if [ "$now" != "$last" ]; then
|
||||
last=$now
|
||||
echo "[nats] configuration changed; reloading in place"
|
||||
echo "[nats] the mesh's user list changed; reloading in place"
|
||||
kill -HUP "$server" || true
|
||||
fi
|
||||
done
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
"scope": "mesh"
|
||||
}
|
||||
],
|
||||
"bus-users": "/var/lib/nats-module/conf/accounts.conf",
|
||||
"capabilities": [
|
||||
"container-runtime"
|
||||
],
|
||||
@@ -42,6 +43,13 @@
|
||||
"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",
|
||||
|
||||
Reference in New Issue
Block a user