Deploying the documentation
The docs are five MkDocs static sites, one directory per audience under docs/, each with its
own markdown and mkdocs.yml. Each builds into a gitignored site/, and serving one is serving
static HTML — there is no application involved. Authoring them is covered in development practices →
Documentation.
One-time toolchain setup
Ubuntu marks its system Python externally-managed (PEP 668), so pip install and even
pip install --user are refused. The toolchain therefore lives in a repo-local virtualenv, pinned by
docs/requirements.txt:
sudo apt install -y python3.12-venv # the only step that needs root
python3 -m venv docs/.venv
docs/.venv/bin/pip install -r docs/requirements.txt
docs/.venv is gitignored and per-machine. Nothing else on the box is touched, and the system
mkdocs on PATH — if there is one — is not what builds these.
Local: read them in a browser
docs/build.sh # all five sites
docs/build.sh zf-general # or just one
It builds each site into its own site/ directory and then prints, for each one, the command that
serves it in a browser:
docs/.venv/bin/mkdocs serve -f docs/zf-deployment-docs/mkdocs.yml
That starts a small web server for the one site, prints the address it answers at, and rebuilds
the site as you save. Stop it with Ctrl-C. One site at a time, on one port: a second one at the
same time takes --dev-addr localhost:8001.
build.sh passes --strict, which makes a nav entry or link pointing at a missing file a build
failure. That is how these sites break — a page is renamed, the nav still names it, and nothing says
so until a reader clicks — so build before committing a page rename. mkdocs serve alone does not
fail on that, which is why the build is the check and the serve is the reader.
Live
Three of the sites are public, and they travel two different ways.
The guides and the home site are published from a development machine, by one command, whenever they change:
docs/publish.sh
It builds them, then copies them to the host over ssh with rsync, as static files. The production
and development guides land at https://deployment.zebrafishfacilitymanager.com, behind a landing
page that asks which of the two you are setting up, with the production guide under /production/
and the development guide under /development/. The home site, what ZFM is, who uses it, the terms
and how to get in touch, lands at https://home.zebrafishfacilitymanager.com. Each copy is a
mirror, so a page deleted here is deleted there, and every page's footer says which build of the
repository it describes. The host does nothing but serve two directories: it has no Python, no
MkDocs and no checkout.
The host side is set up once. Each directory belongs to the account the publish logs in as, so
that publishing needs no root, and Caddy serves each from one file in /etc/caddy/conf.d:
sudo install -d -o <your account> -g <your account> -m 755 /var/www/zfm/docs/deployment /var/www/zfm/docs/home
sudo install -m 644 deploy/caddy/deployment-docs.caddy deploy/caddy/home.caddy /etc/caddy/conf.d/
sudo caddy validate --config /etc/caddy/Caddyfile
sudo systemctl reload caddy
The site addresses in those files are https://, so Caddy obtains each certificate itself at the
first request, once the name resolves to the host.
The usage guide ships inside every release. It is built with the installation artifact and
served by each facility's web server at /usage-guide/ on the facility's own address, from the
release that facility runs, so what a user reads describes the version in front of them. Nothing
publishes it separately; it reaches a facility the way the rest of a release does.
The development-practices and data-migration sites are not published. They are read from a checkout.