Two root folders built from a BQ2 seed, so that no agent OCX runs shares a
sandbox with the repositories: the public server, which runs Fossil and the
CGI programs and starts no agent, and the client, which runs the ocx2 daemon
and reaches the server only over HTTPS. Both start with serve, and carry the
same hosts.json; the hostname each is started with picks its
entry. The server keeps the machine's name. The client is x86-1.
Repositories, certificates, Git mirrors, passwords and sign-ins are data, not build output: no build puts them in a folder.
Build
Each input is checked against its pin, and everything compiles inside the seed with no network. A step that finished is not repeated.
crystal run build-rootfs.cr -- server OUTPUT BQ2 DOWNLOADS
crystal run build-rootfs.cr -- client OUTPUT BQ2 DOWNLOADS
OUTPUT is the new folder, BQ2 a bq2 built from the seed's own version,
and DOWNLOADS where inputs are kept. It must already hold clones, made over
HTTPS, named ollama.fossil, gp-crystal.fossil and crystal-robots.fossil.
Compare two builds, by kind, mode, link target and file hash:
crystal run compare-rootfs.cr -- FOLDER FOLDER
Start
The server:
bq2 sysroot-namespace --rootfs=SERVER --bind=REPOSITORIES:/var/lib/fossil --bind=MIRRORS:/var/lib/ollama-codex/git-mirror -- /usr/local/libexec/ocx/serve
The client holds its name in its /etc/hostname. A folder can hold the name but
not set it: the hostname belongs to the kernel, and the machine's cannot be
changed from inside. So the start command makes a hostname space of its own and
applies the name there:
bq2 sysroot-namespace --rootfs=CLIENT -- /usr/bin/unshare --uts /bin/sh -c 'hostname -F /etc/hostname && exec /usr/local/libexec/ocx/serve'
The client's daemon ends when the server cannot be reached, and nothing
restarts it (failures, item 20). Running
sessions go on. Start it again with confine daemon in place of serve
above, not by restarting a service whose cgroup holds the sessions.
Test
test-rootfs.cr runs both folders together on copies of
repositories, in a sealed network and process list, with the real settings
and certificate. It checks each page against pages.txt, a push,
an approved login, a run sent from the server and reported back from the
client, and a session across a server restart.
It fails one check on copies of today's repositories: a push is not exported
when Fossil's background process follows a request under /ext. That process
holds the CGI environment, so %F git export runs Fossil as a CGI, which
answers "no such file: git". With the hook %F git export --nocgi --if-mirrored -R %R,
that check passes.
What it leaves out
- Old trunk's programs: chat, docs, agent, preview and
ollama-codexare not built.ocxis not either: a logged-in visit to it starts the old agent daemon. Each answers 404. - Certificate renewal: the seed has no certbot.
- aarch64: these pins are x86_64's. An aarch64 seed exists but comes from another check-in.
- Fossil's checkout wait: the seed's Fossil opens no
.fslckoutforfossil sql --no-repository, so OCX's wait in a checkout waits on nothing (docs/fossil.md, ticket fa798aee06). OCX pins the seed's Crystal, 1.19.1.