Installation
Waldo runs as Docker containers and is published as a prebuilt image on
Docker Hub: oldhero5/waldo. The
installer detects your OS, installs the prerequisites it needs (Docker, uv,
NVIDIA Container Toolkit on Linux+NVIDIA), writes .env, optionally downloads
the SAM 3 weights, and brings the stack up by pulling the image. There is no
Node/Vite step in the default flow — the UI is baked into the image.
Two tags are published:
| Tag | Base | Used by |
|---|---|---|
oldhero5/waldo:latest | python:3.11-slim | App, Apple Silicon workers, CPU workers |
oldhero5/waldo:cuda | nvidia/cuda:12.4.0-devel-ubuntu22.04 | NVIDIA GPU workers |
Before you run it
You need a Hugging Face read token so Waldo can pull the SAM 3 weights. Two clicks:
- Sign in at huggingface.co and accept the license
on the
facebook/sam3model page. - Create a read token at huggingface.co/settings/tokens.
The installer prompts for the token early, so it can run unattended after that.
One-shot install
macOS, Linux, WSL
curl -fsSL https://raw.githubusercontent.com/oldhero5/waldo/main/install.sh | bash
Windows (PowerShell)
irm https://raw.githubusercontent.com/oldhero5/waldo/main/install.ps1 | iex
Windows (cmd.exe)
curl -fsSL https://raw.githubusercontent.com/oldhero5/waldo/main/install.cmd -o install.cmd && install.cmd && del install.cmd
The Windows wrappers verify (and install, when needed) WSL2 + Docker Desktop,
then hand off to install.sh inside Ubuntu. WSL2 is where Waldo actually runs
on Windows — the GPU drivers in WSL come from the Windows host driver
automatically.
Pass the HF token non-interactively
Three options, pick whichever fits your workflow:
# Flag (Linux/macOS/WSL)
curl -fsSL https://raw.githubusercontent.com/oldhero5/waldo/main/install.sh \
| bash -s -- --hf-token hf_xxxxxxxxxxxxx
# Env var (gets exported into the installer)
HF_TOKEN=hf_xxxxxxxxxxxxx \
bash -c 'curl -fsSL https://raw.githubusercontent.com/oldhero5/waldo/main/install.sh | bash'
# Windows PowerShell
.\install.ps1 -HfToken hf_xxxxxxxxxxxxx
When the installer finishes, open http://localhost:8000 and sign in with the dev defaults:
- email:
admin@waldo.ai - password:
waldopass
(Override with ADMIN_BOOTSTRAP_PASSWORD for production.)
What the installer does
- Locates or clones the repo. If you ran it from inside a clone, it uses
that. Otherwise it clones to
~/waldo(override with--dir). - Detects your platform and GPU. Prints what it found (OS, package manager, NVIDIA driver, container toolkit). On macOS Apple Silicon it picks the MLX/MPS path; on Linux/WSL with NVIDIA it picks the CUDA path; otherwise it falls back to CPU.
- Prompts for
HF_TOKENup front — before slow prereq installs and container builds. Skipped if you passed--hf-token, setHF_TOKENin your env, already have one in.env, or used--yes/--skip-models. - Installs prerequisites (skip with
--skip-prereqs):- Docker Engine (Linux) — uses
get.docker.comif you have sudo - uv — Python toolchain
nvidia-container-toolkit(Linux + NVIDIA GPU only)- Node.js 20+ — only when you pass
--build-from-source
- Docker Engine (Linux) — uses
- Writes
.envfrom.env.example, setsDEVICEandDTYPEto match the GPU it picked, and saves the HF token from step 3. - Verifies GPU passthrough by running
nvidia-smiinside a CUDA container. If passthrough fails, it falls back to CPU rather than starting workers that can't see the GPU. - Downloads SAM 3 weights via
scripts/download_models.sh(skip with--skip-models). - Brings the stack up:
- Linux / WSL →
docker compose --profile <apple|nvidia> pull && up -d(no local image build). - macOS Apple Silicon →
make up-mac(infra in Docker, MLX workers native so they reach MPS). - Pass
--build-from-sourceto build the image locally instead of pulling — useful for contributors testing unmerged changes. - Skip with
--skip-upto configure only.
- Linux / WSL →
Installer flags
--hf-token TOKEN Hugging Face read token (otherwise prompted; or read from $HF_TOKEN)
--dir PATH Where to clone the repo if needed (default: ~/waldo)
--branch NAME Branch to clone (default: main)
--repo URL Git URL to clone from
--skip-prereqs Don't install Docker/uv
--skip-models Don't download SAM 3 weights
--skip-up Don't run docker compose up
--cpu Force CPU even if a GPU is detected
--gpu nvidia|apple|none Override GPU detection
--build-from-source Build the image locally (slow, requires Node) instead of pulling
--no-sudo Print missing prereqs and exit (install by hand, then re-run with --skip-prereqs)
--yes Non-interactive
--no-color Disable colored output
The PowerShell installer accepts the same flags PascalCased (-HfToken,
-Dir, -SkipUp, -Yes, ...).
You can pipe flags through curl:
curl -fsSL https://raw.githubusercontent.com/oldhero5/waldo/main/install.sh \
| bash -s -- --hf-token hf_xxxxxxxxxxxxx --dir ~/projects/waldo --yes
Prerequisites (manual install)
If you'd rather install everything yourself:
| Platform | Requirement |
|---|---|
| Linux | Docker Engine 24+, Docker Compose v2 |
| macOS (Apple Silicon) | Docker Desktop 4.30+ or OrbStack |
| Windows | Docker Desktop 4.30+ with WSL 2 backend |
| GPU (optional) | NVIDIA Container Toolkit (Linux only — WSL2 inherits from the Windows driver) |
| Local dev | uv; Node.js 20+ only if you --build-from-source |
| Models | HuggingFace token + accepted license on facebook/sam3 |
Then:
git clone https://github.com/oldhero5/waldo.git
cd waldo
cp .env.example .env # set HF_TOKEN, optionally tweak DEVICE
make up # pulls oldhero5/waldo, auto-routes by OS
# or: docker compose --profile nvidia pull && docker compose --profile nvidia up -d
To build the image yourself instead of pulling:
make build PROFILE=nvidia # builds Dockerfile.cuda (or Dockerfile if PROFILE=apple)
# or: docker compose -f docker-compose.yml -f docker-compose.build.yml \
# --profile nvidia up -d --build
A note on SAM 3 vs. SAM 3.1. The PyTorch labeler (Linux + NVIDIA / CPU) uses
facebook/sam3, which ships amodel.safetensorsthattransformers.Sam3VideoModel.from_pretrained()can load directly. The Apple Silicon labeler uses MLX withmlx-community/sam3.1-bf16, a separately repackaged 3.1 checkpoint.facebook/sam3.1itself only shipssam3.1_multiplex.pttoday and isn't loadable via transformers.
Pure Ubuntu / passworded sudo
The installer pulls Docker, uv, and Node from package managers, which require root. On a typical Ubuntu host with a passworded sudo, the script warms sudo up once at the start of the prereq step and reuses the cached credentials for the rest of the run — so you only type your password once.
When the warm-up runs depends on how you launched the script:
# Cleanest: clone first, run from a real terminal — sudo prompts as normal.
git clone https://github.com/oldhero5/waldo.git
cd waldo
./install.sh
# Curl-pipe-bash: the installer reads the password from /dev/tty so the
# prompt still appears even though stdin is the curl pipe.
curl -fsSL https://raw.githubusercontent.com/oldhero5/waldo/main/install.sh | bash
# Pre-authorize first — works on any setup, no surprises mid-run.
sudo -v && \
curl -fsSL https://raw.githubusercontent.com/oldhero5/waldo/main/install.sh | bash
If you're on a host without sudo (locked-down corp box, container, etc.),
pass --no-sudo. The installer will print exactly what it would have
installed and exit:
./install.sh --no-sudo
# install the listed prereqs by hand…
./install.sh --skip-prereqs
NVIDIA: the gotchas
- WSL2 + NVIDIA: install the NVIDIA driver on Windows, not inside WSL. CUDA inside WSL is provided by the Windows driver automatically. Installing a Linux NVIDIA driver inside WSL will break things.
- Linux + NVIDIA:
nvidia-container-toolkitmust be installed and Docker must be restarted afternvidia-ctk runtime configure --runtime=docker. The installer does this for you on apt/dnf. - PyTorch: PyPI's default
torchis CPU-only. Waldo'sDockerfile.cuda(and the publishedoldhero5/waldo:cudatag) installs fromdownload.pytorch.org/whl/cu124so the in-container PyTorch has CUDA. Iftorch.cuda.is_available()isFalse, double-check that thenvidiaprofile is selected — it pulls:cuda, not:latest. - Verify it from outside:
make gpu-checkrunsnvidia-smiin a fresh CUDA container, the same way the installer does.
Production setup
For production, set APP_ENV=production and secure values for:
JWT_SECRET(useopenssl rand -hex 32)POSTGRES_PASSWORDMINIO_ACCESS_KEY/MINIO_SECRET_KEYADMIN_BOOTSTRAP_PASSWORD(the random fallback is dev-only)
The app refuses to start if any of these are still on insecure defaults. See Security for the full hardening checklist.