TrollVNC is a VNC server for iOS devices, allowing remote access and control of the device’s screen.
Run on iOS device or simulator:
trollvncserver -p 5901 -n "My iPhone" [options]Basic:
-p portTCP port for VNC (default:5901)-n nameDesktop name shown to clients (default:TrollVNC)-vView-only (ignore input)-A secKeep-alive interval to prevent device sleep by sending harmless dummy key events; only active while at least one client is connected (15..86400,0disables, default:0)-C on|offClipboard sync (default:on)
Display/Performance:
-s scaleOutput scale factor (0 < s <= 1, default:1.0;1means no scaling)-F specFrame rate: singlefps, rangemin-max, or fullmin:pref:max; on iOS 15+ a range is applied, on iOS 14 the max (or preferred) is used-d secDefer update window in seconds to coalesce changes (0..0.5, default:0.015)-Q nMax in-flight updates before dropping new frames (0..8, default:2;0disables dropping)
Dirty detection:
-t sizeTile size for dirty-detection in pixels (8..128, default:32)-P pctFullscreen fallback threshold percent (0..100, default:0;0disables dirty detection entirely)-R maxMax dirty rects before collapsing to a bounding box (default:256)-aEnable non-blocking swap (may cause tearing).
Scroll/Input:
-W pxWheel step in pixels per tick (0disables, default:48)-w k=v,..Wheel tuning keys:step,coalesce,max,clamp,amp,cap,minratio,durbase,durk,durmin,durmax-NNatural scroll direction (invert wheel delta)-M schemeModifier mapping:std|altcmd(default:std)-KLog keyboard events (keysym -> mapping) to stderr
Cursor & Rotation:
-U on|offEnable server-side cursor overlay (default:off)-O on|offSync UI orientation and rotate output (default:off)
HTTP/WebSockets:
-H portEnable built-in HTTP server on port (0disables; default0)-D pathAbsolute path for HTTP document root-e filePath to SSL certificate file-k filePath to SSL private key file
Discovery:
-B on|offEnable Bonjour/mDNS advertisement for auto-discovery by viewers on the local network (default:on)
Logging:
-VEnable verbose logging (debug only)
Help:
-hShow built-in help message
Notes:
- Capture starts only when at least one client is connected, and stops when the last disconnects.
- You may want to use
-M altcmdon macOS clients.
Quick guidance on key trade-offs (latency vs. bandwidth vs. CPU/battery):
-s scale: Biggest lever for bandwidth and encoder CPU. Start at0.66–0.75for text-heavy UIs; use0.5for tight links or slow networks;1.0for pixel-perfect.-F spec: Cap preferred frame rate to balance smoothness and battery.30–60is a sensible range; on 120 Hz devices,60often suffices. On iOS 14 the max (or preferred if provided) value is used.-d sec: Coalesce updates. Larger values lower CPU/bitrate but add latency. Typical range0.005–0.030; interactive UIs prefer≤ 0.015.-Q n: Throughput vs. latency backpressure.1–2recommended.0disables dropping and can grow latency when encoders are slow.-t size: Dirty-detection tile size.32default;64cuts hashing/rect overhead on slower devices;16(or8) captures finer UI details at higher CPU cost.-P pct: Fullscreen fallback threshold. Practical25–40; higher values stick to rect updates longer.0disables dirty detection (always fullscreen).-R max: Rect cap before collapsing to a bounding box.128–512common; too high increases RFB overhead.-a: Non-blocking swap. Can reduce stalls/contension; may introduce tearing. Try if you see occasional stalls; leave off for maximal visual stability. If a non-blocking swap cannot lock clients, TrollVNC falls back to copying only dirty rectangles to the front buffer to minimize tearing and bandwidth.
Notes:
- Scaling happens before dirty detection; tile size applies to the scaled frame. Effective tile size in source pixels ≈ t / scale.
- With
-Q 0, frames are never dropped. If the client or network is slow, input-to-display latency can grow. - On older devices, prefer lowering
-sand increasing-tto reduce CPU and memory bandwidth.
By default, dirty detection is disabled because it usually has a high CPU cost. You can enable it with -P to set a fullscreen fallback threshold.
Low-latency interactive (LAN):
trollvncserver -p 5901 -n "My iPhone" -s 0.75 -d 0.008 -Q 1 -t 32 -P 35 -R 512Battery/bandwidth saver (cellular/WAN):
trollvncserver -p 5901 -n "My iPhone" -s 0.5 -d 0.025 -Q 2 -t 64 -P 50 -R 128High quality on fast LAN:
trollvncserver -p 5901 -n "My iPhone" -s 1.0 -d 0.012 -Q 2 -t 32 -P 30 -R 512Choppy network (high RTT/loss):
trollvncserver -p 5901 -n "My iPhone" -s 0.66 -d 0.035 -Q 1 -t 64 -P 60 -R 128Older devices (CPU-limited):
trollvncserver -p 5901 -n "My iPhone" -s 0.5 -d 0.02 -Q 1 -t 64 -P 40 -R 256Optional: add -a to any profile if you observe occasional stalls due to encoder contention; remove it if tearing is noticeable:
trollvncserver ... -aUse -F to set the CADisplayLink frame rate:
- Single value:
-F 60 - Range:
-F 30-60 - Full range with preferred:
-F 30:60:120
Notes:
- On iOS 15+, the full range is applied via
preferredFrameRateRange. - On iOS 14, only
preferredFramesPerSecondis available, so the max (or preferred if provided) is used.
Use -A to periodically send a harmless dummy key event to keep the device awake while clients are connected.
- Active only when at least one client is connected; automatically stops when the last client disconnects.
- Set
-A 0(or omit) to disable. Shorter intervals may increase battery usage.
The scroll wheel is emulated with short drags. Fast wheel motion becomes one longer flick; slow motion becomes short drags. You can tune its feel at runtime:
-W px: Base pixels per wheel tick (0disables, default48). Larger = faster scrolls.-w k=v,...keys:step: same as-W(pixels)coalesce: coalescing window in seconds (default0.03,0..0.5)max: base max distance per gesture before clamp (default192)clamp: absolute clamp factor, final max distance = clamp × max (default2.5)amp: velocity amplification coefficient for fast scrolls (default0.18)cap: max extra amplification (default0.75)minratio: minimum effective distance vs step for tiny scrolls (default0.35)durbase: gesture duration base in seconds (default0.05)durk: gesture duration factor applied to sqrt(distance) (default0.00016)durmin: min gesture duration (default0.05)durmax: max gesture duration (default0.14)natural:1to enable natural direction,0to disable
Smooth and slow:
trollvncserver ... -W 32 -w minratio=0.3,durbase=0.06,durmax=0.16Fast long scrolls:
trollvncserver ... -W 64 -w amp=0.25,cap=1.0,max=256,clamp=3.0More sensitive small scrolls:
trollvncserver ... -w minratio=0.5,durbase=0.055Disable wheel entirely:
trollvncserver ... -W 0- UTF-8 clipboard sync is enabled by default; fallbacks to Latin-1 for legacy clients where needed.
- Starts when the first client connects and stops when the last disconnects.
- Disable it with
-C offif not desired.
When -O on is set, TrollVNC tracks iOS interface orientation and rotates the outgoing framebuffer to match (0°, 90°, 180°, 270°). Touch and scroll input are mapped into the device coordinate space with the correct axis and direction in all orientations.
Pipeline overview (per frame):
- Capture portrait buffer from
ScreenCapturer. - Rotate with Accelerate/vImage (90/180/270) into a tight ARGB buffer.
- Scale to the server output size (if
-s < 1.0), reusing a persistent vImage temp buffer to reduce allocations. - Width is rounded up to a multiple of 4 bytes per pixel row to satisfy encoders/clients; height is adjusted to preserve aspect ratio.
- Framebuffer is resized via LibVNCServer when geometry changes; width/height and pixel format are kept consistent (BGRA little-endian).
- Dirty detection (if enabled via
-P > 0) runs on the rotated+scaled back buffer.
Dirty detection and rotation:
- On an orientation change, TrollVNC performs a one-time full-screen update and clears pending tile state to establish a clean baseline.
- Tile/hash tables are reinitialized on any geometry change (e.g., 90°/270° or scale changes).
- Subsequent frames use normal tile hashing and dirty rectangles again.
- Set
-P 0to disable dirty detection entirely and always send full frames.
Input mapping:
- Touch coordinates are transformed from the VNC framebuffer space back into the device’s portrait space, inverting the current rotation.
- The scroll wheel is emulated with short drags; when rotated, the gesture axis and direction are remapped (e.g., in landscape, vertical wheel becomes a horizontal drag).
-Nstill toggles natural direction.
Examples:
# Enable rotation sync and keep dirty detection enabled with a reasonable threshold
trollvncserver -O on -P 35 -t 32 -R 512
# Rotation sync with full frames (dirty detection disabled)
trollvncserver -O on -P 0iOS does not present a native on-screen cursor in this setup. TrollVNC does not draw a cursor by default; most VNC viewers render their own pointer. If your viewer expects the server to render a cursor, enable it with -U on.
Details:
- Overlay style: a simple “X” cursor shape with centered hotspot. Alpha is disabled to keep the cursor crisp.
- Pros: visible even if the client does not draw its own cursor.
- Cons: may show two cursors if the client also renders one. Keep it off unless needed.
Classic VNC authentication can be enabled via environment variables:
TROLLVNC_PASSWORD: full-access password. Enables VNC auth when set.TROLLVNC_VIEWONLY_PASSWORD: optional view-only password. When present, clients authenticating with this password can view but cannot send input.
Semantics:
- Passwords are stored in a NULL-terminated list as
[full..., view-only...]. The index of the first view-only password equals the number of full-access passwords. - Classic VNC only uses the first 8 characters of each password.
Examples (zsh):
export TROLLVNC_PASSWORD=editpass
export TROLLVNC_VIEWONLY_PASSWORD=viewpass # optional
trollvncserver -p 5901 -n "My iPhone"Notes:
-vforces global view-only regardless of password. View-only password applies per client.- You must set a password if you’re using the built-in VNC client of macOS.
- Environment variables may be visible to the process environment; consider using a secure launcher if needed.
TrollVNC can start LibVNCServer’s built-in HTTP server to serve a browser-based VNC client (noVNC).
Behavior:
- When
-His non-zero, the HTTP server listens on that port. - If
-Dis provided, its absolute path is used ashttpDir. - If
-Dis omitted, TrollVNC derives a defaulthttpDirrelative to the executable../share/trollvnc/webclients. - HTTP proxy CONNECT is enabled to support certain viewer flows.
Examples:
# Enable web client on port 5801 using the default web root
trollvncserver -p 5901 -H 5801
# Enable web client on port 8081 with a custom web root
trollvncserver -p 5901 -H 8081 -D /var/www/trollvnc/webclientsNotes:
- Ensure the web root contains the required client assets.
- If the directory is missing or incomplete, the HTTP server may start but won’t serve a functional client.
You can serve the web client over HTTPS/WSS by providing an SSL certificate and key via -e and -k.
What you need:
- A certificate (
cert.pem) and private key (key.pem) that your browser will accept. - The HTTP server enabled on some port with
-H.
Quick start with a local CA (minica):
# 1) Install minica (macOS):
brew install minica
# 2) Create a host cert for your device IP or DNS name
minica -ip-addresses "192.168.2.100"
# This produces a CA (minica.pem) and a host folder (e.g., 192.168.2.100/) with cert.pem and key.pem
# 3) Trust the CA in your browser/OS by importing minica.pem (Authorities/Trusted Roots)
# Without this, the browser will warn about an untrusted certificate.
# 4) Copy the host cert and key to the device (pick any readable path)
scp -r 192.168.2.100 root@192.168.2.100:/usr/share/trollvnc/ssl/
# 5) Start TrollVNC with HTTPS/WSS enabled
trollvncserver -p 5901 -H 5801 \
-e /usr/share/trollvnc/ssl/192.168.2.100/cert.pem \
-k /usr/share/trollvnc/ssl/192.168.2.100/key.pemConnect:
- Open
https://192.168.2.100:5801/in your browser. - Use the bundled web client page to connect to the VNC server.
Notes:
- Certificates must match what the browser connects to (IP or hostname).
- Self-signed setups require trusting the CA (minica.pem) or the specific certificate.
TrollVNC can advertise itself on the local network via Bonjour/mDNS so compatible viewers can discover it without typing an IP/port.
What it does:
- Publishes an mDNS service of type
_rfb._tcp(the standard for VNC). - Uses the desktop name from
-nas the service name and the VNC port from-p. - Starts the advertisement when the server starts and stops it on exit.
How to control it:
- Command line:
-B on|off(default:on). Example to disable:trollvncserver ... -B off - Preferences app: toggle “Enable Auto-Discovery” in TrollVNC settings.
Client discovery tips:
- Many VNC apps (and network scanners) list
_rfb._tcpservices automatically on the LAN. - If you’re using the built-in HTTP client (noVNC), Bonjour is unrelated to WebSockets; it only helps native VNC viewers find the TCP server.
Troubleshooting:
- Ensure the device and client are on the same subnet and that multicast (mDNS) is not filtered by your Wi‑Fi/AP.
- If discovery doesn’t show up, you can still connect manually using the device IP and port shown in the app or logs.
See: https://github.com/Lessica/BuildVNCServer
- libvncserver
- libjpeg-turbo
- libpng
- OpenSSL
- Cyrus SASL
- The majority of the main program
src/trollvncserver.mmwas written/generated by GitHub Copilot (GPT-5).
TrollVNC is licensed under the GPLv2 License. See the COPYING file for more information.