* **New Features** * Added HLS live and catch-up playback for archived streams, manifests, segments, and provider failover. * Improved playlist processing with filtering, renaming, mapping, EPG handling, favourites, watch groups, staged overlays, and disk-based processing. * **Documentation** * Added guidance for environment variables, credentials, password hashes, and authentication secrets. * **Changes** * Removed target editing from the target menu; refresh and delete remain available. * **Bug Fixes** * Improved recovery when cached playlist data is unreadable and strengthened archive stream URL handling.
8.8 KiB
🔐 Secrets & Environment Variables
Every deployment needs credentials: provider logins, output-user passwords, webhook tokens, web server secrets. Tuliprox keeps the repository free of real credentials while making it easy to inject them at runtime.
Host-agnostic. These instructions deliberately do not assume any particular host, container platform, or cloud provider. Secrets are read from the process environment and from files we generate on the machine itself, so the same workflow works whether you run a container, a service manager, a process supervisor, a small server, or a hosted secret store of your choice. The mechanism to supply an environment variable is always the same: it must be present in the environment of the
tuliproxprocess at startup.
What counts as a secret
| File | Field | Example env var |
|---|---|---|
source.yml |
input url, username, password |
CLOUDTV_1_URL, CLOUDTV_1_USER, CLOUDTV_1_PASS |
source.yml |
input epg.sources[].url |
CLOUDTV_1_EPG_URL |
source.yml |
input panel_api.api_key (account management) |
PROVIDER_PANEL_API_KEY |
api-proxy.yml |
output user password / token for every published user |
XTR_USER_LOCAL_PASS, XTR_USER_LOCAL_TOKEN |
config.yml |
web_ui.auth.secret (JWT signing, 64-hex) |
TULIPROX_WEB_SECRET |
config.yml |
messaging webhooks/tokens: Telegram bot token, Discord URL, Pushover token/key, ntfy/Gotify tokens, Slack URL, generic REST URL + signing_secret + Authorization headers |
TULIPROX_DISCORD_WEBHOOK, TULIPROX_TELEGRAM_TOKEN, TULIPROX_SIGNING_SECRET |
config.yml |
metadata_update.tmdb.api_key |
TULIPROX_TMDB_API_KEY |
config.yml |
reverse_proxy.rewrite_secret |
TULIPROX_PROXY_REWRITE_SECRET |
config/user.txt |
Web UI Argon2 password hashes (see below — not env-injectable) | file only |
Anything a provider, a player, a notification bot, or a browser authenticates with is a secret and must not be in git.
${env:VAR} interpolation
Every config file that Tuliprox reads (config.yml, source.yml, api-proxy.yml, mapping.yml, template.yml)
supports environment-variable interpolation with the syntax:
${env:VAR_NAME}
Variable names match [a-zA-Z_][a-zA-Z0-9_]*.
-
How it works: the placeholder is resolved before the file is parsed as YAML, from the environment of the running process. If the variable is missing, Tuliprox logs
Could not resolve env var 'VAR_NAME'and leaves the literal${env:VAR_NAME}in place so the problem is visible. -
Quoting: keep string values quoted, exactly like the value the variable will expand to:
inputs: - name: provider type: xtream url: "${env:CLOUDTV_URL}" username: "${env:CLOUDTV_USER}" password: "${env:CLOUDTV_PASS}"This stays valid YAML before and after substitution.
-
Use only for string fields. Numbers (
exp_date, ports,token_ttl_mins) and booleans (enabled) still belong directly in the file; injecting them through env vars is fragile. -
Not supported in
user.txt. Web UI credential files are read directly and must be written on the machine (see below). -
Also works in CLI paths: any
--home/-c/-i/-aargument can be${env:...}too.
Supplying the variables
Because Tuliprox reads from the process environment, any mechanism that sets environment variables works:
export TULIPROX_WEB_SECRET=...in the shell / init script that starts the process,environment:entries in a container or compose file,Environment=lines of a service unit,- the secret store / environment settings of whatever runtime you picked.
Tuliprox does not read a
.envfile automatically. If your runtime auto-loads.envfiles, that is fine — the process environment is what matters. For a quick manual check on a Linux shell:VAR=value ./tuliprox -sorexport VAR=value && ./tuliprox -s.
Web UI credentials (user.txt)
Tuliprox stores password hashes, never plain text. Each line is username:argon2_hash[:group1,group2]; without
groups the user defaults to admin.
-
Generate a hash with the interactive CLI prompt (it needs a real terminal and cannot read from stdin):
tuliprox --genpwd -
Write the line into
config/user.txt(or the user file configured inconfig.yml):myuser:$argon2id$v=19$m=19456,t=2,p=1$... -
Restart the server (or reload) and verify the login.
user.txt is environment-injectable only in the sense that the path may come from a CLI/${env:...} path; the
hashes themselves are generated on the machine and are never committed. The config/user.txt shipped in this
repository contains sample hashes for the demo accounts test / nobody documented in config/README.md — replace
them before going live.
JWT secret (web_ui.auth.secret)
If web_ui.auth.secret is omitted, Tuliprox generates one in-memory and all active logins are invalidated on every
restart. For production, pin a static 64-character hexadecimal string and keep it stable:
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
Put the result in an environment variable and reference it from config.yml:
web_ui:
auth:
secret: "${env:TULIPROX_WEB_SECRET}"
Rotating it invalidates all sessions — do it deliberately, not on a whim.
Pre-publish checklist
Run these before pushing anything to a public repository:
# Anything obviously credential-like in tracked configs
git grep -n -i -E "(password|secret|token|api_key)[[:space:]]*:" -- config/
# Explicit values that should have been placeholders or generated on-site
git grep -n -i -E "your_|TODO|changeme|example|\.secret|localsecret" -- config/
# Staged files (never a secret should be here)
git diff --cached --stat
git status --porcelain
Other good habits:
- Keep
logging.sanitize_sensitive_info: true(default). It masks passwords, provider URLs and client IPs in logs so shared logs can't leak credentials. - Keep
runtime_config_report_enabled: falseunless you need a startup dump; when enabled it masks sensitive values as***anyway. - Never commit
data/,target/,downloads/,cache/,backup/,.env, or any runtime directory — the repository.gitignorealready covers the common ones. - If a secret ever lands in history, rotate it (it is compromised history, not just a file) and rewrite history
with
git filter-reporather than committing new secrets on top.
Related
config.ymlcore configuration —web_auth, messaging,metadata_update.tmdbsource.ymlinputs & providers — provider credentials, EPG, backup URLsapi-proxy.ymlpublished users — output user credentials and tokens- Getting Started — where config files live and how the home directory is resolved