Skip to content

Configuration

DomeNinchen edited this page Oct 23, 2026 · 18 revisions

Configuration

Almost nothing here is required. JWT_SECRET is the only variable you genuinely have to set; everything else has a working default, and most settings that matter day to day are changed in the UI rather than in .env.

The two that matter from the start

  • JWT_SECRET is required. The backend refuses to start in production without it.
  • ENCRYPTION_KEY is optional but recommended. It encrypts stored credentials — API keys and SSH passwords. If unset, JWT_SECRET is used instead, which means rotating that secret would make every stored credential unreadable.

Generate both:

echo "JWT_SECRET=$(openssl rand -base64 32)" >> .env
echo "ENCRYPTION_KEY=$(openssl rand -base64 32)" >> .env

Backend

Variable Default Description
JWT_SECRET — Required. Secret for JWT signing. Must be set in production.
ENCRYPTION_KEY — Optional. Dedicated key for AES-256-GCM credential encryption. Falls back to JWT_SECRET if not set.
PORT 3001 Backend port
DATABASE_URL file:./data/ts6webui.db SQLite database path
JWT_ACCESS_EXPIRY 15m Access token lifetime
JWT_REFRESH_EXPIRY 7d How long a login lasts without being used; every refresh starts the period again. A whole number with s, m, h, d or w (12h, 30d); anything else keeps 7d and logs a warning at startup. Applies from backend 2.66.4 on - earlier versions ignored it and always used 7 days.
FRONTEND_URL http://localhost:5173 (http://localhost:3000 in docker-compose.yml, https://ts6.example.com in the Coolify one) The address the web interface is opened at. CORS and the Single Sign-On redirect address are built from it, so behind a domain set it to your public origin — see Deployment.
TRUST_PROXY 1 How many reverse proxies stand between a visitor and the backend, so it knows which entry of X-Forwarded-For is the visitor (the sign-in rate limit counts per visitor address). 1 is the frontend container's nginx alone; a proxy of your own in front of it makes 2. A number from 0 to 10 (false = none) or a comma-separated list of proxy addresses, networks and the names loopback, linklocal, uniquelocal. true and anything unusable are refused with a warning in the log and the default applies. Too low shows your proxy instead of the visitor, too high believes an address the visitor wrote himself. Settings → Network shows what fits; details in Deployment.
IP_BANS_DISABLED false Emergency switch for the IP bans of the Connection Journal: with true no address is turned away, whatever the ban list says, and a new web ban is refused. For the day you banned the address you come in from - set it, restart the backend, lift the ban, and unset it again.
DB_BACKUP_KEEP 5 Docker only. How many database copies the backend keeps in data/backups/; it takes one before each start that changes the database schema, and the oldest go first. A whole number of at least 1; anything else keeps 5 and logs a warning. See Deployment.
MUSIC_DIR /data/music Root for the media library. New uploads and downloads are organized into music/ and video/ subfolders underneath it; files sitting directly in the root (from before that split, or a volume shared with another app) are still picked up by the library scan and the stream-source picker
SIDECAR_URL — Optional. Full URL of the WebRTC sidecar service (e.g. http://ts6-sidecar:9800). Set in Docker when the sidecar runs as a separate container.
SIDECAR_BINARY_PATH sidecar Path to the sidecar binary, used only in local mode (running the sidecar as a subprocess instead of a separate container).
FILES_MAX_UPLOAD_MB 100 Largest single file the Files page will upload to a channel's file repository, in megabytes. Checked when the upload is agreed and again against the real body. The frontend image's nginx has a location of its own for upload bodies without a size cap, so raising this needs no rebuild; a reverse proxy of your own in front of it has to allow bodies this large too — see Deployment.
YT_COOKIE_FILE — Optional. Path to a Netscape-format cookies.txt for yt-dlp. Can also be managed under Settings → YouTube. A file mounted into the container has to be writable for uid 1000, because yt-dlp rewrites it after a run (Deployment).
TS_ALLOW_SELF_SIGNED false Set to true/1 to accept self-signed TLS certificates when connecting to the TeamSpeak WebQuery API. This switches certificate checking off entirely (any certificate, any hostname) and for every connection, so leave it unset for a certificate from a public CA — see WebQuery over HTTPS.
VOICE_DEBUG unset (off) Legacy. Verbose voice-bot/audio-pipeline logging. Only read once, on first boot, to seed the database-backed setting if it has never been saved — after that Settings → Debug is authoritative and this variable is ignored.
RANK_CHECK_DEBUG unset (off) Legacy. As above, for per-client Rank Check detail. Promotions, errors and the per-run summary always log regardless. Prefer Settings → Debug, which toggles at runtime without a restart.
QUERY_DEBUG unset (off) Legacy. As above, for logging every ServerQuery command and its answer (credentials written as ***). Set to 1 to seed the switch; Settings → Debug → ServerQuery Debug is authoritative after that.
NODE_ENV development Set to production in Docker; enables the startup guard that refuses a default JWT_SECRET.

Sidecar (video streaming)

Looking for the stream's resolution, frame rate, bitrate or volume? Those are not environment variables. They live in the web interface under Settings → Streaming, which sets what !stream uses when nobody names a quality — see Music Bots. The variables below are the sidecar's own fallbacks for when no preset is in play at all.

These are tuning knobs — none are required for a working setup. Defaults below are the sidecar's own built-in fallbacks, read from packages/sidecar/main.go. The shipped docker-compose.yml raises VIDEO_QUEUE_SIZE and AUDIO_QUEUE_SIZE to 8192/16384, sized for the server this fork was tuned against rather than as a hard requirement.

Variable Default Description
SIDECAR_PORT 9800 HTTP API port. An internal interface of the stack: the shipped compose files do not publish it on the host (see Deployment)
FFMPEG_PATH ffmpeg Path to the ffmpeg binary
SIDECAR_DEBUG_LOGS unset (off) Set to 1 for verbose per-packet debug logging
STUN_SERVERS built-in public list Comma-separated STUN server URLs, overriding the default list
ICE_UDP_PORT_MIN / ICE_UDP_PORT_MAX 50000 / 50100 Fixed UDP port range for WebRTC ICE candidates, so it can be firewalled explicitly. Must match the published Docker port range.
VIDEO_QUEUE_SIZE 1024 (compose: 8192) Video RTP queue between the UDP reader and the pacing goroutine
AUDIO_QUEUE_SIZE 2048 (compose: 16384) Audio RTP queue
VIDEO_RTP_READ_BUFFER 4194304 (4 MiB) OS-level UDP socket read buffer for the video port
AUDIO_RTP_READ_BUFFER 1048576 (1 MiB) OS-level UDP socket read buffer for the audio port
SYNC_PLAYOUT_BUFFER_MS 50 Baseline playout buffer added on top of measured latency in the A/V sync pacing
SYNC_VIDEO_BIAS_MS 0 Extra holdback applied to video only, to fine-tune A/V sync
SYNC_MAX_DELAY_MS 500 Upper bound on the computed pacing delay — stops a single bad RTP timestamp from stalling playback and overflowing the queues
VIDEO_WIDTH / VIDEO_HEIGHT / VIDEO_FRAMERATE 1280 / 720 / 30 Fallback dimensions and framerate when no preset is given (e.g. the idle black-screen source)
VIDEO_BITRATE 1500k Fallback video bitrate when none is passed by the app
AUDIO_BITRATE 128k Audio encode bitrate
AUDIO_DELAY_MS 0 Manual audio delay (adelay filter); expected to stay 0 under the current pacing logic
VIDEO_CPU_USED 4 libvpx -cpu-used — a speed/quality tradeoff (0 = slowest/best, 8 = fastest/worst), not a core count
VIDEO_ENCODE_THREADS host CPU cores -threads passed to libvpx, which unlike most ffmpeg encoders doesn't auto-scale across cores
VIDEO_BUFSIZE 2× the target bitrate ffmpeg -bufsize rate-control buffer. Scales with bitrate so high-bitrate streams aren't limited by too small a buffer; set explicitly to override

GitHub API Token (Update Status)

Settings → Update Status checks this deployment's version against GitHub, using three unauthenticated API calls per check. GitHub limits unauthenticated calls to 60/hour for the whole server, shared with anything else on it that talks to GitHub — a handful of container restarts (each one checks once at boot) plus a couple of manual "Recheck Now" clicks is enough to exhaust it, after which every result reads unknown until the hourly reset. Without a token, "Recheck Now" is throttled to 20 uses/hour server-side specifically to avoid that.

A token raises the limit to 5,000/hour. It needs no repository access at all — it only ever reads this repo's public files.

To create one (GitHub → your profile → Settings → Developer settings → Personal access tokens):

  • Fine-grained token (github_pat_...): generate one here. Set repository access to Public Repositories (read-only) — no specific repository or permission checkboxes needed. These tokens require an expiration date (GitHub caps it, typically at 1 year), so it will eventually need regenerating.
  • Classic token (ghp_...), simpler if you'd rather not think about renewal: generate one here. Leave every scope checkbox unchecked (public read access needs none of them) and set Expiration to No expiration.

Paste the token into Settings → Update Status → GitHub API Token → Save. It's stored encrypted the same way server connection credentials are.

Settings that live in the database

Anything configured through the web interface — server connections, users, bot flows, music bots, debug toggles, the accent colour, the storage-notice switch, scheduled restarts, how long the Connection Journal keeps its entries — is stored in the database, not in environment variables. That means it survives container rebuilds, and that data/ is what you back up.


v0.21, last edited 23.10.2026

Getting started

Home
Getting Started
Install on Debian 13
Setup: same machine
Setup: elsewhere / rented
Users and Roles

Using the app

Dashboard
Virtual Servers and Instance
Channels
Clients
Client Database
Permissions
Server and Channel Groups
Moderation
Tokens and Passwords
Files
Icons
Bot Flows
Music Bots
Server Widgets
Server Maintenance
Server Logs
Query Console
Connection Journal
Themes and Appearance

Running it

Administration
Configuration
Deployment
Privacy and Hosting

When something is odd

Tips and Pitfalls
Troubleshooting

Contributing

Development

Repository · Changelog

Clone this wiki locally