# Install a host

> Install and pair an Ubuntu Server host with one command and a code: every download verified, session services installed, machine paired.

One command turns an Ubuntu Server 24.04 machine into a Community host. It checks the machine, installs the session services, then shows a code to pair the machine with your account. Nothing to copy from the console. About 5 minutes.

## Before you start

- A machine that meets the [Provider requirements](https://nodelodge.com/docs/provider-requirements): Ubuntu Server 24.04 on the machine itself, the HWE kernel (Linux 6.12 or newer), virtualization and IOMMU on in the firmware.
- A terminal on the machine, as a user who can run `sudo`.
- A provider account with a verified email address, as an owner or admin of your organization.

## 1. Run the command on the machine

```bash
curl -fsSL https://nodelodge.com/host | sudo bash
```

Type it as shown. It asks for your sudo password once, then:

1. **Checks the release key.** The start script carries the Node Lodge release key and compares it with the key published in DNS, apart from this site (see [The release key](#the-release-key)). If they differ, nothing runs.
2. **Checks the installer.** It downloads `install.sh` and its signature and checks the signature with that key. If the check fails, nothing runs.
3. **Checks the machine.** Each requirement gets a line: **ok**, **WARN** or **MISSING**, with the fix. When something only you can change is missing (the firmware, the kernel, the system), it stops before changing anything.
4. **Checks the release.** The agent, the session daemon and their service files come in one signed file, checked against the same key before it is unpacked. Cloud Hypervisor and the registry mirror are checked against fixed SHA-256 digests.
5. **Installs.** System packages, Node.js 22, the accounts `nl-vmd`, `nl-mirror` and `nl-agent`, the release under `/opt/nodelodge`, and four services that start at boot.
6. **Shows a code.** The agent generates its key on the machine and prepares to pair. Only the public half of the key leaves the machine.

The terminal then shows:

```console
  To pair this machine, open nodelodge.com/pair on any device signed in to Node Lodge
  and enter the code K7QX-M2PD, or scan:

  (QR code)

  The code expires in 10 minutes. Waiting for approval...
```

## 2. Enter the code

On any device signed in to Node Lodge, your phone included:

1. Open [nodelodge.com/pair](https://nodelodge.com/pair) and enter the code, or scan the QR code: it opens the same page with the code filled in.
2. Check the machine: GPU and VRAM, CPU, memory, system, and the address and country its request came from. If you did not start this install yourself, select **Decline**.
3. Name the machine. The hostname is proposed; renters see the name, so avoid personal details.
4. Select **Pair this machine**.

The machine finishes on its own: it receives its credentials, pairs, and runs the self-test. The console opens its page, awaiting review.

A code works once, for 10 minutes. Only an owner or admin of the organization can approve it, from a signed-in browser.

## What runs on the machine

| Service | Account | Role |
|---|---|---|
| `compute-host` | `nl-agent` | Heartbeats, hardware report, orders signed by Node Lodge |
| `nl-vmd` | `nl-vmd` | Runs each session in its own micro-VM |
| `nl-vmd-helper` | root | Network, firewall and GPU handover of the VMs, nothing else |
| `nl-mirror` | `nl-mirror` | Local cache of container images, shared by the sessions |

No service listens on a network port. The agent connects out to Node Lodge over HTTPS.

## Check the host

```bash
sudo /opt/nodelodge/install.sh --check
```

Reads the machine, the services and the pairing, runs the self-test, and changes nothing. It ends with **host ready**, or with the list of what to fix.

## Update and roll back

```bash
sudo /opt/nodelodge/install.sh --update
sudo /opt/nodelodge/install.sh --rollback
```

`--update` installs the newest release, signed by a release key already pinned on the machine. Releases only move forward: the machine refuses any release older than the newest it has installed, and any key retired by a later release, whatever the server sends. The previous release stays on disk, and `--rollback` returns to it; the next `--update` moves forward again. Sessions keep running through both.

Running the command again is safe: what is already right stays as it is, and a machine already paired is not paired again.

## Options

Add options after `sudo bash -s --`:

```bash
curl -fsSL https://nodelodge.com/host | sudo bash -s -- --skip-dns-check
```

| Option | Use |
|---|---|
| `--skip-dns-check` | Networks that filter DNS. Compare the key with the one below yourself first. |

## Without a browser near the machine

For automation, or a machine where nobody can open the console: in **Setup**, under **No browser at hand**, name the machine and select **Generate pairing code**. The console shows a command that carries the code to the installer on its standard input, never in the arguments of a process. The code works once and expires after 15 minutes.

## GPUs

Rented GPUs belong to the VMs: bound to `vfio-pci`, with no NVIDIA driver on the host. Reserve them as described in [Provider requirements](https://nodelodge.com/docs/provider-requirements#vfio), then check the host again.

## The release key

The start script checks the installer against this public key, the one that signs every Node Lodge release:

```text
MCowBQYDK2VwAyEAMpBEdmKh+jNxfzcsprbjpeoESLOYNWJtfH1Eq3eGekw=
```

The same key is published in DNS, in a DNSSEC-signed zone, apart from the console and this site. The start script reads it before anything runs; to read it yourself:

```bash
dig +short TXT _host-release-key.nodelodge.com
```

The answer is the key above, in quotes. During a key change, it lists both keys. Once installed, the machine checks every update against the keys it pinned.

To read the start script before you run it, download it with its signature and check it with the key above:

```bash
curl -fsSL -o host.sh https://nodelodge.com/host
curl -fsSL -o host.sh.sig https://nodelodge.com/host.sig
printf '%s\n' '-----BEGIN PUBLIC KEY-----' 'MCowBQYDK2VwAyEAMpBEdmKh+jNxfzcsprbjpeoESLOYNWJtfH1Eq3eGekw=' '-----END PUBLIC KEY-----' > release-key.pem
base64 -d host.sh.sig > host.sh.raw
{ printf 'nl-host-bootstrap\0'; cat host.sh; } > host.sh.msg
openssl pkeyutl -verify -pubin -inkey release-key.pem -rawin -in host.sh.msg -sigfile host.sh.raw
sudo bash host.sh
```

## Troubleshooting

| You see | Do this |
|---|---|
| `the release key could not be read from DNS` | Install `dig` (`sudo apt-get install -y bind9-dnsutils`) and run the command again. On a network that filters DNS, compare the key above, then add `-s -- --skip-dns-check`. |
| `is not the one published in DNS` | Nothing was run. Contact support. |
| `signature check failed: nothing was run` | Run the command again. If it fails twice, contact support. |
| `MISSING  Linux 6.12 or newer` | Run the fix the line shows, reboot, then run the command again. |
| `The code expired` | Run the command again: what is installed stays, and a new code appears. |
| `This code is not valid or has expired` in the console | Check the code on the machine's screen. After 10 minutes, run the command again for a new code. |
| `Pairing was declined in the console` | Run the command again when you are ready to approve it. |
| `is older than the newest release installed` | Nothing was changed. Run `--update` again later. If it repeats, contact support. |
| A service is `MISSING` | `journalctl -u <service> -n 20` shows why. Run the command again once fixed. |
