---
id: first-server
title: Add your first server
sidebar_label: Add your first server
---

Enrolling a machine means running one command on it. The control plane issues a
short-lived token, the install script fetches the agent and writes a config, and
the machine registers itself.

## 1. Create the enrolment

In the UI, go to **Servers → Add server**. That calls `POST /api/servers/new`,
which generates a server ID and a pre-registration token and hands back a ready
one-liner.

:::warning The token is single-use and lives one hour
It is the only credential in the flow, and it is spent the moment the agent
calls `Register`. If you paste it somewhere and come back tomorrow, create a new
enrolment instead nothing is lost by doing so.
:::

## 2. Run the one-liner

### Linux

```bash
curl -fsSL "https://vantage.example.com/install?server_id=<id>&token=<token>" | bash
```

Run it as root. The script:

1. Detects architecture `x86_64` and `aarch64` only; anything else exits.
2. Asks the Gitea API for the newest `agent/v*` release.
3. Downloads the binary and `checksums.txt`, and **verifies the SHA-256**,
   aborting on a mismatch.
4. Installs to `/usr/local/bin/vantage-agent`, mode `0755`.
5. Writes `/etc/vantage/config.yaml` (directory `0700`, file `0600`) containing
   the server ID, the pre-registration token and the gRPC host.
6. Writes `/etc/systemd/system/vantage-agent.service` with `Restart=always`, and
   runs `systemctl enable --now vantage-agent`.

### Windows

```powershell
irm "https://vantage.example.com/install.ps1?server_id=<id>&token=<token>" | iex
```

Run from an elevated PowerShell. The agent is registered as a service through
NSSM, with the config at `%ProgramData%\vantage\config.yaml`. There is also an
MSI built by CI if you would rather deploy that.

:::info Windows agents are second-class on purpose
They register, heartbeat, run workflow steps and report inventory. They do
**not** manage `authorized_keys` the key subsystem is Linux-only, and a
Windows agent stops after the heartbeat portion of the poll.
:::

## 3. Watch it come up

The server appears immediately as `pending`. Within one poll interval 30
seconds it flips to `active`.

On the machine:

```bash
systemctl status vantage-agent
journalctl -u vantage-agent -f
```

What happens on that first run:

```
1. Load /etc/vantage/config.yaml
2. pre_reg_token present  → register → save agent_token, clear pre_reg_token
3. Reconnect with the permanent token
4. Start: command stream · hourly update check · inventory · monitors
5. Enter the key poll loop
```

After registration the config no longer contains the pre-registration token; it
contains a permanent agent token instead. The control plane stores only the
SHA-256 of that token, never the token itself.

## 4. Confirm it works

Open the server's detail page. Within a minute or two you should see:

- Status `active`, with a recent last-seen timestamp.
- Inventory CPU, memory, swap, partitions, kernel. Metrics refresh every 30
  seconds; the full static snapshot every 15 minutes.
- Pending OS updates, checked hourly.

## If it does not appear

| Symptom                                    | Cause                                                                                                                             |
| ------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------- |
| Script exits at "Unsupported architecture" | Not amd64 or arm64                                                                                                                |
| "Checksum mismatch!"                       | Interrupted download, or a proxy rewriting the body. Re-run                                                                       |
| "Could not determine latest agent version" | The host cannot reach `gitea.hostxtra.co.uk`, or no `agent/v*` release exists                                                     |
| Service runs, server stays `pending`       | The machine cannot reach `GRPC_HOST`. Test it from that machine                                                                   |
| Registers once then goes `offline`         | Reachable for `Register` but not for the poll usually a firewall that permits the initial connection but drops the long-lived one |

A server is marked `offline` when its last-seen time passes the threshold; that
sweep runs every two minutes, so allow for it before concluding anything.

## Next

- [Assign an SSH key](../vantage/ssh-keys.md)
- [Run a workflow](../vantage/workflows.md)
- [Claim a Free licence](./claim-free-licence.md)
