Skip to content

About

Self-hosted live screen-monitoring system for Windows fleets (Rust client/server + dashboard).

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

Screen Monitor

screen-monitor

Self-hosted live screen monitoring for a fleet of machines. A small client on each machine captures the screen and streams it to a central server, which serves a live web dashboard — thumbnails of every machine, click-to-zoom live view, on-change screenshot history, per-client capture settings, and offline detection.

Built in Rust: one static server binary, one static client binary, no runtime dependencies.

What's new in 2.0

(2.0.1: fixes the Windows installer build and teaches it to write the token into config.toml.)

  • Shared-token authentication on every route (dashboard and the client→server ingest path). Set SCREEN_MONITOR_TOKEN on the server; clients send it back. Without it the server ran wide open to anyone who could reach the port.
  • Automatic TLS: the server generates a self-signed cert.pem/key.pem on first run (via rcgen) so it works out of the box — no more manual openssl step just to start it.
  • Runs on Linux and macOS, not just Windows — the server and client now build for all three, with CI-built release binaries attached to every tag.
  • Env-configurable bind address / public host / TLS name (were hard-coded constants).
  • cargo test coverage for the token, path-sanitizer and tiled-protocol logic; clippy-clean.

⚠️ Read Security model before deploying. This tool captures screens and runs on managed machines. Run it on networks and machines you are authorized to monitor, with the token enabled.

How it works

   ┌─────────────┐   HTTPS (tiled JPEG deltas + heartbeats)   ┌──────────────────┐
   │   client    │ ─────────────────────────────────────────▶ │      server      │
   │ (each PC)   │   Authorization: Bearer <token>             │  (one host)      │
   │             │ ◀───────────────────────────────────────── │                  │
   └─────────────┘   per-client capture config (pull)          │  • composites    │
                                                                │    tiles → JPEG  │
   ┌─────────────┐   HTTPS + sm_token cookie                    │  • MJPEG stream  │
   │  dashboard  │ ◀────────────────────────────────────────── │  • screenshot    │
   │ (browser)   │   live view, thumbnails, screenshots         │    history (disk)│
   └─────────────┘                                              └──────────────────┘
  • The client sends only changed tiles (128×128 JPEG blocks, keyed by a BLAKE3 hash), with a periodic keyframe, so idle screens cost almost no bandwidth. The server keeps a per-client canvas, pastes tiles in, and re-encodes one composite JPEG for viewers.
  • A separate screenshot channel stores full-resolution, high-quality captures on disk (on an interval or on-change), with a per-client history cap.
  • The client prevents sleep/screensaver and, on Windows, captures the active console session so it keeps working across the login screen / session switches.

Quick start

Download the archive for your OS from the latest release and unpack it. Each archive contains screen-monitor-server, screen-monitor-client, this README and the example config.

Server (any machine reachable by the clients):

export SCREEN_MONITOR_TOKEN="a-long-random-secret"     # strongly recommended
export SCREEN_MONITOR_PUBLIC_HOST="monitoring.example.com:3000"
./screen-monitor-server
# First run writes a self-signed cert.pem/key.pem next to the binary.
# Dashboard: https://<PUBLIC_HOST>/   (sign in with the token)
# Health:    https://<PUBLIC_HOST>/health

Windows — two packages (both in the release):

  • Portable zip — screen-monitor-2.0.1-windows-x64.zip contains screen-monitor-server.exe and screen-monitor-client.exe. Run the server with run-server.bat.

  • Client installer — screen-monitor-2.0.1-windows-x64-setup.exe, a silent Inno Setup package for rolling the client out across a fleet. It writes config.toml, registers and starts a scheduled task (from screen-monitor.xml) so the client survives reboots and logon, and cleans up any older screen-monitor* tasks/installs first. Interactive runs prompt for the server URL and access token; silent installs take them on the command line and write both (plus accept_invalid_certs = true) into config.toml:

    screen-monitor-2.0.1-windows-x64-setup.exe /SILENT /ServerUrl="https://mon.example:3000" /Token="a-long-random-secret"

Client (each monitored machine) — create config.toml next to the client binary:

server_url = "https://monitoring.example.com:3000"
token = "a-long-random-secret"       # must equal the server's SCREEN_MONITOR_TOKEN
# client_id = "office-pc-01"          # defaults to the hostname
accept_invalid_certs = true          # needed for the auto-generated self-signed cert

Then run ./screen-monitor-client (or run-client.bat / create-config.bat on Windows).

Server configuration (environment)

Variable Default Purpose
SCREEN_MONITOR_TOKEN (unset) Shared secret. When set, every request must present it. Unset = no auth (loud warning at startup).
SCREEN_MONITOR_BIND 0.0.0.0:3000 Socket to listen on.
SCREEN_MONITOR_PUBLIC_HOST localhost:3000 Host shown in the startup banner (cosmetic).
SCREEN_MONITOR_TLS_CN host part of PUBLIC_HOST CN/SAN baked into the auto-generated certificate.

Runtime state is written next to the binary: cert.pem/key.pem, hosts.yaml (known machines), client_configs.json (per-client settings), and screenshots/<client>/.

Per-client capture settings (fps, JPEG quality, scale, change threshold, screenshot mode & history, expected resolution) are edited live from the dashboard and pulled by the client.

Authentication

One shared token guards everything. Clients authenticate with Authorization: Bearer <token>; browsers sign in at /login, which sets an HttpOnly; Secure; SameSite=Strict cookie. ?token=<token> is also accepted for scripting. /health and /login stay open. The comparison is length-checked and constant-time-ish.

This is deliberately simple — a bearer secret, not per-user accounts. It stops anyone who doesn't hold the token; it is not a substitute for network controls.

TLS

The server speaks HTTPS only. On first run it writes a self-signed cert.pem/key.pem (SAN = SCREEN_MONITOR_TLS_CN + localhost + hostname). Clients that don't trust it must set accept_invalid_certs = true. For production, replace the two files with a certificate from your internal CA — see ssl_guide.txt and cert.cnf. Existing files are never overwritten; delete both to regenerate.

Security model

  • Do: run behind the token, over the network segment you control, on machines you are authorized to monitor. Distribute cert.pem as trusted, or use a real CA cert, rather than leaving accept_invalid_certs = true long-term.
  • Limits: one shared token (no per-user identity or audit); accept_invalid_certs = true disables certificate verification (trusted networks only); the dashboard can change client capture configs, so anyone with the token has full control; screenshots are stored unencrypted on the server disk. Path traversal on client IDs and screenshot names is rejected; payload sizes and tile counts are bounded.
  • Not included: end-to-end encryption beyond TLS, tamper-proof logging, rate limiting.

Build from source

# Linux needs XCB dev headers for screen capture (scrap):
sudo apt-get install -y libxcb1-dev libxcb-shm0-dev libxcb-randr0-dev

cargo build --release --bin screen-monitor-server --bin screen-monitor-client
cargo test --release
# Windows: build.bat

Binaries land in target/release/. The GitHub workflow builds Windows / Linux / macOS on every v* tag (and via Run workflow with a tag input), runs the tests, builds the Windows Inno Setup installer, and attaches the archives to the release.

Project layout

Path
src/main-server.rs axum server: ingest, compositing, MJPEG stream, screenshot store, auth, TLS
src/main-client.rs screen capture (scrap), tiled-delta encoder, screenshot uploader
src/dashboard.html single-page dashboard (served by the server)
screen-monitor.iss Inno Setup installer (silent, registers a scheduled task)
config.toml.example client config template
ssl_guide.txt, cert.cnf bringing your own TLS certificate

About

Self-hosted live screen-monitoring system for Windows fleets (Rust client/server + dashboard).

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages