Install & first boot
This walks an operator from a bare Linux GPU workstation to a running LabPod server with a root admin account. Plan on 10–15 minutes, plus image-pull time the first time a user creates a workspace.
Before you start, skim Requirements. The installer’s --check mode
verifies most of them for you.
What you need
Section titled “What you need”- A supported Linux host: Ubuntu/Debian (apt) or Fedora/RHEL/Rocky (dnf).
sudo/ root on that host.- Network access to the distro package repos and the NVIDIA container-toolkit repo (the installer adds Podman and the GPU toolkit for you).
- For GPU workspaces: an NVIDIA GPU with drivers already installed. The installer wires up the NVIDIA Container Toolkit and a CDI spec; it does not install the GPU driver itself.
Install with the script
Section titled “Install with the script”LabPod ships one public install script. It is a host setup script, not just an app installer -
it installs Podman and rootless dependencies, adds the NVIDIA toolkit repo, generates the CDI spec,
and installs the labpod binary and systemd units. It is idempotent:
already-configured items are skipped, and re-running is safe.
# Dry run - report what's missing, change nothingcurl -fsSL https://labpod.ai/install.sh | sudo bash -s -- --check
# Real install (latest release)curl -fsSL https://labpod.ai/install.sh | sudo bash
# Install a pinned release instead of latestcurl -fsSL https://labpod.ai/install.sh | sudo bash -s -- --version v0.x.y
# Install host prerequisites only, skip the labpod servicecurl -fsSL https://labpod.ai/install.sh | sudo bash -s -- --skip-app# Run these as root# Dry run - report what's missing, change nothingcurl -fsSL https://labpod.ai/install.sh | bash -s -- --check
# Real install (latest release)curl -fsSL https://labpod.ai/install.sh | bash
# Install a pinned release instead of latestcurl -fsSL https://labpod.ai/install.sh | bash -s -- --version v0.x.y
# Install host prerequisites only, skip the labpod servicecurl -fsSL https://labpod.ai/install.sh | bash -s -- --skip-appUseful install options:
| Option | What it does |
|---|---|
--check | Dry run - report what would change, change nothing |
--skip-socket | Skip enabling the target user’s podman.socket |
--skip-app | Install host prerequisites only; skip the labpod binary and service |
--skip-backup | On an upgrade, skip the automatic pre-upgrade DB backup |
--bin <path> | Install a local labpod binary supplied for a support or recovery case |
--admin-password-file <path> | Bootstrap the root LabPod password non-interactively |
--gpu-sharing-lib <path> | Install an existing HAMi/libvgpu-compatible library |
--with-hami | Build the HAMi sharing library with Podman and enable fractional GPU (off by default) |
--uninstall | Remove LabPod-managed binaries, units, and generated assets while keeping config, data, license, and user accounts |
--uninstall --purge | Also remove /etc/labpod and /var/lib/labpod data such as DB, backups, and license. It never removes researcher account-home or work data. |
--uninstall --check | Dry-run uninstall; report what would be removed |
Install from the release tarball
Section titled “Install from the release tarball”If your change-control process does not allow curl | bash, download the GitHub Release assets
first, verify them, extract the tarball, then run the packaged installer:
BASE="https://github.com/LabPod/labpod/releases/latest/download"
curl -fLO "${BASE}/labpod-linux-x86_64.tar.gz"curl -fLO "${BASE}/labpod-linux-x86_64.tar.gz.sig"curl -fLO "${BASE}/SHA256SUMS"
sha256sum -c SHA256SUMS
cat > labpod-artifact-pub.pem <<'EOF'-----BEGIN PUBLIC KEY-----MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEki5c/1B4iOqb16m6ljKHjnbbq5EPD8mP4mNRCYrqniXLDAkDFbpGaMw6WqPBiCQUVqyvDzyL+pADdJTAdxcUSw==-----END PUBLIC KEY-----EOF
openssl dgst -sha256 \ -verify labpod-artifact-pub.pem \ -signature labpod-linux-x86_64.tar.gz.sig \ labpod-linux-x86_64.tar.gz
mkdir labpod-releasetar -xzf labpod-linux-x86_64.tar.gz -C labpod-release
sudo bash labpod-release/scripts/install.sh# Run these as rootBASE="https://github.com/LabPod/labpod/releases/latest/download"
curl -fLO "${BASE}/labpod-linux-x86_64.tar.gz"curl -fLO "${BASE}/labpod-linux-x86_64.tar.gz.sig"curl -fLO "${BASE}/SHA256SUMS"
sha256sum -c SHA256SUMS
cat > labpod-artifact-pub.pem <<'EOF'-----BEGIN PUBLIC KEY-----MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEki5c/1B4iOqb16m6ljKHjnbbq5EPD8mP4mNRCYrqniXLDAkDFbpGaMw6WqPBiCQUVqyvDzyL+pADdJTAdxcUSw==-----END PUBLIC KEY-----EOF
openssl dgst -sha256 \ -verify labpod-artifact-pub.pem \ -signature labpod-linux-x86_64.tar.gz.sig \ labpod-linux-x86_64.tar.gz
mkdir labpod-releasetar -xzf labpod-linux-x86_64.tar.gz -C labpod-release
bash labpod-release/scripts/install.shTo install a pinned version instead, set BASE to a versioned release URL such as
https://github.com/LabPod/labpod/releases/download/v0.1.0. You can pass the same installer
options after the script path, for example sudo bash labpod-release/scripts/install.sh --check.
What the script does:
- Detects the OS (apt vs dnf).
- Installs
podmanand rootless dependencies (only if missing). - Adds
/etc/subuidand/etc/subgidentries for the target user (only if missing). - Enables systemd linger for the user so rootless containers survive logout.
- Enables
podman.socketfor the user. - Validates the environment: cgroup mode (v2 recommended; v1 runs degraded), user namespaces, etc.
- On NVIDIA hosts, installs the GPU stack (NVIDIA Container Toolkit + CDI). Fractional GPU
sharing (HAMi/libvgpu) is off by default — pass
--with-hamito build and enable it. - Installs the
labpodbinary to/usr/local/bin/labpod, seeds/etc/labpod/labpod.env, and registerslabpod.service. - Installs the workspace helper tree under
/opt/labpod/inject(tmux,labpod-monitor, terminfo, and home skeleton files). - Fills in any missing default env keys. Each researcher pulls or builds workspace images in their own rootless Podman store; the installer does not configure a root image cache.
- Installs
labpod-backup.timer/labpod-backup.servicefor a daily SQLite snapshot in/var/lib/labpod/backups/.
First boot
Section titled “First boot”The install script already initializes the database, sets the root admin password, and starts
the service for you - you don’t need to run these by hand. During the real install (not
--check), it prompts on the terminal for the root LabPod admin password (or reads one
non-interactively from --admin-password-file <path>), then runs the schema migration, writes
the password, and does systemctl enable --now labpod.
If you ever need to redo one of these steps manually - for example after --skip-app, or to
recover from a stuck install - put --db after admin:
# Apply the database schemasudo labpod admin --db /var/lib/labpod/labpod.db migrate
# Set (or reset) the root LabPod admin passwordsudo labpod admin --db /var/lib/labpod/labpod.db set-password root
# Enable and start the servicesudo systemctl enable --now labpod# Run these as root# Apply the database schemalabpod admin --db /var/lib/labpod/labpod.db migrate
# Set (or reset) the root LabPod admin passwordlabpod admin --db /var/lib/labpod/labpod.db set-password root
# Enable and start the servicesystemctl enable --now labpodCheck your configuration
Section titled “Check your configuration”The installed /etc/labpod/labpod.env stays short on purpose - only the database path and JWT
secret are set. LabPod detects NVIDIA/MIG capability and everything else on its own, so a
CPU-only host and a GPU host boot from the same minimal file. To see what your host is actually
running:
sudo labpod env # this host's explicit overrides, plus what auto-detection resolved tosudo labpod env --all # every setting, including unset ones at their default, and legacy compatibility keys# Run these as rootlabpod env # this host's explicit overrides, plus what auto-detection resolved tolabpod env --all # every setting, including unset ones at their default, and legacy compatibility keysSee Environment variables for the full reference.
Rootless Podman storage
Section titled “Rootless Podman storage”Every researcher runs Podman rootless and therefore has a separate image, container-layer, and
volume store. Podman normally puts that store under
<passwd-home>/.local/share/containers/storage. This is independent of LabPod user data and
LABPOD_WORK_BASE.
To make another local disk the default for all rootless users, edit the existing [storage]
table in /etc/containers/storage.conf and add rootless_storage_path:
[storage]rootless_storage_path = "/data/labpod-podman/$USER/storage"If /etc/containers/storage.conf does not exist, copy the complete distribution file first,
commonly from /usr/share/containers/storage.conf, and then edit the copy. Storage configuration
files replace lower-precedence files instead of merging with them, so do not create a partial
system file containing only this setting.
Keep the rest of the distribution-provided file intact. $USER is expanded by the Podman storage
library, so every account still gets an isolated store. Never point multiple users at one writable
graphroot. LabPod’s root-managed shared image store is a separate download cache; workspaces do
not run directly from it.
Use a local filesystem that supports OverlayFS metadata and extended attributes, such as a normal
ext4 or XFS data disk. Rootless Podman storage is not supported on NFS, Lustre, GPFS, or similar
distributed home filesystems. See Podman’s
rootless storage documentation
and the
containers-storage.conf reference.
Create an owner-controlled parent for each LabPod user before that user first pulls an image:
sudo install -d -m 0711 /data/labpod-podman
user=alicegroup=$(id -gn "$user")sudo install -d -m 0700 -o "$user" -g "$group" "/data/labpod-podman/$user"# Run these as rootinstall -d -m 0711 /data/labpod-podman
user=alicegroup=$(id -gn "$user")install -d -m 0700 -o "$user" -g "$group" "/data/labpod-podman/$user"On an SELinux host, label the new tree for container storage, then apply the label:
sudo semanage fcontext -a -t container_var_lib_t '/data/labpod-podman(/.*)?'sudo restorecon -RFv /data/labpod-podman# Run these as rootsemanage fcontext -a -t container_var_lib_t '/data/labpod-podman(/.*)?'restorecon -RFv /data/labpod-podmanAn account-level file at <passwd-home>/.config/containers/storage.conf overrides the system
storage file instead of inheriting from it. Adopted accounts may already have one. Preserve its
driver and options, and set that file’s [storage] graphroot to the intended per-user path if you
want the account to follow the new layout.
Move an existing store
Section titled “Move an existing store”Changing rootless_storage_path changes where Podman looks; it does not move existing images or
containers. The simplest and safest time to configure it is before any researcher pulls an image.
For an account that has already used Podman:
- Stop all of that account’s LabPod workspaces and any other rootless containers.
- Record the current graphroot.
- Stop
labpod.serviceso monitoring or lifecycle calls cannot race the migration, then stop Podman’s pause process withpodman system migrate. - Copy the complete graphroot while preserving hard links, extended attributes, ACLs, and numeric subordinate-ID ownership.
- Change the system path template, or the account-level
graphrootoverride described above. - Apply SELinux labels, verify the effective path and inventory, then restart LabPod.
Repeat the following copy for every existing account before changing the system-wide setting:
user=alicehome=$(getent passwd "$user" | cut -d: -f6)uid=$(id -u "$user")group=$(id -gn "$user")runtime="/run/user/$uid"
old=$(sudo -u "$user" env HOME="$home" XDG_RUNTIME_DIR="$runtime" \ podman info --format '{{.Store.GraphRoot}}')new="/data/labpod-podman/$user/storage"
sudo systemctl stop labpodsudo -u "$user" env HOME="$home" XDG_RUNTIME_DIR="$runtime" podman system migratesudo install -d -m 0711 /data/labpod-podmansudo install -d -m 0700 -o "$user" -g "$group" "$new"sudo rsync -aHAX --numeric-ids "$old/" "$new/"# Run these as rootuser=alicehome=$(getent passwd "$user" | cut -d: -f6)uid=$(id -u "$user")group=$(id -gn "$user")runtime="/run/user/$uid"
old=$(sudo -u "$user" env HOME="$home" XDG_RUNTIME_DIR="$runtime" \ podman info --format '{{.Store.GraphRoot}}')new="/data/labpod-podman/$user/storage"
systemctl stop labpodrunuser -u "$user" -- env HOME="$home" XDG_RUNTIME_DIR="$runtime" podman system migrateinstall -d -m 0711 /data/labpod-podmaninstall -d -m 0700 -o "$user" -g "$group" "$new"rsync -aHAX --numeric-ids "$old/" "$new/"After configuring rootless_storage_path and SELinux, verify as the same Linux account:
sudo -u "$user" env HOME="$home" XDG_RUNTIME_DIR="$runtime" \ podman info --format '{{.Store.GraphRoot}}'sudo -u "$user" env HOME="$home" XDG_RUNTIME_DIR="$runtime" podman imagessudo -u "$user" env HOME="$home" XDG_RUNTIME_DIR="$runtime" podman ps -asudo systemctl start labpodsudo labpod admin doctor# Run these as rootrunuser -u "$user" -- env HOME="$home" XDG_RUNTIME_DIR="$runtime" \ podman info --format '{{.Store.GraphRoot}}'runuser -u "$user" -- env HOME="$home" XDG_RUNTIME_DIR="$runtime" podman imagesrunuser -u "$user" -- env HOME="$home" XDG_RUNTIME_DIR="$runtime" podman ps -asystemctl start labpodlabpod admin doctorKeep the old store until the image and container lists match and a workspace starts successfully. Do not delete individual layer directories.
Verify
Section titled “Verify”systemctl status labpodcurl -s http://127.0.0.1:24680/api/healthcurl -s http://127.0.0.1:24680/api/version # short git SHA of the running binarysudo labpod admin doctor # check host prerequisites, GPU sharing runtime, GPU inspector, …# Run these as rootsystemctl status labpodcurl -s http://127.0.0.1:24680/api/healthcurl -s http://127.0.0.1:24680/api/version # short git SHA of the running binarylabpod admin doctor # check host prerequisites, GPU sharing runtime, GPU inspector, …doctor is your friend whenever something looks off - it checks host prerequisites and reports
what to fix. For the full workstation preflight, use the install script’s --check mode.
You can now open http://<host>:24680 in a browser and log in as root. LabPod also uses the
adjacent port, 24681 by default, as the workspace-application gateway. Allow both ports through
the LAN firewall or VPN. Researchers start from the platform URL only; LabPod redirects workspace
apps to the gateway as needed. See Workspace gateway before
putting LabPod behind a reverse proxy.
Next steps
Section titled “Next steps”- Users & quotas - create researcher accounts and set per-user limits.
- GPU configuration - enable fractional GPU sharing or MIG.
- Workspace templates & shared mounts - register images and mount shared datasets.
- Backups & restore - the daily timer and how to restore.
- Security & hardening - TLS, port guard, and the trust boundary.
- Workspace gateway - the paired browser origins and firewall or reverse-proxy requirements.