Skip to content
TraceMote
Fails closedNo backend, no connection — and a way back in

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.

Your own deploymentMonthly, no lock-inAGPL-3.0, source published
console.acme.io/devices
Filter by id, hostname or owner…
Owner: anyStatus: any
DeviceStatus
mac-studio-01
482 913 604
online
ws-lab-04
771 204 338
online
kiosk-lobby-a
336 118 905
online
srv-bench-02
905 442 170
blocked
thinkpad-t14
128 660 741
offline
Live sessions
1 active
dana@acme.iomac-studio-01direct p2p04:12

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 patches
The gap

Vanilla 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.

~3 s
to end a live session
from the console, direct or relayed
13
per-connection permissions
set per grant, enforced on device
100%
of decisions logged
including the ones that said no
0
third parties in your sessions
your deployment, your keys
What you get

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
How it works

What happens when somebody clicks connect

Authorization happens once, during the introduction — before the two devices have said a word to each other.

Controller
The person connecting
PunchHoleRequest { id, token }
hbbs
Rendezvous — the only enforcement point
licence key · peer exists · online
Auth API
Your backend, your database
{ allow, reason, permissions }
Controlled device
Introduced only on an allow
PunchHole + permissions + audit ref

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.

01

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.

02

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.

03

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.

04

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.

05

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.

one session, in the log
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@northwind

One 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 out
Admin console

Everything 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.

Devices
  • mac-studio-01
    482 913 604 · dana@acme.io
    online
  • kiosk-lobby-a
    336 118 905 · field-ops
    online
  • srv-bench-02
    905 442 170 · unassigned
    blocked
The difference

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 connectAnyone holding a nine-digit device ID and the server keyA signed-in user who holds a grant for that device
IdentityNone. The server has no concept of a userAccounts, roles, sessions, and an owner on every device
Access controlA password on the device itselfGrants with expiry and thirteen per-connection permissions
Relay signallingForwarded to the named peer with nothing checkedAuthorized in its own right, as a first-class path
AuditNothing server-side ties a session to a personEvery decision and connection, correlated by one reference
RevocationChange the device password and hopeRevoke blocks the next connection and ends the live one
Backend outageNot applicable — there is no backendFail closed, with a signed, device-scoped break-glass path
Preconfigured installerGated: the config must be signed by upstream's keySigned with your key, produced by your release pipeline
Where it runsYour serversYour servers — same ports, same protocol, same performance
Who it is for

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.

Self-hosted

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.

quickstart
# 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.com
Pricing

Managed 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

$49/mo

3 technicians · 50 devices · 250 GB / mo relay traffic

Team

$129/mo

10 technicians · 250 devices · 1 TB / mo relay traffic

Business

$299/mo

25 technicians · 1,000 devices · 3 TB / mo relay traffic

Questions

The ones people actually ask

Get started

Put a door on your remote access

Download a client, or read how the authorization path actually works before you trust it with anything.