Every remote session,tied to a person.
TraceMote is a self-hosted RustDesk fork with a real identity layer. Nobody connects without signing in, nobody reaches a device without a grant, and revoking access ends the session that is already open.
| Device | Owner | Status | Last seen |
|---|---|---|---|
mac-studio-01 482 913 604 | dana@acme.io | online | now |
ws-lab-04 771 204 338 | priya@acme.io | online | 12s |
kiosk-lobby-a 336 118 905 | field-ops | online | 4s |
srv-bench-02 905 442 170 | unassigned | blocked | 3d |
thinkpad-t14 128 660 741 | sam@acme.io | offline | 2h |
Built on RustDesk
The capture pipeline, the codecs, the NAT traversal and the peer-to-peer transport are upstream’s, and we merge from upstream rather than drift away from it. What we added is the part that was never there: an identity layer that can say no.
Our patchesVanilla RustDesk is anonymous by design
That is not a bug — it is what makes it so easy to stand up. It is also why it stops short of anything you would put in front of an auditor.
A nine-digit number is the whole credential
Upstream's rendezvous server asks two questions: does this ID exist, and did it register recently. Anyone holding the ID and your server key can ask to be introduced to it.
Nothing ties a session to a person
There is no user to log. When somebody asks who connected to the finance machine on Tuesday, the honest answer from a stock deployment is that the server does not know.
Revoking access means changing a password
And telling everyone else the new one. Meanwhile the session that is open stays open, because nothing in the system can reach in and close it.
An identity layer, not a login screen
Every one of these is enforced on the server side, in the path a connection actually takes. None of it is a setting the client can decline.
Sign-in before anything
A device cannot register, and a client cannot start a connection, until somebody is signed in.
- Gate on the service process, not just the window
- Both outbound entry points guarded, not only the obvious one
- Off by default — the unmodified path still exists, and still runs
- Signed-out clients are told why, in words a user can act on
Grants, per user, per device
Access is a grant with an owner, an expiry, and a list of what is allowed once connected.
- Optional expiry, enforced server-side
- Thirteen per-connection permissions, set per grant
- Limits ride the existing protocol field — no client patch
Revoke ends the session
Revoking access does not wait for the session to finish. It closes it, inside about three seconds.
- ~3 s ceiling: the heartbeat runs every 3 s while a session is live
- Works on direct P2P sessions, which never touch the relay at all
- The user sees 'Closed manually by web console'
A session log that can be read
Every authorization decision and every connection, correlated by an id minted at the moment of the decision.
- Who connected to what, when, and from which address
- File-transfer events on the same session record
- Filter by user, device, or date; drill into one session
Live sessions, and a way to end them
See what is connected right now. Close any of it from the browser.
- Owner, target device, duration, transport
- Force-disconnect without revoking the grant
- Same code path as revoke — one mechanism to trust
Fail closed, with a way back in
If the permission API is unreachable, the answer is no — and there is still a documented way onto the box you would fix it from.
- No silent bypass for ordinary users, ever
- Break-glass is signed and scoped to one device, with an expiry
- Its audit record is written locally first — the backend is down, after all
Both chokepoints, not the obvious one
The relay request is authorized in its own right. Gating only the punch-hole path would have been decoration.
- Punch-hole and relay signalling both authorized
- One connection, one decision — the client retries three times
- Refusals that were going to fail anyway cost zero API calls
Your build, your defaults
Server, relay, key, API and the login requirement, baked into the installer you hand out.
- Rendezvous, relay, API and key preconfigured
- require-login on from the first launch
- Your own signing key — the trust anchor is a build input
What happens when somebody clicks connect
Authorization happens once, during the introduction — before the two devices have said a word to each other.
Allow. The two peers are introduced, the grant’s permission set travels with the introduction, and an audit reference ties every later event to this one session.
Deny. No introduction happens, and the reason is shown to the person verbatim — “Please sign in to connect to this device.” — rather than a timeout they will file a ticket about.
Hand out a branded client
The installer already knows your rendezvous server, your relay, your API and your key — and that login is required.
The configuration is signed with your key at release time and verified by the client at startup, so a bundle that has been tampered with is discarded rather than trusted.
A person signs in
The client's account UI is upstream's; the backend answering it is yours. A token lands on the device and travels with every connection it makes.
The rendezvous connection is encrypted before the token crosses it — the server offers its signed key exchange unprompted, which upstream's own server never does.
The device registers to an owner
Registration is tied to an account. A device nobody owns is told so with a code the client already understands.
Registration deliberately does not fail closed: if it did, a backend outage would take every device offline at once and leave the emergency path nothing to reach.
A connection is authorized, or it is not
Before the two peers are introduced, the rendezvous server asks your API: this user, this device, this kind of connection — yes or no?
A no is returned as a sentence the user sees verbatim. A yes carries a permission set and an audit reference to the controlled device, in fields the protocol already has.
The session is logged — and can be ended
Connection and file-transfer events land against one session record. The console can close that session, or revoke the grant behind it.
Termination rides the heartbeat the controlled device already sends, so it reaches direct peer-to-peer sessions that never touch the relay.
session c2f1a9e4
user maria@northwind.example
device 771204338 · reception-pc
from 203.0.113.44 · Windows
opened 14:02:11 closed 14:19:48 (17m 37s)
decision allowed · grant expires 2026-10-01
limits clipboard off · file transfer off
files 2 sent, 0 received
ended closed from the console by admin@northwindOne decision, one record. The same reference follows the session from the moment it is authorized through to the file transfers and the disconnect — which is what makes “who reached that machine on Tuesday” a question with an answer.
The whole path, drawn outEverything an operator needs, in a browser
Users, devices, grants, the session log, what is live right now, and the emergency path — with no database client anywhere near it.
Every device, with an owner
Online state, owner, last seen, version and hostname. Reassign an owner, or block a device outright — a blocked device is refused at registration with a code its own client already understands.
Registration is deliberately the one path that does not fail closed.
- onlinemac-studio-01482 913 604 · dana@acme.io
- onlinekiosk-lobby-a336 118 905 · field-ops
- blockedsrv-bench-02905 442 170 · unassigned
Same protocol. Different answer to “who are you”.
Everything on the left is upstream working exactly as intended. Everything on the right is what we added on top of it.
| Self-hosted RustDesk (upstream) | TraceMote | |
|---|---|---|
| Who can connect | Anyone holding a nine-digit device ID and the server key | A signed-in user who holds a grant for that device |
| Identity | None. The server has no concept of a user | Accounts, roles, sessions, and an owner on every device |
| Access control | A password on the device itself | Grants with expiry and thirteen per-connection permissions |
| Relay signalling | Forwarded to the named peer with nothing checked | Authorized in its own right, as a first-class path |
| Audit | Nothing server-side ties a session to a person | Every decision and connection, correlated by one reference |
| Revocation | Change the device password and hope | Revoke blocks the next connection and ends the live one |
| Backend outage | Not applicable — there is no backend | Fail closed, with a signed, device-scoped break-glass path |
| Preconfigured installer | Gated: the config must be signed by upstream's key | Signed with your key, produced by your release pipeline |
| Where it runs | Your servers | Your servers — same ports, same protocol, same performance |
Teams that have to answer for the access they hand out
Internal IT and helpdesk
Technicians reach the machines they are assigned to, and only those. Every session is attributable to a person without asking anybody to keep a spreadsheet.
Managed service providers
One deployment, many customers, grants that expire when an engagement does. A departing engineer loses access the moment their account does — including the session they are in.
Regulated environments
Who connected to what, when, for how long, and what moved — on your own infrastructure, with no third-party cloud in the path and no vendor holding your keys.
Field and unattended devices
Kiosks, signage, lab equipment and vehicles enrol with a token, register to an owner, and answer only to grants — even when nobody is standing in front of them.
Your servers. Your keys. Your logs.
No shared cloud sits in the middle of your sessions. You run the rendezvous server, the relay, the API and the console — or we run that same stack as a deployment that is still yours alone.
# one host: rendezvous, relay, API, console
docker compose up -d
# hbbs :21116 rendezvous, tcp + udp
# hbbr :21117 relay fallback
# api :21114 the client's API and the console's backend
# web the console, behind your TLS terminator
# seed the first administrator, then sign in
docker compose exec api node dist/scripts/seed-admin.js \
--email you@example.comManaged from $49 a month, or run it yourself for nothing
Every plan is one isolated deployment that belongs to you. The software is AGPL-3.0 either way — what a plan buys is somebody else operating it.
Starter
3 technicians · 50 devices · 250 GB / mo relay traffic
Team
10 technicians · 250 devices · 1 TB / mo relay traffic
Business
25 technicians · 1,000 devices · 3 TB / mo relay traffic
The ones people actually ask
Put a door on your remote access
Download a client, or read how the authorization path actually works before you trust it with anything.