TrollVNC is a VNC server for iOS devices, allowing remote access and control of the device’s screen.
- Low-latency capture with scaling, frame rate control, and back-pressure.
 - Optional dirty-region updates for bandwidth savings.
 - Tunable scroll wheel gestures and natural direction toggle.
 - UTF‑8 Clipboard sync (UltraVNC).
 - Orientation sync and rotation-aware input mapping.
 - Optional server-side cursor overlay.
 - Classic VNC authentication with full-access and view-only passwords.
 - Built-in HTTP/WebSockets for browser access (HTTPS/WSS supported).
 - Bonjour/mDNS auto-discovery on the local network.
 - Reverse VNC
 - Pre-seeded configuration
 
- Fork this repo and run GitHub workflow “Build TrollVNC”.
 - Download “TrollVNC” from Releases and install it on your iOS device.
 - Configure the VNC server settings from “Settings” → “TrollVNC” or the standalone “TrollVNC” app as needed.
 - Or, run the following command on iOS device or simulator:
 
trollvncserver -p 5901 -n "My iPhone" [options]Basic:
-p portTCP port for VNC (default:5901)-c portTCP port for client management (listening on localhost only;0disables, default:0)-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)
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
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)
Accessibility:
-O on|offSync UI orientation and rotate output (default:on)-E on|offEnable AssistiveTouch auto-activation (default:off)-U on|offEnable server-side cursor overlay (default:off)
Notifications:
-i on|offEnable a single user notification when the first client connects (default:on)-I on|offEnable user notifications for client connect/disconnect (default:on)
Extensions:
-C on|offEnable UltraVNC UTF-8 clipboard extension (default:on)-T on|offEnable TightVNC 1.x file transfer extension (default:off)
Logging:
-VEnable verbose logging (debug only)
Help:
-hShow built-in help message
Reverse Connection:
-reverse host:portConnect out to a listening VNC viewer (TightVNC/UltraVNC). IPv6 as[addr]:port.-repeater id host:portConnect out to an UltraVNC Repeater (Mode II) with numericid;host:portis the repeater’s server (invers) port (often5500).
When reverse is enabled, TrollVNC disables the local VNC port (
-p), HTTP/WebSockets (-H), and Bonjour (-B). See “Reverse VNC” below for full setup with examples.
Mouse:
- Left button: single-finger touch. Hold to drag; move updates while held.
 - Right button: Home/Menu button. Press = short press; hold ≈ long press. Release ends the press.
 - Middle button: Power button. Press = short press; hold ≈ long press. Release ends the press.
 - Wheel: translated into short drags with coalescing/velocity; see “Wheel/Scroll Tuning”.
 
Keyboard:
- Standard ASCII keys, Return/Tab/Backspace/Delete, arrows, Home/End/PageUp/PageDown, and function keys F1..F24 are sent as HID keyboard usages.
 - Modifier mapping (
-M):std(default): Alt -> Option; Meta/Super -> Command.altcmd(macOS): Alt -> Command; Meta -> Option; Super -> Command.
 - Media/consumer keys (when the client sends XF86 keysyms):
- Brightness Up/Down -> display brightness increment/decrement
 - Volume Up/Down/Mute -> volume increment/decrement/mute
 - Previous / Play-Pause / Next -> previous track / toggle play-pause / next track
 
 
Touch, scroll, and button mappings respect the current rotation when
-O onis used.
AssistiveTouch Auto-Activation (-E on):
- When the first client connects, TrollVNC enables AssistiveTouch if it’s currently off; when the last client disconnects, it restores the previous state (disables it only if TrollVNC enabled it).
 - Applies on device builds; no-op on the simulator.
 
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.
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
Examples:
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 0Many VNC clients support clipboard sync, but behavior may vary. This feature is primarily supported by UltraVNC.
- 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.
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.
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.
Examples:
export TROLLVNC_PASSWORD=editpass
export TROLLVNC_VIEWONLY_PASSWORD=viewpass   # optional
trollvncserver -p 5901 -n "My iPhone"Notes:
- Classic VNC only uses the first 8 characters of each password.
 - You must set a password if you’re using the built-in VNC client of macOS.
 -vforces global view-only regardless of password. View-only password applies per client.
TrollVNC can start LibVNCServer’s built-in HTTP server to serve a browser-based VNC client, noVNC.
- When 
-His non-zero, the HTTP server listens on that port. - If 
-Dis provided, its absolute path is used ashttpDir. If 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/webclientsWSS encrypts the WebSocket transport (TLS for ws).
Prerequisites:
- A certificate (
cert.pem) and private key (key.pem) accepted by your browser. - The built‑in HTTP server enabled on some port with 
-H(it also exposes the WebSocket endpoint). 
Steps:
Generate or obtain a cert/key (example using a local CA on macOS).
brew install minica
minica -ip-addresses "192.168.2.100"Trust the CA: import minica.pem into your OS/browser trust store (otherwise the browser will warn).
Copy the host cert and key to the device (choose any readable path).
scp -r 192.168.2.100 [email protected]:/usr/share/trollvnc/ssl/Start TrollVNC with 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 from your browser. Open the bundled web page at http://<host>:5801/. The secure endpoint will be available when -e/-k are provided.
Notes:
- The certificate must match what the browser connects to (IP or hostname/SAN).
 - Self‑signed setups require trusting the CA or the specific certificate.
 
- Publishes a VNC service on the local network via Bonjour/mDNS (type 
_rfb._tcp), using the name from-nand the port from-p. - Enabled by default. Toggle with 
-B on|offor in Settings → TrollVNC → “Enable Auto-Discovery”. - Viewers on the same LAN that support Bonjour can find it automatically; otherwise connect by 
ip:portshown in the app/logs. 
TrollVNC can initiate an outbound connection to a listening VNC viewer or an UltraVNC repeater. This avoids opening inbound ports on the device and is helpful behind NAT/firewalls.
When reverse connection is enabled:
- The normal server listening port is disabled (equivalent to not using 
-p). - The built-in HTTP server is disabled (any 
-His ignored). - Bonjour/mDNS advertisement is disabled.
 - Classic VNC authentication via environment variables still applies if set (see “Authentication”).
 
TrollVNC can connect to a viewer running in Listening mode. The viewer listens for inbound reverse connections; TrollVNC dials out.
Roles and steps:
- Start TightVNC or UltraVNC Viewer in “Listen” mode (UltraVNC: Connections → Listen mode, or Toolbar → Listen).
 - Default listening port is 
5500; you can change it in the viewer options. - Ensure your desktop firewall allows inbound on the chosen listening port.
 
- 
CLI examples (use your viewer’s listening
host:port):# IPv4 trollvncserver -reverse 203.0.113.10:5500 -n "My iPhone" # IPv6 trollvncserver -reverse [2001:db8::1]:5500 -n "My iPhone"
 - 
Preferences (Settings → TrollVNC):
- Reverse Connection → Mode: Viewer
 - Server: 
host:port(e.g.,viewer.example.com:5500or[2001:db8::1]:5500) 
 
Notes:
- Only an outbound TCP connection from the device to the viewer is required.
 - If your viewer uses a custom port, specify that port in 
-reverse host:portand in the Server field. - The desktop viewer shows the incoming reverse connection with the name from 
-n. 
TrollVNC can connect to an UltraVNC Repeater in Mode II. Both the Server (TrollVNC) and the Viewer make outbound connections to the Repeater and pair via a numeric ID.
Roles and steps:
- Deploy or start an UltraVNC Repeater that both device and viewer can reach (public, DMZ, or with NAT port forwards).
 - Common defaults (may vary by setup):
- Server (invers) port: 
5500 - Viewer port: 
5901(sometimes5900) 
 - Server (invers) port: 
 - Make a note of the repeater’s 
host:portfor the Server side (oftenhost:5500) and for the Viewer side (oftenhost:5901). 
- 
Choose a numeric Repeater ID (commonly up to 9 digits). Do not include
ID:— enter only the number. - 
CLI example (use the repeater’s server port):
trollvncserver -repeater 12345679 repeater.example.com:5500 -n "My iPhone"12345679is the numeric Repeater ID.repeater.example.com:5500should point to the repeater’s server (invers) port. IPv6 example:-repeater 12345679 [2001:db8::1]:5500
 - 
Preferences (Settings → TrollVNC):
- Reverse Connection → Mode: UltraVNC Repeater
 - Server: 
host:server_port(e.g.,repeater.example.com:5500or[2001:db8::1]:5500) - Repeater ID: numeric (e.g., 
12345679) 
 
Behavior when reverse is enabled: local VNC port is disabled, HTTP/WebSockets are disabled, and Bonjour/mDNS is disabled.
Optional: set TROLLVNC_REPEATER_RETRY_INTERVAL (seconds) to wait before exit if the connection fails (useful when a supervisor always restarts the process).
- UltraVNC Viewer is recommended for Mode II:
- Select “Repeater”; in “ID:12345679”, enter 
ID:<your_id>(e.g.,ID:12345679). - Enter the repeater’s viewer address, e.g., 
repeater.example.com:5901. - Connect; the repeater pairs the viewer with the server using the matching ID.
 
 - Select “Repeater”; in “ID:12345679”, enter 
 
Notes:
- Connections are outbound from both sides; no inbound port on the iOS device is needed.
 - Use the repeater’s server port for TrollVNC (
-repeater <id> host:server_port) and the viewer port for UltraVNC Viewer. - UltraVNC “Mode SSL” repeaters require special viewer/server builds; TrollVNC connects to standard (non-SSL) Mode II repeaters.
 
TrollVNC can be preconfigured via a bundled Managed.plist for supervised or fleet deployments where end users shouldn’t change settings.
- Create 
prefs/TrollVNCPrefs/Resources/Managed.plistin the repo. - Populate it with the keys you need (see “Supported keys” below).
 - Build/package the project as usual; the file is embedded into 
TrollVNCPrefs.bundleautomatically. - Install the build on device. TrollVNC detects 
Managed.plistat startup and applies the configured values. - Verify & expected behavior:
- “Settings” → “TrollVNC” shows a banner: “This TrollVNC instance is managed by your organization”.
 - The preferences UI is effectively locked down.
 - In‑app update prompts are suppressed while managed.
 - Configured values take effect at startup; you don’t need equivalent CLI flags for these options.
 
 
- 
Strings:
DesktopName: Desktop name shown to clientsModifierMap:std|altcmdFrameRateSpec: e.g.,"60","30-60", or"30:60:120"WheelTuning: advanced wheel tuning string, e.g.,"amp=0.25,cap=1.0,max=256,clamp=3.0"HttpDir: absolute path to HTTP doc rootSslCertFile: absolute path to TLS cert (PEM)SslKeyFile: absolute path to TLS key (PEM)- Reverse connection:
ReverseMode:viewer|repeaterReverseSocket:host:portor[ipv6]:port(preferred)- Backward-compat: 
ReverseHost+ReversePort 
 - Authentication:
FullPassword: full-access password (first 8 chars used)ViewOnlyPassword: view-only password (first 8 chars used)
 
 - 
Numbers:
Port(1024..65535;0/<1024 is treated as invalid and falls back to 5901)KeepAliveSec(0 or 15..300; values 0..15 are treated as 0)Scale(0.1..1.0)DeferWindowSec(0..0.5)MaxInflight(0..8)TileSize(8..128)FullscreenThresholdPercent(0..100)MaxRects(1..4096)WheelStepPx(0 disables wheel; else 5..1000)HttpPort(0 disables; else 1024..65535)ReverseRepeaterID(numeric ID for UltraVNC Repeater Mode II)
 - 
Booleans:
Enabled,ClipboardEnabled,ViewOnly,OrientationSync,NaturalScroll,ServerCursor,AsyncSwap,KeyLogging,AutoAssistEnabled,BonjourEnabled,FileTransferEnabled,SingleNotifEnabled,ClientNotifsEnabled
 
Notes:
- When reverse connection is enabled via Managed.plist, behavior matches CLI reverse: local VNC port disabled, HTTP/WebSockets disabled, Bonjour disabled.
 HttpDir,SslCertFile, andSslKeyFilemust be absolute paths.
Minimal preset: reverse to a listening viewer with a custom desktop name:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>Enabled</key>
  <true/>
  <key>DesktopName</key>
  <string>My iPhone</string>
  <key>ReverseMode</key>
  <string>viewer</string>
  <key>ReverseSocket</key>
  <string>203.0.113.10:5500</string>
  <key>ClipboardEnabled</key>
  <true/>
  <key>KeepAliveSec</key>
  <integer>60</integer>
</dict>
</plist>LAN example: enable built‑in HTTP client and TLS:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>Enabled</key>
  <true/>
  <key>DesktopName</key>
  <string>TrollVNC</string>
  <key>Port</key>
  <integer>5901</integer>
  <key>Scale</key>
  <real>0.75</real>
  <key>FrameRateSpec</key>
  <string>30:60:120</string>
  <key>DeferWindowSec</key>
  <real>0.012</real>
  <key>MaxInflight</key>
  <integer>2</integer>
  <key>TileSize</key>
  <integer>32</integer>
  <key>FullscreenThresholdPercent</key>
  <integer>35</integer>
  <key>MaxRects</key>
  <integer>512</integer>
  <key>HttpPort</key>
  <integer>5801</integer>
  <key>HttpDir</key>
  <string>/usr/share/trollvnc/webclients</string>
  <key>SslCertFile</key>
  <string>/usr/share/trollvnc/ssl/host/cert.pem</string>
  <key>SslKeyFile</key>
  <string>/usr/share/trollvnc/ssl/host/key.pem</string>
  <key>ClipboardEnabled</key>
  <true/>
  <key>ViewOnly</key>
  <false/>
  <key>FullPassword</key>
  <string>editpass</string>
  <key>ViewOnlyPassword</key>
  <string>viewpass</string>
</dict>
</plist>You can build TrollVNC entirely in GitHub Actions using the built-in workflow.
- Fork this repository (or enable “Actions” in your own clone).
 - Go to the “Actions” tab → “Build TrollVNC” → “Run workflow”.
 - Choose the branch to run on (usually main) and fill the form inputs below.
 
Due to a GitHub limit, the manual form exposes 10 commonly used options:
is_managed: whether to bundle aManaged.plist(managed deployment)desktop_name: display name shown to VNC clientsport: VNC TCP port (default5901)view_only: force view-only (ignore input)scale: output scale (0.1–1.0)frame_rate_spec: frame rate, e.g.60|30-60|30:60:120modifier_map: std | altcmdreverse_mode: none | viewer | repeaterreverse_socket:host:portor[ipv6]:port(for viewer or repeater server port)reverse_repeater_id: numeric ID (UltraVNC Repeater Mode II)
When is_managed is true, the workflow generates a Managed.plist from these inputs and bundles it.
You may set these repository secrets so the managed build embeds VNC passwords. If you don’t set them, the keys are omitted.
TVNC_FULL_PASSWORDTVNC_VIEWONLY_PASSWORD
Add them under: “Settings” → “Secrets and variables” → “Actions” → “New repository secret”.
In the workflow-managed build, the following keys are fixed to safe defaults:
Enabled=trueClipboardEnabled=trueSingleNotifEnabled=trueClientNotifsEnabled=trueKeepAliveSec=15OrientationSync=trueNaturalScroll=falseAutoAssistEnabled=falseServerCursor=falseBonjourEnabled=falseKeyLogging=false
For advanced tuning (HTTP/TLS, wheel tuning, dirty detection, etc.), commit your own prefs/TrollVNCPrefs/Resources/Managed.plist to the repo and leave is_managed unchecked, or extend the workflow locally.
- Each run uploads artifacts per scheme:
packages-default,packages-rootless,packages-roothide,packages-bootstrapdsym-default,dsym-rootless,dsym-roothide,dsym-bootstrap
 - Download them from the run page → 
Artifacts. - If you push to the 
releasebranch (and the workflow runs there), a GitHub Release is created automatically with packaged files attached. 
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 an open-source VNC solution, licensed under GPLv2. You are free to access, use, and modify the source code. See the COPYING file for more information.
- Ready-to-use, pre-compiled builds
 - Automatic updates and continuous improvements
 - Priority support and troubleshooting assistance
 - Sustainable development through your contribution
 
If you prefer, you can always build TrollVNC yourself directly from the source.
- Compile for free.
 - Pay for convenience, updates, and support.
 
Support TrollVNC and help us keep remote access fast, secure, and evolving.