Repository navigation
Berth v0.3.4
The gateway can now switch the card and give it back without a prompt (/v1/berth/switch,
/v1/berth/stop), read the whole node in one call (/v1/berth/board), and fall back to an engine
that needs no card while the primary starts. berth pair pairs a phone or browser with the harbor.
Two experimental additions: Linux AMD support, contributed by @jenerestain, and passing the card to
a VM with berth vfio. Windows testers' reports fixed the stowaway list, the CPU meter and engine
rates. One upgrade note: the gateway no longer forwards the node's API key to engines (see Security).
Added
- Gateway:
POST /v1/berth/switchandPOST /v1/berth/stopswitch the card to an engine or give it back without
sending a prompt. Stop never touches a pinned holder. The/gui/board's Launch now uses the same switch. berth pairpairs a phone or browser with the harbor: a one-time link and its QR code, a
Pair this device page, and a device cookie for a year.--list,--revoke IDand--revoke-all
manage devices. berthd keeps only hashes. Pairing is the groundwork for switching engines from the harbor.- Gateway:
GET /v1/berth/boardreads the node in one call: the card and who holds it, every engine's state and
actions, and each engine's models with which are loaded. - Linux AMD support (experimental), contributed by @jenerestain.
berth daemon --gpu-backend amd
governs a discrete RDNA3 or RDNA4 card, or a Phoenix APU (Radeon 780M), read from sysfs and DRM
fdinfowith no ROCm.--gpu Nnames DRM cardN. On an APU, reserved VRAM and GTT (shared host
RAM) are tracked apart, only whole-card leases are granted, and parking is refused.autokeeps
NVIDIA whenevernvidia-smiis installed, so existing NVIDIA setups are unchanged. - Card passed through to a VM (experimental). While the governed card is bound to
vfio-pci,
berth statusand its JSON show it as passed through to a VM, and waiters are told why nothing is
granted. While a VFIO hold is granted, berthd does not open the card, so a driver switch can run.
card.passthroughandcard.returnedevents mark each change. - The harbor shows a card passed through to a VM (experimental): a GPU IN VM tag on every tab, the
card's panel and the departures board marked, the change named in the log, and the session left as a
gap in the tide. berth vfio statusandberth vfio run(experimental, Linux only) for passing the governed card to
a VM.statusshows IOMMU, the card's IOMMU group with each function's driver, and the processes
holding the card.run -- CMDdrains the card, stops berthd's own probe for the hold, refuses while
any process holds it, runs your own switch script withBERTH_VFIO_DEVICESset, and releases the
hold only when the card is back on its host driver.--beforeand--afterrun your own commands
around the session, for example to stop a service that holds the card and start it again once the
card is back. Berth never switches drivers or asks for passwords. See docs/vfio.md;contrib/vfio
has an example launcher and the libvirt device entries.- Gateway fallback routing: an
[[engine]]may name afallback, another engine in the file that
needs no card (a CPU llama-server, an Ollama on another box), andfallback_after(10 s by
default). A request that has waited that long for its own engine is proxied to the fallback when
the fallback answers its probe at that moment, with the body's model renamed whenfallback_model
is set. A non-streaming answer carriesX-Berth-Fallback: <fallback>; a streaming one, whose SSE
preamble was already sent, gets the fallback's stream after one: berth: fallback <fallback>
comment. The gateway never starts, leases or drains the fallback, and the primary's start is never
cancelled, so later requests land on it. The fallback never receives the node's API key, only its
own key from its entry when it has one. One hop:berth config checkrefuses chains. - Cgroup attribution closes the one known stowaway window (chaos scenario 3: a child
whose parent exits within one 2 s tick). On Linux with a systemd user manager,
berth runexecs the engine in its own transient cgroup scope (systemd-run --user --scope, unitberth-run-<name>-<rand>), which every child inherits on fork: a
child that escapes its process group and reparents stays the lease's, the lease
turns stuck naming it,berth reclaimlists it, and a whole-card request is never
grantedcontestedover it. A GPU process in a scope no live lease recorded is a
stowaway as before, and a process outside every scope is never attributed to a
scopeless lease. Without a user manager, inside aType=notifyservice (where
systemd only accepts readiness from the service's own cgroup), and on Windows, the run
starts as before and the window stands. kv_snapshotsandkv_snapshots_mibon an[[engine]]entry: the drain saves an idle slot's
prompt cache into the engine's--slot-save-pathdirectory once the boundary is reached, keeps
the directory within its budget (16 GiB by default, above the library free floor), and the
gateway restores the newest snapshot of the engine's model into its empty slots before the first
request, so a sequence of agents skips the prefill after each switch. The snapshots are keyed by
the model the engine itself names on/v1/models, so an engine that lists none or many
(llama-swap) never snapshots, and nothing crosses models. The restore also warms the files into
the page cache during the start's wait: cached, never reserved. A save is bounded at 60 s and a
restore at 30 s, so whatever goes wrong along the way costs one line and the switch goes on as
before. A snapshot holds the conversation's tokens: the ledger is owner-only, and the README asks
for a private directory.park_ttlon an[[engine]]entry sets how long that engine stays parked before Berth stops it,
in place of[park] ttl. Withkeep_comfyui_up = trueand a shortpark_ttl, a ComfyUI node that
calls another engine (a chat panel calling llama-swap) gets its answer. The drain leaves ComfyUI
up, and Berth stops the server once the ttl passes
(#121).
Changed
- The
chatshelf is now calledtext: the shelf names the kind of engine that loads a model, and
embedders, rerankers and vision or OCR models sit there too.berth models, its JSON and the
harbor saytext.shelf = "chat"in berth.toml,--shelf chatand catalogs from older
machines still read astext. Asked by @azrael-229
(#148). - The README keeps the overview, quick start and screenshots, and the reference moved to pages under
docs/: install, engines, leasing, models, gateway, the harbor, interfaces, benchmarks, roadmap and
FAQ. The README's old Tested hardware, Swap numbers and Roadmap headings link to their new pages.
Security
- The gateway no longer forwards the node's API key to engines. A proxied request, fallback and
ComfyUI routes included, carries the engine's own key when its entry has one (api_key_envor
api_key_file) and noAuthorizationwhen it has none. If an engine of yours checked the node's
key, give it its own key in itsberth.tomlentry.
Fixed
- Windows: the host's CPU is read (GetSystemTimes), so the harbor's machine meter and
berth statusshow real CPU
use instead of 0%. Windows has no load averages: the node now leaves them out of its JSON and the harbor and
berth statussay n/a instead of three zeros. Reported by @azrael-229 (#139). - One empty
models--*husk no longer makes a whole store read as an HF cache with no models,
reported by @azrael-229 (#138). A root is an HF cache only when amodels--*directory holds
snapshots, so an abandoned download beside plain models keeps them listed. - The gateway's
/gui/board launches an engine that has astartcommand but noguiURL (Strata, a
llama-server). Its Launch button answered 404 and stayed on "Launching..."; it now starts the engine under a
lease and shows Running once it answers. A refused start shows its reason instead of hanging. berth vfio status ADDRasks berthd for its view instead of calling it unreachable, and while the
card is in a VM it says so instead of printing the last memory reading as current.- The wake page and start errors show an engine's last log line without terminal color codes
([32m[INFO][0m), and a progress bar's line as its last redraw. - Windows: a process the GPU counters report but nvidia-smi does not list, such as dwm.exe
holding the card's memory, now shows its name instead of a blank one. - The harbor engine cards and
berth statusdraw an unreported rate as unknown, not zero. An
engine whose counters endpoint never answered (a llama-swap whose llama-server starts without
--metrics) shows n/a for decode, prefill and the token totals, and the ENGINE table prints a
dash. Reported by @azrael-229 (#140). - Windows: desktop apps no longer fill the stowaway list. nvidia-smi lists every graphics client with
no memory figure, so explorer, Chrome, OneDrive and 30 more showed as 0.0 GiB stowaways. A listed
process now needs the same 64 MiB in the GPU counters as an unlisted one. dwm.exe, whose counter
reports a committed reservation of 11 to 14 GiB, counts as the desktop baseline, as Xorg does on
Linux, so DOCKED and STOWAWAY no longer add up past the card. Reported by @azrael-229
(#149). - An engine card no longer reads 0.0 t/s for most of a llama.cpp generation. llama.cpp adds a
request's tokens to its counters only when the request ends, so the decode and prefill rates
sat at 0 and spiked once per request. While a request runs, the card now shows the rate the
last finished request measured; an idle engine still reads 0. Reported by @azrael-229
(#147).