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.
35 lines
1.7 KiB
SYSTEMD
35 lines
1.7 KiB
SYSTEMD
# 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
|