Installing the Stack

On a QB2 from Tenstorrent, this is already done. The venvs are there, the driver is loaded, the firmware is flashed. This chapter is for understanding what exists and where — so you know which environment to activate when, and what to do if something’s missing.

If your QB2 came pre-configured: jump to What You Have below. The install already ran.

Installing the Tenstorrent Software Stack

On a QB2 from Tenstorrent, the stack is already there — but it is the stack that was current when your box was built, not the stack that is current today. So there are two jobs here: upgrade what you have (almost everyone) and install onto a fresh Ubuntu system (fewer people). Upgrading comes first.

Upgrade before you start

This is the step nobody thinks to take, and it is the one that saves the most time. A QB2 that has been in a box for a few weeks is behind on driver, firmware, tooling and container images, and the symptoms of being behind rarely say “you are behind” — they look like broken hardware or a broken tutorial.

See where you are first:

tt-smi -s | python3 -m json.tool | grep -E 'fw_version|driver'
apt list --upgradable 2>/dev/null | grep -E 'tt-|tenstorrent' || echo '(apt packages current)'

1. Re-run tt-installer. It is the same command as a fresh install and it is safe to run again — this is the intended way to move an existing machine forward:

/bin/bash -c "$(curl -fsSL https://tenstorrent.ai/install.sh)"

That brings the kernel driver, firmware, HugePages, tt-smi/tt-flash, sfpi and the container wrappers up to the newest tested baseline. Firmware updating is on by default, so expect it to ask about a reboot at the end.

2. Then apt. Most of the stack is packaged, and this is what picks up anything newer than the installer’s pinned baseline:

sudo apt-get update && sudo apt-get upgrade

3. Pull the two git checkouts — the installer will not do it for you. tt-studio and tt-inference-server are cloned into ~/.local/lib/, and on a re-run the installer skips a directory that already exists (“Skipping clone, will create wrapper script only”). So they stay at whatever revision they were first cloned at, however many times you re-run it. This is why a box can report an old tt-studio while the docs describe a much newer one:

git -C ~/.local/lib/tt-studio pull
git -C ~/.local/lib/tt-inference-server pull

4. Refresh the container images. The tt-metalium wrapper is a plain docker run, which pulls an image only when it is missing locally — once you have it, it never updates on its own:

docker pull ghcr.io/tenstorrent/tt-metal/tt-metalium-ubuntu-22.04-release-amd64:latest-rc

(Re-running the installer with --pull-container-images does the same thing for the images it manages.)

Do the installer first and apt second — that order is deliberate. By default the installer pins every component to a tested golden baseline (--versions=release), and it passes --allow-downgrades to apt to enforce it. So if you apt-get upgrade past the baseline and then re-run the installer, it will quietly pull those packages back down. If you want the installer itself to take the newest of everything rather than the pinned set, run it with --versions=rolling.

--dry-run --mode-non-interactive prints the whole plan without changing anything, which is a cheap way to see what an upgrade would actually do before you commit to it.

Installing on a fresh Ubuntu system

Prerequisites: Ubuntu 24.04 LTS (or 22.04), internet connection, sudo access.

sudo apt update && sudo apt install -y curl jq
/bin/bash -c "$(curl -fsSL https://tenstorrent.ai/install.sh)"

The installer handles drivers, firmware, kernel modules, one Python virtual environment for the hardware tooling, and the container wrappers that stand in for the old source-tree environments. Accept the defaults — they’re right for a QB2.

After it finishes, reboot:

sudo reboot

The Tenstorrent apt repository (and its signing key)

Most of what the installer puts on the machine — the tenstorrent-dkms kernel driver, tt-smi, tt-flash, tt-topology, tt-toplike, tt-metalium, tt-nn, sfpi — comes from Tenstorrent’s own apt repository. (The tt-metalium and tt-nn packages there are the C++ runtime libraries, for linking native code — they are not the Python ttnn module, which only exists inside the Metalium container.) Two things have to be in place for that: the repository line, and the key apt uses to verify it. Miss the key and apt refuses the repository outright.

tt-installer sets both up. These are the commands it runs, if you’d rather add the repository without the full installer, or need to repair it:

# 1. Keyring directory
sudo mkdir -p /etc/apt/keyrings
sudo chmod 755 /etc/apt/keyrings

# 2. The signing key — this is the step that gets skipped
sudo curl -fsSL -o /etc/apt/keyrings/tt-pkg-key.asc https://ppa.tenstorrent.com/tt-pkg-key.asc

# 3. The repository, pinned to that key
echo "deb [signed-by=/etc/apt/keyrings/tt-pkg-key.asc] https://ppa.tenstorrent.com/ubuntu/ $(. /etc/os-release && echo "$VERSION_CODENAME") main" \
  | sudo tee /etc/apt/sources.list.d/tenstorrent.list > /dev/null

# 4. Refresh
sudo apt-get update

On Debian, swap /ubuntu/ for /debian/. On Fedora, write /etc/yum.repos.d/tenstorrent.repo with gpgkey=https://ppa.tenstorrent.com/tt-pkg-key.asc — dnf fetches the key from the URL, so there’s no keyring file to manage.

Check it took:

# The key: a PGP block, non-zero size, readable by _apt (mode 644)
head -1 /etc/apt/keyrings/tt-pkg-key.asc
ls -l /etc/apt/keyrings/tt-pkg-key.asc

# The repository line, and where packages now resolve from
cat /etc/apt/sources.list.d/tenstorrent.list
apt-cache policy tt-smi

If apt update says “The repository … is not signed” or reports NO_PUBKEY, the key at /etc/apt/keyrings/tt-pkg-key.asc is missing, empty, or unreadable — re-run step 2 above and sudo apt-get update. Breaking & Fixing Things has the full diagnostic.

What ends up on your QB2

Path What it is
~/.tenstorrent-venv/ Python venv for the hardware toolingtt-smi, tt-flash, and tt-topology if you opted in. That is all it contains
~/.local/bin/tt-metalium TT-Metalium container wrapper — this is the TTNN / Direct API environment
~/.local/lib/tt-inference-server Serving stack; run.py launches vLLM in a container
~/.local/bin/tt-forge Forge container wrapper — only if you passed --install-forge-container; it is off by default
~/.tenstorrent-venv/bin/tt-smi Hardware monitoring CLI — on PATH whenever that venv is active, which on a QB2 is every login
~/models/ Model weights storage (create it: mkdir -p ~/models)
/etc/apt/keyrings/tt-pkg-key.asc Signing key for the Tenstorrent apt repository
/etc/apt/sources.list.d/tenstorrent.list The repository line, pinned to that key via signed-by=

As of tt-installer v3.2.0, Docker is the default container runtime (Podman is still supported — pass --install-container-runtime=podman). The Metalium container installs by default. Forge does not--install-forge-container is off unless you ask for it, and when you do, the installer pulls ghcr.io/tenstorrent/tt-xla-slim and writes the tt-forge wrapper to ~/.local/bin/tt-forge. The pip-wheel install the TT-Forge docs describe is a separate thing you do yourself, and it belongs in its own venv — see TT-Forge.

Nothing is installed into ~/.tenstorrent-venv but the hardware tooling — keep it that way. tt-smi and tt-flash live there, and on a factory QB2 it is activated for you in every shell. A bad dependency resolution in that venv costs you the tools you diagnose the machine with. Install anything of your own (huggingface_hub, Forge, vLLM) into a separate venv, or with uv tool / pipx so it gets one automatically.

~/.local/bin is not on PATH in every shell. That is where tt-smi, tt-metalium, tt-forge and tt-studio land, and tt-installer itself warns about this when it finishes: zsh never reads ~/.profile, which is where Ubuntu’s default ~/.local/bin rule lives. If a Tenstorrent command comes back command not found, run export PATH="$HOME/.local/bin:$PATH" and add that line to your ~/.zshrc.

tt-installer post-install state on a QB2 — the hardware-tooling venv and tt-smi on PATH
After tt-installer and reboot — the tooling venv and tt-smi are ready

What You Have

On a QB2 from Tenstorrent, the stack is pre-installed. Here’s your map:

Component Location When to use it
TTNN / Metalium tt-metalium wrapper in ~/.local/bin/ Direct API work, TTNN operations, cookbook examples
Hardware tooling ~/.tenstorrent-venv/tt-smi, tt-flash Monitoring and firmware. Nothing else belongs in here
Serving ~/.local/lib/tt-inference-server Serving models via HTTP, OpenAI-compatible API — runs vLLM in a container
Forge/XLA tt-forge wrapper in ~/.local/bin/ Compile PyTorch/JAX models via container — opt-in, may not be present
tt-smi in ~/.tenstorrent-venv/bin/ — on PATH once that venv is active Hardware monitoring, always available
Model storage ~/models/ (convention) Where you put downloaded model weights
Scratch space ~/tt-scratchpad/ Working directory for scripts and experiments

There is no ~/tt-metal and no ~/tt-metal/python_env. Older QB2 notes — and earlier versions of this page — told you to activate a TTNN venv at that path. Nothing on a current machine creates it: tt-installer ships TT-Metalium as a container image and gives you the tt-metalium wrapper instead. If a command in some other guide starts with source ~/tt-metal/python_env/bin/activate, substitute tt-metalium.

Installing on a fresh Ubuntu machine? tt-installer uses Docker containers for Metalium and (optionally) Forge. It creates ~/.tenstorrent-venv for the Python hardware tools and installs the tt-metalium / tt-forge wrapper scripts in ~/.local/bin/. The paths here reflect a configured QB2; a fresh install may differ slightly.

Create the scratch directory if it doesn’t exist yet:

mkdir -p ~/tt-scratchpad ~/models

The Three Environments, Explained

Two of them are containers and one is a venv. That’s the thing worth internalising: only the hardware tooling lives in a virtual environment on the host.

TTNN — the tt-metalium container

This is the workhorse. Use it for direct Python API work — opening devices, running TTNN operations, the cookbook examples in this guide.

tt-metalium
# you're now in a shell inside the container, home directory mounted
python3 -c "import ttnn; print('TTNN ready')"
exit

TTNN is already on the container’s default interpreter (/opt/venv/bin/python3), so there’s nothing to activate. The first run pulls a multi-GB image; later runs start immediately.

Serving — tt-inference-server

Use this to run a model as a server with an OpenAI-compatible HTTP API. You don’t invoke vllm yourself and it isn’t installed on the host — it ships inside a container that tt-inference-server launches:

export HF_TOKEN=hf_...   # gated repos need it even when the weights are already local

python3 ~/.local/lib/tt-inference-server/run.py \
  --model Llama-3.1-8B-Instruct \
  --workflow server \
  --tt-device p300x2 \
  --docker-server

run.py picks the container image, sets TT_METAL_ARCH_NAME, MESH_DEVICE and the vLLM timeouts per model, and publishes the API on port 8000. --tt-device p300x2 is the whole QB2 — two P300 boards, four chips. Add --print-docker-cmd to see the docker run it would issue.

Or use tt-studio for a no-code UI that handles all of this for you.

Watch the startup log for a line saying the tt platform has been selected. Without it, vLLM is running but cannot see your hardware — see the vLLM on QB2 chapter, which also covers running vllm serve by hand if you want the lower-level control surface.

TT-Forge (tt-forge wrapper)

tt-forge is a Docker container wrapper installed to ~/.local/bin/ by tt-installer. It runs the TT-XLA/Forge compiler stack without requiring a local Python venv:

# Use the tt-forge wrapper directly
tt-forge --help

For scripting with import forge in Python, use the tt-forge-fe source tree or check docs.tenstorrent.com/tt-forge for current installation instructions.

Confirming Each Environment Works

Run this check sequence:

# TTNN — inside the container
tt-metalium -c 'python3 -c "import ttnn; print(\"OK TTNN\")"'""

# The serving stack — the launcher is a file on disk, so just check it's there
python3 ~/.local/lib/tt-inference-server/run.py --help > /dev/null && echo '✓ tt-inference-server'

# The hardware tooling
which tt-smi && tt-smi --version

All three should respond without errors.

Note what is not in that list: there’s no import vllm check, because vLLM isn’t installed on the host — it lives in the container run.py starts. If you run python3 -c "import vllm" in ~/.tenstorrent-venv and get a ModuleNotFoundError, nothing is broken; that venv only ever contained tt-smi and tt-flash.

If any Tenstorrent command comes back command not found, the wrapper is almost certainly installed and merely unreachable — add ~/.local/bin to your PATH (see below).

Checking which python3 is active on the QB2 host and inside the tt-metalium container
Checking what which python3 reports on the host versus inside tt-metalium
📁 Why there's no ~/tt-metal at all: TT-Metalium reaches your QB2 as a container image — ghcr.io/tenstorrent/tt-metal/tt-metalium-ubuntu-22.04-release-amd64 — with the Python environment and compiled shared libraries inside it. Nothing is unpacked into your home directory, which is why ls ~/tt-metal comes back empty-handed and why the TTNN import only works after tt-metalium. Most users never need more than that. If you do want a real checkout to build from source (for kernel modification or upstream contributions), the build-tt-metal lesson walks through it.

Installing tt-smi if it’s Missing

On a QB2 it shouldn’t be missing, but on another Ubuntu system:

# Option A — public PyPI (any machine, no PPA needed):
pip install tt-smi

# Option B — via apt (requires the Tenstorrent repository, set up by tt-installer):
sudo apt install tt-smi

Both install the same tool. Option A works anywhere with Python; option B integrates with your system package manager. On a freshly installed Ubuntu machine without tt-installer, option A is the easier path.

Option B needs the Tenstorrent repository and its signing key at /etc/apt/keyrings/tt-pkg-key.asc — see The Tenstorrent apt repository above. If apt complains the repository isn’t signed, that key is what’s missing.

Disk Space and Model Storage

Models consume significant disk space. Plan accordingly:

Model Size on disk
Qwen3-0.6B ~1.5 GB
Qwen3-8B ~16 GB
Llama-3.1-8B-Instruct ~16 GB
Llama-3.1-70B ~140 GB

The convention across all Tenstorrent documentation is ~/models/<model-name>/. Nothing enforces this — you can store models anywhere and point --model at any path — but using the convention means every tutorial command works without substitution.

Check space before any download:

df -h ~/models
tt-installer post-install state on a QB2 — the hardware-tooling venv and tt-smi on PATH
After tt-installer and reboot — the tooling venv and tt-smi are ready

Next: Your First Model →