Skip to content
Coming soon

Configuration Overview

You configure Sovereign’s server through environment variables on the container. There’s no settings page for them in the app. Values that aren’t sensitive go in your compose file or manifest, and sensitive ones go in through your platform’s secret mechanism.


Every setting is an environment variable. Its name is a path through the settings, with a double underscore (__) between each part:

Sovereign__Authentication__AdminPassword

A setting you don’t set keeps the default listed in the reference below, so you only set the ones your deployment needs.


Settings marked sensitive are redacted from log output. The one exception is the first-run admin username and password, which are printed once to the console when the account is created and never reach the log files. Sensitive settings must never be passed as plain inline environment variables, which land in your shell history and in any compose file you commit. Pass them through your platform’s own secret mechanism instead:

Platform Recommended approach
Docker --env-file pointing to a file outside version control
Docker Compose env_file: key pointing to the same kind of file
Kubernetes Secret resource with secretKeyRef

See the individual platform pages for examples. Sovereign reads its settings from environment variables, so a secret mounted as a file (a Compose or Swarm secrets: entry under /run/secrets/) is never read.


Environment Variable Description Default Sensitive
Sovereign__EnableSensitiveDataLogging Log database values and credentials. Never enable in production. false
Sovereign__Authentication__Issuer Token issuer URI, used as both the token issuer and the registered audience, and the public origin clients use to reach the server, so it must be reachable by all clients. A localhost address only works from the server’s own machine, and logs a warning at startup. An https address also turns on Strict-Transport-Security (see Production Hardening). See Authentication http://localhost:5000/
Sovereign__Authentication__ClientId OAuth client ID for the web app. If unset, one is generated on first start and stored on the data volume, so it and existing sessions survive restarts. Setting a value overrides the stored id (generated once, then stored)
Sovereign__Authentication__Tokens__Web__AccessTokenMinutes Lifetime of an access token issued to the web app, in minutes. Access tokens aren’t re-checked against the database on every call, so a role change (for example moving someone back to Unapproved) can take up to this long to apply, while a deleted account stops working on its next request. See Session Length 15
Sovereign__Authentication__Tokens__Web__RefreshTokenDays How long a browser may sit unused before it asks for a sign-in, in days. Refresh tokens slide as they rotate, so this is an idle timeout 30
Sovereign__Authentication__Tokens__Web__MaxSessionDays The longest one web sign-in may last, in days, however often it’s used. 0 turns the cap off 90
Sovereign__Authentication__Tokens__Device__AccessTokenMinutes As the web app’s, for the Roku and Android apps 15
Sovereign__Authentication__Tokens__Device__RefreshTokenDays As the web app’s, for the Roku and Android apps. Raise it for a television that gets used sporadically 90
Sovereign__Authentication__Tokens__Device__MaxSessionDays As the web app’s, for the Roku and Android apps 0 (no cap)
Sovereign__Authentication__AdminUsername Username for the default admin account seeded on first run (random 12-char string) ✓
Sovereign__Authentication__AdminPassword Password for the default admin account seeded on first run (random 12-char string) ✓
Sovereign__Authentication__Google__ClientId OAuth client ID enabling “Sign in with Google”. Google sign-in activates only when both this and the secret are set (none)
Sovereign__Authentication__Google__ClientSecret OAuth client secret for Google sign-in (none) ✓
Sovereign__Authentication__Entra__ClientId Application (client) ID enabling “Sign in with Microsoft”. Entra sign-in activates only when both this and the secret are set (none)
Sovereign__Authentication__Entra__ClientSecret Client secret for Microsoft Entra sign-in (none) ✓
Sovereign__Authentication__Entra__TenantId Directory (tenant) ID, or common to allow sign-ins from any tenant common
Sovereign__DataSources__Radarr__N__Url Base URL of a Radarr instance (repeat for multiple, starting at 0) (none)
Sovereign__DataSources__Radarr__N__ApiKey API key for the Radarr instance (none) ✓
Sovereign__DataSources__Sonarr__N__Url Base URL of a Sonarr instance (repeat for multiple, starting at 0) (none)
Sovereign__DataSources__Sonarr__N__ApiKey API key for the Sonarr instance (none) ✓
Sovereign__DataSources__Filesystem__N__Path Absolute path, inside the container, of a directory of media files to import directly, with no Radarr or Sonarr in front of it (repeat for multiple, starting at 0). Scanned recursively; titles are identified on TMDb, with no key to set (none)
Sovereign__DataSources__Filesystem__N__MediaType What the directory holds: Movie or Television. A Mixed or Unknown entry is skipped at startup Movie
Sovereign__DataSources__Filesystem__N__Description Optional label shown on the admin Media Sources page (none)
Sovereign__DataSources__Tmdb__MaxMoviesPerRun Maximum movies to fetch credits for in a single job run; the backlog drains across consecutive runs 500
Sovereign__DataSources__Tmdb__MaxPeoplePerRun Maximum people to fetch biographies for in a single job run. Each person costs one request and a large library holds tens of thousands, so the backlog drains across consecutive runs, most-credited people first 2000
Sovereign__DataSources__Tmdb__SendCensus Whether the server sends Sovereign’s metadata service an anonymous daily token and its license standing, so the service can count servers once a day. The token changes every day and can’t be linked to your server. Set to false to send neither, and the server isn’t counted. See the Privacy Policy true
Sovereign__Obfuscation__Alphabet Character set used to write the IDs in links, as a reordering of 0-9a-zA-Z. If unset, one is generated on first start and stored on the data volume, so those IDs survive restarts. Setting a value overrides the stored alphabet (generated once, then stored)
Sovereign__Obfuscation__AssetSecuritySecretKey Secret that protects the media and artwork links Sovereign hands out. If unset, one is generated on first start and stored on the data volume, so those links survive a restart. Changing this value invalidates every outstanding link (generated once, then stored) ✓
Sovereign__AssetWork__MaxConcurrentJobs Maximum heavy asset jobs running at once across every queue. 0 derives it from the host as half the processor count, clamped to between 1 and 4 0
Sovereign__AssetWork__ReservedInteractiveJobs Jobs held back from background work so something a viewer is waiting on can start. Capped at one below the total 1
Sovereign__Trickplay__TimeoutMinutes Minutes before a trickplay generation job is cancelled and marked as an error 30
Sovereign__Trickplay__TimeoutMinutesPerGigabyte Extra minutes of budget added per gigabyte of the source file, on top of TimeoutMinutes. 0 keeps a flat budget. Trickplay seeks between keyframes rather than reading the file through, so this is a backstop for an unusually slow source 2
Sovereign__Images__MaxConcurrentDownloads Maximum parallel image download and conversion workers 2
Sovereign__Images__TimeoutMinutes Minutes before an image download job is cancelled 1
Sovereign__Images__TimeoutMinutesPerGigabyte Has no effect. An image download has no source file to scale against, so its budget is always flat 0
Sovereign__Subtitles__TimeoutMinutes Minutes before a subtitle extraction job is cancelled and marked as an error 30
Sovereign__Subtitles__TimeoutMinutesPerGigabyte Extra minutes of budget added per gigabyte of the source file. Bitmap subtitle extraction falls back to reading the whole file where the source carries no index to seek by, so its budget scales with the source 2
Sovereign__Subtitles__BitmapCueCanvasMaxLongEdge Cap on the longer edge, in pixels, of the plane bitmap (PGS) subtitles are drawn onto. The video’s aspect is kept and the plane is never scaled up; 0 draws at the video’s own size. PGS is authored at 1080p, so an uncapped plane on a 2160p source costs four times the pixels for detail the source doesn’t carry 1920
Sovereign__Trickster__ExecutablePath Advanced. Path to the bundled trickster binary, which generates both trickplay sprite sheets and bitmap subtitle cues. It loads its FFmpeg libraries from beside itself, so repointing this means moving the whole directory rather than the one file /opt/trickster/trickster
Sovereign__Transcoding__VideoEncoderPreset FFmpeg encoder preset (speed/quality tradeoff): Fast, Medium, or Slow. These are the only values accepted, because they’re the only ones safe across every encoder: the x264-only presets fail hardware transcodes Medium
Sovereign__Transcoding__MaxVideoBitrateBps Maximum video bitrate ceiling (bits per second) applied to transcoded streams. A user preference may request a lower value but never a higher one 30000000
Sovereign__Transcoding__VideoQualityTier Quality target for transcoded video: Efficient, Balanced, or HighQuality. Drives how much detail is preserved, bounded by the bitrate ceiling. See Video Quality. A user preference may request an equal-or-lower tier but never a higher one HighQuality
Sovereign__Transcoding__HlsSegmentDurationSeconds Advanced. Duration of each HLS segment in seconds, passed to FFmpeg. A latency-against-playlist-size trade; rarely worth changing 6
Sovereign__Transcoding__MinCopySegmentDurationSeconds Advanced. Shortest segment a direct-played copy may be cut into when the default would produce segments too large for a client’s media buffer. Only ever applies to a copy that would otherwise be re-encoded. Can’t be longer than HlsSegmentDurationSeconds 1
Sovereign__Transcoding__ProgressReportPeriodSeconds Advanced. How often, in seconds, a playback session’s FFmpeg reports its progress to the server. The reports let Sovereign fail a start whose FFmpeg has stuck well before the 30-second limit, and record the rate each session encoded at. Every report is held in memory until the session’s FFmpeg exits, so a very long session at a very short period costs a few megabytes 1
Sovereign__Transcoding__VaapiToneMapBrightness Advanced, VAAPI only. Brightness offset, from -100 to 100, applied to the HDR picture going into the driver’s fixed tone curve rather than to the SDR picture coming out of it. A value outside the range is clamped into it. Ignored by every other encoder. See HDR Tone Mapping 19
Sovereign__Transcoding__VaapiToneMapContrast Advanced, VAAPI only. Luma gain, from 0 to 10, applied ahead of the tone-map and paired with the brightness offset. A value below 1.0 is normal, because it acts on the HDR input, and a value outside the range is clamped into it. Setting this to 1.0 alongside a brightness of 0 turns the correction off entirely 0.95
Sovereign__StreamLifecycle__HeartbeatIdleTimeoutSeconds Seconds a stream may go without a client heartbeat before it’s evicted (FFmpeg killed, stream directory deleted). The heartbeat is how Sovereign tells a stream is still being watched, so a watched stream is never evicted, even after its transcode finishes 60
Sovereign__StreamLifecycle__EvictionScanIntervalSeconds How often the background scan runs to reap idle streams 20
Sovereign__Playback__DefaultAudioLanguage System-wide default audio language as an ISO-639 code. Used when a stream has a matching track and the user has no preference; set to empty to use the media’s own default track instead eng
Sovereign__Playback__DefaultSubtitleLanguage System-wide default subtitle language as an ISO-639 code. When a stream has a matching subtitle track and the user has no preference, that track is marked the stream’s default so a client can auto-select it. Unset by default, unlike the audio equivalent: audio plays whether or not anyone chose it, so a default only picks which track, whereas defaulting subtitles would turn them on for every viewer who never asked (none)
Sovereign__ContinueWatching__ResumeWindowDays Days a paused title keeps being offered in the Continue Watching row after it was last watched. A title left untouched for longer drops off the row. This only hides it: the saved position is kept, so the title still resumes from where it was left if you open it from its own page. Set to 0 (or any non-positive value) to keep offering in-progress titles indefinitely 90
Sovereign__ActivityLog__RetentionDays Days to retain user activity log entries before the daily maintenance job prunes them. Set to 0 (or any non-positive value) to retain indefinitely 90
Sovereign__ClientDevices__RetentionDays Days of inactivity after which a client device drops off the device list, pruned by the daily maintenance job. Set to 0 (or any non-positive value) to retain indefinitely 90
Sovereign__ClientDevices__UserPickerAfterMinutes Minutes the Android app has to spend in the background before it asks “Who’s watching?” again on its return, on a device where two or more people are signed in. It never asks during playback. The Roku channel asks every time it starts, so this setting doesn’t change it. Set to 0 to ask only when the app starts 60
Sovereign__ClientErrors__RetentionDays Days to retain client-reported errors before the daily maintenance job prunes them. Set to 0 (or any non-positive value) to retain indefinitely 30
Sovereign__Storage__RetentionDays Days to retain the hourly storage samples behind the usage chart on the admin Overview page. Set to 0 (or any non-positive value) to retain indefinitely 400
Sovereign__Storage__WarningPercentFree Free space, as a percentage of a monitored volume’s capacity, at or below which it’s reported as a warning. Set to 0 to grade the volume on free bytes alone 10
Sovereign__Storage__WarningBytesFree Free bytes at or below which a monitored volume is a warning. This is a floor under the percentage, so a small volume is caught before the proportion starts to look alarming, and whichever of the two trips first wins. Set to 0 to grade the volume on the percentage alone 5368709120 (5 GiB)
Sovereign__Storage__CriticalPercentFree Percentage at or below which a monitored volume is critical. Must be no greater than the warning percentage when both are set 5
Sovereign__Storage__CriticalBytesFree Free bytes at or below which a monitored volume is critical, roughly what one in-flight transcode needs to keep buffering ahead. Must be no greater than the warning figure when both are set 1073741824 (1 GiB)
Sovereign__Network__TrustedProxyNetwork__N Trusted proxy IP address or CIDR range for X-Forwarded-For resolution (repeat for multiple, starting at 0) (none)

You can register more than one Radarr instance, Sonarr instance or trusted proxy network by incrementing the index (N), starting at 0.

Two groups of settings are documented on their own pages rather than repeated here: the Sovereign__Notification__* settings for outbound mail and the daily digest are on Email, and the Sovereign__Authentication__Certificates__* settings for supplying your own token certificates are on Authentication.

The container’s TZ variable is a standard Linux one rather than a Sovereign setting. It sets the time zone the server log’s timestamps are written in, and the image defaults it to America/Chicago, so set it to your own zone (for example TZ=Europe/London). The startup log reports which zone took effect.


Sovereign checks its configuration as it starts, before it serves any requests. If any value is invalid, the server refuses to start and reports the problems it finds together in the logs. Each message names the environment variable and how to correct it, so most can be fixed in one pass.


Repeat the variable with an incrementing index to register more than one instance:

Terminal window
# Two Radarr instances
Sovereign__DataSources__Radarr__0__Url=http://radarr-4k:7878
Sovereign__DataSources__Radarr__0__ApiKey=<api-key-1>
Sovereign__DataSources__Radarr__1__Url=http://radarr-sd:7878
Sovereign__DataSources__Radarr__1__ApiKey=<api-key-2>
# Two Sonarr instances
Sovereign__DataSources__Sonarr__0__Url=http://sonarr-hd:8989
Sovereign__DataSources__Sonarr__0__ApiKey=<api-key-3>
Sovereign__DataSources__Sonarr__1__Url=http://sonarr-4k:8989
Sovereign__DataSources__Sonarr__1__ApiKey=<api-key-4>

A directory of films or of series can be imported with no Radarr or Sonarr in front of it. Point an entry at the directory as the container sees it, and say what it holds. Titles are named from TMDb through Sovereign’s metadata service, so there’s no API key to set.

A film is identified from its folder or file name: a {tmdb-1234}, [tmdbid-1234] or tt1234567 tag wins outright, otherwise a Title (Year) folder or a Title.Year... release name is searched on TMDb. A series is identified from its folder, where a [tvdbid-1234] or {tmdb-1234} tag wins outright, and the season and episode numbers come from each file name (S01E02, 1x02, S05E15E16). Either way a match is taken only when the title and year agree, and anything less confident is logged and skipped rather than guessed at. -sample and -trailer files and extras folders are ignored.

Terminal window
Sovereign__DataSources__Filesystem__0__Path=/media/Movies
Sovereign__DataSources__Filesystem__0__MediaType=Movie
Sovereign__DataSources__Filesystem__0__Description=Films on the NAS
Sovereign__DataSources__Filesystem__1__Path=/media/Television
Sovereign__DataSources__Filesystem__1__MediaType=Television
Sovereign__DataSources__Filesystem__1__Description=Series on the NAS

A title the directory and an Arr both supply is one entry with two files, with the Arr’s metadata taking precedence, so the two kinds of source can coexist. One directory holds one kind of media, so keep films and series in separate trees. See Filesystem Media Sources for the file and folder naming rules.

Specify one or more IP addresses or CIDR ranges to trust for X-Forwarded-For header resolution. This is required when Sovereign runs behind a reverse proxy, so that logging and the sign-in rate limit see each client’s real IP instead of the proxy’s:

Terminal window
# Single proxy (exact IP)
Sovereign__Network__TrustedProxyNetwork__0=192.168.1.1
# Multiple proxies / subnets
Sovereign__Network__TrustedProxyNetwork__0=10.0.0.0/8
Sovereign__Network__TrustedProxyNetwork__1=172.16.0.0/12
Sovereign__Network__TrustedProxyNetwork__2=192.168.0.0/16

Behind a proxy that isn’t listed, every request appears to come from the proxy. The activity log, the Clients page and each device’s last-seen address all show the proxy, and every user shares one sign-in rate limit, so one device retrying a sign-in can stop everyone else signing in, or renewing their session, for up to a minute. Nothing else breaks, which makes it easy to miss. To make it visible, Sovereign writes one warning to its log the first time a request arrives with an X-Forwarded-For header from an address it doesn’t trust:

A request from 172.18.0.1 carried X-Forwarded-For, but no trusted proxy network is configured, so the header was ignored. ...

The address in that line is your proxy, as Sovereign sees it, and is usually what to trust. Otherwise, it depends on where the proxy runs:

  • In Docker, or on the same host as a Sovereign container - Docker’s own network. 172.16.0.0/12 covers the networks Docker creates by default, and docker network inspect <network> shows the exact subnet of the one the proxy and Sovereign share.
  • On another machine - that machine’s address on your network, such as 192.168.1.10.
  • In Kubernetes - the cluster’s pod network, where the ingress controller connects from. 10.244.0.0/16 is a common default, and k3s uses 10.42.0.0/16.

Keep the range as narrow as your setup allows. Sovereign believes whatever client address a trusted address passes along, so a range that also covers your users’ own devices lets any of them claim to be someone else in the log and the rate limit. If your devices on 192.168.1.0/24 reach Sovereign directly and a proxy on 192.168.1.10 handles everything from outside, trust 192.168.1.10 and not the whole subnet.

After a restart, sign in from another device and open the Clients page. That device should show its own address rather than the proxy’s, and the warning shouldn’t come back. If Sovereign is reached directly with no proxy in front of it, leave the setting empty: a device that sends the header itself triggers the warning once, and it can be ignored.

© 2026 Sovereign Media LLCdocs/v1.0.5@98b57ac305fc

Titles, artwork, people and descriptions shown in screenshots are fictional and were created for illustration. Sovereign doesn't include or supply any media: it plays the library you bring.