Files
Piik/docs/reference/configuration.md
T
AAA cfc323adce feat(media): integrate embedded media services and shared native encoding
Embed STUN and SFU in the shared Go process, reuse native encoding pipelines with independent adaptation, and complete Client lifecycle, settings, diagnostics and packaging fixes. Retain standard Browser senders after measured encoded-reuse limitations.
2026-09-09 06:09:06 +08:00

9.3 KiB

Configuration And Ports

The tracked .env.example is the executable schema companion; internal/server/config is validation truth. Keep real values in the service secret store or an untracked access-restricted environment file.

Application Environment

Variable Contract
SCREENER_ENV development or production, default development; required for every server deployment: production enables production-only validation and the Secure site-access cookie.
LISTEN_HOST Defaults to 0.0.0.0; bare-metal production normally uses 127.0.0.1.
PORT Positive TCP port, default 8787; the tracked release wrapper supports only that default.
PUBLIC_BASE_URL Exact public HTTP(S) origin; production requires HTTPS.
ALLOWED_ORIGINS Comma-separated exact HTTP(S) origins; wildcard is invalid.
SITE_ACCESS_PASSWORD Production-required independent 8-128 visible-ASCII byte secret.
ROOM_LEASE_SECONDS Positive dormant lease, default 86400; active Host prevents expiry.
ROOM_DATABASE_PATH Optional absolute SQLite file path; unset selects memory mode.
MAX_VIEWERS_PER_ROOM 1..20, default 8.
ENDPOINT_MEDIA_COPY_CAPACITY Shared endpoint steady-copy cap 1..3, default 2.
STUN_URLS Comma-separated advertised stun: discovery URLs; at least one is required in production. These are not local bind addresses and may use an unproxied DNS name separate from the Web origin.
STUN_LISTEN_HOST Hosted IPv4 STUN bind address, default 0.0.0.0 when STUN_URLS is configured; independent of HTTP LISTEN_HOST. Local Client construction creates no STUN listeners.
NAT_PREDICTION_ENABLED Optional bounded NAT prediction capability, default false; requires an ordinary STUN_URLS endpoint on UDP 3478. Hosted startup binds UDP 3479/3480 before advertising the capability. Firewall reachability remains an operator requirement.

Automatic SFU fallback runs inside the Hosted process when SFU_UDP_PORT is set:

Variable Contract
SFU_UDP_PORT Optional UDP media port 1..65535; unset or blank disables SFU. Set 7882 for the standard public listener.
SFU_LISTEN_HOST IPv4 bind address, default 0.0.0.0; independent of HTTP LISTEN_HOST. Read only when SFU is enabled.
SFU_PUBLIC_IP Optional explicit IPv4 advertised-address override for a host behind NAT. Read only when SFU is enabled.

SFU control uses the application's authenticated signaling connection. No separate control origin or infrastructure credentials are configured. Local and public-link Client construction create no SFU listener. The relay does not provide application E2EE.

Removed access, room TTL, endpoint-tier, room-rollout, and TURN variables fail startup even when blank. A present NODE_ENV fails the same way, so a stale environment file cannot silently drop a deployment out of production. The private deployment is upgraded atomically; there are no compatibility aliases or dual configuration readers.

Diagnostics

Client file diagnostics default off; enable them with --debug or SCREENER_DEBUG=client. Structured lifecycle, build-revision, native-capability, fixed native-failure and sanitized Local route events go to client.log. Native share changes, validated capture states, connection states and selected candidate types/provenance are included without source names or addresses. Failed profile preparation records a fixed rejection stage. Native outbound connections record ICE and DTLS state separately; local-bridge closure records candidate type/transport counts, never candidate addresses or SDP. The embedded Local server uses the same file. Debug events do not stream through the TUI or change machine-readable stdout. On the Client, SCREENER_DEBUG=route alone retains console route tracing and does not enable file capture or D.

The default Client directory is logs beside the executable. If that directory is not writable, the Client uses Screener/logs inside the OS user-cache directory and displays the actual log path. --log-dir <directory> overrides SCREENER_LOG_DIR; either explicit choice must be writable or startup fails. Selecting a directory alone does not enable diagnostics.

Press D in the interactive Client terminal to export a ZIP without stopping the Client. The terminal shows the saved path as a local-file hyperlink when supported; the visible path can also be copied normally. English, Chinese and visual modes share that action. Non-interactive and TERM=dumb sessions export at orderly shutdown, since they do not read TUI keys.

Hosted Server diagnostics use --debug, SCREENER_DEBUG=server or SCREENER_DEBUG=route. They persist structured events in server.log while normal service journal output continues. The directory is SCREENER_LOG_DIR, otherwise the first systemd LOGS_DIRECTORY, otherwise logs under the working directory. The tracked systemd unit supplies /var/log/screener with mode 0700 through LogsDirectory, which remains writable with ProtectSystem=strict. An unwritable selection fails startup. In a running debug-enabled Unix server, kill -USR1 <pid> saves a bundle and prints its path in the journal. Every platform also exports at orderly debug shutdown. Windows does not have the Unix signal action; forced termination cannot produce a shutdown snapshot. No diagnostic HTTP listener or automatic upload is added.

--debug enables the existing sanitized route events for the local Go process; SCREENER_DEBUG=route also works when loaded from the Server .env. Those events record room and participant ordinals, route reasons, candidates, revisions, quality states and commit/failure outcomes. They exclude raw Peer IDs, SDP, ICE candidates, tokens and media credentials. Raw third-party protocol logging is not enabled or copied into these files.

Each component retains an 8 MiB current JSON log and one 8 MiB previous log. Exports contain those existing logs, build/platform metadata, Go runtime.MemStats, a sampled Go heap/allocation profile (heap.pprof) and aggregate goroutine stacks (goroutines.txt). These are runtime counters and allocation/stack profiles, not raw process-memory dumps. They do not collect environment values, configuration files, credentials, media payloads, Browser logs or memory from the separate C++ capture process. Exported ZIPs remain in the selected directory until the user or operator removes them; log rotation does not delete exports.

For Browser diagnostics, add ?debug=1 to the page before reproducing the problem. The page retains its last 256 bounded events and exposes window.__SCREENER_DEBUG__.export() for manual JSON export from DevTools. The report includes the Browser asset name and signaling contract, capture exception categories, capture-setting outcomes, signaling state and native request/state outcomes. The Native bridge's failure snapshot includes ICE/DTLS states, live receiver counts and candidate type counts without delaying teardown. It excludes raw exception messages, credentials, invitation fragments, URLs, SDP, ICE candidates and media payloads. Collection stays in the current page; there is no automatic upload or persistent log.

Public And Private Ports

Port Scope Owner
TCP 80/443 public HTTP redirect and HTTPS/WSS reverse proxy
UDP 3478 public in-process STUN-only Screener listener
UDP 3479/3480 public when NAT prediction is enabled in-process auxiliary STUN-only Screener listeners
UDP 7882 (or SFU_UDP_PORT) public when SFU enabled in-process Screener WebRTC media
TCP 8787 private Screener application

TCP 3478, TCP/TLS 5349, TURN relay ranges, media TCP, and other media ports remain closed. HTTPS/WSS transport is independent of the UDP-only media contract.

When NAT_PREDICTION_ENABLED=true, the server derives stun:<same-hostname>:3479 and :3480 from the first ordinary STUN authority on UDP 3478. The Host sees a pre-share switch that defaults on and may disable it. The capability adds no media route or third-party service. It needs both cloud security-group rules and the host's /etc/nftables.conf rule. Screener binds every required UDP listener before opening room persistence or accepting signaling; a bind failure rolls back all newly owned sockets. Close and End retire these listeners with the application. Existing coturn listeners must be retired in the coordinated deployment because two processes cannot own the same ports. Opening a cloud port without a listener has no effect, and local binding alone does not prove external reachability. Disable the capability before removing firewall rules. Same-IP ports expose destination-port allocation behavior; a full RFC 5780 alternate-address test requires a second public IPv4.

Bounds

  • Site-access requests are rate-limited at the reverse proxy and use constant- time secret comparison in the application.
  • HTTP body, WebSocket payload, total/unauthed connections, room count, Viewer count, output buffers, endpoint copies, and SFU resources are bounded.
  • The four-digit code space fixes the maximum managed Host publications at 9,000; maximum subscription admission is that capacity times the configured per-room Viewer limit. These are admission bounds, not throughput claims.
  • One application process owns room authority and SFU admission. Multiple processes require a new shared atomic owner.