How Configuration Works
Configuration Sources and Precedence
Section titled “Configuration Sources and Precedence”SyncTV builds the effective runtime configuration by merging several sources. The precedence order from lowest to highest is:
- Built-in defaults from the Rust configuration structs.
- A configuration file such as
synctv.yamlor/config/synctv.yaml. - Environment variables such as
SYNCTV_SERVER_PORT=8080. - CLI flags for a small set of startup-level overrides such as
--configand--data-dir.
When the same value is defined in multiple places, the higher-precedence source wins. This is important in containers and Kubernetes because an environment variable can silently override a YAML value that looks correct.
Config File Search Paths
Section titled “Config File Search Paths”If --config is not provided, SyncTV searches common locations:
- Current directory:
./synctv.yaml - Linux user config:
$XDG_CONFIG_HOME/synctv/synctv.yamlor~/.config/synctv/synctv.yaml - Linux system config:
/etc/synctv/synctv.yaml - macOS user config:
~/.synctv/synctv.yaml - Container-friendly path:
/config/synctv.yaml
Use an explicit path in production scripts:
synctv serve --config /etc/synctv/synctv.yamlEnvironment Variable Naming
Section titled “Environment Variable Naming”Runtime environment variables use the SYNCTV_ prefix and convert the configuration path to uppercase underscores.
| Config field | Environment variable |
|---|---|
server.host | SYNCTV_SERVER_HOST |
server.port | SYNCTV_SERVER_PORT |
database.url | SYNCTV_DATABASE_URL |
redis.password | SYNCTV_REDIS_PASSWORD |
jwt.secret | SYNCTV_JWT_SECRET |
security.opaque_server_setup_secret | SYNCTV_SECURITY_OPAQUE_SERVER_SETUP_SECRET |
cache.proxy_slice_cache_enabled | SYNCTV_CACHE_PROXY_SLICE_CACHE_ENABLED |
Boolean values accept:
true/false1/0yes/no
List values usually accept JSON or comma-separated strings. Prefer JSON for complex values because it avoids ambiguity:
export SYNCTV_SERVER_CORS_ALLOWED_ORIGINS='["https://app.example.com"]'See Environment Variables for the full runtime environment variable list.
Secret Files
Section titled “Secret Files”Sensitive fields support loading values from files. This works well with Docker Secrets, Kubernetes Secrets, Vault Agent, External Secrets, and similar systems.
YAML form:
jwt: secret_file: "/run/secrets/jwt_secret"Environment variable form:
export SYNCTV_JWT_SECRET_FILE=/run/secrets/jwt_secretCommon fields that support file references include:
server.cluster_secretsecurity.credential_encryption_keysecurity.opaque_server_setup_secretmanagement.auth_tokendatabase.urldatabase.passwordredis.urlredis.passwordjwt.secretemail.smtp_passwordbootstrap.root_passwordlivestream.hls_oss.access_key_idlivestream.hls_oss.secret_access_key- Media provider secret-like fields such as
token,api_key,password,access_token, andrefresh_token
Relative *_file paths are resolved relative to the configuration file directory, not data_dir.
What data_dir Controls
Section titled “What data_dir Controls”data_dir is the root for runtime-owned local files written by SyncTV. It is not the configuration directory and it is not the database directory.
Paths affected by data_dir:
management.unix_socket_pathlogging.file_pathlivestream.hls_storage_pathcache.proxy_slice_file_cache_dir
Paths not affected by data_dir:
*_filesecret pathsmetrics.tls.cert_pathmetrics.tls.key_path
Example:
data_dir: "/var/lib/synctv"
cache: proxy_slice_file_cache_dir: "cache/proxy-slice"The actual slice cache path becomes:
/var/lib/synctv/cache/proxy-sliceBut this secret file remains relative to the configuration file location:
jwt: secret_file: "./secrets/jwt"Inspect and Validate the Effective Config
Section titled “Inspect and Validate the Effective Config”Use config show to inspect the final merged configuration. Secrets are redacted.
synctv --config /etc/synctv/synctv.yaml config show --output yamlValidate before deployment:
synctv --config /etc/synctv/synctv.yaml config validateValidation checks required secrets, unsafe placeholder values, CORS origins, WebAuthn origins, cluster dependencies, gRPC size limits, and path resolution constraints.