Skip to main content

Configuration Files

OTT is configured using TOML files located in the env/ directory. The configuration system loads files in the following order:
  1. Base configuration: env/base.toml (always loaded)
  2. Environment-specific: env/<NODE_ENV>.toml (e.g., env/production.toml)
  3. Environment variables: Override any config option
Start by copying the example configuration:
cp env/example.toml env/production.toml

Required Configuration

These settings must be configured for production deployment:

Hostname

hostname = "example.com:8080"
The domain name where your server is running. Include the port if not using standard HTTP/HTTPS ports. Environment variable: OTT_HOSTNAME

Session Secret

session_secret = "your-secure-random-string-at-least-80-characters-long"
Must be at least 80 characters long. Use a password generator to create a secure alphanumeric secret.
Environment variable: SESSION_SECRET

API Key

api_key = "your-api-key-at-least-40-characters"
Required for performing admin tasks. Must be at least 40 characters. Environment variable: OPENTOGETHERTUBE_API_KEY

YouTube API Key

[info_extractor.youtube]
api_key = "your-youtube-api-key"
Obtain from Google Cloud Console. Required for YouTube video functionality. Environment variable: YOUTUBE_API_KEY

Server Configuration

Port

port = 3000
The port the server listens on. Default: 3000 Environment variable: PORT

Base URL

base_url = "/ott"
Base path for the application if not serving from root. Default: "" Environment variable: OTT_BASE_URL

Logging

[log]
level = "info"  # Options: silly, debug, info, warn, error
file = "/var/log/ott.log"  # Optional: log to file
Environment variables: LOG_LEVEL, LOG_FILE

Trust Proxy

trust_proxy = 1
Number of reverse proxy layers to trust for IP addresses. Important for rate limiting and security. Environment variable: TRUST_PROXY

Database Configuration

See the Database Configuration guide for detailed PostgreSQL and SQLite setup.
[db]
mode = "postgres"  # Options: postgres, sqlite
host = "localhost"
port = 5432
name = "opentogethertube"
user = "ott"
password = "your-password"
Alternatively, use a connection URL:
[db]
url = "postgresql://user:password@localhost:5432/opentogethertube"
Environment variables: DB_MODE, DATABASE_URL, POSTGRES_HOST, POSTGRES_PORT, POSTGRES_DB, POSTGRES_USER, POSTGRES_PASSWORD

Redis Configuration

[redis]
host = "localhost"
port = 6379
username = ""  # Optional
password = ""  # Optional
db = 0
Or use a connection URL:
[redis]
url = "redis://username:password@localhost:6379/0"
Environment variables: REDIS_URL, REDIS_HOST, REDIS_PORT, REDIS_USERNAME, REDIS_PASSWORD, REDIS_DB

Video Services

Enabled Services

[info_extractor]
services = ["youtube", "vimeo", "googledrive", "peertube"]  # Allowlist
By default, all services are enabled. Specify an array to limit which video services are allowed.

YouTube Configuration

[info_extractor.youtube]
api_key = "your-key"
truncate_description = 500  # Optional: limit description length

Google Drive Configuration

[info_extractor.google_drive]
api_key = "your-google-drive-api-key"  # Optional

Direct Video Configuration

[info_extractor.direct]
ffprobe_path = "/usr/bin/ffprobe"
preview_max_bytes = 10485760  # 10MB
ffprobe_strategy = "stream"  # Options: stream, disk, run
Environment variable: FFPROBE_PATH

PeerTube Configuration

[info_extractor.peertube]
instances = [
  "video.sadmin.io",
  "tube.shanti.cafe",
  "peertube.tmp.rcp.tf"
]
emit_as_direct = true  # Use if embeds are broken

Invidious Configuration

[info_extractor.invidious]
instances = ["yt.safh.de", "inv.nadeko.net", "yewtu.be"]

Search Configuration

[add_preview.search]
enabled = true
provider = "youtube"
min_query_length = 3
results_count = 8
[add_preview]
playlist_results_count = 40
Environment variables: ENABLE_SEARCH, SEARCH_PROVIDER

Authentication

Discord OAuth

[discord]
client_id = "your-discord-client-id"
client_secret = "your-discord-client-secret"
1

Create Discord application

Go to the Discord Developer Portal and create a new application.
2

Set callback URL

Set the OAuth2 redirect URL to:
https://<your-domain>/<base-url>/api/auth/discord/callback
For local development:
http://localhost:8080/api/auth/discord/callback
3

Add credentials to config

Copy the client ID and secret to your configuration file.
Environment variables: DISCORD_CLIENT_ID, DISCORD_CLIENT_SECRET

Rate Limiting

[rate_limit]
enabled = true
key_prefix = "rateLimit"  # Redis key prefix
Environment variable: ENABLE_RATE_LIMIT

Room Settings

[room]
enable_create_temporary = true
enable_create_permanent = true
unload_after = 300  # Seconds of inactivity before unloading
expire_after = 7200  # Seconds to keep room state in Redis

User Settings

[users]
enable_registration = true
Set to false to disable new user registrations.

Video Features

SponsorBlock

[video.sponsorblock]
enabled = true
cache_ttl = 604800  # 1 week in seconds

Advanced Configuration

CORS Proxy

cors_proxy = "https://cors-proxy.example.com"
Required for CORS-protected video services.

Short URL

short_url = "ott.app"
Domain for shortened invite URLs. Environment variable: OTT_SHORT_URL_HOSTNAME

Force Insecure Cookies

force_insecure_cookies = false
Only enable this if running behind a reverse proxy that handles SSL termination.
Environment variable: FORCE_INSECURE_COOKIES

Load Balancing

[balancing]
enabled = false
port = 3002
region = "us-east"
Enable if using the OTT load balancer. Environment variables: BALANCING_ENABLED, BALANCING_PORT, BALANCING_REGION

Email Configuration

[mail]
enabled = false
mailjet_api_key = "your-mailjet-key"
mailjet_api_secret = "your-mailjet-secret"
sender_email = "[email protected]"
sender_name = "OpenTogetherTube"
mailjet_sandbox = false
Environment variables: MAILJET_API_KEY, MAILJET_API_SECRET

Configuration Schema

The complete configuration schema is defined in server/ott-config.ts. Most options support environment variable overrides as documented above.

Build docs developers (and LLMs) love