feat(open-notebook): Quadlet pair — app + SurrealDB on a private bridge
Two containers, because that is what upstream runs (docker-compose.yml:6,13): the app image under supervisord, plus SurrealDB. The `v1-latest-single` tag is not in play — it bundles its own database, is deprecated upstream, and would give the host a second hidden DB. Both images are digest-pinned with Pull=never and a documented one-time pull, the frank-dragoon posture: a Quadlet on :latest re-resolves on the first restart after an unrelated daemon-reload, and the failure is silent. Port map paid for by what is already on the host: seerr holds 127.0.0.1:5055 (since 2026-10-14, live `ss -ltn` agrees), so the API leaves on 5056 and the env file has to set API_URL to match, because the frontend derives the API URL from the window origin when it is unset. 8502 publishes on 0.0.0.0 — the service carries its own password and the episode-audio route is unauthenticated. 8000 is published nowhere, where upstream exposes it on loopback with root credentials. The app joins dankclaw_default first and the private systemd-open-notebook second: it reaches the published fleet endpoints through the former (host.containers.internal, the arrangement Prometheus is proven against) and finds its database by container name through the latter. Generated --network flags keep file order, so the tunable file is listed before the host secret file in both units — podman applies last-match-wins. No UserMapping: the app runs as root in its namespace (no USER in the Dockerfile) and writes only paths owned by that root. Exec= carries no database credential — `exec start --user --pass` puts it in world-readable argv; the image's own entrypoint passes it on stdin, so only the container env holds it.
This commit is contained in:
1 parent
f206ddfde5
commit
09b0badaf5
3 files changed
+219
No files matched your search
@@ -0,0 +1,34 @@
|
||||
# Quadlet network: private bridge for the open-notebook pair (rootless).
|
||||
#
|
||||
# Install path on dankclaw: ~/.config/containers/systemd/open-notebook.network
|
||||
# Unit name: open-notebook-network.service (podman network name:
|
||||
# systemd-open-notebook — quadlet prefixes "systemd-", so probe the runtime
|
||||
# name, never the filename; see [[Container Network Namespaces]]).
|
||||
#
|
||||
# WHY A PRIVATE BRIDGE. The app reaches its database by container name
|
||||
# (SURREAL_URL=ws://open-notebook-surrealdb:8000/rpc), and container DNS names
|
||||
# resolve only on the network that owns them. Putting SurrealDB here instead of
|
||||
# on dankclaw_default keeps the datastore reachable ONLY to the container that
|
||||
# owns it: 8000 is not published (an unpublished port is refused outright from
|
||||
# every other namespace anyway), and nothing else on the fleet-wide network can
|
||||
# dial it with the root credentials. Same reasoning as the gitea and authentik
|
||||
# database pairs.
|
||||
#
|
||||
# Kernel bridge, not slirp4netns: the 2026-08-22 open-webui incident (a dead
|
||||
# per-container userspace helper left a container that accepted TCP and reset
|
||||
# every request for two days, logging nothing). A bridge has no such helper.
|
||||
#
|
||||
# Subnet registry on dankclaw (rootless):
|
||||
# 10.88.0.0/16 default "podman" bridge
|
||||
# 10.89.0.0/24 gitea (systemd-gitea)
|
||||
# 10.89.1.0/24 compose stack (dankclaw_default)
|
||||
# 10.89.2.0/24 searxng (systemd-searxng)
|
||||
# 10.89.3.0/24 open-webui (systemd-open-webui)
|
||||
# 10.89.4.0/24 open-notebook (systemd-open-notebook) <- this file
|
||||
# Pinned so the container IPs stay deterministic across reboots, like the
|
||||
# other pinned nets; 10.89.4.0/24 was the next unclaimed /24 in this registry.
|
||||
|
||||
[Network]
|
||||
Driver=bridge
|
||||
Subnet=10.89.4.0/24
|
||||
Gateway=10.89.4.1
|
||||
Reference in new issue
Block a user