Settings Reference
Every command-line option and environment variable of the selkies server, with its type and default.
Every setting below is one entry of SETTING_DEFINITIONS in src/selkies/settings.py, which is also what selkies --help prints. Each one is read with the precedence command-line flag > SELKIES_<NAME> environment variable > fallback environment variable (where one is listed) > built-in default. The flag accepts both spellings, --my-setting and --my_setting, and a bool flag takes a value (--enable-resize=false) or stands alone for true (--public). A flag or variable set to an empty value means the built-in default; an unknown flag is ignored with a warning, never an error.
The settings are grouped by what they govern, the ones a deployment reaches for first at the top of each group. The stream settings are the client's to choose from the dashboard, and a deployment sets them only to narrow the menu or to lock a single value; see Usage for how a locked value reads.
Value syntax
- List/enum (e.g.
SELKIES_ENCODER="jpeg,h264enc"): first item is the default, the full list is the allowed options; a single value locks the choice. Invalid items are dropped; an entirely-invalid override keeps the full built-in menu and default. - Bool (case-insensitive):
"true"/"1"is on, anything else off, and a bare flag (--public) is on; a"|locked"suffix (e.g."true|locked") forbids the client changing it. - Range:
"8-240"restricts the allowed span (initial value = built-in default, clamped in); a bare value"60"keeps the built-in span and makes it the initial value, widening the span if it falls outside (so legacy fixed-value configs still resolve);"60,8-240"sets initial and span in one value; a degenerate span"60-60"locks the setting. - An override set to
""means "use the built-in default"; list types keep their explicit""/"none"= disable semantics.
Stream
The video encoder and its rate control. The dashboard chooses among what the server allows.
| Setting | Default | Description |
|---|---|---|
--encoderSELKIES_ENCODER | h264encenum: one of h264enc, h265enc, vp8enc, vp9enc, av1enc, h264enc-striped, jpeg | The default video encoder. Every full-frame encoder runs on NVENC or VA-API where the GPU carries the codec and falls back to the software encoder pixelflux was built with: h264enc (x264, or OpenH264 in a GPL-free build), h265enc (x265, or kvazaar in a GPL-free build), vp8enc and vp9enc (libvpx), av1enc (SVT-AV1). h264enc-striped is CPU-striped H.264, jpeg is CPU-striped JPEG. Clients are offered only the encoders this host serves: those whose codec the encode node's GPU encodes (probed once at startup) or the pixelflux build carries a software encoder for. A client whose browser cannot decode the codec steps through the allowed encoders it does decode, taking the codecs this host encodes in hardware, most efficient first, before those it encodes in software, in order of encode time, then h264enc-striped, and jpeg last of all. The WebRTC transport carries the full-frame encoders and offers them in the same order behind the display's codec, so a browser that declines the codec answers with the next one it decodes and the display moves to it; h264enc-striped and jpeg are WebSocket-only. |
--video-fullcolorSELKIES_VIDEO_FULLCOLOR | falsebool | Encode with 4:4:4 chroma rather than 4:2:0 where the codec and encoder carry it (H.264 and H.265 on NVENC, VA-API, x264, and x265; VP9 profile 1 on VA-API and libvpx); other codecs and encoders stay 4:2:0. The server knows which of its encoders carry it on this host, so a client whose decoder has no 4:4:4 profile turns it off for itself only where the stream would carry it, whether it or this default asked for it, and streams 4:2:0 on the same codec; where it is locked on, such a client steps over WebSockets to the next allowed encoder whose 4:4:4 it decodes or that has none, and to JPEG last, and reports the stream over WebRTC. A WebRTC client names the 4:4:4 it decodes in its hello, so its first offer already fits it. |
--framerateSELKIES_FRAMERATE | 60range, within 8-240 | Framerate: allowed range (e.g., "8-240"), initial value (e.g., "60"), or both ("60,8-240"); "60-60" locks. |
--video-bitrateSELKIES_VIDEO_BITRATE | 8000range, within 100-1000000 | Video bitrate aka CBR, in kilobits per second (kbps): allowed range (e.g., "100-1000000"), initial value (e.g., "8000" for 8 Mbps, "250" for 250 kbps), or both ("8000,100-1000000"); "8000-8000" locks. |
--video-crfSELKIES_VIDEO_CRF | 25range, within 5-50 | Video CRF (constant quality): allowed range (e.g., "5-50"), initial value (e.g., "25"), or both ("25,5-50"); "25-25" locks. |
--rate-control-modeSELKIES_RATE_CONTROL_MODE | crfenum: one of cbr, crf | Rate control mode for the video encoders (crf = constant quality/QP, cbr = constant bitrate). Honored for every video encoder when enable_rate_control is true (the default). |
--enable-rate-controlSELKIES_ENABLE_RATE_CONTROL | truebool | Honor the client-selected rate_control_mode (crf/cbr). Enabled by default so both modes are selectable; set false to lock the encoder to its built-in default. |
--congestion-controlSELKIES_CONGESTION_CONTROL | falsebool | Adapt the video bitrate to the transport-wide-cc (GCC-style) bandwidth estimate from WebRTC receiver feedback. Effective in CBR rate-control mode; may trade quality/stability for congestion responsiveness. |
--keyframe-intervalSELKIES_KEYFRAME_INTERVAL | 0.0float, 0.0 to 300.0 | Seconds between scheduled video recovery keyframes (any video codec). 0 (default) keeps the GOP infinite: keyframes are sent only on demand (client join/reset, keyframe requests), which keeps bitrate and quality steady. |
--video-min-qpSELKIES_VIDEO_MIN_QP | 0int, 0 to 51 | CBR-mode minimum quantizer on the H.264 QP scale, mapped onto each codec's own quantizer range (0 = encoder default). Raising it caps bit spend on easy content when the bitrate budget is generous. |
--video-max-qpSELKIES_VIDEO_MAX_QP | 0int, 0 to 51 | CBR-mode maximum quantizer on the H.264 QP scale, mapped onto each codec's own quantizer range (0 = encoder default). Lowering it keeps screen text legible under motion at the cost of overshooting the bitrate target on hard content (measured at 720p60 scrolling text: 35 lifts x264 by ~19 dB at ~2.5x the target). |
--jpeg-qualitySELKIES_JPEG_QUALITY | 40range, within 1-100 | JPEG quality: allowed range (e.g., "1-100"), initial value (e.g., "40"), or both ("40,1-100"); "40-40" locks. |
--video-streaming-modeSELKIES_VIDEO_STREAMING_MODE | truebool | Enable video streaming mode (Turbo: encode every frame like a traditional video encoder) for pixelflux encoders. |
--use-paint-over-qualitySELKIES_USE_PAINT_OVER_QUALITY | truebool | Enable high-quality paint-over for static scenes. |
--paint-over-jpeg-qualitySELKIES_PAINT_OVER_JPEG_QUALITY | 90range, within 1-100 | JPEG paint-over quality: allowed range, initial value, or both ("90,1-100"); "90-90" locks. |
--video-paintover-crfSELKIES_VIDEO_PAINTOVER_CRF | 18range, within 5-50 | H.264 paint-over CRF: allowed range, initial value, or both ("18,5-50"); "18-18" locks. |
--video-paintover-burst-framesSELKIES_VIDEO_PAINTOVER_BURST_FRAMES | 5range, within 1-30 | H.264 paint-over burst frames: allowed range, initial value, or both ("5,1-30"); "5-5" locks. |
--use-cpuSELKIES_USE_CPU | falsebool | Force CPU-based encoding for pixelflux. |
--gpu-idSELKIES_GPU_ID | (empty) str | GPU ID for hardware video encoders: selects /dev/dri/renderD{128 + n} and the GPU-stats index. Empty (default) sets no explicit pick, encoding on ID 0 — the first GPU — or on the GPU chosen by --auto-gpu; -1 disables hardware encoding. Ignored when --encode-dri specifies a device path. |
--encode-driSELKIES_ENCODE_DRIDRI_NODE | (empty) str | Path to the DRI render node the ENCODER uses (VA-API/NVENC device selection). |
--webrtc-pacerSELKIES_WEBRTC_PACER | truebool | Pace outgoing WebRTC packets per transport with strict priorities (audio/RTCP > data-channel > video), an IDR-aware video queue budget and GOP-reset recovery, so audio and interactive signaling are protected from video bursts on congested links. Enabled by default; set SELKIES_WEBRTC_PACER=false to disable. SELKIES_WEBRTC_PACER_STALE_MS sets the stale-GOP purge deadline in milliseconds (0 = disabled). |
--backpressure-queue-sizeSELKIES_BACKPRESSURE_QUEUE_SIZE | 120int, 1 to 100000 | Max frames/audio chunks buffered per stream before dropping under backpressure (WebSockets mode). Higher tolerates larger client hiccups at the cost of latency. |
Audio
Server-to-client audio and the microphone uplink.
| Setting | Default | Description |
|---|---|---|
--audio-enabledSELKIES_AUDIO_ENABLED | truebool | Enable server-to-client audio streaming. Disabling this will also disable microphone support. |
--audio-bitrateSELKIES_AUDIO_BITRATE | 128000enum: one of 32000, 48000, 64000, 96000, 128000, 192000, 256000, 320000, 384000, 510000, or any value from 6000 to 510000 | The default audio bitrate. |
--audio-channelsSELKIES_AUDIO_CHANNELS | 2int, from 1 | Number of audio channels, defaults to stereo (2 channels) |
--audio-device-nameSELKIES_AUDIO_DEVICE_NAME | output.monitorstr | Audio device name for pcmflux capture. |
--audio-frame-duration-msSELKIES_AUDIO_FRAME_DURATION_MS | 10enum: one of 2.5, 5, 10, 20, 40, 60 | Opus frame duration in milliseconds for server-to-client audio. Lower values cut audio latency (each frame must fill before it can be sent, and the client buffers a fixed number of frames) at a small bitrate-efficiency and packet-rate cost. On WebRTC the SDP ptime/minptime follow this value. |
--audio-redundancySELKIES_AUDIO_REDUNDANCY | truebool | Enable Opus RED (RFC 2198) audio redundancy to cut dropouts/concealment under packet loss. On by default; carries prior frames as redundancy on WebRTC (browsers de-RED natively, plain-opus fallback for peers that decline) and, on WebSocket, is gated on every client supporting it. |
--audio-redundancy-distanceSELKIES_AUDIO_REDUNDANCY_DISTANCE | 2int, 0 to 4 | Number of prior Opus frames carried as RED redundancy when audio_redundancy is enabled (0-4; higher survives longer loss bursts at proportionally more bandwidth). |
--microphone-enabledSELKIES_MICROPHONE_ENABLED | falsebool | Enable client-to-server microphone forwarding. |
Display
Resolution, scaling, cursors, and the second display.
| Setting | Default | Description |
|---|---|---|
--enable-resizeSELKIES_ENABLE_RESIZE | truebool | Enable dynamic resizing to match browser size |
--manual-resolutionSELKIES_MANUAL_RESOLUTION | falsebool | Lock the resolution to the manual width/height values. |
--manual-widthSELKIES_MANUAL_WIDTH | 0int | Lock width to a fixed value. Setting this forces manual resolution mode. |
--manual-heightSELKIES_MANUAL_HEIGHT | 0int | Lock height to a fixed value. Setting this forces manual resolution mode. |
--force-aligned-resolutionSELKIES_FORCE_ALIGNED_RESOLUTION | falsebool | Forces the display resolution to be a multiple of 16 pixels. |
--scaling-dpiSELKIES_SCALING_DPI | 96enum: one of 96, 120, 144, 168, 192, 216, 240, 264, 288 | The default DPI for UI scaling. |
--use-css-scalingSELKIES_USE_CSS_SCALING | falsebool | HiDPI when false, if true a lower resolution is sent from the client and the canvas is stretched; the UI scaling pick then divides that resolution and the desktop stays at 96 DPI. |
--second-screenSELKIES_SECOND_SCREEN | truebool | Enable support for a second monitor/display. |
--enable-cursorsSELKIES_ENABLE_CURSORS | truebool | Enable passing remote cursors to client |
--cursor-sizeSELKIES_CURSOR_SIZEXCURSOR_SIZE | -1int | Cursor size in points at 96 DPI (scaled with the session DPI) for the X11 server cursor and the Wayland compositor cursor theme; -1 uses the platform default (32 on X11, 24 on Wayland). Independent of it, remote-cursor capture delivers an application's own cursor whole up to 128 points, the most a browser shows as a cursor, and a size set here beyond that raises the cap with it. |
--use-browser-cursorsSELKIES_USE_BROWSER_CURSORS | truebool | Use browser CSS cursors instead of rendering to canvas. |
--raw-pointer-motionSELKIES_RAW_POINTER_MOTION | truebool | Ask the browser for unaccelerated (raw) pointer movement under pointer lock, so a locked pointer travels by the mouse's own counts rather than the local acceleration curve; Windows and macOS grant it, Linux and Android refuse it and keep the curve either way. Clients leave it off on macOS unless it is chosen or set here, since that curve is what carries a slow hand across the remote screen. Clients may override per user unless the value is locked. |
--watermark-pathSELKIES_WATERMARK_PATHWATERMARK_PNG | (empty) str | Absolute path to the watermark PNG file. |
--watermark-locationSELKIES_WATERMARK_LOCATIONWATERMARK_LOCATION | -1int | Watermark location enum (0-6). |
--debug-cursorsSELKIES_DEBUG_CURSORS | falsebool | Enable cursor debug logging |
Backends
The X11 or Wayland capture backend and the GPU it renders on.
| Setting | Default | Description |
|---|---|---|
--waylandSELKIES_WAYLANDPIXELFLUX_WAYLAND | falsebool | Run the Wayland (headless compositor) backend instead of X11 capture/input (default: X11); PIXELFLUX_WAYLAND remains as a legacy fallback. |
--render-driSELKIES_RENDER_DRIDRINODE | (empty) str | Path to the DRI render node the Wayland compositor RENDERS on (defaults to auto_gpu selection, else software rendering). |
--auto-gpuSELKIES_AUTO_GPUAUTO_GPU | truestr | GPU auto-selection for rendering, enabled by default: "true" picks the first GPU; "false" disables it; otherwise a case-insensitive token picks the first GPU it matches — a vendor name (nvidia, amd/ati, intel, arm/mali, qualcomm/adreno, broadcom/videocore, apple, imagination/powervr, vmware, virtio, ...), a kernel driver name (amdgpu, i915, xe, nouveau, panfrost, msm, v3d, ...), a devicetree vendor prefix (qcom, rockchip, brcm, ...), or a raw PCI vendor ID (0x10de). |
--app-wayland-displaySELKIES_APP_WAYLAND_DISPLAY | (empty) str | Wayland socket where applications run — the target for input injection and clipboard — when it differs from the pixelflux capture compositor (e.g. a nested session that pixelflux captures). Empty auto-detects the nested compositor socket in XDG_RUNTIME_DIR, falling back to the capture compositor when nothing is nested. |
--wayland-host-displaySELKIES_WAYLAND_HOST_DISPLAY | (empty) str | Wayland socket of an EXTERNAL compositor (e.g. labwc started with WLR_BACKENDS=headless, or the GNOME/KDE session's own socket) that pixelflux captures and injects into as a client, instead of compositing its own. Frames arrive by screencopy into pixelflux-allocated GPU buffers (zero-copy into the encoder) and input rides virtual-keyboard/pointer devices where the compositor offers those protocols; a compositor without them (GNOME, KDE) is captured and driven through xdg-desktop-portal over the session bus, PipeWire frames imported in place. Empty keeps the built-in compositor. |
--wayland-socket-indexSELKIES_WAYLAND_SOCKET_INDEX | 0int, from 0 | Index for the Wayland command socket (e.g. 0 for wayland-0). |
--computer-use-bindSELKIES_COMPUTER_USE_BIND | (empty) str | Start pixelflux's Computer-Use HTTP server on comma-separated entries: a bare port listens on the loopback addresses only, host:port names the address to listen on (0.0.0.0:9500,[::]:9500 accepts connections on every interface). Empty leaves it off; the PIXELFLUX_CU environment variable remains the standalone fallback. |
Session start
What a session starts with, and hooks around its first and last client.
| Setting | Default | Description |
|---|---|---|
--video-on-startSELKIES_VIDEO_ON_START | truebool | Start a session with the display's video stream on. Off, nothing is captured for the primary display until the client turns video on with the side menu toggle; a shared viewer and a second display page always start their stream. |
--audio-on-startSELKIES_AUDIO_ON_START | truebool | Start a session with server-to-client audio on. Off, the audio capture stays stopped until the client turns audio on with the side menu toggle; on WebRTC the audio track is negotiated but carries nothing until then. Unlike audio_enabled=false, nothing is torn down and the microphone keeps working. |
--microphone-on-startSELKIES_MICROPHONE_ON_START | falsestr | Microphone uplink policy: "true" asks the browser for the device as soon as the session connects, "false" waits for the side menu toggle, and "demand" asks only while an application in the session records from the virtual source, released ten seconds after the last one stops (an application that records in the background and mutes in software keeps it asked for). A microphone_enabled locked off leaves it off either way. |
--webcam-on-startSELKIES_WEBCAM_ON_START | falsestr | Webcam uplink policy: "true" asks the browser for the camera as soon as the session connects, "false" waits for the side menu toggle, and "demand" asks only while an application in the session holds the virtual device open, released two seconds after the last one closes it; the device then exists before any uplink, so a webcam_pixel_format of "auto" resolves to I420. A webcam_enabled locked off leaves it off either way. |
--gamepad-on-startSELKIES_GAMEPAD_ON_START | truebool | Start a session with gamepad input on. Off, connected gamepads are not polled until the client turns them on with the side menu toggle; a choice made there is remembered by the browser and takes precedence on its later visits. |
--app-wait-readySELKIES_APP_WAIT_READY | falsebool | Waits for --app-ready-file to exist before starting stream if set to "true" |
--app-ready-fileSELKIES_APP_READY_FILE | /tmp/selkies-appreadystr | File set by sidecar used to indicate that app is initialized and ready |
--run-after-connectSELKIES_RUN_AFTER_CONNECT | (empty) str | Shell command run after the first client has connected ('' = off); runs again each time a client connects while no others are connected. |
--run-after-disconnectSELKIES_RUN_AFTER_DISCONNECT | (empty) str | Shell command run after the last client has disconnected ('' = off), including on server shutdown while clients are connected. |
Input
Gamepads, keyboard chords, and the input devices published to the session.
| Setting | Default | Description |
|---|---|---|
--gamepad-enabledSELKIES_GAMEPAD_ENABLED | truebool | Enable gamepad support. |
--uinput-gamepadSELKIES_UINPUT_GAMEPAD | autostr | Register gamepads as kernel devices through /dev/uinput, which applications (Steam, Proton, in-desktop browsers) find without the Input Interposer or fake-udev: "auto" does so only where the interposer is not configured for the session and /dev/uinput is writable — typically a desktop host rather than a container — while "true" always attempts it and "false" never does. |
--js-socket-pathSELKIES_JS_SOCKET_PATH | /tmpstr | Directory to write the Selkies Input Interposer communication sockets to, default: /tmp, results in socket files: /tmp/selkies_js{0-3}.sock |
--uinput-mouse-socketSELKIES_UINPUT_MOUSE_SOCKET | (empty) str | Path to the uinput mouse socket, if not provided uinput is used directly |
--publish-input-devicesSELKIES_PUBLISH_INPUT_DEVICES | falsebool | Mirror the session keyboard and pointer onto input devices applications can read, for the few that enumerate evdev instead of the display server (fullscreen games, remappers). The desktop is driven by the compositor's virtual keyboard or XTEST either way, so this adds a copy of each event and never carries it; it costs a kernel device where /dev/uinput is writable, else an Input Interposer one. |
--keyboard-shortcutsSELKIES_KEYBOARD_SHORTCUTS | truebool | Let the client keep its own chords (Control+Shift with F, M, X, or G, and Control+Shift+click) instead of passing them to the session. Turn it off where an application in the session binds the same chords; the side menu's buttons still reach every function, and pressing Escape three times still leaves gaming mode. Clients may override per user unless the value is locked. |
--mac-cmd-as-ctrlSELKIES_MAC_CMD_AS_CTRL | truebool | Send a macOS client's Command chords as their Control chords, so Cmd+C copies in the remote application the way it does locally. Turn it off where the session's window manager takes Super as its own modifier: remapped, a Cmd+Return bound to open a terminal arrives as Ctrl+Return, and Cmd+C interrupts the foreground program instead of copying. Command then arrives as the Super it physically is. Only macOS clients read it. Clients may override per user unless the value is locked. |
Clipboard, files, and printing
What leaves and enters the session besides the stream.
| Setting | Default | Description |
|---|---|---|
--enable-clipboardSELKIES_ENABLE_CLIPBOARD | truestr | Clipboard policy for both transports: "true" (both directions), "in" (client-to-server only), "out" (server-to-client only), "false" (disabled). "out" is what stops the page reading the local clipboard at all, which is the read Firefox and Safari raise their paste prompt for; the dashboard's clipboard box still sends. |
--enable-binary-clipboardSELKIES_ENABLE_BINARY_CLIPBOARD | truebool | Allow binary data (e.g., images) on the clipboard. |
--clipboard-seamlessSELKIES_CLIPBOARD_SEAMLESS | truebool | Synchronize the clipboard as the session and the browser change it, so a copy on either side is ready to paste on the other without asking. Turn it off to move clipboard content only when the user asks for it, through the side menu's clipboard box, which suits a session whose content should not follow the user out of it by accident. The direction settings still bound what moves either way. Clients may override per user unless the value is locked. |
--file-transfersSELKIES_FILE_TRANSFERS | upload,downloadlist: any of upload, download | Allowed file transfer directions (comma-separated: "upload,download"). Set to "" or "none" to disable. |
--file-manager-pathSELKIES_FILE_MANAGER_PATHFILE_MANAGER_PATH | ~/Desktopstr | Directory for client file transfers on both transports: uploads land here and the file-browser/download API serves it (created at startup if missing). |
--file-transfer-limit-mbpsSELKIES_FILE_TRANSFER_LIMIT_MBPS | 0.0float, from 0.0 | Static file-transfer throttle in Mbit/s, one allowance shared by all downloads and uploads, for links whose rate the operator knows. 0 disables. The congestion-control pacing protects the video stream without it, in both directions and end to end through a reverse proxy; the cap is for holding transfers to a fixed share regardless. |
--printing-enabledSELKIES_PRINTING_ENABLED | truebool | Hand the documents printed in the session to the browser: a job printed to the session's Selkies queue lands in the print spool as a PDF, and the page opens it in the browser's print dialog. Off refuses the documents and shows no printer section. |
--print-spool-pathSELKIES_PRINT_SPOOL_PATH | ~/.local/state/selkies/printstr | Directory the session's print queue writes finished jobs into as PDFs, watched for documents to hand to the browser and created at startup when missing; a document is removed once a page has taken it. |
Webcam
The camera uplink and the virtual V4L2 device it is published as.
| Setting | Default | Description |
|---|---|---|
--webcam-enabledSELKIES_WEBCAM_ENABLED | falsebool | Enable client-to-server webcam forwarding to the virtual V4L2 device. |
--webcam-encoderSELKIES_WEBCAM_ENCODER | autoenum: one of auto, h264, h265, vp8, vp9, av1, mjpeg | Codec clients encode the webcam uplink with. Over WebSockets "auto" runs the measured ladder (H.264, else VP8, then VP9, AV1, and H.265 where the engine encodes them, JPEG when none keeps up) on engines that stream camera frames through MediaStreamTrackProcessor, and JPEG on the <video>-element path (Firefox): its software encoders can hold the camera rate while costing a full core, which no client-side probe can price. A codec name runs that one codec on every path, trading client CPU for a fraction of the uplink bandwidth, still falling to JPEG where it cannot keep up or encodes the wrong colors; "mjpeg" pins JPEG everywhere. Over WebRTC the browser sends its camera as the named codec when the answer negotiated it, and otherwise, as for "auto" and "mjpeg", as the first codec negotiated. Clients may override per user unless the value is locked. |
--webcam-widthSELKIES_WEBCAM_WIDTH | 1280int | Width of the virtual webcam device; client camera frames are scaled and letterboxed to fit. |
--webcam-heightSELKIES_WEBCAM_HEIGHT | 720int | Height of the virtual webcam device; client camera frames are scaled and letterboxed to fit. |
--webcam-pixel-formatSELKIES_WEBCAM_PIXEL_FORMAT | autostr | Pixel format of the virtual webcam device. "auto" follows the uplink: a browser sending JPEG (no WebCodecs) gets an MJPEG device that carries its frames as received, any other uplink an I420 device, and a later uplink of the other kind re-creates the device for itself while no application is reading it. Or pin "I420" (planar 4:2:0, the browsers' preference), "NV12", "YUYV", or "MJPEG", which is then kept whatever arrives. |
--webcam-deviceSELKIES_WEBCAM_DEVICE | autostr | Also mirror the webcam into a v4l2loopback kernel device, which applications find without the V4L2 Interposer: "auto" uses the first v4l2loopback output device found (typically a desktop host or privileged container), a path such as "/dev/video10" uses that device, and "false" never does. The interposer socket is always served. |
--webcam-socket-pathSELKIES_WEBCAM_SOCKET_PATH | /tmpstr | Directory to write the Selkies V4L2 Interposer webcam socket to, default: /tmp, results in socket file: /tmp/selkies_webcam0.sock |
Sharing
Viewer and player links for a session without provisioned tokens.
| Setting | Default | Description |
|---|---|---|
--enable-sharingSELKIES_ENABLE_SHARING | truebool | Master toggle for all sharing features. |
--enable-sharedSELKIES_ENABLE_SHARED | truebool | Enable view-only sharing links. |
--enable-collabSELKIES_ENABLE_COLLAB | truebool | Let a viewer holding the session's master-key token act as a read-write collaborator (secure mode only; not a sharing link of its own). |
--enable-player2SELKIES_ENABLE_PLAYER2 | truebool | Enable sharing link for gamepad player 2. |
--enable-player3SELKIES_ENABLE_PLAYER3 | truebool | Enable sharing link for gamepad player 3. |
--enable-player4SELKIES_ENABLE_PLAYER4 | truebool | Enable sharing link for gamepad player 4. |
Client interface
What the shipped web interface shows; the feature behind a hidden control keeps working.
| Setting | Default | Description |
|---|---|---|
--ui-titleSELKIES_UI_TITLE | Selkiesstr | Title in top left corner of sidebar. |
--ui-show-logoSELKIES_UI_SHOW_LOGO | truebool | Show the Selkies logo in the sidebar. |
--ui-show-sidebarSELKIES_UI_SHOW_SIDEBAR | truebool | Show the main sidebar UI. |
--ui-show-core-buttonsSELKIES_UI_SHOW_CORE_BUTTONS | truebool | Show the core components buttons display, audio, microphone, webcam, and gamepad. |
--ui-sidebar-show-video-settingsSELKIES_UI_SIDEBAR_SHOW_VIDEO_SETTINGS | truebool | Show the video settings section in the sidebar. |
--ui-sidebar-show-screen-settingsSELKIES_UI_SIDEBAR_SHOW_SCREEN_SETTINGS | truebool | Show the screen settings section in the sidebar. |
--ui-sidebar-show-audio-settingsSELKIES_UI_SIDEBAR_SHOW_AUDIO_SETTINGS | truebool | Show the audio settings section in the sidebar. |
--ui-sidebar-show-statsSELKIES_UI_SIDEBAR_SHOW_STATS | truebool | Show the stats section in the sidebar. |
--ui-sidebar-show-shortcutsSELKIES_UI_SIDEBAR_SHOW_SHORTCUTS | truebool | Show the keyboard shortcuts section in the sidebar (both dashboards honor this). |
--ui-sidebar-show-clipboardSELKIES_UI_SIDEBAR_SHOW_CLIPBOARD | truebool | Show the clipboard section in the sidebar. |
--ui-sidebar-show-filesSELKIES_UI_SIDEBAR_SHOW_FILES | truebool | Show the file transfer section in the sidebar. |
--ui-sidebar-show-appsSELKIES_UI_SIDEBAR_SHOW_APPS | truebool | Show the applications section in the sidebar. |
--ui-sidebar-show-sharingSELKIES_UI_SIDEBAR_SHOW_SHARING | truebool | Show the sharing section in the sidebar. |
--ui-sidebar-show-gamepadsSELKIES_UI_SIDEBAR_SHOW_GAMEPADS | truebool | Show the gamepads section in the sidebar. |
--ui-sidebar-show-webcamSELKIES_UI_SIDEBAR_SHOW_WEBCAM | truebool | Show the webcam toggle among the core buttons (classic sidebar) and stream controls (wish top menu). Hides the control only; webcam_enabled governs whether the server accepts webcam frames. |
--ui-sidebar-show-fullscreenSELKIES_UI_SIDEBAR_SHOW_FULLSCREEN | truebool | Show the fullscreen button in the sidebar. |
--ui-sidebar-show-gaming-modeSELKIES_UI_SIDEBAR_SHOW_GAMING_MODE | truebool | Show the gaming mode button in the sidebar. |
--ui-sidebar-show-trackpadSELKIES_UI_SIDEBAR_SHOW_TRACKPAD | truebool | Show the virtual trackpad button in the sidebar. |
--ui-sidebar-show-keyboard-buttonSELKIES_UI_SIDEBAR_SHOW_KEYBOARD_BUTTON | truebool | Show the on-screen keyboard button in the display area. |
--ui-sidebar-show-soft-buttonsSELKIES_UI_SIDEBAR_SHOW_SOFT_BUTTONS | truebool | Show the soft buttons section in the sidebar. |
Server
The transport, the listening address, TLS, the login, and the master token.
| Setting | Default | Description |
|---|---|---|
--modeSELKIES_MODE | websocketsstr | Specify the mode: 'webrtc' or 'websockets'; defaults to websockets |
--enable-dual-modeSELKIES_ENABLE_DUAL_MODE | truebool | Enable switching Streaming modes from UI |
--addrSELKIES_ADDR | localhoststr | Address the streaming service listens on: a host name or IP address, or a comma-separated list of them, bound on every address each resolves to. The default binds the loopback addresses only (127.0.0.1,::1); to accept connections on every interface pass --public instead, never both. |
--publicSELKIES_PUBLIC | falsebool | Accept connections on every interface, IPv4 and IPv6 (0.0.0.0,::), instead of the loopback addresses only; the bare flag turns it on. Given together with --addr, the server refuses to start. |
--portSELKIES_PORTCUSTOM_WS_PORT | 8080int, 1 to 65535 | Port to start the streaming service, default: "8080" |
--unix-socketSELKIES_UNIX_SOCKET | (empty) str | Unix socket path to start the streaming service; when set, a Unix domain socket is bound instead of the TCP addr/port pair. |
--subfolderSELKIES_SUBFOLDERSUBFOLDER | (empty) str | URL path prefix the server is reverse-proxied under; prepended to every route (websockets, tokens, metrics, static files). Slashes are optional, so "desk", "/desk", and "/desk/" are the same prefix and "/" is the root. The web client reads its own prefix from the URL it was loaded from, so only the server needs telling. |
--web-rootSELKIES_WEB_ROOT | (empty) str | Path to directory containing web application files. Defaults to web files packaged with Selkies application |
--allowed-originsSELKIES_ALLOWED_ORIGINS | (empty) str | Comma-separated browser Origins allowed to open the streaming WebSocket (cross-site WebSocket-hijacking guard). Empty (default) allows only same-origin plus non-browser clients that send no Origin; use '*' to allow any origin. |
--enable-httpsSELKIES_ENABLE_HTTPS | falsebool | Enable or disable HTTPS for the web application, specifying a valid server certificate is recommended |
--https-certSELKIES_HTTPS_CERT | /etc/ssl/certs/ssl-cert-snakeoil.pemstr | Path to the TLS server certificate file when HTTPS is enabled |
--https-keySELKIES_HTTPS_KEY | /etc/ssl/private/ssl-cert-snakeoil.keystr | Path to the TLS server private key file when HTTPS is enabled, set to an empty value if the private key is included in the certificate Never sent to clients. |
--cert-reload-intervalSELKIES_CERT_RELOAD_INTERVAL | 30int, from 0 | Seconds between checks for SSL certificate file changes when HTTPS is enabled, set to 0 to disable automatic certificate reloading |
--enable-basic-authSELKIES_ENABLE_BASIC_AUTH | truebool | Enable basic authentication on the server. On by default, and the server refuses to start until a password is set through --basic-auth-password, SELKIES_BASIC_AUTH_PASSWORD, PASSWORD or PASSWD; pass --enable-basic-auth=false to serve without a login instead. |
--basic-auth-userSELKIES_BASIC_AUTH_USERCUSTOM_USERUSERNAMEUSER | ubuntustr | Username for basic authentication; resolves from the CUSTOM_USER, then USERNAME, then USER environment variables, and defaults to "ubuntu" when none is set. Never sent to clients. |
--basic-auth-passwordSELKIES_BASIC_AUTH_PASSWORDPASSWORDPASSWD | (empty) str | Password used when basic authentication is set; resolves from SELKIES_BASIC_AUTH_PASSWORD, then PASSWORD, then PASSWD, so an image that already names a container account password does not have to repeat it. There is no default: the server will not start with basic authentication enabled until one of these is set. Never sent to clients. |
--basic-auth-viewonly-passwordSELKIES_BASIC_AUTH_VIEWONLY_PASSWORDVIEWONLY_PASSWORD | (empty) str | Optional second basic-auth password that grants view-only access. Clients authenticating with it are capped at the viewer role (no keyboard, mouse, clipboard, gamepad, or command input) regardless of the role they request, while the main password authorizes full control. Empty disables the split. Ignored in secure mode, where the master token governs roles. Never sent to clients. |
--master-tokenSELKIES_MASTER_TOKEN | (empty) str | Master token to enable secure mode and protect the control plane API. Never sent to clients. |
--command-enabledSELKIES_COMMAND_ENABLED | falsebool | Enable parsing of command websocket messages. Disabled by default for security; opt in with SELKIES_COMMAND_ENABLED=true (or --command-enabled true). |
--debugSELKIES_DEBUG | falsebool | Enable debug logging. |
WebRTC and TURN
The opt-in WebRTC transport's ICE, STUN and TURN configuration.
| Setting | Default | Description |
|---|---|---|
--rtc-config-jsonSELKIES_RTC_CONFIG_JSON | /tmp/rtc.jsonstr | JSON file with WebRTC configuration to use, checked periodically, overriding all other STUN/TURN settings |
--turn-hostSELKIES_TURN_HOST | staticauth.openrelay.metered.castr | TURN host when generating RTC config from shared secret or using long-term credentials, IPv6 addresses must be enclosed with square brackets such as [::1] |
--turn-portSELKIES_TURN_PORT | 443int, 1 to 65535 | TURN port when generating RTC config from shared secret or using long-term credentials |
--turn-protocolSELKIES_TURN_PROTOCOL | udpstr | TURN protocol for the client to use ("udp" or "tcp"), set to "tcp" without the quotes if "udp" is blocked on the network, "udp" is otherwise strongly recommended |
--turn-tlsSELKIES_TURN_TLS | falsebool | Enable or disable TURN over TLS (for the TCP protocol) or TURN over DTLS (for the UDP protocol), valid TURN server certificate required |
--turn-shared-secretSELKIES_TURN_SHARED_SECRET | openrelayprojectsecretstr | Shared TURN secret used to generate HMAC credentials, also requires --turn-host and --turn-port Never sent to clients. |
--turn-usernameSELKIES_TURN_USERNAME | (empty) str | Legacy non-HMAC TURN credential username, also requires --turn-host and --turn-port |
--turn-passwordSELKIES_TURN_PASSWORD | (empty) str | Legacy non-HMAC TURN credential password, also requires --turn-host and --turn-port Never sent to clients. |
--turn-rest-uriSELKIES_TURN_REST_URI | (empty) str | URI for TURN REST API service, example: http://localhost:8008 |
--turn-rest-api-keySELKIES_TURN_REST_API_KEY | (empty) str | API key to pass to the TURN REST API service Never sent to clients. |
--turn-rest-usernameSELKIES_TURN_REST_USERNAME | (empty) str | Username sent to the TURN REST API service (x-auth-user header); the service embeds it in the HMAC credential. Empty (default) uses the generic 'selkies'. |
--turn-rest-username-auth-headerSELKIES_TURN_REST_USERNAME_AUTH_HEADER | x-auth-userstr | Header to pass user to TURN REST API service |
--turn-rest-protocol-headerSELKIES_TURN_REST_PROTOCOL_HEADER | x-turn-protocolstr | Header to pass desired TURN protocol to TURN REST API service |
--turn-rest-tls-headerSELKIES_TURN_REST_TLS_HEADER | x-turn-tlsstr | Header to pass TURN (D)TLS usage to TURN REST API service |
--stun-hostSELKIES_STUN_HOST | stun.l.google.comstr | STUN host for NAT hole punching with WebRTC, change to your internal STUN/TURN server for local networks without internet, defaults to "stun.l.google.com" |
--stun-portSELKIES_STUN_PORT | 19302int, 1 to 65535 | STUN port for NAT hole punching with WebRTC, change to your internal STUN/TURN server for local networks without internet, defaults to "19302" |
--enable-cloudflare-turnSELKIES_ENABLE_CLOUDFLARE_TURN | falsebool | Enable Cloudflare TURN service, requires SELKIES_CLOUDFLARE_TURN_TOKEN_ID, and SELKIES_CLOUDFLARE_TURN_API_TOKEN |
--cloudflare-turn-token-idSELKIES_CLOUDFLARE_TURN_TOKEN_ID | (empty) str | The Cloudflare TURN App token ID. Never sent to clients. |
--cloudflare-turn-api-tokenSELKIES_CLOUDFLARE_TURN_API_TOKEN | (empty) str | The Cloudflare TURN API token. Never sent to clients. |
--webrtc-public-ipSELKIES_WEBRTC_PUBLIC_IP | (empty) str | Public IP address(es) to advertise in WebRTC host ICE candidates (Pion-style NAT1TO1), for a host behind static 1:1 NAT such as a cloud instance whose private address maps to a fixed public/elastic IP with the WebRTC UDP ports forwarded. Accepts one IPv4 and/or one IPv6 address (comma- or space-separated); each replaces the private address of host candidates in its own family, while server-reflexive (STUN) and relay (TURN) candidates are left untouched so hole-punching and TURN fallback still work. Empty (default) keeps the gathered addresses unchanged. |
--webrtc-port-rangeSELKIES_WEBRTC_PORT_RANGE | (empty) str | Inclusive UDP port range "min-max" (e.g. "50000-50100") that the local sockets behind direct WebRTC host ICE candidates bind into, for scheduler-managed deployments that allot each session a small firewalled window. Both bounds must lie within 1024-65535; a malformed or out-of-range value is rejected rather than clamped. Distinct from TURN_MIN_PORT/TURN_MAX_PORT, which confine the TURN relay allocation on the TURN server. Empty (default) keeps ephemeral OS-assigned ports. |
--webrtc-udp-mux-portSELKIES_WEBRTC_UDP_MUX_PORT | 0int, 0 to 65535 | Single UDP port every WebRTC session shares for its host ICE candidates (UDPMUX): bound once on each host address at startup, with sessions told apart by their ICE username fragment, so one forwarded port (e.g. "-p 59000:59000/udp") serves any number of sessions. STUN server-reflexive discovery rides the same port; TURN relay and mDNS sockets stay separate, and webrtc_port_range is unused. 0 (default) gives each session sockets of its own. |
--webrtc-tcp-mux-portSELKIES_WEBRTC_TCP_MUX_PORT | 0int, 0 to 65535 | Single TCP port on which the server accepts ICE-TCP connections (TCPMUX), advertised as a passive TCP host candidate on each host address next to the UDP ones, so a client on a network that blocks UDP still connects; UDP is preferred whenever it works. It may equal the UDP mux port, and a port firewalls pass, such as 443, is the usual choice for a public deployment. 0 (default) offers no TCP candidates. |
--webrtc-ice-liteSELKIES_WEBRTC_ICE_LITE | falsebool | Run the server's ICE agent as ICE-lite: it offers host candidates only, takes the controlled role and answers the client's connectivity checks instead of sending its own, which suits a server whose host candidates are reachable as advertised (a public address, a static 1:1 NAT with webrtc_public_ip, or forwarded mux ports). STUN and TURN are then unused by the server itself; clients still receive them for candidates of their own. |
Recording, audit, and metrics
The recording tap, the audit webhook and the metrics endpoints.
| Setting | Default | Description |
|---|---|---|
--recording-socketSELKIES_RECORDING_SOCKETPIXELFLUX_RECORDING_SOCKET | (empty) str | Unix socket path for the out-of-band H.264 recording tap ('' = off); pixelflux binds it and multiplexes the elementary stream to connected clients. |
--audit-webhook-urlSELKIES_AUDIT_WEBHOOK_URL | (empty) str | URL that receives one JSON POST per clipboard transfer, file upload, file download, printed document handed over, page connection, and recording, carrying metadata only (the event, an RFC 3339 timestamp, byte size, MIME type, or file name) and never the content. Events are delivered in order over one keep-alive connection; a collector that is slow or down loses what overflows the queue rather than stalling the session. Empty (default) sends nothing. |
--audit-webhook-tokenSELKIES_AUDIT_WEBHOOK_TOKEN | (empty) str | Bearer token sent in the Authorization header of every audit POST. Empty sends no header. Never sent to clients. |
--audit-webhook-timeoutSELKIES_AUDIT_WEBHOOK_TIMEOUT | 2.0float, from 0.1 | Seconds one audit POST may take before it counts as failed and the next event is sent. |
--enable-metrics-httpSELKIES_ENABLE_METRICS_HTTP | falsebool | Enable the Prometheus HTTP /metrics endpoint. |
--enable-webrtc-statisticsSELKIES_ENABLE_WEBRTC_STATISTICS | falsebool | Enable WebRTC Statistics CSV dumping to the directory --webrtc-statistics-dir with filenames selkies-stats-video-[timestamp].csv and selkies-stats-audio-[timestamp].csv |
--webrtc-statistics-dirSELKIES_WEBRTC_STATISTICS_DIR | /tmpstr | Directory to save WebRTC Statistics CSV from client with filenames selkies-stats-video-[timestamp].csv and selkies-stats-audio-[timestamp].csv |