---
title: "Create a Pairing Code"
url: "https://control.actana.ai/docs/pairing/create-a-pairing-code"
description: "actana pair new and its framed handout, the code's rules, and the lifecycle: list, revoke one client, rotate the CA."
updated: 2026-09-01T09:03:05+00:00
---

You are on the Core. `actana pair new` mints a one-time code for **one** client and prints everything that client needs.

```bash
actana pair new --label laptop
# compose:
docker compose exec core actana pair new
```

## The handout

Since 0.4.3, at a terminal the command answers with a framed **handout** — the code in bold, the expiry, the full CA fingerprint (wrapped, never truncated), the session id, and your label — followed by what to do with it:

```text
┌────────────────────────────────────────────────────────────────────────┐
│                                                                        │
│   Pairing code                                                         │
│                                                                        │
│      XXXX-XXXX                                                         │
│                                                                        │
│   Expires        2026-09-01 14:05 (in 5 minutes)                       │
│                                                                        │
│   CA fingerprint                                                       │
│      AA:BB:CC:DD:EE:FF:00:11:22:33:44:55:66:77:88:99:AA:BB:CC:DD:      │
│      EE:FF:00:11:22:33:44:55:66:77:88:99                               │
│                                                                        │
│   Session        3f2a9c1e-…                                            │
│   Label          laptop                                                │
│                                                                        │
└────────────────────────────────────────────────────────────────────────┘

From the Panel
  Settings (gear icon) -> Cores -> Add a Core: this Core's address, then
  compare the CA fingerprint, then the session and the code

From a terminal
  npm i -g @actana/cli

  # dial 192.168.1.50:8443 — and that is the endpoint this code registers
  actana core pair laptop 192.168.1.50:8443 XXXX-XXXX --session 3f2a9c1e-… --fingerprint AA:BB:…
```

The **From a terminal** block prints one pasteable [`actana core pair`](/docs/pairing/cli-pairing) command per address in the Core's `ACTANA_PUBLIC_HOST` list, with every minted value already in it. The name slot is your `--label` when the client's registry would accept it, and a literal `NAME` placeholder otherwise — swap it for what the client machine should call this Core. Each command's comment says which endpoint the **credential** will register, because that comes from the code, not from the address dialled: a code minted with `--public-host <addr>` registers that address; without it, the Core's primary. `--public-host` selects from the configured list and can never extend it.

**Down a pipe the output is the plain labelled lines** (`Pairing code`, `CA fingerprint`, `Expires`, `Session`, `Label`), byte-identical to what earlier releases printed — they are a screen-scraping contract, and there is deliberately no `--json` for this command. `NO_COLOR` is honoured at a terminal.

## What the code is

Eight characters from `ABCDEFGHJKMNPQRSTUVWXYZ23456789`, grouped `XXXX-XXXX`. The alphabet drops `0`, `O`, `1`, `I`, and `L` so a code survives being spoken. Hyphen and case do not matter when the client types it; out-of-alphabet characters do — they are not folded into a neighbour.

The code is printed once and never stored. The Core keeps only a keyed digest, so nothing — including `actana pair ls` — can print it again. A lost code is re-minted, not recovered.

| Rule | Default |
| --- | --- |
| TTL | 5 minutes (`--ttl 30s`, `5m`, or `2h`; a unit is required; ceiling 24 hours) |
| Wrong guesses | 5, then the session is dead |
| Use | Single. Nothing accepts it twice. |
| Session id | Travels with the code. The Core will not search for a session a code might fit. |

`--ttl` without a unit is refused: a bare `5` would be seconds or minutes depending on a guess, and neither failure announces itself. `--label` is a flag, not a positional — `actana pair new laptop` is a usage error, not an unnamed code you later cannot revoke.

The code is not a credential. It authorises exactly one certificate issuance; after expiry, the attempt cap, or a successful redeem it is worthless. The [private key](/docs/pairing/how-pairing-works) is generated on the client; this command never prints one.

## Setup first

Pairing signs against this Core's CA. If there is no material yet:

```text
actana pair new: this Core has no pairing material at ...
Run `actana setup` — pairing needs a CA to sign against.
```

Inside a container the same command works through the image's `actana`: `docker compose exec core actana pair new`.

## List

```bash
actana pair ls
```

Pending codes (still redeemable) and paired clients: labels, session ids, certificate serials, status. `--json` for scripts. The pairing code itself is not in this list — the Core never stored it.

## Revoke one

```bash
actana pair revoke <serial|session|label>
```

A serial matches on a prefix. A label matches in full, so `laptop` does not steal `laptop-2`. If the target matches more than one row, the command refuses rather than guessing — name the serial or the session id.

Pointed at a **paired** client it unpairs that machine: the certificate and the bearer stop working, including any core-link already open. Pointed at a **pending** code it cancels the code before anyone spends it. A session already redeemed is not a pending code; revoke the client instead.

## Rotate the CA

```bash
actana token regenerate
```

Fresh material: new CA, new certs, new bearer secret, new core id. **Every credential this Core ever issued stops working.** On metal the daemon restarts as part of the command; in a container, restart it yourself (`docker compose restart`) before you treat the old identity as gone.

Then pair every client again: `actana pair new` here, spend the code there.

**Panel:** remove the Core first (Settings → Cores → Remove Core). Rotation does not move the endpoint, so [Add a Core](/docs/pairing/panel-pairing) refuses an address it already holds — and refuses **before** spending the code. Forget that step and you mint a code you then cannot use.

**CLI:** [`actana core pair`](/docs/pairing/cli-pairing) replaces the stored credential in place. No extra remove.

`pair revoke` is the narrower tool when one laptop should lose access and the rest should not.

## See also

- [How Pairing Works](/docs/pairing/how-pairing-works)
- [Actana CLI Pairing](/docs/pairing/cli-pairing)
- [Panel Pairing](/docs/pairing/panel-pairing)
- [Pairing Troubleshooting](/docs/pairing/troubleshooting)
