# Onboarding

NTerminal uses one interactive command for both the main server and secondary servers.

```bash
npm install -g nterminal
nterminal onboarding
```

NTerminal stores `.env`, state, pid, and log files under `~/.nterminal`. Install with a user-writable npm global prefix so in-app updates can run `npm install -g nterminal@latest --prefer-online` without sudo.

Run `nterminal onboarding` as the account that should own and run NTerminal. Do not prefix the command with `sudo`; that writes runtime files under the wrong home directory. If a VPS is intentionally operated as the real `root` account, running `nterminal onboarding` from that root login is supported and stores runtime files under `/root/.nterminal`.

## Main Server

Run onboarding on the machine that should serve the browser UI:

```bash
nterminal onboarding
```

Choose `main`.

The main setup flow:

1. Picks a bind address and port. The default main bind is `127.0.0.1`, so public traffic goes through the configured reverse proxy instead of bypassing TLS.
2. Requires a public `https://<domain>` URL for the proxy setup path. Raw IPs, `http://`, `localhost`, and `.local` URLs are rejected in that path.
3. Writes `.env`, including a generated `NTERMINAL_SESSION_SECRET` and absolute `NTERMINAL_STATE_PATH`.
4. Sets the login password and enables TOTP headlessly. The CLI prints a terminal QR code, base32 secret, and `otpauth://` URI, then verifies the 6-digit code.
5. Optionally starts the installed package with `nterminal deploy`.
6. Optionally provisions nginx, DNS verification, firewall rules, and Let's Encrypt TLS.

The final summary prints the public URL, internal bind, and next steps.

## Secondary Server

Run onboarding on each additional machine that should appear in the main UI:

```bash
nterminal onboarding
```

Choose `secondary`.

The secondary setup flow:

1. Binds to `0.0.0.0` and picks a free port, preferring `3107`.
2. Suggests the URL the main server should use to reach this machine. If the local interface is private and a public IP can be detected, that public IP is offered as the default.
3. Asks for a display name.
4. Generates a session secret and `NTERMINAL_AGENT_TOKEN`, then writes `.env` with an absolute state path.
5. Prompts for the main server URL, password, and authenticator code.
6. Registers this secondary server with the main server automatically.
7. Optionally starts the installed package.

Onboard the main server first. The main must already have password and TOTP configured before a secondary server can register itself.

The detected public IP is only a convenience default. NAT gateways, load balancers, Cloudflare tunnels, VPN/private networks, and cloud security groups can make that address wrong or unreachable, so override it with the URL/IP the main can actually reach when needed.

Logging into the main server from the secondary CLI counts as a login, so the single-active-session policy may revoke an open browser session. Log in again in the browser afterward.

## Proxy Setup

When main onboarding configures a public URL, it verifies and provisions:

- public IP detection through `1.1.1.1`
- DNS A record match
- nginx installation when missing
- nginx site config
- nginx reload and local proxy verification
- `ufw` or `firewalld` rules for HTTP/HTTPS
- `certbot --nginx` certificate issuance
- real HTTPS verification against the final domain

Privileged work uses one of two modes:

- **auto-sudo**: if `sudo -n true` works, onboarding runs the needed commands directly with sudo.
- **manual**: onboarding prints the exact command, explains it, waits, and re-verifies before continuing.

The "Main is ready" summary is printed only after the selected setup path has completed its checks.

## Re-Running Onboarding

You can re-run onboarding to refresh generated config or register a secondary server again.

Existing `NTERMINAL_PORT`, `NTERMINAL_SESSION_SECRET`, and `NTERMINAL_AGENT_TOKEN` values are preserved on re-run. Main onboarding always forces `NTERMINAL_HOST=127.0.0.1` so public traffic goes through nginx/TLS; secondary onboarding preserves its existing bind host.

Registering the same secondary server URL again replaces the previous entry for that URL.
