This page lists the default configuration shipped with SyncTV. Effective values combine config files, environment variables, CLI overrides, path resolution, and timezone fallback.
See Full Configuration Example for YAML templates. Run synctv config show --output yaml to inspect the effective configuration for the current binary with secrets redacted.
OAuth2 provider instances are Runtime Settings . Remote media provider instances are persisted through the management API/CLI and are not static config-file fields.
Most fields can keep their defaults. Production launch should prioritize secrets, database, entrypoints, security boundaries, and backups.
Setting
When to change it
Common mistake
After change
Production guidance
jwt.secret
Any production deployment
Keeping change-me-in-production or committing it
Restart required; old tokens may become invalid
Inject through Secret Manager or secret file
security.opaque_server_setup_secret
Local password/OPAQUE login
Regenerating it on every deployment
Restart required; casual changes can break password records
Generate once and back it up
security.credential_encryption_key
Storing encrypted provider credentials
Not 64 hex chars, or losing the key
Restart required; losing it breaks encrypted credential reads
Use openssl rand -hex 32 and back it up
security.email_outbox_encryption_key
Every production deployment
Different replicas use different keys
Restart required; queued email depends on this key
Generate once and back it up with the database
database.url / split fields
Production PostgreSQL
Pointing at local dev DB or oversizing the pool
Restart required
PostgreSQL must be persistent and backed up
redis.url / split fields
Production, OAuth2, multi-replica, rate limits, L2 cache
Different replicas use different Redis or key prefixes collide
Restart required
Recommended in production, required for multi-replica mode
server.cors_allowed_origins
Web frontend and API use different origins
Using * or adding a path
Restart required
Use exact origins such as https://app.example.com
server.trusted_proxies
A reverse proxy or Ingress sits in front
Trusting the whole internet
Restart required
Trust only proxy networks you control
management.*
CLI or operations control plane is needed
Exposing TCP management publicly without a token
Restart required
Prefer Unix socket; TCP must be authenticated
metrics.*
Prometheus or alerting is used
Exposing /metrics publicly
Restart required
Use auth and network isolation
webauthn.*
Passkeys are enabled
rp_origin does not match the real origin
Restart required
Use only production HTTPS origins
email.*
Email verification, password reset, email MFA, notifications
TLS/port/from address mismatch
Restart required
Verify with synctv settings test-email
cluster.* / cluster.secret
Multi-replica cluster
Cluster enabled without Redis or cluster secret
Restart required
All replicas share PostgreSQL, Redis, and secrets
livestream.*
RTMP/FLV/HLS livestreaming
HLS storage model differs between replicas
Restart required
Use shared filesystem or S3 for high traffic
proxy_slice_cache.*
Proxy Range slice cache is needed
Expecting full-file cache
Restart required
Mount enough storage; only Range slices are cached
Run these checks after changing configuration:
synctv config show --output yaml
curl -fsS http://localhost:8081/health/ready
Production Compose uses .env.postgres, .env.redis, and .env.synctv; it does not require a hand-written full YAML file. Before launch, confirm:
Goal
Compose/env focus
Config field
Initial administrator
SYNCTV_BOOTSTRAP_ROOT_PASSWORD
bootstrap.root_password
Token signing
SYNCTV_JWT_SECRET
jwt.secret
OPAQUE password login
SYNCTV_SECURITY_OPAQUE_SERVER_SETUP_SECRET
security.opaque_server_setup_secret
Provider credential encryption
SYNCTV_SECURITY_CREDENTIAL_ENCRYPTION_KEY
security.credential_encryption_key
Email queue encryption
SYNCTV_SECURITY_EMAIL_OUTBOX_ENCRYPTION_KEY
security.email_outbox_encryption_key
Web frontend CORS
SYNCTV_SERVER_CORS_ALLOWED_ORIGINS='["https://app.example.com"]'
server.cors_allowed_origins
PostgreSQL
.env.postgres and Compose volume
database.*
Redis
.env.redis, Compose Redis service, and key prefix
redis.*
Runtime files
Compose /data volume
data_dir
Use the field index below for bare-metal, Kubernetes, secret files, or custom YAML.
Field
Type / values
Default
Meaning
server.host
IP/listen address
0.0.0.0
Main API listen address
server.port
port
8080
HTTP REST and public gRPC listen port
server.enable_reflection
boolean
false
Enable public gRPC reflection
server.trusted_proxies
string array
[]
Trusted reverse proxy IPs/CIDRs
server.cors_allowed_origins
string array
[]
Frontend origins allowed by startup CORS
server.advertise_host
string
""
Address other nodes use to reach this node
server.shutdown_drain_timeout_seconds
seconds
30
Graceful shutdown drain timeout
server.grpc_max_message_size_bytes
bytes
16777216
Maximum gRPC message size
server.grpc_compression_enabled
boolean
true
Allow gRPC gzip compression negotiation
Field
Type / values
Default
Meaning
health.enabled
boolean
true
Enable the dedicated health listener
health.host
IP/listen address
127.0.0.1
Health listener address
health.port
port
8081
Health listener port for liveness and readiness endpoints
Field
Type / values
Default
Meaning
time.timezone
IANA timezone
""
Timezone for human-readable formatting and local datetime parsing
public_ids.sqids
object or null
null
Enable sqids public IDs when configured
public_ids.sqids.alphabet
string or null
null
sqids alphabet
public_ids.sqids.min_length
integer
12
Minimum sqids length
security.credential_encryption_key
64-character hex secret
""
Provider credential encryption key
security.totp_encryption_key
64-character hex secret
""
Dedicated TOTP encryption key; required
security.email_outbox_encryption_key
64-character hex secret
""
Dedicated email outbox encryption key; required in production
security.opaque_server_setup_secret
secret string
""
Stable OPAQUE server setup secret
security.proxy_signing_key
at least 32 characters
""
Dedicated media proxy URL signing key; required
security.media_swarm_signing_key
at least 32 characters
""
Dedicated WebRTC media swarm announcement signing key; required
security.provider_session_encryption_key
at least 32 characters
""
Dedicated provider login session key; required
security.login_discovery_key
at least 32 characters
""
Login discovery enumeration-protection key; required
security.webauthn_enumeration_key
at least 32 characters
""
WebAuthn enumeration-protection key; required
security.ssrf.enabled
boolean
false
Enable global SSRF protection for server-side outbound requests
security.ssrf.allow_private_network_targets
boolean
false
Allow server-side outbound requests to private/loopback/link-local/reserved/metadata targets
security.ssrf.allowed_hosts
string array
[]
Additional hostnames allowed by the global SSRF policy
security.ssrf.allowed_ip_ranges
IP/CIDR string array
[]
Additional IPs or CIDR ranges allowed by the global SSRF policy
Field
Type / values
Default
Meaning
metrics.enabled
boolean
false
Start the dedicated metrics listener
metrics.host
IP/listen address
0.0.0.0
Metrics listen address
metrics.port
port
9090
Metrics listen port
metrics.tls.enabled
boolean
false
Enable TLS on the metrics listener
metrics.tls.cert_path
file path
""
Metrics TLS certificate
metrics.tls.key_path
file path
""
Metrics TLS private key
metrics.auth.mode
bearer_token, basic, or kubernetes
bearer_token
Metrics authentication mode
metrics.auth.bearer_token
secret string
""
Bearer token for bearer-token mode
metrics.auth.basic_username
string
""
Basic-auth username
metrics.auth.basic_password
secret string
""
Basic-auth password
metrics.auth.kubernetes.audience
string
""
Kubernetes TokenReview audience
metrics.auth.kubernetes.authentication_cache_ttl_seconds
seconds
60
TokenReview result cache TTL
metrics.auth.kubernetes.authorization_cache_ttl_seconds
seconds
60
SubjectAccessReview result cache TTL
Field
Type / values
Default
Meaning
management.enabled
boolean
true
Enable the management endpoint
management.transport
unix or tcp
unix on Unix, tcp elsewhere
Management endpoint transport
management.port
port
50052
TCP management port
management.unix_socket_path
file path
platform-specific
Unix socket path
management.auth_token
secret string
""
TCP management bearer token
management.enable_reflection
boolean
false
Management gRPC reflection
Field
Type / values
Default
Meaning
database.url
PostgreSQL URL
postgresql://synctv:synctv@localhost:5432/synctv
Complete database connection URL
database.host
string
""
Database host for split configuration
database.port
port
0
Database port for split configuration
database.username
string
""
Database username
database.password
secret string
""
Database password
database.name
string
""
Database name
database.max_connections
integer
20
Maximum pool connections
database.min_connections
integer
5
Minimum idle pool connections
database.connect_timeout_seconds
seconds
10
Connection timeout
database.idle_timeout_seconds
seconds
600
Idle connection timeout
database.max_lifetime_seconds
seconds
1800
Maximum connection lifetime
Field
Type / values
Default
Meaning
redis.url
Redis URL
""
Complete Redis connection URL
redis.host
string
""
Redis host for split configuration
redis.port
port
0
Redis port for split configuration
redis.username
string
""
Redis username
redis.password
secret string
""
Redis password
redis.database
integer
0
Redis database index
redis.connect_timeout_seconds
seconds
5
Redis connection timeout
redis.response_timeout_seconds
seconds
5
Redis command response timeout
redis.pipeline_buffer_size
integer
512
Redis connection manager pipeline buffer size
redis.key_prefix
string
synctv:
Redis key prefix
redis.deployment_mode
standalone or sentinel
standalone
Redis deployment mode
redis.sentinel_master_name
string or null
null
Sentinel master name
redis.sentinel_addresses
string array
[]
Sentinel node addresses
Top-level logging receives logs from the database, Redis, caches, proxies, realtime, outbox, migrations, startup, third-party dependencies, and all remaining targets. <component> is one of server, health, metrics, management, cluster, livestream, or webrtc; each component has an independent output.
Field
Type / values
Default
Meaning
jwt.secret
secret string
change-me-in-production
Token signing secret
jwt.access_token_duration_hours
hours
1
Access-token lifetime
jwt.refresh_token_duration_days
days
30
Refresh-token lifetime
jwt.guest_token_duration_hours
hours
4
Guest-token lifetime
jwt.clock_skew_leeway_secs
seconds
60
Token timestamp skew allowance
logging.level
error, warn, info, debug, or trace
info
Global log level
logging.format
text or json
text
Global log format
logging.output
stdout, stderr, or a file object
stdout
Global log output
logging.output.path
file path
""
Global log file path; relative paths resolve under data_dir
logging.output.rotation.strategy
daily, hourly, or never
daily
Global log file rotation period
logging.output.rotation.max_files
positive integer
30
Global log files retained
logging.color
auto, always, or never
auto
Global color output
<component>.logging.level
error, warn, info, debug, or trace
info (warn for metrics/cluster)
Component log level
<component>.logging.format
text or json
text
Component log format
<component>.logging.output
stdout, stderr, or a file object
stdout
Independent component output
<component>.logging.output.path
file path
""
Component log file path; relative paths resolve under data_dir
<component>.logging.output.rotation.strategy
daily, hourly, or never
daily
File rotation period
<component>.logging.output.rotation.max_files
positive integer
30
Files retained per component
<component>.logging.color
auto, always, or never
auto
Component color output
Field
Type / values
Default
Meaning
livestream.rtmp_port
port
1935
RTMP ingest port
livestream.public_rtmp_host
string
""
Public RTMP host returned to publishers
livestream.public_webrtc_base_url
HTTP(S) origin or empty
""
Public WHIP origin in publish-key responses; empty returns a relative URL
livestream.gop_cache_size
integer
2
Number of GOPs cached per stream
livestream.stream_timeout_seconds
seconds
300
Pull-stream idle timeout
livestream.cleanup_check_interval_seconds
seconds
60
Cleanup check interval
livestream.pull_max_retries
integer
10
Maximum pull-stream retries
livestream.pull_initial_backoff_ms
milliseconds
1000
Initial pull retry backoff
livestream.pull_max_backoff_ms
milliseconds
30000
Maximum pull retry backoff
livestream.max_flv_tag_size_bytes
bytes
10485760
Maximum accepted FLV tag size
livestream.gop_cache_max_memory_mb
MB
100
GOP cache memory limit
livestream.hls_storage.type
memory, file, shared_file, or s3
memory
HLS segment storage backend
livestream.hls_storage.memory_max_mb
MB
0
HLS storage limit for memory; 0 uses the built-in default
livestream.hls_storage.path
path
""
HLS file path for the file / shared_file backend
livestream.hls_storage.endpoint
string
""
S3-compatible endpoint for the s3 backend; required when s3 is enabled
livestream.hls_storage.access_key_id
secret string
""
Access key ID for the s3 backend; required when s3 is enabled
livestream.hls_storage.secret_access_key
secret string
""
Secret access key for the s3 backend; required when s3 is enabled
livestream.hls_storage.bucket
string
""
Bucket for the s3 backend; required when s3 is enabled
livestream.hls_storage.region
string or null
null
Region for the s3 backend
livestream.hls_storage.base_path
string
hls/
Object key prefix inside the bucket
livestream.flv_max_connection_duration_seconds
seconds
86400
Maximum HTTP-FLV connection duration
livestream.flv_write_timeout_seconds
seconds
30
HTTP-FLV write timeout
livestream.webrtc.enabled
boolean
true
Enable WHIP/WHEP livestream sessions
livestream.webrtc.ice_servers
ICE server list
[]
STUN/TURN servers used by livestream PeerConnections
livestream.webrtc.ice_gathering_timeout_seconds
seconds
10
Time allowed to gather local ICE candidates
livestream.webrtc.max_sdp_bytes
bytes
262144
Limit for WHIP/WHEP SDP requests and upstream WHEP SDP responses
livestream.webrtc.max_sessions
integer
1000
Total WHIP/WHEP session limit on one node
livestream.webrtc.max_session_duration_seconds
seconds
86400
Maximum lifetime of one WHIP/WHEP session
Field
Type / values
Default
Meaning
file_storage.default_backend
backend name
disabled
Fallback backend used by product features
file_storage.chat_attachments_backend
backend name or empty
""
Backend for chat attachments; empty inherits default_backend
file_storage.user_avatars_backend
backend name or empty
""
Backend for user avatars; empty inherits default_backend
file_storage.media_covers_backend
backend name or empty
""
Backend for media covers; empty inherits default_backend
file_storage.room_covers_backend
backend name or empty
""
Backend for room covers; empty inherits default_backend
file_storage.playlist_covers_backend
backend name or empty
""
Backend for playlist covers; empty inherits default_backend
file_storage.upload_token_secret
at least 32 characters
""
Dedicated signing key for file upload/read tokens; required
file_storage.unreferenced_object_retention_seconds
seconds
86400
Grace period before uploaded objects with no active product reference are cleaned; 0 disables orphan cleanup
file_storage.backends.<name>.type
disabled, database, or s3
disabled
Registered backend implementation type
file_storage.backends.<name>.compression
none, lz4, or zstd
zstd
Compression algorithm used by type: "database" backends for persisted file_blob_parts segments
file_storage.backends.<name>.compression_min_size_bytes
bytes
4096
Minimum original payload size before compression is attempted
file_storage.backends.<name>.compression_min_savings_percent
0 to 100
10
Minimum saved percentage required before compressed bytes are stored
file_storage.backends.<name>.<s3-field>
S3 config
default S3 fields
S3-compatible settings for backends with type: "s3"; public_base_url is required for readable file URLs after upload or ownership proof validation
Upload sessions use a server-provided part plan: clients first request FileUploadPlan with empty parts, hash every planned part with SHA-256, then submit FileUploadManifestPart[]. SyncTV computes content_manifest_sha256 from the canonical manifest and uses it for instant-upload object lookup and unfinished resumable-session lookup. Database backends persist fixed file_blob_parts segments and serve HTTP Range requests directly from those segments, decompressing only the parts that overlap the requested byte range. S3 backends use native multipart uploads with presigned part URLs, sign x-amz-checksum-sha256 into each part URL, and validate object identity from the recorded part manifest at completion without reading GB-scale objects back from S3. Duplicate objects return upload_required=false with an ownership proof challenge; readable URLs are signed after proof validation and business-reference persistence.
Disable file storage:
default_backend : " disabled "
Store file bytes in PostgreSQL:
default_backend : " database "
chat_attachments_backend : " database "
user_avatars_backend : " database "
media_covers_backend : " database "
room_covers_backend : " database "
playlist_covers_backend : " database "
upload_token_secret_file : " /run/secrets/file_upload_token_secret "
Use S3-compatible object storage:
default_backend : " s3_public "
chat_attachments_backend : " s3_public "
user_avatars_backend : " s3_public "
media_covers_backend : " s3_public "
room_covers_backend : " s3_public "
playlist_covers_backend : " s3_public "
upload_token_secret_file : " /run/secrets/file_upload_token_secret "
endpoint : " https://s3.example.com "
access_key_id_file : " /run/secrets/file_storage_s3_access_key_id "
secret_access_key_file : " /run/secrets/file_storage_s3_secret_access_key "
public_base_url : " https://cdn.example.com/files "
upload_expires_seconds : 900
Field
Type / values
Default
Meaning
webauthn.enabled
boolean
false
Enable passkey endpoints
webauthn.rp_id
domain
""
WebAuthn relying-party ID
webauthn.rp_origin
origin
""
Primary WebAuthn origin
webauthn.rp_name
string
SyncTV
Authenticator display name
webauthn.allowed_origins
origin array
[]
Additional accepted origins
webauthn.apple_app_ids
Apple application identifier array
[]
Web Credentials associations for native Apple apps
webauthn.android_apps
Android app association array
[]
Package names and signing-certificate SHA-256 fingerprints
webauthn.allow_subdomains
boolean
false
Allow subdomains of configured origins
webauthn.allow_any_port
boolean
false
Ignore origin ports
webauthn.timeout_seconds
seconds
300
Challenge timeout
Field
Type / values
Default
Meaning
media_providers.alist.request_timeout_seconds
seconds
30
Local Alist provider request timeout
media_providers.alist.connect_timeout_seconds
seconds
10
Local Alist provider connection timeout
media_providers.bilibili.request_timeout_seconds
seconds
30
Local Bilibili provider request timeout
media_providers.bilibili.connect_timeout_seconds
seconds
10
Local Bilibili provider connection timeout
media_providers.emby.request_timeout_seconds
seconds
30
Local Emby/Jellyfin provider request timeout
media_providers.emby.connect_timeout_seconds
seconds
10
Local Emby/Jellyfin provider connection timeout
webrtc.mode
signaling_only or peer_to_peer
peer_to_peer
WebRTC operating mode
webrtc.enable_builtin_stun
boolean
false
Enable built-in STUN
webrtc.stun_port
port
3478
STUN port
webrtc.stun_host
IP/listen address
0.0.0.0
STUN listen address
webrtc.stun_external_addr
string
""
STUN external address announced to clients
webrtc.filter_private_ice_candidates
boolean
false
Filter private ICE candidates
Field
Type / values
Default
Meaning
connection_limits.max_per_user
integer
20
Maximum connections per user
connection_limits.max_per_room
integer
2000
Maximum connections per room
connection_limits.max_total
integer
100000
Maximum service-wide connections
connection_limits.idle_timeout_seconds
seconds
300
Idle connection timeout
connection_limits.max_duration_seconds
seconds
86400
Maximum connection lifetime
connection_limits.ws_message_rate_limit_per_second
per-second count
50
WebSocket message rate per connection
bootstrap.create_root_user
boolean
false
Create the initial root user automatically
bootstrap.root_username
string
root
Initial root username
bootstrap.root_password
secret string
""
Initial root password
cluster.enabled
boolean
false
Enable cluster mode
cluster.host
IP/listen address
0.0.0.0
Dedicated internal gRPC listen address
cluster.port
port
50051
Dedicated internal gRPC listen port
cluster.advertise_host
hostname or IP
""
Internal address advertised to peers; empty uses server.advertise_host
cluster.advertise_port
port or 0
0
Internal port advertised to peers; 0 uses cluster.port
cluster.secret
secret string
""
Authentication secret for internal cluster gRPC
cluster.secret_file
file path or empty
""
File containing the internal cluster request authentication secret
cluster.critical_channel_capacity
integer
10000
High-priority cluster event queue capacity
cluster.publish_channel_capacity
integer
100000
Normal cluster publish queue capacity
cluster.discovery_mode
redis, static, or k8s_dns
redis
Node discovery mode
cluster.leader_election_mode
redis or k8s_lease
redis
Leader election mode
cluster.peers
string array
[]
Static peer addresses
cluster.catchup_window_secs
seconds
300
Redis Stream catch-up replay window
cluster.stream_max_length
integer
100000
Approximate Redis Stream maximum length
Field
Type / values
Default
Meaning
password_complexity.min_length
integer
8
Minimum password length
password_complexity.require_uppercase
boolean
true
Require uppercase letters
password_complexity.require_lowercase
boolean
true
Require lowercase letters
password_complexity.require_digit
boolean
true
Require digits
password_complexity.require_special
boolean
false
Require special characters
password_complexity.max_repeated_chars
integer
3
Maximum repeated consecutive characters; 0 disables this check
password_complexity.zxcvbn_enabled
boolean
false
Enable zxcvbn entropy scoring for account passwords
password_complexity.zxcvbn_min_score
integer 0-4
3
Minimum zxcvbn score when enabled
buffer_sizes.websocket_outbound
integer
256
Per-connection WebSocket outbound queue size
buffer_sizes.audit_buffer
integer
10000
Audit event buffer capacity
cache.l1_capacity
integer
5000
L1 in-memory cache capacity
cache.l1_ttl_seconds
seconds
300
L1 in-memory cache TTL
cache.l2_ttl_seconds
seconds
300
Redis L2 cache TTL
cache.username_cache_capacity
integer
10000
Username cache capacity
cache.username_cache_ttl_seconds
seconds
3600
Username cache TTL
proxy_slice_cache.enabled
boolean
true
Enable proxy slice cache at startup
proxy_slice_cache.slice_size_bytes
integer
2097152
Individual Range slice size
proxy_slice_cache.max_cache_size_bytes
integer
536870912
Maximum total slice cache capacity
proxy_slice_cache.segment_ttl_seconds
seconds
300
Fresh slice TTL
proxy_slice_cache.stale_max_age_seconds
seconds
60
Time expired slices may be served as stale
proxy_slice_cache.stale_while_revalidate
boolean
true
Refresh expired hits in the background
proxy_slice_cache.file_backend_enabled
boolean
false
Enable file backend for proxy slice cache
proxy_slice_cache.file_cache_dir
path
""
Proxy slice cache file directory
proxy_slice_cache.eviction_interval_seconds
seconds
60
Background eviction check interval
proxy_slice_cache.watermark_ratio
float
0.875
Target usage ratio after eviction
Field
Type / values
Default
Meaning
messaging_rate_limits.chat_per_second
integer
10
Maximum chat messages per window
messaging_rate_limits.window_seconds
seconds
1
Chat rate-limit window
Field
Type / values
Default
Meaning
request_rate_limits.auth_max_requests
integer
5
Maximum authentication requests per window
request_rate_limits.auth_window_seconds
seconds
60
Authentication request window
request_rate_limits.write_max_requests
integer
120
Maximum write requests per window
request_rate_limits.write_window_seconds
seconds
60
Write request window
request_rate_limits.read_max_requests
integer
600
Maximum read requests per window
request_rate_limits.read_window_seconds
seconds
60
Read request window
request_rate_limits.media_max_requests
integer
120
Maximum media requests per window
request_rate_limits.media_window_seconds
seconds
60
Media request window
request_rate_limits.admin_max_requests
integer
180
Maximum admin requests per window
request_rate_limits.admin_window_seconds
seconds
60
Admin request window
request_rate_limits.streaming_max_requests
integer
1200
Maximum streaming requests per window
request_rate_limits.streaming_window_seconds
seconds
60
Streaming request window
request_rate_limits.websocket_max_requests
integer
60
Maximum WebSocket connection attempts per window
request_rate_limits.websocket_window_seconds
seconds
60
WebSocket connection window