Syntax
Options
lager update targets one box per invocation. To update several, loop over them
in your shell — the --all flag and its multi-box loop were removed in v0.18.2.Pre-built box images
Release tags publish a box container image to the GitHub Container Registry. If a pull is enabled, the client does three things:- It resolves the tag to an immutable digest.
- It pulls that digest, pinned to the box’s own architecture.
- It verifies that the image reports the version you asked for.
For
lager update, pulling is off by default. It changes how the most
load-bearing command in the fleet obtains the code it runs, so it soaks on
Lager’s own boxes first. Pass --pull to opt a single run in. To opt in a whole
shell, set LAGER_BOX_IMAGE_PULL to 1, true or yes (in any letter case).
Any other value leaves the pull off.This differs from lager install, which already
uses a pre-built image for a release tag by default. --no-pull works the same
way on both. It is the switch that routes a fleet around a bad published image,
and it needs no CLI release.--forcenever pulls. It always builds the image on the box.--pulltogether with--no-pullis a usage error.- The pull runs before the update stops the container, so the box keeps serving during the download. A miss leaves the box on its previous version.
- The update records the image source in
/etc/lager/image-source:ghcr:<digest>for a pulled image, orlocal:<build-hash>for a build.
Version pinning
Since lager 0.22.0, a semver value passed to--version resolves to the
release tag vX.Y.Z. The leading v is optional (e.g. 0.26.0 or
v0.26.0), and the common pre-release suffixes (-rc1, -beta2, -alpha,
-preview) are accepted too. Release tags are the single source of truth for a
pinned version.
--version main is re-resolved against origin/main each time it runs, so it
can mean a different commit minutes later. A commit has no pre-built image,
because only release tags publish one. So a SHA builds on the box just as a
branch does. The commit must also be reachable from a branch or tag on the
remote.
Any other value (main, staging, or a feature branch name) resolves to
origin/<name> as before.
Usage
Basic Update
Updating Several Boxes
There is no built-in multi-box update. Loop in your shell, and use--check
first if you want to see which boxes are actually behind:
A
--all flag existed before v0.18.2 and was removed along with the multi-box
loop it drove. A plain shell loop continues to the next box when one fails, so an
unreachable box does not stop the run.Check Mode
--check changes nothing on the box. It prints a preview:
Current: comes from /etc/lager/version. The preview does not show the
deployed ref. Use lager hello for the ref.
Exit
1 does not always mean that the box is behind. The check also exits 1
when it fails. Examples are an SSH timeout, a failed probe of the box state, and
a box directory that is not a git checkout. A failed git fetch also gives 1,
and that includes a commit SHA that the box cannot fetch. A box locked by another
holder also gives 1. Read the output before you treat 1 as “update needed”.
Update Process
The update command performs the following steps (shown in progress bar):- SSH Check - Confirm key-based SSH access to the Lager Box
- Inspect and Fetch - Read the box state, then fetch the target version
- Pull Updates - Check out the target version on the box
- Host Setup - Check the udev rules, the modprobe blacklists, the sudoers files and the host CLI
- Image Pull - With
--pulland a release tag, pull the pre-built image - Container Stop and Build - Stop the running container, then build the image on the box if the update did not pull one
- Directories - Set up the directories that the container mounts, such as the custom binaries directory
- Version Update - Record the version in
/etc/lager/versionand the deployed ref in/etc/lager/ref - Container Start - Start the new container
- Status Verification - Wait for the services, then confirm that they answer
- J-Link - Install J-Link if the box does not have it (a failure here is not fatal)
- Host CLI - Reinstall the
lagerCLI in~/.lager_venvon the box host, because the code changed
Host CLI on the box host was NOT updated: .... The box host needs
python3 3.10 or newer, or the update skips this step with a warning. A box that
is already up to date still gets the host CLI if its copy is absent, broken or
older.
lager update does not change the host firewall.
Version Tracking
The Lager Box tracks its current version in/etc/lager/version. The
lager boxes listing queries each configured box and shows its current version
in the version column:
/etc/lager/ref, as
<ref>@<short-sha> (for example main@85c1b64). If the update cannot read the
commit, the file holds the bare <ref>. lager update writes the file on every
successful run, including a run where the box is already up to date.
lager install writes it too.
The version number alone cannot tell a branch deploy from a release deploy, so
two commands show the ref:
lager helloshows the full ref. A ref that is not a release tag adds-- not a release build.lager boxesshows<version> (<ref-name>)for a ref that is not a release tag.
SSH Key Authentication
The update command checks for a working SSH key before it changes anything:- With a working key: The update runs without password prompts.
- Without a working key: The update offers to set up the
lager_boxkey. That setup asks for the box password once. - If the key setup fails: The update asks whether to continue with password authentication.
- With
--yes: The update accepts both prompts. - With
--check: The update does not set up a key. It exits2when no key works.
Firewall
lager update does not install, change or run the host firewall. lager install
configures it. To run the firewall script again, run it on the box:
lagernet network, these rules do not filter the
ports that the container publishes. See
lager install and the Security Model section
of SECURITY.md.
Examples
Troubleshooting
Update Fails at Git Pull
Container Build Fails
Firewall Issues
Notes
- Progress bar is disabled when
--verboseis used - Container builds use the BuildKit layer cache.
--forceremoves the cached image and the cargo/npm volumes first - Version defaults to
mainif not specified - Update automatically verifies container health after restart
--checkreports what will change without modifying the box, so it is the safe way to find out whether a box is behind--forceupdates even when the box reports it is already current, wiping the cached image and the cargo/npm volumes (useful after major code changes)

