Environment Variables¶
Most Docker installs should use very few environment variables. If you're not sure whether you need one below, you probably don't — most day-to-day configuration (endpoint security, HDHomeRun behavior, observability, stream proxy tuning) is managed from the web UI once M3Undle is running, and is persisted in the database rather than requiring a container restart.
Required / Recommended¶
| Variable | Default | Description |
|---|---|---|
TZ |
host timezone | Timezone for log timestamps (e.g. America/New_York, Europe/London, UTC) |
M3UNDLE_ENCRYPTION_KEY |
(none) | Required for Xtream Codes providers unless M3UNDLE_ENCRYPTION_KEYS is set. Base64-encoded 32-byte AES key used to encrypt passwords at rest. Generate with openssl rand -base64 32. Keep this secret — treat it like a master password. |
M3UNDLE_ENCRYPTION_KEYS |
(none) | Rotatable alternative to M3UNDLE_ENCRYPTION_KEY — a comma-separated keyId:base64key list. The first entry is the active key used for new encryption; every entry is usable for decryption. Takes precedence over M3UNDLE_ENCRYPTION_KEY if both are set. See Manage Providers for the full rotation workflow. |
Optional — Authentication¶
| Variable | Default | Description |
|---|---|---|
M3UNDLE_AUTH_ENABLED |
false |
Set to true to require login for the UI and management APIs. |
M3UNDLE_ADMIN_USER |
admin |
Admin username/email. Used only on first startup when no account exists. |
M3UNDLE_ADMIN_PASSWORD |
(none) | Required when M3UNDLE_AUTH_ENABLED=true and no admin account exists yet. Also required when running one-time password recovery. |
M3UNDLE_ADMIN_PASSWORD_RESET |
false |
One-time recovery switch. Set to true to force-reset the existing admin password from M3UNDLE_ADMIN_PASSWORD on startup, then set back to false. |
Password recovery workflow (lost admin password):
- Set
M3UNDLE_ADMIN_PASSWORDto the new password. - Set
M3UNDLE_ADMIN_PASSWORD_RESET=true. - Restart the container once and log in with the new password.
- Set
M3UNDLE_ADMIN_PASSWORD_RESET=falseand restart again.
Endpoint security (M3U/XMLTV/stream/HDHR username/password auth) is managed in Settings → Security → Endpoint Credentials and stored in the database — see Security.
Optional — Provider Features¶
| Variable | Default | Description |
|---|---|---|
M3UNDLE_M3U_DIR |
/m3u_data |
Directory the file browser exposes when adding a provider from a local .m3u file. Mount a host directory to that path, or set this variable to a different container path and mount there. |
Optional — Observability¶
Most users should configure metrics from Settings → Observability after first startup — see Observability. The variables below are useful for managed deployments or bootstrap defaults.
| Variable | Default | Description |
|---|---|---|
M3Undle__Observability__Metrics__Enabled |
true |
Master switch for the Prometheus-compatible scrape endpoint. |
M3Undle__Observability__Metrics__Path |
/metrics |
Scrape endpoint path. |
M3Undle__Observability__Metrics__Mode |
LocalOnly |
Metrics access mode: Disabled, LocalOnly, Token, or Public. |
M3Undle__Observability__Metrics__EnableChannelLabels |
false |
Reserved guard for channel-level labels. Leave disabled unless you understand the Prometheus cardinality impact. |
M3Undle__Observability__Metrics__LocalAllowedCidrs__0 |
(empty) | First CIDR allowed in LocalOnly mode, e.g. 192.168.1.0/24. Add more with __1, __2, etc. |
Example:
environment:
M3Undle__Observability__Metrics__Mode: "LocalOnly"
M3Undle__Observability__Metrics__LocalAllowedCidrs__0: "192.168.1.0/24"
Optional — Stream Relay Tuning¶
Most stream proxy settings are managed from Settings → Streaming, and restart-required changes are tracked in the UI. The variables below are advanced startup/config controls for behavior not exposed as a normal UI field.
| Variable | Default | Description |
|---|---|---|
M3Undle__Streaming__ProviderMaxConcurrentUpstreams |
(unset) | Optional global provider-upstream cap used when a provider doesn't have its own max concurrent stream limit. |
M3Undle__Streaming__Reconnect__ContentStallTimeout |
00:00:08 |
MPEG-TS content-stall timeout. Real TS content resets this timer; null-only packets don't, so prolonged CDN gaps can reconnect before the generic read-stall timeout. |
M3Undle__Streaming__Reconnect__StrikeCooldown |
00:05:00 |
Cooldown after retry exhaustion for a failing source, used to avoid provider retune storms. |
M3Undle__Streaming__GeneratedHls__Directory |
/data/hls-work |
Where generated-HLS scratch files (rolling playlists/segments) are written. A relative value is resolved under the configured data directory (defaults to /data in the container); an absolute path is used as-is and does not need to live under the data directory — useful for mounting it on separate storage (e.g. /hls-work). The directory is created automatically if it doesn't exist. See Browser Playback. |
App Settings¶
| Variable | Default | Description |
|---|---|---|
ASPNETCORE_HTTP_PORTS |
5004;8080 |
Ports the app listens on inside the container. 5004 is used for HDHomeRun-compatible tuning and 8080 for the web UI and general endpoints. |
M3Undle__Refresh__TimeoutMinutes |
30 |
Maximum time a single refresh or build run may take before it is cancelled |
M3Undle__Refresh__StartupDelaySeconds |
30 |
Delay before first refresh after startup |
M3Undle__Snapshot__RetentionCount |
3 |
Number of snapshots to retain |
M3Undle__Snapshot__SafetySnapshotAgeHours |
24 |
In addition to the newest snapshots, always keep the newest snapshot at least this many hours old, so a burst of rebuilds cannot discard the last known-good lineup. 0 disables it. |
M3Undle__Snapshot__SuspectFetchMinRetainedRatio |
0.5 |
A provider fetch whose live channel count falls below this fraction of the currently active channels is held instead of applied (an empty fetch is always held). |
M3Undle__Snapshot__SuspectFetchAcceptAfterRuns |
3 |
A held fetch is accepted as a real change after this many consecutive refreshes return the same reduced lineup. 0 never accepts automatically. |
M3Undle__Refresh__ChannelRetentionDays |
30 |
How long an inactive provider channel is kept before it can be purged. Channels you have mapped, numbered, overridden or added to a custom group are never purged. |
M3Undle__Cors__ApplicationAllowedOrigins__0 |
(unset) | First allowed CORS origin for the application surface (/api, UI, /Account/*). Add more with __1, __2, etc. |
M3UNDLE_DATA_DIR |
/data (in image) |
Override the data directory (database, logs, snapshots). Rarely needed with the standard Docker volume layout. |
M3UNDLE_CONFIG_DIR |
/config (in image) |
Path M3Undle looks in for config.yaml and /config/.env. |
Optional — Notifications¶
| Variable | Default | Description |
|---|---|---|
M3UNDLE_EXTERNAL_BASE_URL |
(none) | When set, administrator notifications link back to M3Undle at this address. When unset, messages carry no link — an internal or container address is never used. |
M3UNDLE_NOTIFICATIONS_ALLOW_INSECURE_MATRIX_HTTP |
(unset) | Isolated labs only. Set to true to let a Matrix setup that also ticks Allow plain HTTP use an http:// homeserver. Leave unset in production: a Matrix homeserver must use HTTPS. |
See Administrator Notifications. To trust a private certificate authority for your SMTP server, add it to the container's trust store; the authority must publish a CRL or OCSP address because certificate revocation is checked.
Optional — HDHomeRun¶
Most users can skip this entire section. Use Settings → HDHomeRun for normal setup and day-to-day changes — see HDHomeRun Compatibility. The environment variables below are optional advanced overrides, not required setup.
Most HDHR behavior is configurable in the UI. The main exceptions are:
M3UNDLE_HDHR_ENABLED, which can force HDHR off at startupM3Undle__HdHomeRun__FriendlyName, which is currently env/config only
| Variable | Default | Description |
|---|---|---|
M3UNDLE_HDHR_ENABLED |
true |
Master switch for all HDHomeRun endpoints. Normally leave this unset. Set to false only to disable HDHR completely — this overrides the UI setting at startup, and also prevents normal HDHR management from the UI until removed. |
M3Undle__HdHomeRun__DiscoveryEnabled |
true |
Enables SSDP and SiliconDust network discovery. Requires UDP ports — see HDHomeRun-Compatible Clients for Docker networking details. |
M3Undle__HdHomeRun__SsdpEnabled |
true |
Controls the SSDP/UPnP listener on UDP 1900. |
M3Undle__HdHomeRun__SiliconDustDiscoveryEnabled |
true |
Controls the SiliconDust discovery listener on UDP 65001. |
M3Undle__HdHomeRun__TunerCount |
6 |
Virtual tuner count advertised when no provider limit or UI override is in effect — advertised only, not a server-side cap. Clients allocate against it and often reserve one tuner for EPG, so keep it well above 1. |
M3Undle__HdHomeRun__AdvertisedBaseUrl |
(auto-detect) | Base URL returned in discover.json and discovery responses (e.g. http://192.168.1.50:5004). Normally leave blank; set only for advanced Docker NAT, LAN discovery, or reverse-proxy scenarios. |
M3Undle__HdHomeRun__FriendlyName |
M3Undle HDHomeRun |
Device name shown in client apps. Env/config-only, not a web UI field. |
Quick rule: if you're running Docker on a normal home server, don't add HDHR env vars just because they exist. Bring the app up first, then use Settings → HDHomeRun. The main exception is M3UNDLE_HDHR_ENABLED=false.
Optional — Reverse Proxy¶
| Variable | Default | Description |
|---|---|---|
M3Undle__ReverseProxy__ForwardLimit |
1 |
Max entries to process from X-Forwarded-* headers. |
M3Undle__ReverseProxy__TrustedProxies |
(empty) | Comma-separated list of trusted proxy IPs (e.g. 192.168.1.1). Forwarded headers are only honored from these IPs, TrustedNetworks, or loopback. |
M3Undle__ReverseProxy__TrustedNetworks |
(empty) | Comma-separated CIDR blocks (e.g. 10.0.0.0/8). |