Subshell Docs
Nodes

Add a node

Mint a setup key on the control plane, run the install command on the target machine, and bring the node row online.

Add a machine as a node: mint a setup key on the control plane, run the install command it renders on the target machine, and watch the row come online.

Before you start

  • A signed-in account on the control plane. By default anyone signed in can add their own machines; an admin can narrow minting to admins only.
  • A machine to enroll that can reach one of the server's addresses.

Mint a setup key

  1. Open the Nodes page and press Add node.
  2. Press Generate setup key.

The mint asks for nothing, not even a name. Earlier versions opened with a "Node name" field, but that text only ever labeled the key: the one-liner named the machine from its own hostname whatever you had typed, so the question moved to the machine itself. After you press Generate setup key, the dialog renders a copy-ready install command with the key baked in.

A setup key is an nsk_… code. It is single-use, it expires 24 hours after it is created, and it is revocable by deleting it. An admin can see and revoke every key on the instance: the Setup keys card has a switch that lists all accounts' keys, each row names its creator, and the same Revoke button closes a foreign row. For everyone else, deleting stays the creator's act: the delete answers "not found" for every row the caller did not mint.

A setup key is not shown only once. The Setup keys list on the same page keeps every key you minted readable in full, with a copy button, until it is used, expires, or is revoked, so closing the dialog mid-copy costs nothing. Listing keys has a cost: the server stores them in plaintext. The exposure is bounded by what the credential is. It enrolls exactly one machine, works once, and is inert after 24 hours or the moment you delete it. The list is also scoped: you see the keys you minted, not anyone else's, unless you are an admin and ask for the whole instance. Minting and revoking are audited by key id, and the key text never reaches the audit trail.

Who may mint a key is an instance setting. By default anyone signed in can add their own machines, and the switch on the Settings page narrows it to admins only. Turning it off means "stop handing out new keys": keys already minted stay usable until they expire or are deleted.

Run the command on the target machine

The dialog renders something like:

curl -fsSL "http://your-server:3080/install.sh?setup_key=<your-key>" | bash

On the target machine this:

  1. Checks for tmux and warns if it is missing, with the install command for the platform. A node without tmux can run no subshell at all. The install itself continues; enrollment is what refuses.
  2. Downloads the node binary for your platform (linux-x64, linux-arm64, darwin-arm64, or darwin-x64 for Intel Macs) from that same server, to ~/.local/bin/subshell.
  3. Verifies the published .sha256 digest of the download before the file is made executable, and replaces nothing until the digest matches. A corrupt or partial download leaves any existing install untouched.
  4. Runs subshell setup, which asks what to call the machine, enrols it, and offers the background service, as the next section describes.

If the server has no binary for your platform, it usually downloads one from the project's own public release on first request and serves it to you. When that is impossible (an air-gapped instance), the command says so rather than failing obscurely, and names the fallback: install the node binary another way and run subshell setup by hand.

The server address is baked into the command

The row you pick in the dialog's Select Subshell server address dropdown is the address the node will dial forever. Choose an address the new machine can actually reach, usually your VPN or tailnet address, before copying: the choice rides along in the command (a server= argument the server accepts only for addresses it already trusts) and is baked into the script when the machine downloads it. A remote machine pointed at localhost enrolls, then dials itself and stays offline. If the instance knows no other address, the dropdown has only that one row, so set the base URL first. See Networking and addresses.

What subshell setup does

The one-liner ends at a single CLI verb, and the same verb is the whole path on a machine that already has the binary:

subshell setup --server http://your-server:3080 --key <your-key>

It checks for tmux first, before it asks you anything and before your single-use key is spent. A machine that could host no pane therefore costs you neither a key nor an answer.

It then asks "Name this node", and this is where a node gets its name. The answer is prefilled with the machine's hostname, so Enter accepts what the machine calls itself, and typing replaces it. The hostname is a prompt default, never an assumed answer. If you cancel the name question, nothing is enrolled and your single-use key is still unspent. --name <n> answers the name question ahead of time, and anything that cannot ask must bring it: setup requires --name under --yes, under --json, or when there is no terminal to prompt. A piped one-liner takes no arguments, so its spelling is an environment variable on the bash side of the pipe:

curl -fsSL "http://your-server:3080/install.sh?setup_key=<your-key>" | SUBSHELL_NODE_NAME="mac mini" bash

After the name, setup generates an identity keypair and a link-encryption keypair on that machine, enrols with the control plane, and writes its config 0600. The node's long-lived key is stored only on that machine and is never echoed, not even with --json. From its first connect, every byte the machine and the plane exchange rides a link both ends encrypt. The node's traffic is not readable off the network just because this server runs on plain http://.

Finally it asks: "Run the agent in the background and start it at login?" If you answer yes, it installs a systemd user unit on Linux or a launchd agent on macOS. --no-service (or SUBSHELL_NO_SERVICE=1 for the piped install) skips the question, and subshell service install does the same thing later.

On Linux, a user service dies at logout unless the user has lingering enabled. When lingering is off, or logind never answers, the install prints the command that fixes it: loginctl enable-linger $USER. Running that command may need an administrator's rights.

The node is online

The node appears in the list. Opening its page (or pressing Re-check) has the control plane probe it for the agent CLIs this instance offers; a node is only ever offered the harnesses actually installed on it. You can then launch subshells there as on any other machine. Two fleet decisions remain, and we recommend making both deliberately: who may launch on it, and whether to restrict its directories.

If it does not come online

  • subshell: the setup key was rejected: invalid, expired, or already used.: the key is bad, spent, or too old. Mint a fresh one and rerun the command. Nothing was consumed on the machine's side except the download.
  • The node runs but the row stays offline: this is almost always the baked loopback URL, or the machine cannot reach the address. Run subshell status --probe on the node: it dials the stored address and names it.
  • A node started by hand dies when you close the SSH session: that is subshell run, the foreground daemon. Install the background service, as the setup section describes.

Other pages

Edit on GitHub

Last updated on

On this page