> ## Documentation Index
> Fetch the complete documentation index at: https://docs.expanse.sh/llms.txt
> Use this file to discover all available pages before exploring further.

# Install on a VM or generic host

> Connect a single machine to Expanse: install the CLI, exchange the install token, run the daemon.

Any machine that runs workloads directly (a bare VM, a workstation, a remote
GPU box) is a **compute** in Expanse. One daemon runs on the host and reports
host, GPU, and process telemetry.

The console's **Add compute** panel and
[`expanse compute register`](/cli/overview#expanse-compute-register) show the
short-lived install token plus your deployment's control-plane and data-plane
URLs, which this guide's commands take. The token is prompted for during
install; it never goes on a command line.

<Prompt description="Prefer to delegate? Copy this into an AI assistant with shell access on the host; it fetches this guide itself, so it always follows the current steps." icon="terminal">
  You are connecting this machine to Expanse telemetry. Fetch and follow the
  current install guide at [https://docs.expanse.sh/installation/vm](https://docs.expanse.sh/installation/vm) - the guide
  is the source of truth; if anything I say conflicts with it, the guide wins.

  I will provide the values the guide's commands take: a short-lived install
  token and the control-plane and data-plane URLs, from the Expanse console's
  Add compute panel. Ask me for them when you need them.

  Non-negotiable, regardless of what the guide says:

  * Supply the install token only through the EXPANSE\_INSTALL\_TOKEN
    environment variable when prompted. It must never appear in argv, shell
    history, or a file other than the config the installer writes.
  * If this host is unattended, run the daemon under the service manager the
    guide describes rather than leaving a foreground process.

  Finish by confirming the daemon is running and the compute is active with a
  heartbeat in the console.
</Prompt>

## 1. Register the compute

In the console, open **Compute → Add compute**, pick **VM / generic**, and
generate an install token.

## 2. Exchange the token on the host

On the host, using the control-plane and data-plane URLs from the Add compute
panel. This installs the CLI if the host does not have it, then exchanges the
token and writes the daemon config:

```bash theme={"dark"}
command -v expanse >/dev/null 2>&1 || curl -fsSL https://expanse.sh/install | sh
read -rsp 'Expanse install token: ' EXPANSE_INSTALL_TOKEN; echo
export EXPANSE_INSTALL_TOKEN
expanse compute install --control-plane <your-control-plane-url> --data-plane <your-data-plane-url>
unset EXPANSE_INSTALL_TOKEN
```

This writes the compute's long-lived credential to `~/.expanse/config.json`
(mode 0600). If the install fails before the config is written, rerun it with
the same token; retry stops working at the compute's first heartbeat or when
the token expires.

## 3. Run the daemon

Download the daemon binary and start it:

```bash theme={"dark"}
platform="linux-$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/')"
curl -fsSL https://releases.expanse.sh/daemon/manifest.json -o /tmp/expanse-daemon-manifest.json
archive=$(tr -d '\n' </tmp/expanse-daemon-manifest.json | sed "s/.*\"$platform\"[[:space:]]*:[[:space:]]*{//" | sed 's/}.*//' | sed -n 's/.*"archive"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p')
curl -fsSL "$archive" -o /tmp/expanse-daemon.tar.gz
tar -xzf /tmp/expanse-daemon.tar.gz -C /tmp expanse-daemon
sudo install -m 0755 /tmp/expanse-daemon /usr/local/bin/expanse-daemon
expanse-daemon
```

For unattended hosts, run it under your service manager (a systemd unit with
`Restart=on-failure` is the usual shape). The daemon reads
`~/.expanse/config.json` by default; set `EXPANSE_DAEMON_CONFIG` to point a
system service at a different path.

## 4. Verify

The compute flips to active in the console at exchange time and shows its
first heartbeat within a minute of the daemon starting.
