Self-host the complete Stremio experience β the web player and a powerful, open BitTorrent streaming engine β in a single container on your own hardware. It's a full torrent client, not just a streamer: it downloads whole files and can pin favorites to keep & seed. Point any Stremio client (browser, Android TV, Tizen, webOS, desktop) at it and press play.
No subscription. No tracking. No black box. 100% free and open β our gift to the community. π
Sharing back with the community. π This is a real torrent client, so a title you started keeps downloading to completion and seeding (uploading) back to other Stremio users even after you close the player β that's how you help keep the swarm fast and healthy for everyone. Unpinned titles are cleared automatically; pin the ones you'd like to keep sharing. Prefer to limit it? Cap up/down bandwidth in the settings any time β your box, your call.
- π Install in one command.
docker run β¦β that's the whole setup. No building, no config files. - πΊ Just works on TVs. Automatic trusted HTTPS (a real Let's Encrypt cert) that smart TVs actually accept β zero certificate headaches.
- β‘ Faster, more reliable. Unlike the closed stock server, this one accepts inbound peers and fetches playhead-first, so streams start quicker and hold up on thin swarms.
- ποΈ Truly yours to control. Real dials for cache, buffering, peers, and transcode β tune deeply, or never touch a thing.
- π₯οΈ Hardware transcode, optional. Intel VAAPI / NVIDIA NVENC when you expose a GPU to the container (opt-in β see Advanced), with graceful CPU fallback β and a missing GPU never stops it from starting.
- π§© Your addons, your choice. It's neutral infrastructure: it streams whatever a Stremio addon hands it. It bundles no content and is not a source.
- π Open source. Read it, change it, trust it.
Architecture: the published image is
linux/amd64(x86-64) only. It runs on any normal PC/server/NAS. ARM hosts (Raspberry Pi, most ARM TV boxes, Apple Silicon) aren't supported by the prebuilt image β build from source on those.
1. Install Docker.
2. Copy one command below β whichever matches your hardware β and replace YOUR_SERVER_IP
with your machine's LAN IP (e.g. 192.168.1.50). Not sure which? Use the first one β it works on
everything. (The GPU options only speed up the occasional video that needs converting; they're not required.)
π» No GPU β works everywhere (start here)
docker run -d --name stremio --restart unless-stopped \
-e IPADDRESS=YOUR_SERVER_IP \
-p 8080:8080 -p 12470:12470 -p 6881:6881/tcp -p 6881:6881/udp \
-v stremio-data:/root/.stremio-server \
androshack/stremio-libtorrent-serverπ¦ Intel / AMD GPU (VAAPI) β same, plus --device /dev/dri
docker run -d --name stremio --restart unless-stopped \
-e IPADDRESS=YOUR_SERVER_IP \
--device /dev/dri:/dev/dri \
-p 8080:8080 -p 12470:12470 -p 6881:6881/tcp -p 6881:6881/udp \
-v stremio-data:/root/.stremio-server \
androshack/stremio-libtorrent-serverπ© NVIDIA GPU (NVENC) β plus --gpus all (first install the NVIDIA Container Toolkit on the host)
docker run -d --name stremio --restart unless-stopped \
-e IPADDRESS=YOUR_SERVER_IP \
--gpus all \
-p 8080:8080 -p 12470:12470 -p 6881:6881/tcp -p 6881:6881/udp \
-v stremio-data:/root/.stremio-server \
androshack/stremio-libtorrent-serverπ¦π© Both Intel + NVIDIA β both flags
docker run -d --name stremio --restart unless-stopped \
-e IPADDRESS=YOUR_SERVER_IP \
--gpus all --device /dev/dri:/dev/dri \
-p 8080:8080 -p 12470:12470 -p 6881:6881/tcp -p 6881:6881/udp \
-v stremio-data:/root/.stremio-server \
androshack/stremio-libtorrent-server3. Open it:
- π In a browser (same network):
http://YOUR_SERVER_IP:8080β browser playback covers MP4/H.264; for MKV/HEVC content use the desktop or TV apps (browsers can't decode those). - π Trusted HTTPS (and TVs): run
docker logs stremioand use the printed URL β it looks likehttps://192-168-1-50.519b6502d940.stremio.rocks:12470(replace192-168-1-50with your internal IP, dots written as dashes).
Sign into Stremio, add your addons, press play. πΏ
(Prefer a file? Grab compose.hub.yaml β IPADDRESS=YOUR_SERVER_IP docker compose -f compose.hub.yaml up -d.)
It's light β direct play (most content) barely touches the CPU; the GPU only matters for transcoding.
| Resource | Minimum | Recommended | Notes |
|---|---|---|---|
| CPU | 2 cores, x86-64 | 4+ cores | amd64 only. Transcoding (clients that can't direct-play) is the only heavy load. |
| RAM | 1 GB | 2 GB+ | Engine + buffers + nginx; transcoding adds ~0.5β1 GB. |
| Disk | ~3 GB + cache | SSD, cache β₯ largest file | Image ~1.5 GB; download cache defaults to 18 GiB (tune with STREMIOSRV_CACHE_SIZE). Keep free space β₯ your biggest single file. |
| GPU | none | Intel VAAPI / NVIDIA NVENC | Optional β only speeds up transcoding; a missing/broken GPU never blocks startup. |
| Network | any | wired + 6881 forwarded |
Wired beats Wi-Fi for 4K; forward port 6881 for the full swarm (see below). |
Smart TVs insist on a trusted HTTPS connection β a self-signed cert won't do. Set IPADDRESS
and this server fetches a real Let's Encrypt certificate for you automatically (via Stremio's
*.stremio.rocks magic DNS, which maps that long URL back to your server's IP β even on your LAN).
In the TV's Stremio app, set the Streaming Server URL to the β¦stremio.rocks:12470 address shown
by docker logs stremio.
Note β the Stremio desktop app (v6). The desktop shell launches its own bundled streaming server and reβpoints itself at
127.0.0.1:11470on every start β it injects a?streamingServerUrl=parameter that overwrites the saved URL β so simply setting the Streaming Server URL doesn't stick. (This is the shell's behaviour, not aserverVersiongate β that part is already correct.) Two ways to use this box from the desktop:
- Best β launch with a flag (native player, full MKV/HEVC): start Stremio with
--development --webui-url=<your β¦stremio.rocks:12470 URL>(the trusted URL fromdocker logs stremio). A nonβdefault--webui-urlskips the localhost injection and loads the player from this box;--developmentalso skips the unused bundled server. Add the flag to your shortcut and launch from it each time. It must be the trusted:12470URL β a selfβsigned cert is refused. After signing into your account, relaunch via the shortcut (login resets the URL).- Zeroβinstall (MP4/H.264 only): open the
:12470URL in a browser, or install it as an app.TVs are unaffected β Samsung/LG accept the
:12470URL directly and it sticks.
A lot of BitTorrent's speed comes from peers reaching you β and home routers block that by
default. For maximum peers and throughput, forward port 6881 (TCP and UDP) on your router to
your server. It works fine without forwarding β you'll just reach fewer peers on sparse torrents.
(Unlike the stock server, this one actually listens for inbound peers, so the forward genuinely pays off.)
Tunnel only the streaming server's BitTorrent traffic through a VPN (kill-switch + optional port-forwarding) using gluetun, while your LAN keeps reaching the player/admin directly:
WIREGUARD_PRIVATE_KEY=... WIREGUARD_ADDRESSES=10.2.0.2/32 IPADDRESS=<your-LAN-IP> \
docker compose -f compose.vpn.yaml up -dNotes:
- The VPN's kill-switch is on by default β if the tunnel drops, torrent traffic stops (no IP leak).
- Inbound peers / seeding need a provider that supports port-forwarding (e.g. ProtonVPN, PIA, AirVPN). Without it you still stream, but with outbound-only connectivity.
- Set
FIREWALL_OUTBOUND_SUBNETSto your LAN CIDR(s) so the player and admin stay reachable.
Everything is a plain -e NAME=value environment variable:
| Setting | Default | What it does |
|---|---|---|
IPADDRESS |
(unset) | Your server IP β auto trusted TV cert via *.stremio.rocks. Unset β self-signed. |
SERVER_URL |
auto | URL the web player targets. Set for a custom domain. |
STREMIOSRV_CACHE_SIZE |
19327352832 (18 GiB) |
Download-cache budget in bytes (LRU-evicted). Keep it above your largest file. |
STREMIOSRV_READAHEAD_BYTES |
134217728 (128 MiB) |
Playhead buffer β bigger absorbs more swarm jitter (fewer rebuffers). |
STREMIOSRV_BT_LISTEN_PORT |
6881 |
BitTorrent peer port (TCP and UDP, IPv4 and IPv6). The one to forward. If you change it, publish the same port β the compose files and docker/launch.sh follow this var automatically; a hand-rolled docker run must use matching -p <port>:<port>/tcp -p <port>:<port>/udp (mapping to a different container port silently kills inbound peering). |
STREMIOSRV_BT_MAX_CONNECTIONS |
400 |
Max peer connections. |
STREMIOSRV_DOWNLOAD_RATE_LIMIT |
0 |
Cap download throughput in bytes/sec (0 = unlimited). E.g. 12500000 β 100 Mbit/s. |
STREMIOSRV_UPLOAD_RATE_LIMIT |
0 |
Cap upload throughput in bytes/sec (0 = unlimited). Handy so seeding doesn't saturate your line. |
STREMIOSRV_IDLE_DOWNLOAD_RATE_LIMIT |
1048576 (1 MiB/s) |
Cross-torrent playback priority. While anything is being streamed, every other (idle) torrent is capped to this many bytes/sec so the torrent you're watching wins the bandwidth. 0 disables it (idle torrents compete freely). |
STREMIOSRV_MAX_STREAMS |
0 |
Max concurrent playbacks (distinct torrents being streamed). A new play past the cap gets 503. 0 = unlimited. |
STREMIOSRV_SEED_ON_COMPLETE |
true |
Keep seeding after a torrent finishes (full torrent-client behaviour). false = stop seeding + drop peers the moment it completes. Pinned items always keep seeding. |
STREMIOSRV_MAX_SEED_MINUTES |
0 |
Stop seeding this many minutes after completion (0 = seed forever). Applies on top of SEED_ON_COMPLETE. |
STREMIOSRV_EXTRA_TRACKERS |
(empty) | Extra trackers appended to every torrent (on top of the built-in defaults). Comma/space/newline-separated udp:///http(s):///ws(s):// URLs. |
STREMIOSRV_TRACKER_LIST_URL |
(empty) | Optional URL of a community tracker list (e.g. the raw ngosang/trackerslist trackers_best.txt). Fetched in a background thread to keep the list current β best-effort, never blocks startup or playback; offline falls back to the last cached list, then the built-in defaults. Empty = fully static. |
STREMIOSRV_TRACKER_LIST_REFRESH_HOURS |
24 |
How often the background tracker-list source re-fetches (only when a URL is set). |
STREMIOSRV_ADAPTIVE_PICKING |
false |
Experimental. While playing, relax strict sequential download to parallel once enough is buffered ahead of the playhead (harvests more swarm throughput), re-tightening to in-order when the buffer drains or on a seek β the playhead window stays deadline-rushed, so continuity is protected. Off by default; needs on-box tuning. |
DOMAIN |
localhost |
CN for the self-signed cert (when not using IPADDRESS). |
CERT_FILE |
certificates.pem |
Bring-your-own cert (full-chain + key) filename in the data volume. |
Trackers & peer discovery. Every torrent is announced to a curated set of public trackers (baked-in
defaults) plus DHT, LSD and PEX β so a bare infohash finds peers even when the magnet carries no
tracker, exactly like the stock Stremio server. Extend it two ways: add your own with
STREMIOSRV_EXTRA_TRACKERS, or point STREMIOSRV_TRACKER_LIST_URL at a maintained list (e.g.
ngosang/trackerslist) to keep the set current β that fetch
runs in a background thread and never blocks startup or playback (offline β last cached list β the
built-in defaults). The bigger peering win, though, is inbound connectivity: forward
STREMIOSRV_BT_LISTEN_PORT (6881) so you reach the whole swarm, not just what trackers hand back.
GPU transcode (only for clients that can't direct-play). Docker does not expose the host GPU to a container by default, so the one-command install above is CPU-only. The server auto-detects a GPU, but only one you've handed in β so opt in at launch:
- Intel/AMD VAAPI β add
--device /dev/dri:/dev/dri - NVIDIA NVENC β add
--gpus all(requires the NVIDIA Container Toolkit on the host) - Or just use
docker/launch.shβ it probes the host and adds the right flags for you, degrading gracefully (a broken or absent driver never blocks startup). Full NVIDIA driver + Proxmox passthrough setup: NVIDIA-GPU.md (companion fork).
Your own domain instead of stremio.rocks: put a full-chain+key PEM as certificates.pem in the
data volume, set -e SERVER_URL=https://yourdomain:12470, and leave IPADDRESS unset.
Tailscale (zero port-forwarding, trusted HTTPS): if you reach the server over a Tailscale
tailnet, you can skip both port-forwarding and the *.stremio.rocks dependency. Provision a cert for the
node's MagicDNS name (tailscale cert <node>.<tailnet>.ts.net), concatenate the cert + key into one PEM,
drop it in the data volume as certificates.pem, and set -e SERVER_URL=https://<node>.<tailnet>.ts.net:12470
with IPADDRESS unset. Point your devices' Stremio Streaming Server URL at that tailnet address β works
across your own devices and anyone you share the tailnet with, with a browser/TV-trusted cert.
Ports: 8080 web+API (HTTP/LAN) Β· 12470 web+API (HTTPS) Β· 11470 direct API Β· 6881 BitTorrent.
π Full ops guide: docs/DEVOPS.md Β· TLS deep-dive: docs/cert-guide.md.
The stock Stremio streaming server is closed-source and, in practice:
- outbound-only β it never listens for inbound peers, so you only reach the connectable half of a swarm;
- it hides the torrent levers β no real control over piece picking, connectivity, or cache.
This opens it up: inbound connectivity + playhead-first piece picking for faster starts and better reliability on sparse swarms, plus hardware transcode for clients that can't direct-play β all in an image you run yourself. It is content-neutral infrastructure: it streams whatever infohash a Stremio addon hands it, and bundles or surfaces nothing.
One image, two source repos. The runtime image is built FROM a GPU/ffmpeg base (the companion
fork) and layers the open server on top:
ββββββββββββββββ stremio-docker-dual (companion fork, MIT) βββββββββββββββ
β jellyfin-ffmpeg (NVENC/VAAPI) Β· nginx Β· bundled Stremio web player β
βββββββββββββββββββββββββββββββββ²βββββββββββββββββββββββββββββββββββββββββββ
β FROM
ββββββββββββββββ stremio-libtorrent-server (this repo) βββββββββββββββββββ
β FastAPI + libtorrent engine Β· nginx serves web player + proxies the API β
β β one container: web player + open engine on a single origin β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Companion fork: andrewhack/stremio-docker
(builds the stremio-docker-dual image; see its NVIDIA-GPU.md for GPU/Proxmox setup).
Modules: api/ (Stremio HTTP API) Β· torrent/ (libtorrent + piece-picker) Β· stream/ (Range file
server) Β· transcode/ (ffmpeg NVENC/VAAPI β HLS) Β· config.py Β· health.py. Protocol reference:
docs/protocol-map.md.
All stages shipped and verified on hardware:
| Stage | Scope | State |
|---|---|---|
| 0β1 | Protocol map Β· FastAPI skeleton Β· /health |
β |
| 2 | Torrent core + direct play (inbound peers, head & holes, Range serving, stats) | β |
| 3 | Transcode / HLS (hlsv2, NVENC/VAAPI) |
β |
| 4 | Subtitles Β· opensubHash Β· casting |
β |
| 5 | Productionise β compose, DEVOPS, healthcheck, AHM | β |
| 6 | All-in-one (web player + engine) Β· TV-trusted SSL Β· GPU-optional Β· Docker Hub | β |
uv sync
uv run pytest -q # unit tests
uv run ruff check . # lint
uv run uvicorn stremiosrv.app:create_app --factory --host 0.0.0.0 --port 11470Skip this unless you're curious or customizing certs β the Quick Start needs none of it.
When you set IPADDRESS, the container prints a TV-ready HTTPS URL like:
https://192-168-1-50.519b6502d940.stremio.rocks:12470
ββββββ¬ββββββ ββββββ¬ββββββ βββββββ¬ββββββ βββ¬ββ
your IP, shared ID Stremio's HTTPS
dashed (see below) free DNS port
192-168-1-50β your server's IP with dots turned into dashes.β¦stremio.rocksβ a free service Stremio runs that (a) resolves<dashed-ip>.β¦stremio.rocksback to that IP (even a LAN IP β no DNS setup by you), and (b) carries a trusted Let's Encrypt wildcard cert, so TVs/browsers accept the HTTPS connection with no warning.:12470β the container's HTTPS port.
A TV opening it β resolves to your server's IP β connects on 12470 β sees a trusted cert β connects.
The name resolves to your internal IP, so the TV must be on the same network (normal home
setup). For remote access, use your public IP in the URL and forward port 12470.
This ID belongs to Stremio's own certificate service, not to any docker image: the cert is fetched
from Stremio's API (api.strem.io/api/certificateGet), which issues it for a subdomain of Stremio's
stremio.rocks domain. It is not unique to your install β everyone running this (or the upstream
tsaridas/stremio-docker) image shares the same
*.519b6502d940.stremio.rocks wildcard cert from Stremio's free certificate service. The image
only calls that Stremio API; it didn't create the ID.
- β Zero-config trusted HTTPS for TVs.
β οΈ It depends on Stremio's cert service keeping that wildcard alive; if it's ever rotated or taken down, the automatic cert path stops working (your stream still runs β only the trusted-HTTPS URL is affected).
Independent fallback β bring your own cert (no reliance on stremio.rocks): put a full-chain + key
PEM as certificates.pem in the data volume, set -e SERVER_URL=https://yourdomain:12470, and leave
IPADDRESS unset β the server uses your cert as-is. Or, on a trusted LAN, skip HTTPS entirely and
use http://<your-server-ip>:8080.
MIT β built on the MIT-licensed stremio-docker fork.
This is not a commercial product, and we don't monetize it. It's our contribution to the people who just want their own open, private streaming server. Use it, share it, make it better. π
Keep it legal: this is neutral infrastructure for content you have the right to stream.