NetDesk — your own self-hosted remote desktop
Website & live demo: netdesk.space · Download: Windows agent · Pricing: free to self-host
A TeamViewer/RustDesk-style remote desktop system you fully own: a signaling/relay server for your VPS, a Windows service on your powerful PC (reachable at boot, at the logon screen, and across UAC prompts), and a zero-install web viewer (Chrome/Edge) you can use from any laptop or phone while traveling.
┌──────────────────────────┐ WSS outbound only ┌──────────┐ WSS ┌──────────────┐
│ HOME PC (Windows service)│ ──────────────────► │ VPS │ ◄────── │ TRAVEL laptop│
│ broker (SYSTEM, boot) │ │ netdesk │ │ any browser │
│ └─ desktop agent │ ◄──── relayed ────► │ server │ │ (phone works)│
│ (console session) │ E2E-encrypted └──────────┘ └──────────────┘
└──────────────────────────┘
│
└──── optional direct mode: ws://home-ip:8901 (LAN / port-forward) ────┘
Features
Access & unattended operation
- Boot-time Windows service (SYSTEM): no auto-logon needed, survives reboots
- Reachable at the Windows logon screen — view and type credentials to log in
- Input works across desktop switches (user desktop, logon screen, UAC prompts) via desktop-following injection
- Auto-reconnect to server forever (works behind any NAT, no port forwarding)
- Wake displays automatically when a viewer connects
Video / audio
- H.264 (x264 ultrafast/zerolatency), up to 1080p60 @ 20 Mbps, idle screens send nothing
- Hardware decode in the browser (WebCodecs) + HTML5 canvas
- Adaptive Auto quality mode (RTT/decoder-queue based preset stepping)
- System audio (WASAPI loopback → Opus) — bundled in the packaged exe;
pip install PyAudioWPatchfor source runs
Full control
- Mouse (all buttons, wheel), keyboard via SendInput scancodes, keyboard-lock for Alt+Tab/Win/Ctrl+W in fullscreen
- Privacy mode — turn the physical monitor off while you keep working
- Lock PC on disconnect (per-viewer checkbox)
- Process manager — list & kill remote processes
- Remote power — lock, sign out, reboot, shut down, run command
- Clipboard sync (two-way), chat
Files
- Browse/download/upload/rename/delete/mkdir, folder upload with drag & drop
- Atomic uploads (.part → final), folder creation on demand
Security
- End-to-end encryption (default): ephemeral ECDH P-256 → AES-256-GCM per frame — the VPS cannot see your screen
- Password never leaves the host un-hashed (PBKDF2 200k challenge/response, 0.4 s throttle per bad attempt)
- Optional TOTP 2FA (
--set-totp auto→ authenticator code required at connect) - Optional server registration key so only your hosts can register;
/statusAPI behind a token - The service broker relays opaque bytes only — agents hold all keys
Accounts (RustDesk-style)
- Sign up / sign in in the desktop app and on the website — no email verification wall (the account works immediately; the email only confirms it)
- My computers: every PC where you sign in with your account is listed on the website for one-click connect (online/offline/in-session status shown)
- Server address is pre-filled (netdesk.space) and no registration key is needed by default; point the app at your own server anytime
- Pre-configured builds: name the exe
NetDeskHost-host=your.server,key=SECRET.exeand it auto-configures — hand it out with zero setup
Viewer niceties
- Address book (saved connections), remember-password, view-only mode
- Session recording to .webm (one click)
- TCP tunneling — reach any TCP service on the host (SSH, RDP, web UIs) through the server; portal-gated, with a panel in the viewer
- Installable app (PWA) — install the viewer like a native app from Chrome/Edge/Safari on laptop or phone
- Host-side remote printing — send a file to the host's printer from the file manager
- Multi-monitor switching, quality presets, live stats (fps/RTT/bitrate/E2E badge)
Quick start (try on one PC)
cd path\to\netdesk
scripts\run_local_demo.bat
First run prints and saves a 9-digit ID and a random password
(%APPDATA%\NetDesk\config.json). Automated end-to-end test:
.venv\Scripts\python tools\smoke_test.py (23 checks: auth, 2FA, E2E video,
clipboard, processes, privacy, files, input, broker path…).
Portable exe — a regular desktop app, no Python needed
portable\ (and ..\NetDesk-portable-win64.zip) ships standalone Windows x64
binaries built with PyInstaller, tested end-to-end (full 20-check suite
passes against the packaged exes):
| File | Purpose |
|---|---|
NetDeskHost.exe (54 MB, windowed) |
the agent desktop app — double-click it: a control panel opens with live status, your ID, server settings, password/2FA management, start/stop, and one-click service install |
NetDeskServer.exe (14 MB, console) |
server for a Windows VPS; serves the viewer and the portal |
Double-clicking NetDeskHost.exe opens the control panel (config + logs are
created next to the exe — the folder is fully portable). Advanced users can
still drive everything from a terminal (--server …, --install,
--set-password, --set-totp auto, --uninstall); the app itself is
windowless, so CLI output goes to host.log next to the exe. --install
sets up the same boot-time SYSTEM service with full logon-screen/UAC access.
macOS (MacBook M4 / Apple Silicon and Intel)
Mac binaries cannot be cross-compiled from Windows, so the repo builds them ON the Mac — native, one command:
git scp the netdesk folder to the Mac, then:
bash scripts/build_mac.sh # -> dist/NetDeskHost + dist/NetDeskServer (arm64)
NetDeskHoston the Mac = control the Mac remotely (capture via mss, input via CoreGraphics CGEvent, clipboard via pbpaste/pbcopy, process manager, power via osascript). First run: grant Screen Recording and Accessibility permissions (System Settings → Privacy & Security); if Gatekeeper complains:xattr -cr NetDeskHost.- Autostart on login:
scripts/deploy/com.netdesk.host.plist→ copy to~/Library/LaunchAgents/(edit the path/server inside first), thenlaunchctl load ~/Library/LaunchAgents/com.netdesk.host.plist. NetDeskServeralso builds on the Mac if you want a Mac VPS.- macOS audio capture needs a loopback device (e.g. BlackHole) — off by default.
- Connecting TO a Mac or PC from the MacBook: just the browser — open the server URL in Chrome/Edge/Safari; nothing to install.
Web management portal
Start the server with --portal-password "YourPortalPassword" and open
https://your-server:8443/portal — a TeamViewer-console-style dashboard:
- Computers list — every host that ever registered, online/offline status,
version, last-seen, and a Connect button that deep-links into the viewer
(
/?id=<id>— ID prefilled, just type the host password) - Live stats — hosts online, sessions total, relayed traffic, uptime
- Activity feed — host online/offline, connect attempts, accepted sessions, wrong-password/2FA failures (auth failures are visible server-side; passwords never are)
- Downloads — anything you drop into the server's
files/folder (e.g.NetDeskHost.exe) is offered to logged-in users, so your travel laptop can always grab the current agent from your own server
Access control: single portal password (cookie session, HttpOnly, 7 days). The portal runs over the same TLS as everything else — keep TLS on for internet use. By design the portal cannot see or store host passwords (end-to-end encryption); connecting always needs the host's own password.
Production setup
1. Server on your VPS (Debian/Ubuntu)
cd netdesk/scripts/deploy && sudo bash deploy_vps.sh # installs systemd service, prints REG_KEY
# add --portal-password "..." to the unit for the web portal at /portal
sudo ufw allow 8443/tcp
TLS (recommended): Let's Encrypt via certbot, then add --cert/--key to the unit
and restart. Quick alternative: --gen-cert (self-signed, accept browser warning once).
2. Host on your powerful PC (twice, then forget it)
:: once, as your user: pick the password and server
.venv\Scripts\python host\netdesk_host.py --set-password "YourStrongPassword"
.venv\Scripts\python host\netdesk_host.py --server wss://desk.yourdomain.com:8443/ws --reg-key REG_KEY --listen 8901
:: once, as Administrator: install the boot-time service
scripts\install_autostart.bat (runs: netdesk_host.py --install)
The installer copies credentials to C:\ProgramData\NetDesk and creates a
SYSTEM scheduled task (ONSTART) running the broker. The broker spawns a
desktop agent into your console session and re-spawns it on user switches.
Optional: --set-totp auto for a 2FA secret (print → add to your authenticator).
Optional: pip install PyAudioWPatch for remote sound.
3. Travel
Open https://desk.yourdomain.com:8443/ — enter ID (+ 2FA code if enabled) and
password. Save it in the address book. Works on phones too. At the office logon
screen after a reboot? Connect and type your Windows password — you're in.
Security model
TLS to the server + end-to-end AES-GCM media + PBKDF2 password proof + optional TOTP + registration key. Single session per host; second viewer gets "host busy". Everything is stateless on the VPS.
Silent operation & what "undetected" means here
Like RustDesk 1.2, NetDesk is invisible on the host while you work:
- The engine is headless — no window, no tray icon, nothing pops up when a session starts. In service mode it runs as a hidden SYSTEM task from boot.
- Privacy mode turns the physical monitor off while you keep working. Enable "Blank the monitor while controlled" in the app (or per-session via the viewer's privacy button) and the screen goes dark the moment a viewer connects; it comes back when the session ends.
- Sessions inject input only; a person sitting at the PC would see the mouse move (true for RustDesk/TeamViewer too — blocking local input needs a driver).
Be honest about the detection surface, because "undetected" does not mean
"forensically invisible": the process shows in Task Manager, Windows sees the
scheduled task, the host keeps logs (host.log), and the machine makes an
outbound connection to your VPS. RustDesk has the same surfaces. That is the
correct trade-off for administering your own or explicitly authorized
computers; covertly controlling a machine you do not own or are not
authorized to manage is illegal in most jurisdictions and this tool is not
designed for it.
Honest limitations
- No UDP P2P hole-punching: browsers can't send raw UDP, so traffic relays
through your VPS (~1 extra RTT; same as RustDesk when its punch fails). Direct
mode (
--listen+ port-forward) bypasses the VPS on your LAN. - Remote printing is not implemented (needs a printer driver); use file transfer + local printing.
- True privacy mode (fake desktop) needs a virtual display driver — NetDesk turns the physical monitor off instead.
- Session-0 notes: input at the logon screen/UAC requires the service install (agent as SYSTEM). Ctrl+Alt+Del itself is never injectable without a driver.
- No mobile native apps (the web viewer works in phone browsers).
Files
netdesk/
├── server/netdesk_server.py # signaling + relay + web host (stateless)
├── server/web/ # viewer UI
├── host/netdesk_host.py # broker + desktop agent + service installer
├── tools/smoke_test.py # 23-check end-to-end suite
├── scripts/ # local demo, service install, VPS deploy
└── requirements.txt
Troubleshooting
| Symptom | Fix |
|---|---|
| "host offline" | Broker not running: schtasks /Run /TN NetDesk, or start --broker manually; logs in the config folder's host.log |
| "bad 2FA code" | Host clock drift — resync Windows time, or re-set --set-totp |
| Black screen + "logon screen" banner | Nobody logged in — type credentials via keyboard, desktop switches automatically |
| Input dead on UAC prompt | Only in simple (non-service) mode — install the service for SYSTEM desktop access |
| Choppy | Auto quality preset, or direct mode on LAN |
| E2E badge missing | Old browser — needs WebCodecs + WebCrypto (Chrome/Edge 102+) |
Get the source code
The full source is published on the project website (no GitHub account needed):
# Clone directly from netdesk.space
git clone https://netdesk.space/git/netdesk.git
# …or download a snapshot
# https://netdesk.space/source → .tar.gz / .zip
Repository layout
netdesk/
├── server/ Python aiohttp signaling + relay + web client
├── host/ Python Windows host/agent + desktop GUI (pywebview)
├── native/ from-scratch native client (Rust core + Flutter UI)
├── docker/ Dockerfile + compose for the server
├── scripts/ tools/ helper + maintenance scripts
└── requirements.txt Python deps for the server/host
License
Source-available — free to self-host and modify for your own use. See LICENSE.