Selkies

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.

SettingDefaultDescription
--encoder
SELKIES_ENCODER
h264enc
enum: 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-fullcolor
SELKIES_VIDEO_FULLCOLOR
false
bool
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.
--framerate
SELKIES_FRAMERATE
60
range, within 8-240
Framerate: allowed range (e.g., "8-240"), initial value (e.g., "60"), or both ("60,8-240"); "60-60" locks.
--video-bitrate
SELKIES_VIDEO_BITRATE
8000
range, 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-crf
SELKIES_VIDEO_CRF
25
range, 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-mode
SELKIES_RATE_CONTROL_MODE
crf
enum: 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-control
SELKIES_ENABLE_RATE_CONTROL
true
bool
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-control
SELKIES_CONGESTION_CONTROL
false
bool
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-interval
SELKIES_KEYFRAME_INTERVAL
0.0
float, 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-qp
SELKIES_VIDEO_MIN_QP
0
int, 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-qp
SELKIES_VIDEO_MAX_QP
0
int, 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-quality
SELKIES_JPEG_QUALITY
40
range, 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-mode
SELKIES_VIDEO_STREAMING_MODE
true
bool
Enable video streaming mode (Turbo: encode every frame like a traditional video encoder) for pixelflux encoders.
--use-paint-over-quality
SELKIES_USE_PAINT_OVER_QUALITY
true
bool
Enable high-quality paint-over for static scenes.
--paint-over-jpeg-quality
SELKIES_PAINT_OVER_JPEG_QUALITY
90
range, within 1-100
JPEG paint-over quality: allowed range, initial value, or both ("90,1-100"); "90-90" locks.
--video-paintover-crf
SELKIES_VIDEO_PAINTOVER_CRF
18
range, within 5-50
H.264 paint-over CRF: allowed range, initial value, or both ("18,5-50"); "18-18" locks.
--video-paintover-burst-frames
SELKIES_VIDEO_PAINTOVER_BURST_FRAMES
5
range, within 1-30
H.264 paint-over burst frames: allowed range, initial value, or both ("5,1-30"); "5-5" locks.
--use-cpu
SELKIES_USE_CPU
false
bool
Force CPU-based encoding for pixelflux.
--gpu-id
SELKIES_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-dri
SELKIES_ENCODE_DRI
DRI_NODE
(empty)
str
Path to the DRI render node the ENCODER uses (VA-API/NVENC device selection).
--webrtc-pacer
SELKIES_WEBRTC_PACER
true
bool
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-size
SELKIES_BACKPRESSURE_QUEUE_SIZE
120
int, 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.

SettingDefaultDescription
--audio-enabled
SELKIES_AUDIO_ENABLED
true
bool
Enable server-to-client audio streaming. Disabling this will also disable microphone support.
--audio-bitrate
SELKIES_AUDIO_BITRATE
128000
enum: one of 32000, 48000, 64000, 96000, 128000, 192000, 256000, 320000, 384000, 510000, or any value from 6000 to 510000
The default audio bitrate.
--audio-channels
SELKIES_AUDIO_CHANNELS
2
int, from 1
Number of audio channels, defaults to stereo (2 channels)
--audio-device-name
SELKIES_AUDIO_DEVICE_NAME
output.monitor
str
Audio device name for pcmflux capture.
--audio-frame-duration-ms
SELKIES_AUDIO_FRAME_DURATION_MS
10
enum: 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-redundancy
SELKIES_AUDIO_REDUNDANCY
true
bool
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-distance
SELKIES_AUDIO_REDUNDANCY_DISTANCE
2
int, 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-enabled
SELKIES_MICROPHONE_ENABLED
false
bool
Enable client-to-server microphone forwarding.

Display

Resolution, scaling, cursors, and the second display.

SettingDefaultDescription
--enable-resize
SELKIES_ENABLE_RESIZE
true
bool
Enable dynamic resizing to match browser size
--manual-resolution
SELKIES_MANUAL_RESOLUTION
false
bool
Lock the resolution to the manual width/height values.
--manual-width
SELKIES_MANUAL_WIDTH
0
int
Lock width to a fixed value. Setting this forces manual resolution mode.
--manual-height
SELKIES_MANUAL_HEIGHT
0
int
Lock height to a fixed value. Setting this forces manual resolution mode.
--force-aligned-resolution
SELKIES_FORCE_ALIGNED_RESOLUTION
false
bool
Forces the display resolution to be a multiple of 16 pixels.
--scaling-dpi
SELKIES_SCALING_DPI
96
enum: one of 96, 120, 144, 168, 192, 216, 240, 264, 288
The default DPI for UI scaling.
--use-css-scaling
SELKIES_USE_CSS_SCALING
false
bool
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-screen
SELKIES_SECOND_SCREEN
true
bool
Enable support for a second monitor/display.
--enable-cursors
SELKIES_ENABLE_CURSORS
true
bool
Enable passing remote cursors to client
--cursor-size
SELKIES_CURSOR_SIZE
XCURSOR_SIZE
-1
int
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-cursors
SELKIES_USE_BROWSER_CURSORS
true
bool
Use browser CSS cursors instead of rendering to canvas.
--raw-pointer-motion
SELKIES_RAW_POINTER_MOTION
true
bool
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-path
SELKIES_WATERMARK_PATH
WATERMARK_PNG
(empty)
str
Absolute path to the watermark PNG file.
--watermark-location
SELKIES_WATERMARK_LOCATION
WATERMARK_LOCATION
-1
int
Watermark location enum (0-6).
--debug-cursors
SELKIES_DEBUG_CURSORS
false
bool
Enable cursor debug logging

Backends

The X11 or Wayland capture backend and the GPU it renders on.

SettingDefaultDescription
--wayland
SELKIES_WAYLAND
PIXELFLUX_WAYLAND
false
bool
Run the Wayland (headless compositor) backend instead of X11 capture/input (default: X11); PIXELFLUX_WAYLAND remains as a legacy fallback.
--render-dri
SELKIES_RENDER_DRI
DRINODE
(empty)
str
Path to the DRI render node the Wayland compositor RENDERS on (defaults to auto_gpu selection, else software rendering).
--auto-gpu
SELKIES_AUTO_GPU
AUTO_GPU
true
str
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-display
SELKIES_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-display
SELKIES_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-index
SELKIES_WAYLAND_SOCKET_INDEX
0
int, from 0
Index for the Wayland command socket (e.g. 0 for wayland-0).
--computer-use-bind
SELKIES_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.

SettingDefaultDescription
--video-on-start
SELKIES_VIDEO_ON_START
true
bool
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-start
SELKIES_AUDIO_ON_START
true
bool
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-start
SELKIES_MICROPHONE_ON_START
false
str
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-start
SELKIES_WEBCAM_ON_START
false
str
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-start
SELKIES_GAMEPAD_ON_START
true
bool
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-ready
SELKIES_APP_WAIT_READY
false
bool
Waits for --app-ready-file to exist before starting stream if set to "true"
--app-ready-file
SELKIES_APP_READY_FILE
/tmp/selkies-appready
str
File set by sidecar used to indicate that app is initialized and ready
--run-after-connect
SELKIES_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-disconnect
SELKIES_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.

SettingDefaultDescription
--gamepad-enabled
SELKIES_GAMEPAD_ENABLED
true
bool
Enable gamepad support.
--uinput-gamepad
SELKIES_UINPUT_GAMEPAD
auto
str
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-path
SELKIES_JS_SOCKET_PATH
/tmp
str
Directory to write the Selkies Input Interposer communication sockets to, default: /tmp, results in socket files: /tmp/selkies_js{0-3}.sock
--uinput-mouse-socket
SELKIES_UINPUT_MOUSE_SOCKET
(empty)
str
Path to the uinput mouse socket, if not provided uinput is used directly
--publish-input-devices
SELKIES_PUBLISH_INPUT_DEVICES
false
bool
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-shortcuts
SELKIES_KEYBOARD_SHORTCUTS
true
bool
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-ctrl
SELKIES_MAC_CMD_AS_CTRL
true
bool
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.

SettingDefaultDescription
--enable-clipboard
SELKIES_ENABLE_CLIPBOARD
true
str
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-clipboard
SELKIES_ENABLE_BINARY_CLIPBOARD
true
bool
Allow binary data (e.g., images) on the clipboard.
--clipboard-seamless
SELKIES_CLIPBOARD_SEAMLESS
true
bool
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-transfers
SELKIES_FILE_TRANSFERS
upload,download
list: any of upload, download
Allowed file transfer directions (comma-separated: "upload,download"). Set to "" or "none" to disable.
--file-manager-path
SELKIES_FILE_MANAGER_PATH
FILE_MANAGER_PATH
~/Desktop
str
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-mbps
SELKIES_FILE_TRANSFER_LIMIT_MBPS
0.0
float, 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-enabled
SELKIES_PRINTING_ENABLED
true
bool
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-path
SELKIES_PRINT_SPOOL_PATH
~/.local/state/selkies/print
str
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.

SettingDefaultDescription
--webcam-enabled
SELKIES_WEBCAM_ENABLED
false
bool
Enable client-to-server webcam forwarding to the virtual V4L2 device.
--webcam-encoder
SELKIES_WEBCAM_ENCODER
auto
enum: 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-width
SELKIES_WEBCAM_WIDTH
1280
int
Width of the virtual webcam device; client camera frames are scaled and letterboxed to fit.
--webcam-height
SELKIES_WEBCAM_HEIGHT
720
int
Height of the virtual webcam device; client camera frames are scaled and letterboxed to fit.
--webcam-pixel-format
SELKIES_WEBCAM_PIXEL_FORMAT
auto
str
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-device
SELKIES_WEBCAM_DEVICE
auto
str
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-path
SELKIES_WEBCAM_SOCKET_PATH
/tmp
str
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.

SettingDefaultDescription
--enable-sharing
SELKIES_ENABLE_SHARING
true
bool
Master toggle for all sharing features.
--enable-shared
SELKIES_ENABLE_SHARED
true
bool
Enable view-only sharing links.
--enable-collab
SELKIES_ENABLE_COLLAB
true
bool
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-player2
SELKIES_ENABLE_PLAYER2
true
bool
Enable sharing link for gamepad player 2.
--enable-player3
SELKIES_ENABLE_PLAYER3
true
bool
Enable sharing link for gamepad player 3.
--enable-player4
SELKIES_ENABLE_PLAYER4
true
bool
Enable sharing link for gamepad player 4.

Client interface

What the shipped web interface shows; the feature behind a hidden control keeps working.

SettingDefaultDescription
--ui-title
SELKIES_UI_TITLE
Selkies
str
Title in top left corner of sidebar.
--ui-show-logo
SELKIES_UI_SHOW_LOGO
true
bool
Show the Selkies logo in the sidebar.
--ui-show-sidebar
SELKIES_UI_SHOW_SIDEBAR
true
bool
Show the main sidebar UI.
--ui-show-core-buttons
SELKIES_UI_SHOW_CORE_BUTTONS
true
bool
Show the core components buttons display, audio, microphone, webcam, and gamepad.
--ui-sidebar-show-video-settings
SELKIES_UI_SIDEBAR_SHOW_VIDEO_SETTINGS
true
bool
Show the video settings section in the sidebar.
--ui-sidebar-show-screen-settings
SELKIES_UI_SIDEBAR_SHOW_SCREEN_SETTINGS
true
bool
Show the screen settings section in the sidebar.
--ui-sidebar-show-audio-settings
SELKIES_UI_SIDEBAR_SHOW_AUDIO_SETTINGS
true
bool
Show the audio settings section in the sidebar.
--ui-sidebar-show-stats
SELKIES_UI_SIDEBAR_SHOW_STATS
true
bool
Show the stats section in the sidebar.
--ui-sidebar-show-shortcuts
SELKIES_UI_SIDEBAR_SHOW_SHORTCUTS
true
bool
Show the keyboard shortcuts section in the sidebar (both dashboards honor this).
--ui-sidebar-show-clipboard
SELKIES_UI_SIDEBAR_SHOW_CLIPBOARD
true
bool
Show the clipboard section in the sidebar.
--ui-sidebar-show-files
SELKIES_UI_SIDEBAR_SHOW_FILES
true
bool
Show the file transfer section in the sidebar.
--ui-sidebar-show-apps
SELKIES_UI_SIDEBAR_SHOW_APPS
true
bool
Show the applications section in the sidebar.
--ui-sidebar-show-sharing
SELKIES_UI_SIDEBAR_SHOW_SHARING
true
bool
Show the sharing section in the sidebar.
--ui-sidebar-show-gamepads
SELKIES_UI_SIDEBAR_SHOW_GAMEPADS
true
bool
Show the gamepads section in the sidebar.
--ui-sidebar-show-webcam
SELKIES_UI_SIDEBAR_SHOW_WEBCAM
true
bool
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-fullscreen
SELKIES_UI_SIDEBAR_SHOW_FULLSCREEN
true
bool
Show the fullscreen button in the sidebar.
--ui-sidebar-show-gaming-mode
SELKIES_UI_SIDEBAR_SHOW_GAMING_MODE
true
bool
Show the gaming mode button in the sidebar.
--ui-sidebar-show-trackpad
SELKIES_UI_SIDEBAR_SHOW_TRACKPAD
true
bool
Show the virtual trackpad button in the sidebar.
--ui-sidebar-show-keyboard-button
SELKIES_UI_SIDEBAR_SHOW_KEYBOARD_BUTTON
true
bool
Show the on-screen keyboard button in the display area.
--ui-sidebar-show-soft-buttons
SELKIES_UI_SIDEBAR_SHOW_SOFT_BUTTONS
true
bool
Show the soft buttons section in the sidebar.

Server

The transport, the listening address, TLS, the login, and the master token.

SettingDefaultDescription
--mode
SELKIES_MODE
websockets
str
Specify the mode: 'webrtc' or 'websockets'; defaults to websockets
--enable-dual-mode
SELKIES_ENABLE_DUAL_MODE
true
bool
Enable switching Streaming modes from UI
--addr
SELKIES_ADDR
localhost
str
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.
--public
SELKIES_PUBLIC
false
bool
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.
--port
SELKIES_PORT
CUSTOM_WS_PORT
8080
int, 1 to 65535
Port to start the streaming service, default: "8080"
--unix-socket
SELKIES_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.
--subfolder
SELKIES_SUBFOLDER
SUBFOLDER
(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-root
SELKIES_WEB_ROOT
(empty)
str
Path to directory containing web application files. Defaults to web files packaged with Selkies application
--allowed-origins
SELKIES_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-https
SELKIES_ENABLE_HTTPS
false
bool
Enable or disable HTTPS for the web application, specifying a valid server certificate is recommended
--https-cert
SELKIES_HTTPS_CERT
/etc/ssl/certs/ssl-cert-snakeoil.pem
str
Path to the TLS server certificate file when HTTPS is enabled
--https-key
SELKIES_HTTPS_KEY
/etc/ssl/private/ssl-cert-snakeoil.key
str
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-interval
SELKIES_CERT_RELOAD_INTERVAL
30
int, from 0
Seconds between checks for SSL certificate file changes when HTTPS is enabled, set to 0 to disable automatic certificate reloading
--enable-basic-auth
SELKIES_ENABLE_BASIC_AUTH
true
bool
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-user
SELKIES_BASIC_AUTH_USER
CUSTOM_USER
USERNAME
USER
ubuntu
str
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-password
SELKIES_BASIC_AUTH_PASSWORD
PASSWORD
PASSWD
(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-password
SELKIES_BASIC_AUTH_VIEWONLY_PASSWORD
VIEWONLY_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-token
SELKIES_MASTER_TOKEN
(empty)
str
Master token to enable secure mode and protect the control plane API. Never sent to clients.
--command-enabled
SELKIES_COMMAND_ENABLED
false
bool
Enable parsing of command websocket messages. Disabled by default for security; opt in with SELKIES_COMMAND_ENABLED=true (or --command-enabled true).
--debug
SELKIES_DEBUG
false
bool
Enable debug logging.

WebRTC and TURN

The opt-in WebRTC transport's ICE, STUN and TURN configuration.

SettingDefaultDescription
--rtc-config-json
SELKIES_RTC_CONFIG_JSON
/tmp/rtc.json
str
JSON file with WebRTC configuration to use, checked periodically, overriding all other STUN/TURN settings
--turn-host
SELKIES_TURN_HOST
staticauth.openrelay.metered.ca
str
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-port
SELKIES_TURN_PORT
443
int, 1 to 65535
TURN port when generating RTC config from shared secret or using long-term credentials
--turn-protocol
SELKIES_TURN_PROTOCOL
udp
str
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-tls
SELKIES_TURN_TLS
false
bool
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-secret
SELKIES_TURN_SHARED_SECRET
openrelayprojectsecret
str
Shared TURN secret used to generate HMAC credentials, also requires --turn-host and --turn-port Never sent to clients.
--turn-username
SELKIES_TURN_USERNAME
(empty)
str
Legacy non-HMAC TURN credential username, also requires --turn-host and --turn-port
--turn-password
SELKIES_TURN_PASSWORD
(empty)
str
Legacy non-HMAC TURN credential password, also requires --turn-host and --turn-port Never sent to clients.
--turn-rest-uri
SELKIES_TURN_REST_URI
(empty)
str
URI for TURN REST API service, example: http://localhost:8008
--turn-rest-api-key
SELKIES_TURN_REST_API_KEY
(empty)
str
API key to pass to the TURN REST API service Never sent to clients.
--turn-rest-username
SELKIES_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-header
SELKIES_TURN_REST_USERNAME_AUTH_HEADER
x-auth-user
str
Header to pass user to TURN REST API service
--turn-rest-protocol-header
SELKIES_TURN_REST_PROTOCOL_HEADER
x-turn-protocol
str
Header to pass desired TURN protocol to TURN REST API service
--turn-rest-tls-header
SELKIES_TURN_REST_TLS_HEADER
x-turn-tls
str
Header to pass TURN (D)TLS usage to TURN REST API service
--stun-host
SELKIES_STUN_HOST
stun.l.google.com
str
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-port
SELKIES_STUN_PORT
19302
int, 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-turn
SELKIES_ENABLE_CLOUDFLARE_TURN
false
bool
Enable Cloudflare TURN service, requires SELKIES_CLOUDFLARE_TURN_TOKEN_ID, and SELKIES_CLOUDFLARE_TURN_API_TOKEN
--cloudflare-turn-token-id
SELKIES_CLOUDFLARE_TURN_TOKEN_ID
(empty)
str
The Cloudflare TURN App token ID. Never sent to clients.
--cloudflare-turn-api-token
SELKIES_CLOUDFLARE_TURN_API_TOKEN
(empty)
str
The Cloudflare TURN API token. Never sent to clients.
--webrtc-public-ip
SELKIES_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-range
SELKIES_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-port
SELKIES_WEBRTC_UDP_MUX_PORT
0
int, 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-port
SELKIES_WEBRTC_TCP_MUX_PORT
0
int, 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-lite
SELKIES_WEBRTC_ICE_LITE
false
bool
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.

SettingDefaultDescription
--recording-socket
SELKIES_RECORDING_SOCKET
PIXELFLUX_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-url
SELKIES_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-token
SELKIES_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-timeout
SELKIES_AUDIT_WEBHOOK_TIMEOUT
2.0
float, from 0.1
Seconds one audit POST may take before it counts as failed and the next event is sent.
--enable-metrics-http
SELKIES_ENABLE_METRICS_HTTP
false
bool
Enable the Prometheus HTTP /metrics endpoint.
--enable-webrtc-statistics
SELKIES_ENABLE_WEBRTC_STATISTICS
false
bool
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-dir
SELKIES_WEBRTC_STATISTICS_DIR
/tmp
str
Directory to save WebRTC Statistics CSV from client with filenames selkies-stats-video-[timestamp].csv and selkies-stats-audio-[timestamp].csv