Skip to content

How Configuration Works

SyncTV builds the effective runtime configuration by merging several sources. The precedence order from lowest to highest is:

  1. Built-in defaults from the Rust configuration structs.
  2. A configuration file such as synctv.yaml or /config/synctv.yaml.
  3. Environment variables such as SYNCTV_SERVER_PORT=8080.
  4. CLI flags for a small set of startup-level overrides such as --config and --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.

If --config is not provided, SyncTV searches common locations:

  • Current directory: ./synctv.yaml
  • Linux user config: $XDG_CONFIG_HOME/synctv/synctv.yaml or ~/.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.yaml

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
security.credential_encryption_key SYNCTV_SECURITY_CREDENTIAL_ENCRYPTION_KEY
security.totp_encryption_key SYNCTV_SECURITY_TOTP_ENCRYPTION_KEY
security.email_outbox_encryption_key SYNCTV_SECURITY_EMAIL_OUTBOX_ENCRYPTION_KEY
security.proxy_signing_key SYNCTV_SECURITY_PROXY_SIGNING_KEY
security.media_swarm_signing_key SYNCTV_SECURITY_MEDIA_SWARM_SIGNING_KEY
security.provider_session_encryption_key SYNCTV_SECURITY_PROVIDER_SESSION_ENCRYPTION_KEY
security.login_discovery_key SYNCTV_SECURITY_LOGIN_DISCOVERY_KEY
security.webauthn_enumeration_key SYNCTV_SECURITY_WEBAUTHN_ENUMERATION_KEY
file_storage.upload_token_secret SYNCTV_FILE_UPLOAD_TOKEN_SECRET
proxy_slice_cache.enabled SYNCTV_PROXY_SLICE_CACHE_ENABLED

Boolean values accept:

  • true / false
  • 1 / 0
  • yes / 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.

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_secret

Common fields that support file references include:

  • cluster.secret
  • security.credential_encryption_key
  • security.totp_encryption_key
  • security.email_outbox_encryption_key
  • security.opaque_server_setup_secret
  • security.proxy_signing_key
  • security.media_swarm_signing_key
  • security.provider_session_encryption_key
  • security.login_discovery_key
  • security.webauthn_enumeration_key
  • file_storage.upload_token_secret
  • management.auth_token
  • database.url
  • database.password
  • redis.url
  • redis.password
  • jwt.secret
  • metrics.auth.bearer_token
  • metrics.auth.basic_password
  • bootstrap.root_password
  • livestream.hls_storage.access_key_id
  • livestream.hls_storage.secret_access_key
  • Media provider secret-like fields such as token, api_key, password, access_token, and refresh_token

Relative *_file paths are resolved relative to the configuration file directory, not data_dir.

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_path
  • logging.output.path
  • <component>.logging.output.path, where <component> is server, health, metrics, management, cluster, livestream, or webrtc
  • livestream.hls_storage.path
  • proxy_slice_cache.file_cache_dir

Paths not affected by data_dir:

  • *_file secret paths
  • metrics.tls.cert_path
  • metrics.tls.key_path

Example:

data_dir: "/var/lib/synctv"
proxy_slice_cache:
file_cache_dir: "cache/proxy-slice"

The actual slice cache path becomes:

/var/lib/synctv/cache/proxy-slice

But this secret file remains relative to the configuration file location:

jwt:
secret_file: "./secrets/jwt"

Use config show to inspect the final merged configuration. Secrets are redacted.

终端窗口
synctv --config /etc/synctv/synctv.yaml config show --output yaml

Validate before deployment:

终端窗口
synctv --config /etc/synctv/synctv.yaml config validate
synctv --config /etc/synctv/synctv.yaml config validate --strict

Validation checks required secrets, unsafe placeholder values, CORS origins, WebAuthn origins, cluster dependencies, gRPC size limits, and path resolution constraints. config validate reports unknown config-file keys and unsupported SYNCTV_ environment variables as warnings by default. Add --strict to make those unknown inputs fail validation. synctv serve always uses strict startup loading, so production startup fails instead of ignoring misspelled settings.

Runtime settings loaded through the management API, CLI, or an import snapshot ignore unknown fields while continuing to validate known fields for type, range, and business rules. This lets a newer settings snapshot be read safely by an older binary; static startup configuration follows the strict rules above.