Open Laboratory Docs
Run Laboratory OS
Documentation

Run Laboratory OS

Laboratory OS runs as a Docker container. See Install Dependencies for setup instructions.

Basic Usage

docker run -d --restart unless-stopped \
  --gpus all \
  --pid host \
  --name laboratory \
  -e UPLINK_DEVICE_TOKEN='your-device-token' \
  -v laboratory_os_workspace:/workspace \
  openlaboratoryorg/laboratory-os

The example uses an Uplink account device token. Create one in the Uplink console, then start the container. It establishes the tunnel and logs the assigned desktop URL.

Options Reference

FlagDescription
--gpus allPass through all NVIDIA GPUs. Requires NVIDIA Container Toolkit.
-e TS_AUTHKEY=...
-e TS_HOSTNAME=...
Tailscale mode. Join the station to a tailnet. The auth key works on its own or alongside either Uplink mode; the hostname is optional.
-e UPLINK_DEVICE_TOKEN=...Managed mode. A host-bound, serve-only token created in the Uplink console for the account that should own this Laboratory instance.
-e UPLINK_EDGE=...
-e UPLINK_EDGE_API_KEY=...
Self-hosted mode. The Uplink edge domain and its static admission key. Use these together instead of a managed device token.
-v /host/path:/workspaceBind mount for persistent storage. All app data and models are written to /workspace.
-v laboratory_os_workspace:/workspaceNamed Docker volume for persistence — simpler than a bind mount.
-dRun detached (in the background).
--restart unless-stoppedAuto-restart on failure or host reboot.
--name laboratoryAssign a name for easy docker stop laboratory / docker start laboratory.
--pid hostShare the host PID namespace — required for process monitoring inside the container.

Choosing an Image

TagArchitectureBaseUse when
:latestamd64 + arm64Ubuntu 22.04Default for most setups. Docker pulls the matching CPU image for your host.
:amd64amd64Ubuntu 22.04Pin x86_64 hosts explicitly. GPU passthrough works via NVIDIA Container Toolkit.
:arm64arm64Ubuntu 22.04Pin ARM hosts explicitly — Apple Silicon VMs, Raspberry Pi, etc.
:cuda-12.8 / :cuda-12 / :cudaamd64CUDA 12.8 + Ubuntu 22.04Apps that compile CUDA extensions at install time.
:cuda-13.2 / :cuda-13amd64CUDA 13.2 + Ubuntu 22.04Apps requiring the latest CUDA toolkit.

The :latest image is the right choice for most setups and now resolves to either the amd64 or arm64 CPU image automatically. The CUDA-bundled tags remain amd64-only, are larger, and are required for some apps that build native extensions (e.g. bitsandbytes, flash-attention) during installation. If an app install fails with a CUDA compile error, switch to a CUDA image.

For example, pass a tag to run a CUDA-bundled image. Everything else stays the same:

docker run -d --restart unless-stopped \
  --gpus all \
  --pid host \
  --name laboratory \
  -e UPLINK_DEVICE_TOKEN='your-device-token' \
  -v laboratory_os_workspace:/workspace \
  openlaboratoryorg/laboratory-os:cuda-12.8

Docker Compose

A sample docker-compose.yml for a persistent GPU setup:

services:
  ol:
    image: openlaboratoryorg/laboratory-os:latest
    restart: unless-stopped
    pid: host
    environment:
      - UPLINK_DEVICE_TOKEN=your-device-token
    volumes:
      - type: volume
        source: laboratory_os_workspace
        target: /workspace
    gpus: all # Remove for non-GPU mode

volumes:
  laboratory_os_workspace:

Run it:

docker compose up -d

To use a CUDA image, change the image: line to openlaboratoryorg/laboratory-os:cuda-12.8 (or whichever tag you need).

To use a bind mount instead of a named volume, change the service’s volume entry to - /your/host/path:/workspace and remove the top-level volumes: block.

To use a custom Uplink edge instead, replace UPLINK_DEVICE_TOKEN with UPLINK_EDGE=your-edge-domain and UPLINK_EDGE_API_KEY=your-edge-key.

To join a tailnet, add TS_AUTHKEY=your-tailscale-auth-key. This works by itself or alongside either Uplink configuration.

The other supported path is a custom key-mode Uplink edge. Set UPLINK_EDGE and UPLINK_EDGE_API_KEY together instead of UPLINK_DEVICE_TOKEN:

docker run -d --restart unless-stopped \
  --gpus all \
  --pid host \
  --name laboratory \
  -e UPLINK_EDGE='your-edge-domain' \
  -e UPLINK_EDGE_API_KEY='your-edge-key' \
  -v laboratory_os_workspace:/workspace \
  openlaboratoryorg/laboratory-os

In this mode the lab does not log into an Uplink account or appear in an account’s Devices list. The lab root is protected by the access token printed during boot.

Tailscale

Pass a Tailscale auth key to join the station to your tailnet. It can be the only remote-access method or run alongside either Uplink mode:

docker run -d --restart unless-stopped \
  --gpus all \
  --pid host \
  --name laboratory \
  -e TS_AUTHKEY='your-tailscale-auth-key' \
  -v laboratory_os_workspace:/workspace \
  openlaboratoryorg/laboratory-os

Tailscale access follows your tailnet ACLs. Set TS_HOSTNAME if you want to choose the station’s tailnet hostname.

CPU-Only Mode

Drop --gpus all to run without a GPU:

docker run -d --restart unless-stopped \
  --pid host \
  --name laboratory \
  -e UPLINK_DEVICE_TOKEN='your-device-token' \
  -v laboratory_os_workspace:/workspace \
  openlaboratoryorg/laboratory-os

The desktop, tunnel, and app management all work identically — the difference is purely in AI inference performance. CPU-only mode is useful for:

  • Coding agent environments — Run coding agents against external LLM APIs while keeping their default files and tools inside the container. Treat the container as a convenience boundary, not a sandbox for hostile code.
  • Cloud dev environments — Run VS Code and a terminal from any remote server, no GPU required.
  • Jupyter notebooks — Data science, scripting, anything not GPU-bound.
  • Testing your setup — Verify your Uplink credentials, tunnel, and desktop before moving to a GPU host.
  • Small LLMs — Llama 3.2 3B or Phi-3 Mini run at usable speeds on CPU (16+ core machines recommended).

Note: Most image-generation apps require a GPU. LLM inference via Ollama and llama.cpp works on a CPU but is significantly slower.

Search across 15 pages.
↑↓ navigate openEsc close