Authoritative project documentation
Manual Compose install — no Scout Bee
Tested against
apiarylens-0.1.0-preview.5-compose-97e5ce858208.tar.gzfrom the publishedv0.1.0-preview.5release on 2026-07-19. The published artifact's byte count and SHA-256 were verified against the release manifest andSHA256SUMS, its keyless attestation verified withgh attestation verify, the bundle was extracted, and every command in this guide was checked against its actual layout,docker/README.md,compose.yaml, and.env.example. The runtime lifecycle (install → health → bootstrap → backup → restore → teardown) is verified by the exact-artifact UAT record in UAT-001 item 5, which walked these procedures end to end on the Ubuntu 24.04 reference host against the prior build's bundle — whosedocker/deployment tree is content-identical to this one; the two corrections that run produced (#83: secret-file permissions and.env.exampleidentity) are incorporated below and confirmed fixed in this bundle.
Deploy the ApiaryLens backend and web frontend with Docker Compose on a Linux host you control, without Scout Bee. This is the fully supported direct path; Scout automates the same steps but is never required.
Supported host
- x86-64 Linux; Ubuntu Server 24.04 LTS is the verified reference
- Docker Engine with the Compose v2 plugin
- 2 vCPU, 4 GiB RAM, 32 GiB persistent disk for the family profile
- Inbound TCP 80 and 443; TCP 22 restricted to your own address
- A DNS name resolving to the host
- Outbound HTTPS for image retrieval and certificate issuance (for a host without any egress, use the offline deployment bundle and the air-gap install and transported update guide instead)
- UTC system time and enough free disk for one release plus backups
See Cloud VM Compose for Azure, AWS, and Google Cloud host preparation and cost notes.
1. Verify the release bundle
Never deploy from a mutable tag or an unverified download.
Download the Compose bundle and the release manifest from the release page of the exact version you are installing.
Transfer the bundle to the server over SSH with strict host-key checking.
On the server, verify the byte count and SHA-256 digest against the manifest entry:
stat --format=%s apiarylens-<version>-compose-<sha12>.tar.gz sha256sum apiarylens-<version>-compose-<sha12>.tar.gzBoth values must match the manifest exactly. Stop on any mismatch.
2. Lay out the release and secrets
The bundle extracts into the current directory (it has no top-level version
folder), so create the versioned release directory first and extract into it.
Take ownership of the /opt/apiarylens base directory itself — everything
below it (releases, secrets, your own records) is then created without
sudo:
sudo install -d -o "$USER" /opt/apiarylens
install -d /opt/apiarylens/releases/<version>
tar -xzf apiarylens-<version>-compose-<sha12>.tar.gz \
-C /opt/apiarylens/releases/<version>
cd /opt/apiarylens/releases/<version>/docker
Create the two deployment secrets outside the release tree so they survive updates, in a directory only you can enter:
install -d -m 700 /opt/apiarylens/secrets
openssl rand -base64 36 > /opt/apiarylens/secrets/bootstrap-token
openssl rand -base64 48 > /opt/apiarylens/secrets/auth-root
chmod 644 /opt/apiarylens/secrets/bootstrap-token \
/opt/apiarylens/secrets/auth-root
The chmod 644 is required: the secret files are bind-mounted read-only
into the api container, which runs as the unprivileged user apiarylens
(uid 10001) and cannot open host-user-only files — with mode-600 files the
API fails at startup with EACCES on /run/secrets/bootstrap_token and the
stack never becomes healthy. The mode-700 directory is what keeps the files
private to you on the host.
- The bootstrap token is the one-time first-owner setup code. Keep it only until the first owner and family exist, then delete the local copy.
- The authentication root is durable deployment state. Losing or rotating it invalidates sessions and makes stored family credentials unverifiable. Protect it and include it in every backup.
Copy .env.example to .env (mode 600). It ships preset with the release's
identity values (APIARYLENS_VERSION, APIARYLENS_ARTIFACT_IDENTITY, …);
leave those as shipped, set APIARYLENS_SITE_ADDRESS to your real DNS name,
and point the deployment at your secret files:
APIARYLENS_BOOTSTRAP_SECRET_FILE=/opt/apiarylens/secrets/bootstrap-token
APIARYLENS_AUTH_ROOT_SECRET_FILE=/opt/apiarylens/secrets/auth-root
Never put either secret value directly in .env or shell history — the
variables above carry file paths, not secrets.
3. Start and verify
From the release's docker/ directory (Compose reads .env from the
working directory, and compose.yaml sets the project name apiarylens):
docker compose config --quiet
docker compose build --pull
docker compose up -d --wait
Then verify every one of the following before calling the install done:
Containers are healthy:
docker compose ps.Public HTTPS answers and
/healthreports the release identity you installed:curl --fail --show-error --silent "https://<your-dns-name>/health"The bootstrap flow is protected: creating the first family requires the one-time setup code.
An authenticated sign-in can read and write records.
Media is private: media URLs require authentication.
A backup can be created and verified — do this now, not after the first real data exists. See the Operations Guide backup procedure.
Hard rules
- Do not expose the API container directly or publish plain HTTP.
- Do not bind any unauthenticated service to LAN or public interfaces.
- Do not use default or example credential values.
- Do not run
docker compose down --volumesas an update or troubleshooting step — it destroys data volumes.
Updates, rollback, and removal
Updates follow the shared lifecycle — backup first, verify the new bundle,
migrate, activate, health-check, and only then commit:
Operations Guide and the
update lifecycle reference.
The manual update path must keep the same
/opt/apiarylens/releases/<version> layout so guided tooling and your own
records agree about what is installed. Removal choices are covered in the
Operations Guide uninstall section.