Remedia

Deployment

Local operation, TLS termination, network restrictions, and independent nodes.

Release binaries

Standalone releases cover Linux x64/ARM64 glibc, macOS x64/ARM64, and Windows x64 MSVC. Download the target .tar.gz archive and keep its LICENSE and THIRD_PARTY_NOTICES.md plus the THIRD_PARTY_LICENSES.txt appendix with the executable. Raw binaries are also accompanied by those notices in the release assets. Release archives include both the FFmpeg-independent administrative CLI and the separately linked server runtime. The release archives do not bundle FFmpeg. The one-command installer provisions FFmpeg 9 in an isolated directory, or you can install compatible shared libraries independently. See runtime ABI versions and library discovery and licensing and media responsibility. The server needs no Node.js runtime.

Docker

The published ghcr.io/twlite/remedia image and Compose example run the standalone server with persistent configuration and a loopback-only published port. See Run the server in Docker.

Local development

For local use, install the server with the installer, run remedia init, read the generated credentials from remedia.config.json, and start remedia-server. The listener defaults to 127.0.0.1:8787 and accepts WebSocket RPC at /v1/ws.

Discord bot identity is sent by each client as the X-Remedia-Bot-Id WebSocket handshake header. The server configuration contains only server-side accounts and access policy, allowing one authenticated account to serve multiple independent bot identities.

Contributors building from source can use cargo run -p remedia-server with the repository's example configuration. See CONTRIBUTING.md.

TLS reverse proxy

The server does not terminate TLS. For remote clients, expose only a TLS reverse proxy, bind Remedia to a private interface, and firewall the plain listener. The proxy must support WebSocket upgrades, forward Authorization, and allow long-lived connections. Example Nginx location (with TLS server configuration and certificates supplied by the operator):

location /v1/ws {
    proxy_pass http://127.0.0.1:8787/v1/ws;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header Authorization $http_authorization;
    proxy_set_header X-Remedia-Bot-Id $http_x_remedia_bot_id;
    proxy_read_timeout 1h;
    proxy_send_timeout 1h;
}

Clients then connect to wss://media.example.net/v1/ws. Keep passwords and resume credentials in secret storage. Do not put them in URLs, logs, shell history, or source control. The server supports standard ws:// and wss:// clients. @remedia/client also maps remedia:// to ws:// and remedias:// to wss://. Optional URL userinfo is stripped and sent only in the WebSocket Basic Authorization header.

Media network policy

Use allowedFileRoots to expose only intended media directories. URL access is denied unless a host is explicitly allowlisted. Keep blockPrivateNetworks enabled. FFmpeg may follow redirects after the initial host check, so also restrict server egress at the host/network layer. For workloads that accept client-selected URLs, firewall access to loopback, RFC 1918 networks, link-local addresses, cloud metadata endpoints, and internal service networks. Use a narrow host allowlist and prefer HTTPS.

The filtergraph API executes native FFmpeg filters. It is suitable for trusted applications and should be limited to trusted control clients. RPC authentication alone does not turn arbitrary filter expressions into a safe sandbox.

Session durability and capacity

Each process owns independent in-memory sessions. Unexpected socket loss permits resumption for a bounded timeout. Explicit close, expiry, and graceful shutdown release playback and voice resources. A process restart loses active sessions. Servers have no shared session store or cluster coordinator.

Set connection, player, message, request, and event limits to match host resources. node.stats reports local capacity, player/connection counts, process uptime, CPU parallelism/load and resident memory when the host exposes them, plus transport and processing health. Memory counters differ by OS and unsupported values are null. See Process resources.

Multiple nodes do not share state and do not proxy commands. @remedia/client selects a healthy node for a new guild and routes later operations for that guild to the same node. Existing assignments stay put during outages. Applications can explicitly migrate supported URL playback to a healthy node, or restore sessions with fresh Discord credentials after loss.

Manual Discord test

The remote_discord example connects as an RPC client, creates a guild player, uses voice credentials supplied by an external bot Gateway implementation, plays a URL, replaces and clears filters, then stops and disconnects. It never sends OP 4. CI does not use Discord credentials. It validates server playback through a null output and localhost WebSocket connections.

On this page