Devices
A device (or machine) is a Mac or Windows PC that runs rd-agent and shows up in the
portal. This page explains how the gateway recognises a device, and walks through adding,
renaming, rotating and removing one.
How it works
Section titled “How it works”Every device has a machine id, for example mbp or studio. The id is 1–64 characters
of [A-Za-z0-9_-] (no dots, no slashes). It appears in the portal URL (/m/<machine>) and in
the token, so pick something short and stable.
Each device has its own token:
rd1.<machine>.<secret>The agent sends it as Authorization: Bearer … when it dials out. The gateway never stores
the token itself, only its SHA-256, in one of two places:
- Added in the portal (Add device, the usual way): the gateway creates the token, keeps
its hash in
RD_STATE_DIR/devices.jsonand shows the token once, inside a setup code that you paste intord-agent setupon the device. - Provisioned: you create the token yourself and put its hash in a file named after the
machine in
RD_AGENT_TOKENS_DIR(default/etc/rd/agents), for example from a Kubernetes secret. See Provisioned tokens.
A machine id belongs to one of the two: the portal refuses to add an id that has a token file.
When an agent connects, the gateway:
- reads the machine id from the token,
- hashes the token and compares it with the device’s hash (
devices.json, else the token file), - checks that the agent’s
registermessage names the same machine (otherwise close 4002).
Both are read again on every connection attempt, so adding, rotating or removing a device needs no gateway restart.
A device appears in the portal in one of these ways:
| Shown while offline | Friendly name | Recovery links | Needs restart | |
|---|---|---|---|---|
| Added in the portal | ✅ always | ✅ the name you gave it | no | no |
Listed in RD_MACHINES_FILE |
✅ always | ✅ | ✅ | yes, the file is read at start-up |
| Neither (a provisioned token only) | only after it has connected once since the gateway started | no, the id is shown | no | no |
A device added in the portal can also be listed in the machines file, for its recovery links; the file’s name then wins.
Add a device
Section titled “Add a device”1. Add it in the portal
Section titled “1. Add it in the portal”Open the portal (for example https://rd.example.com) and click Add device. Give the
device a name, for example Mac Studio. The machine id follows the name (mac-studio); change
it before you click Add if you want a shorter one, because it cannot change later.
The portal then shows the device’s setup code, a single line starting with rds1_. It holds
the gateway URL agents connect to and the device’s token. It is shown only once and works
like a password: copy it and keep it until step 3, but don’t store it anywhere else. Lost it?
Click New token in the device’s details (click its name in the portal) for a new one.
Add device is missing when the gateway has no RD_STATE_DIR or no RD_AGENT_PUBLIC_URL
(see Gateway).
2. Install the agent on the device
Section titled “2. Install the agent on the device”At the device itself, follow Mac agent (signing identity, build, install) or Windows agent (the installer).
3. Run setup with the code
Section titled “3. Run setup with the code”rd-agent setup starts by asking for the setup code: paste it and press Enter. Setup reads the
gateway URL, machine id and token from it, writes the config file and installs the login
service. On Windows the installer’s last page runs setup for you; the rd agent setup shortcut
runs it again later.
"/Applications/RD Agent.app/Contents/MacOS/rd-agent" setup # Mac& "$env:LOCALAPPDATA\Programs\rd-agent\rd-agent.exe" setup # WindowsWithout a code (press Enter at the prompt, or pass --gateway / --machine), setup asks for
the gateway URL (the agent host, for example wss://rd-agent.example.com, not the portal
URL), the machine id and the token one by one. The portal shows these three under Set
up without the code.
4. Check
Section titled “4. Check”"/Applications/RD Agent.app/Contents/MacOS/rd-agent" status(rd-agent.exe status on Windows.) status reports whether the gateway accepts the token.
The device should now be online in the portal, and the gateway logs agent registered with
machine=mac-studio.
Rotate a token
Section titled “Rotate a token”Click New token in the device’s details (click its name in the portal). The old token stops working at once: a connected agent
is disconnected (close 4002) and stays offline. Run rd-agent setup on the device again with
the new setup code.
Rename a device
Section titled “Rename a device”The machine id is part of the token, so a rename is a new device: add the device again with the
new id, run setup with its code, then remove the old one.
Remove a device
Section titled “Remove a device”- Click Remove device in the device’s details. Its token stops working, a connected agent is disconnected and the device leaves the portal.
- On the device:
packaging/macos/uninstall.sh --purgeon a Mac; on Windows uninstall rd agent under Settings → Apps (Windows agent).
The portal logs every change in the audit log (target: audit) as device_add,
device_token or device_remove, with the user, IP and machine id.
Provisioned tokens
Section titled “Provisioned tokens”For devices whose token you manage outside the gateway, for example in a password manager that syncs into a Kubernetes secret. The portal shows these devices without New token and Remove device.
-
Choose a machine id, for example
studio. It must be unique on the gateway. -
Create the token, on any machine with a checkout of this repo:
Terminal window tools/new-agent-token.sh studioIt prints the token (only for the agent, in step 4; don’t store it in the cluster or in git) and its sha256 (for the gateway, in step 3). Without the script:
Terminal window TOKEN="rd1.studio.$(openssl rand -hex 32)"printf '%s' "$TOKEN" | shasum -a 256 | cut -d' ' -f1 -
Put the hash in a file named after the machine in
RD_AGENT_TOKENS_DIR:- Kubernetes (our setup): add a field
studiowith the hash to the 1Password itemrd-agent-tokens(vaultk3s-vault). The ExternalSecret mounts every field as/etc/rd/agents/<field>. Wait for it to sync (or force a refresh of the ExternalSecret). - Elsewhere: write the file directly, for example
printf '%s\n' <sha256> > /etc/rd/agents/studio.
Optionally add the device to
RD_MACHINES_FILE, so it has a name and stays visible while offline (restart the gateway after changing the file; start-up fails on an invalid or duplicate id):[{ "machine": "mbp", "name": "MacBook Pro" },{ "machine": "studio", "name": "Mac Studio", "recovery": [{ "label": "Screen Sharing", "url": "https://guac.example.com/#/client/…" }] }] - Kubernetes (our setup): add a field
-
Run
rd-agent setupon the device, press Enter at the setup code prompt and enter the gateway URL,studioand the token. Setup can also take the first two as flags:Terminal window "/Applications/RD Agent.app/Contents/MacOS/rd-agent" setup \--gateway wss://rd-agent.example.com --machine studio
Rotate: create a new token and hash, replace the hash, and run setup again with the new
token. The old token stops working on its next connection attempt; a control socket that is
already connected stays up until it reconnects, so restart the agent to apply the change right
away (launchctl kickstart -k gui/$(id -u)/dev.thijmen.rd.agent on a Mac,
rd-agent.exe install on Windows).
Remove: delete /etc/rd/agents/<machine> (or the 1Password field), and the entry in
RD_MACHINES_FILE if there is one, then restart the gateway. Without a restart, a device that
connected earlier stays in the portal list as offline.
Troubleshooting
Section titled “Troubleshooting”Failed agent connections are logged as agent auth failed with a reason:
| Reason / close code | Cause | Fix |
|---|---|---|
unknown machine |
no device and no /etc/rd/agents/<machine> file |
add the device; for a provisioned token, has the secret synced? |
token mismatch |
the token is not the device’s current one (replaced in the portal, or a wrong hash) | run setup with the current setup code or token |
malformed token |
the token is not rd1.<machine>.<secret> |
run setup again |
corrupt token file |
the file is not a 64-character hex hash | write only the hash into the file |
| close 4002 | the token was replaced or the device removed in the portal, or the setup machine id differs from the id in the token |
run setup with a new setup code |
| HTTP 429 | more than 5 failed attempts per minute from one IP | fix the cause, then wait about a minute |
Only one agent per machine id can be online. A second agent with the same id replaces the first, which is closed with 4009, so two devices that keep replacing each other means they share an id.
In --dev mode the gateway skips the token check, so any RD_AGENT_TOKEN=rd1.<machine>.dev
works, and Add device keeps devices in memory unless --state-dir is set. See
Mac agent or
Windows agent.