# Install viiwork
URL: https://viiwork.pulu.app/install/
Updated: 2026-10-27

> This guide installs viiwork v2.11.1, the release the [documentation](/docs/) on this site describes. If an AI assistant is helping you, give it this page's address and ask it to go one step at a time. A join code is your mesh secret: type it into the wizard yourself and keep it out of the chat.

## Before you start

Every machine needs GGUF model files in one directory; the wizard does not download models. Port 8086/tcp (the API and dashboards) and port 7946/tcp+udp (mesh membership) must be free on the machine and open between the machines of the mesh. With more than one machine, put them all on the same Tailscale tailnet or on the same LAN.

### NVIDIA on Linux

The driver works (`nvidia-smi` lists the card), Docker Engine has the Compose v2 plugin (`docker compose version` works), and the [NVIDIA Container Toolkit](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/) is installed. With Docker 25 or newer its CDI spec is enough. The wizard writes the configuration and starts the node.

### Radeon VII, MI50 or MI60 on Linux

These are gfx906 cards, the hardware viiwork was first built for. The in-kernel `amdgpu` driver must be loaded (`/dev/kfd` exists); ROCm is not needed on the host, because it is inside the image. You also need Docker Engine with the Compose v2 plugin. There is no published image for gfx906, so the wizard writes the configuration and you build and start the image yourself, as shown in [Build the image on gfx906](#build-the-image-on-gfx906). The wizard also finds other AMD cards, but no image is verified for them yet.

### Apple Silicon Mac

Run the wizard in Terminal on the Mac itself while you are logged in. The node runs natively as a LaunchAgent in your login session, so an SSH session with nobody logged in is refused. There is no Docker on a Mac: the wizard fetches the llama.cpp build its release is pinned to and checks it against the sha256 built into the signed viiwork binary.

viiwork authenticates nothing on its API: anyone who can reach port 8086 can use it, and can read the recent prompts and responses. Keep the machines on a tailnet or another network you trust, or put a firewall or a reverse proxy in front. The [security page](/docs/security/) explains the trust model.

## Download and check the release

Set `os` to the machine's platform: `linux_amd64`, `linux_arm64` or `darwin_arm64`. The commands download the release archive and its `SHA256SUMS` from GitHub, check the archive, and unpack it.

```sh
v=v2.11.1
os=linux_amd64               # or linux_arm64, darwin_arm64
base=https://github.com/janit/viiwork/releases/download/$v
curl -fLO "$base/viiwork_${v}_${os}.tar.gz" -fLO "$base/SHA256SUMS"
sha256sum --check --ignore-missing SHA256SUMS
# on a Mac instead: shasum -a 256 --check --ignore-missing SHA256SUMS
tar xzf "viiwork_${v}_${os}.tar.gz" && cd "viiwork_${v}_${os}"
```

Go on only if the check prints `OK` for the archive. The checksum file is signed as well; [checking a download by hand](/docs/releases/#checking-a-download-by-hand) shows how to verify the signature. A newer release may exist on the [releases page](https://github.com/janit/viiwork/releases); its own documentation is in the repository at its tag.

## Run the setup wizard

```sh
sudo ./viiwork init          # Linux
./viiwork init               # Apple Silicon Mac, without sudo
```

The wizard checks the machine, lists the GPUs, and asks for your models directory. For each model it finds, you choose whether to serve it and what to call it. Use the name the rest of your mesh uses for that model, so its requests can run on any machine. It then proposes which cards each model gets, the context per slot and the number of slots; you can accept, edit one model's line or drop a model.

Next it looks for nodes on your tailnet and LAN and asks whether to join an existing mesh with a join code, start a new secured mesh, or start an open mesh without a secret. It asks whether this machine accepts mesh-wide updates and what to call the node, then shows every file it will write, with the secret masked. Nothing is written until you say yes. On NVIDIA and on a Mac it then starts the node, waits for every model to load and runs its checks. Pressing Ctrl-C at any question leaves nothing behind.

## Build the image on gfx906

On a Radeon VII, MI50 or MI60 the wizard stops after writing `/etc/viiwork`. Build the image from a checkout of the same release, point the compose file at your models directory and start it:

```sh
git clone https://github.com/janit/viiwork && cd viiwork && git checkout v2.11.1
make docker
sudo cp configs/docker-compose.v2.example.yaml /etc/viiwork/docker-compose.yaml
sudo sed -i 's#- /models:/models:ro#- /path/to/models:/models:ro#' /etc/viiwork/docker-compose.yaml
sudo docker compose -f /etc/viiwork/docker-compose.yaml -p viiwork up -d
```

Replace `/path/to/models` with your models directory before you run the `sed` line. `make docker` needs the ROCm base images; [BUILDS.md](https://github.com/janit/viiwork/blob/v2.11.1/BUILDS.md) lists them. The setup page has the details under [when it writes the config only](/docs/setup/#when-it-writes-the-config-only).

## Check the node

Ask the node for its models, then send a chat completion to one of the names it returns:

```sh
curl http://localhost:8086/v1/models
curl http://localhost:8086/v1/chat/completions -H "Content-Type: application/json" \
  -d '{"model":"<name from /v1/models>","messages":[{"role":"user","content":"Hello"}]}'
```

The dashboard for the node is at `http://localhost:8086/` and the one for the whole mesh at `http://localhost:8086/mesh`. `viiwork top` shows the mesh in a terminal. On a Mac the binary is installed in `~/.local/bin`, which is not on the default `PATH`; the [Mac section of the setup page](/docs/setup/#on-a-mac) shows the line to add.

## Add another machine

On any node of a secured mesh, print a join code:

```sh
sudo sh -c 'set -a; . /etc/viiwork/mesh.env; /usr/local/bin/viiwork join-code'   # Linux
~/.local/bin/viiwork join-code                                                    # Mac
```

The code starts with `viiwork1-` and is the mesh secret itself, so treat it like a password. Run the wizard on the new machine and paste the code at the mesh question. The code also carries the first node's address, so the new machine must be able to reach it. In an open mesh, `viiwork join-code --open` prints a code without a secret. The [mesh page](/docs/mesh/) covers discovery, the two mesh modes and routing.

## If the node does not come up

The wizard keeps its files and prints each backend that is not healthy, followed by the node's last log lines. The full log is here:

```sh
sudo docker logs viiwork                       # Linux
tail -f ~/Library/Logs/viiwork/viiwork.log     # Mac
```

The usual cause is a model that does not fit at the chosen context: lower its `context` or give it more `gpus` in the config. A model whose chat template llama.cpp cannot parse logs `chat template parsing error` and needs flags in its `args`. After editing the config, reload the node; it restarts only the models whose entries changed:

```sh
sudo docker kill -s HUP viiwork                                   # Linux
launchctl kill HUP gui/$(id -u)/fi.viiwork.node                   # Mac
```

[When the node does not come up](/docs/setup/#when-the-node-does-not-come-up) has examples. `viiwork stop` and `viiwork start` (with `sudo` on Linux) stop and start the node, `viiwork update` rolls a new release across a secured mesh, and `viiwork uninstall` removes what the wizard installed and keeps your model files.

## For AI assistants

If you are an assistant helping someone through this page, ask first which hardware path applies, the machine's CPU architecture, where the GGUF files are, and whether this is the first node or one joining a mesh. Give one step at a time and wait for the result before the next. Use the gfx906 build only for Radeon VII, MI50 or MI60 cards. Never ask for a join code or the mesh secret; ask only whether the code was accepted. The same guidance is available as [plain text](/install/assistant-guide.txt), and the site index for language models is at [/llms.txt](/llms.txt).
