Documentation Index Fetch the complete documentation index at: https://mintlify.com/moqtail/moqtail/llms.txt
Use this file to discover all available pages before exploring further.
The MOQtail relay server is a high-performance Rust application that forwards MOQT messages between publishers and subscribers. It supports WebTransport and provides configurable caching, logging, and connection management.
Prerequisites
Before deploying the relay server, ensure you have:
Rust (1.70 or later) - Install Rust
SSL/TLS Certificates - Required for WebTransport
Linux/Unix environment - Recommended for production
Quick Start
Clone the repository
git clone https://github.com/moqtail/moqtail.git
cd moqtail
Generate certificates
For development, use mkcert to generate self-signed certificates: # Install mkcert
brew install mkcert # macOS
# or follow https://github.com/FiloSottile/mkcert#installation
# Install local CA
mkcert -install
# Generate certificates (run from apps/relay/cert)
cd apps/relay/cert
mkcert -key-file key.pem -cert-file cert.pem localhost 127.0.0.1 ::1
For production deployments, use certificates from a trusted Certificate Authority (CA) like Let’s Encrypt.
Run the relay server
cargo run --bin relay -- --port 4433 --cert-file cert/cert.pem --key-file cert/key.pem
Configuration Options
The relay server supports extensive configuration through command-line arguments:
Network Configuration
/// Port to bind
#[arg(long, default_value_t = 4433)]
pub port : u16 ,
/// Host to bind
#[arg(long, default_value = "localhost" )]
pub host : String ,
cargo run --bin relay -- \
--port 4433 \
--host localhost \
--cert-file apps/relay/cert/cert.pem \
--key-file apps/relay/cert/key.pem
Certificate Configuration
/// Certificate PEM file
#[arg(long, default_value = "apps/relay/cert/cert.pem" )]
pub cert_file : String ,
/// Private key PEM file
#[arg(long, default_value = "apps/relay/cert/key.pem" )]
pub key_file : String ,
Certificates are loaded using the wtransport Identity API:
let identity = Identity :: load_pemfiles ( & self . cert_file, & self . key_file) . await ? ;
let config = ServerConfig :: builder ()
. with_bind_default ( self . port)
. with_identity ( identity )
. keep_alive_interval ( Some ( Duration :: from_secs ( self . keep_alive_interval)))
. max_idle_timeout ( Some ( Duration :: from_secs ( self . max_idle_timeout)))
. unwrap ()
. build ();
Connection Management
# Keep-alive and timeout settings
cargo run --bin relay -- \
--max-idle-timeout 7 \
--keep-alive-interval 3
Parameters:
--max-idle-timeout: Maximum idle time (seconds) before closing inactive connections
--keep-alive-interval: Interval (seconds) for sending keep-alive packets
Cache Configuration
The relay implements a sophisticated caching system for subgroups and fetches:
/// Number of cached subgroups/fetches per track
#[arg(long, default_value_t = 1000)]
pub cache_size : u16 ,
/// Cache expiration type (ttl or tti)
#[arg(long, value_enum, default_value = "ttl" )]
pub cache_expiration_type : CacheExpirationType ,
/// Cache expiration duration in minutes
#[arg(long, default_value_t = 30)]
pub cache_expiration_minutes : u64 ,
Time-to-Live (TTL)
Time-to-Idle (TTI)
# Entries expire after fixed duration from creation
cargo run --bin relay -- \
--cache-size 1000 \
--cache-expiration-type ttl \
--cache-expiration-minutes 30
Logging Configuration
#[arg(long, default_value = "/tmp" )]
pub log_folder : String ,
/// Enable object logging
#[arg(long, default_value_t = false)]
pub enable_object_logging : bool ,
/// Enable token logging
#[arg(long, default_value_t = false)]
pub enable_token_logging : bool ,
/// Token log file path
#[arg(long, default_value = "/tmp/tokens.csv" )]
pub token_log_path : String ,
Development Logging
Production Logging
cargo run --bin relay -- \
--log-folder ./logs \
--enable-object-logging \
--enable-token-logging \
--token-log-path ./logs/tokens.csv
The relay uses tracing for structured logging with daily log rotation:
fn init_logging ( log_dir : & str ) {
let env_filter = EnvFilter :: builder ()
. with_default_directive ( LevelFilter :: INFO . into ())
. from_env_lossy ();
std :: fs :: create_dir_all ( log_dir ) . expect ( "Failed to create log directory" );
let file_appender = tracing_appender :: rolling :: daily ( log_dir , "relay.log" );
let ( non_blocking , _guard ) = tracing_appender :: non_blocking ( file_appender );
tracing_subscriber :: fmt ()
. with_target ( true )
. with_level ( true )
. with_env_filter ( env_filter )
. with_writer ( non_blocking . and ( std :: io :: stdout ))
. init ();
}
Advanced Configuration
# Initial maximum request ID
cargo run --bin relay -- \
--initial-max-request-id 2305843009213693951
Parameter:
--initial-max-request-id: Starting maximum request ID (default: u64::MAX / 8)
Production Deployment
Building for Production
# Build optimized binary
cargo build --release --bin relay
# Binary location
./target/release/relay
Systemd Service
Create a systemd service file /etc/systemd/system/moqtail-relay.service:
[Unit]
Description =MOQtail Relay Server
After =network.target
[Service]
Type =simple
User =moqtail
Group =moqtail
WorkingDirectory =/opt/moqtail
ExecStart =/opt/moqtail/target/release/relay \
--port 443 \
--host 0.0.0.0 \
--cert-file /etc/ssl/moqtail/cert.pem \
--key-file /etc/ssl/moqtail/key.pem \
--log-folder /var/log/moqtail \
--cache-size 5000 \
--max-idle-timeout 30 \
--keep-alive-interval 5 \
--enable-token-logging \
--token-log-path /var/log/moqtail/tokens.csv
Restart =always
RestartSec =10
[Install]
WantedBy =multi-user.target
Enable and start the service:
sudo systemctl daemon-reload
sudo systemctl enable moqtail-relay
sudo systemctl start moqtail-relay
sudo systemctl status moqtail-relay
Docker Deployment
Create a Dockerfile in the relay directory:
FROM rust:1.70 as builder
WORKDIR /app
COPY . .
# Build the relay
RUN cargo build --release --bin relay
FROM debian:bookworm-slim
RUN apt-get update && apt-get install -y \
ca-certificates \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY --from=builder /app/target/release/relay /app/relay
EXPOSE 4433
ENTRYPOINT [ "/app/relay" ]
CMD [ "--port" , "4433" , "--host" , "0.0.0.0" , "--cert-file" , "/certs/cert.pem" , "--key-file" , "/certs/key.pem" ]
Build and run:
docker build -t moqtail-relay .
docker run -d \
-p 4433:4433/udp \
-v /path/to/certs:/certs \
-v /path/to/logs:/var/log/moqtail \
--name moqtail-relay \
moqtail-relay
Environment Variables
Control logging level via environment variable:
# Set log level
export RUST_LOG = info
# More verbose logging
export RUST_LOG = debug , relay = trace
# Run with custom log level
RUST_LOG = info cargo run --bin relay
Monitoring
Server Startup
When the relay starts successfully, you’ll see:
info! (
"{} is running at https://{}:{}" ,
env! ( "MOQTAIL_VERSION" ),
self . app_config . host,
self . app_config . port
);
Example output:
moqtail/0.12.0+a1b2c3d is running at https://localhost:4433
Log Files
The relay generates daily rotating logs:
# View relay logs
tail -f /var/log/moqtail/relay.log
# View token logs (if enabled)
tail -f /var/log/moqtail/tokens.csv
Health Checks
Monitor server health by checking:
Process status : systemctl status moqtail-relay
Port binding : ss -tulpn | grep 4433
Log output : Check for errors in relay.log
Troubleshooting
Failed to load identity from PEM files
Error: Failed to load identity from PEM files
Solution:
Verify certificate files exist and have correct permissions
Check certificate format (must be PEM)
Ensure paths are correct (absolute or relative to working directory)
ls -la apps/relay/cert/
chmod 600 apps/relay/cert/key.pem
chmod 644 apps/relay/cert/cert.pem
Error: Failed to create server endpoint: Address already in use
Solution:
Check if another process is using the port:
lsof -i :4433
# or
ss -tulpn | grep 4433
cargo run --bin relay -- --port 8443
Failed to create log directory
Error: Failed to create log directory
Solution:
Create the directory manually:
sudo mkdir -p /var/log/moqtail
sudo chown moqtail:moqtail /var/log/moqtail
Or use a writable location:
cargo run --bin relay -- --log-folder ./logs
Connection refused from clients
Possible causes:
Firewall blocking UDP traffic on port 4433
Certificate not trusted by client browser
Server bound to localhost instead of 0.0.0.0
Solution: # Allow UDP traffic
sudo ufw allow 4433/udp
# Bind to all interfaces
cargo run --bin relay -- --host 0.0.0.0
Complete Configuration Reference
#[derive( Parser , Debug )]
pub struct Cli {
#[arg(long, default_value_t = 4433)]
pub port : u16 ,
#[arg(long, default_value = "localhost" )]
pub host : String ,
#[arg(long, default_value = "apps/relay/cert/cert.pem" )]
pub cert_file : String ,
#[arg(long, default_value = "apps/relay/cert/key.pem" )]
pub key_file : String ,
#[arg(long, default_value_t = 1000)]
pub cache_size : u16 ,
#[arg(long, default_value_t = 7)]
pub max_idle_timeout : u64 ,
#[arg(long, default_value_t = 3)]
pub keep_alive_interval : u64 ,
#[arg(long, default_value = "/tmp" )]
pub log_folder : String ,
#[arg(long, value_enum, default_value = "ttl" )]
pub cache_expiration_type : CacheExpirationType ,
#[arg(long, default_value_t = 30)]
pub cache_expiration_minutes : u64 ,
#[arg(long, default_value_t = false)]
pub enable_object_logging : bool ,
#[arg(long, default_value_t = false)]
pub enable_token_logging : bool ,
#[arg(long, default_value = "/tmp/tokens.csv" )]
pub token_log_path : String ,
#[arg(long, default_value_t = u64 :: MAX / 8)]
pub initial_max_request_id : u64 ,
}
Next Steps
WebTransport Setup Configure WebTransport for browser clients
Client Integration Connect clients to your relay server