Self-Hosted

Run the whole thing on your own box — the workspace, the database and the relay. Nothing leaves your network unless you allow it.

Your data, your control

Chat, files, projects, tracked hours and work-diary screenshots live in a SQLite file on your server. Take a copy whenever you like; it is one file.

Two small services

A Node.js server (signalling + workspace API + admin panel) and a coturn STUN/TURN relay. Both run comfortably on a 1 vCPU VPS.

Same clients

Point the desktop and Android apps at your server URL — no separate build, no fork, no per-seat call home.

What you are actually hosting

One Node process does four jobs, so there is one thing to keep alive rather than four:

Signalling

Introduces two devices to each other by their 9-digit IDs and gets out of the way. Screens, keystrokes, files and meeting media then travel directly between the peers, encrypted with DTLS-SRTP. The server cannot read them and never stores them.

Workspace API

Accounts, chat, uploads, projects and tasks, meetings, WorkTrack hours, timesheets and invoices. This is the part that is stored — on your disk, so history and search work from any device.

Admin panel

At /admin, behind a token. Workspaces and their plans, accounts, licence keys, installer download counts, and the ability to block a specific machine.

Installer hosting

Drop your builds into the data directory and the server serves and counts them at /download/win, /mac, /linux and /android. No third-party analytics needed to answer “how many downloads?”.

Quick start

On a fresh Ubuntu server with Node.js 18+ installed:

# 1. the server
git clone https://example.com/remotedesk.git
cd remotedesk/server
npm install                       # builds better-sqlite3 for THIS machine
export RD_DATA_DIR=/var/lib/officedesk
export RD_LICENSE_SECRET="$(openssl rand -hex 32)"   # keep this; it signs licence keys
export RD_ADMIN_TOKEN="$(openssl rand -hex 24)"      # unset = /admin stays off
export RD_PUBLIC_URL=https://desk.example.com
node signaling.js                 # listens on :9000

# 2. STUN + TURN relay (coturn)
sudo apt install coturn
sudo nano /etc/turnserver.conf    # realm, static-auth-secret, external-ip
sudo systemctl enable --now coturn

# 3. point the clients at your server
#    Settings -> Server URL
wss://desk.example.com

The database is created and migrated automatically on first start — there is no separate schema step. Upgrading is the same command; pending migrations run at boot.

One thing to get right when you deploy: build node_modules on the server. better-sqlite3 is a native module, so copying a Windows or macOS node_modules to a Linux box gives you a process that exits before it ever listens.

Ports to open

ServicePortProtocol
Signalling + API + admin9000 (443 via proxy)TCP / TLS
STUN & TURN3478TCP + UDP
TURN over TLS5349TCP
TURN relay range49152-65535UDP

Run coturn and you also get your own STUN. The apps do not need a public STUN service, so no address discovery goes to a third party.

Environment

VariableWhat it does
RD_DATA_DIRDatabase, uploads, installers
RD_LICENSE_SECRETSigns licence keys — unset means they die on restart
RD_ADMIN_TOKENUnlocks /admin; unset keeps it off
RD_TURN_SECRETMust match coturn’s static-auth-secret
RD_PUBLIC_URLBase URL used in invite links
RD_WORKSPACE_TRIAL_DAYSWorkspace trial length (default 7)
PORT / HOSTDefault 9000 / 0.0.0.0

Recommended setup

Self-hosting is the deployment we recommend to anyone with a confidentiality obligation to their own clients — and to anyone enabling WorkTrack, since employee monitoring data is far easier to defend when it never left your building.

Ready to get started?

Download Office Remote Desk and connect your first device in under a minute.

⇩ Download Office Remote Desk