One line on Ubuntu. One compose file anywhere else.
Three ways in, and one fact about your host picks it. The shell installer wants Ubuntu 24.04 or 26.04 and the ISO brings its own; Docker runs on any distribution, which is also the answer on Ubuntu 26.04 — resolute ships Python 3.14 and does not package Guacamole, so the native install has nothing to build against. No signup, no key, nothing to register.
Whichever you pick: the RDMA lab alone wants Linux 7.1+ on the host, where rdma_rxe gained its per-namespace UDP 4791 socket. Below that it starts and moves no data, and says so on first run. Detail and the check.
On 26.04 there is no RDP console. Ubuntu stopped packaging Guacamole after 24.04, so Labtris builds guacd from source there, and 1.6.0 does not compile against FreeRDP 3 — the only FreeRDP 26.04 ships. VNC, SSH and telnet consoles all work, and QEMU consoles are VNC. It only bites if you connect to a Windows guest over RDP, in which case use 24.04 or the compose install, which pulls a prebuilt guacd with RDP in it.
On a fresh Ubuntu 24.04 or 26.04 host
Runs about five minutes and finishes with the URL to open, where the config lives, and where the generated database password sits. Idempotent — re-run to upgrade.
curl -fsSL https://labtris.com/install | sudo bashhttps://github.com/labtris/labtris. To install your own fork, set LABTRIS_REPO; if the fork is private, also set LABTRIS_TOKEN, which is sent as a header on the clone and written nowhere on the host.- Refuses to run on anything but Ubuntu 24.04 or 26.04 x86_64 (override with
LABTRIS_FORCE_OS=1). - Installs
git,curl,ca-certificates. - Clones the repository to
/opt/labtris, using the token for that one request. - Hands off to
packaging/install-labtris.sh, which sets up Postgres, the service user, systemd units, nginx, everything. - Prints a summary block and writes
/root/labtris-install-summary.txt.
sudo bash is a trust exercise. The installer at /install is get.sh from the repository, served here unchanged — kept tiny and readable on purpose. The real installer, packaging/install-labtris.sh, is in the clone it makes; read it there before the hand-off if you want to.One compose file, any Linux host
No distribution requirement at all. Verified on Ubuntu 24.04 and 26.04; Debian, RHEL, Arch, Alpine and anything else with a working Docker are expected to be fine but are not ones we run. Only the RDMA lab cares what is underneath, and only about the kernel version, not the distribution. Docker and a working /dev/kvm are the only two things it asks for. Nothing is cloned — the compose file is served from this site and the image from GitHub’s registry — and upgrading is a tag bump rather than a reinstall.
curl -fsSL https://labtris.com/compose | docker compose -f - up -d- Every Labtris process shares one private container namespace, so lab bridges, taps and nftables rules land there — the host’s own networking is untouched.
- Container nodes run on a private Docker daemon, not the host’s socket.
- Ports publish on
127.0.0.1by default; widen withLABTRIS_BINDonce you have an admin account. - Two things it can’t do, because of that isolation: cloud networks that put a lab on a physical segment, and the settings that rewrite the host’s netplan.
/dev/kvm to hand it, and the container would be sharing a namespace inside Docker’s own Linux VM rather than your machine. Run a Linux VM instead.Bootable ISO for bare metal or air-gapped
Every Debian package, every Python wheel and the built interface baked in — nothing fetched during install. 3.8 GB as of 0.12.0, so GitHub’s 2 GiB asset cap splits it in two. BIOS and UEFI both boot from the same image.
# the two parts and the checksum, from https://github.com/labtris/labtris/releases/latest
cat labtris-0.13.13-amd64.iso.part-* > labtris-0.13.13-amd64.iso
sha256sum -c labtris-0.13.13-amd64.sha256ghcr.io/labtris/uet-ref and ghcr.io/labtris/rdma-host are published by CI, the rest come from Docker Hub. Nothing to build first.docker pull fails with “no matching manifest for linux/arm64/v8”; add --platform linux/amd64 to inspect one. Labtris itself needs a Linux host with KVM, so arm64 would mean the whole set, not just a node image — say so if you need it.One command, with a backup taken first.
Goes to the latest release, dumps the database before it migrates anything, and tells you whether the result is actually serving. Your labs, pods, images and database are carried across, not replaced.
curl -fsSL https://labtris.com/upgrade | sudo bashA specific release instead: … | sudo bash -s -- --to v0.12.0. To see what it would do and change nothing: … | sudo bash -s -- --check. The -s -- matters — without it bash takes the flags for itself rather than passing them on.
Compose install
The command above is for the native install. With the compose file, the image is the release, so upgrading is pulling a newer one. Back up the database first; the api container migrates it on start and a migration cannot be undone.
docker compose exec postgres pg_dump -U labtris labtris > labtris-$(date +%F).sql
docker compose pull
docker compose up -dLabs, images and pods live in named volumes (postgres-data, labtris-state, labtris-images, dind-storage), not in the image, so a new image finds them where the old one left them. Container nodes keep running through the upgrade. VMs stop with the old api, because it is their parent process, and the new one starts again every node that was running, four at a time; set LABTRIS_RESTORE_RUNNING_NODES=false to leave them stopped instead. The first upgrade onto a compose file from before October 2026 restarts container nodes once too. To pin a release instead of latest, set LABTRIS_IMAGE=ghcr.io/labtris/labtris:v0.13.12 in .env next to the compose file; to roll back, set the old tag and run docker compose up -d.
--depth 1 clone has no tags locally and sorting them as text puts v0.9.0 above v0.12.0. Then pg_dump to /var/backups/labtris — always, with no flag to skip, because alembic upgrade head is not reversible. Then fetch, check out, reinstall dependencies, migrate, restart. Then it verifies labtris-api and labtris-netd are active and the interface answers, and on failure prints the journal command, the previous commit and the path to the dump.docker compose pull && docker compose up -dWhere to look when something breaks.
| Shell installer or ISO | Docker | |
|---|---|---|
| Web UI | https://<host>/ (also :8081, plain HTTP) | http://<host>:8080 |
| Config | /etc/labtris/labtris.env | environment: in docker-compose.yml |
| DB password | /etc/labtris/db-password | set in docker-compose.yml |
| Health check | labtris system doctor | docker compose exec api labtris system doctor |
| Logs | journalctl -u labtris-api -u labtris-netd -f | docker compose logs -f api netd |
| Restart | systemctl restart labtris-api labtris-netd | docker compose restart |
The full handbook lives at docs.labtris.com.