A lightweight, Jellyfin-compatible media server written in Rust.
Implements the Jellyfin REST API — use any Jellyfin client (Web, Android, iOS, TV, Roku, Kodi) to browse and stream your library.
| Aspect | Jellyfin (C#/.NET) | Rustyfin (Rust) |
|---|---|---|
| Memory (idle) | ~200–400 MB | ~15–30 MB |
| Startup | ~5–15 s | < 500 ms |
| Binary size | ~100 MB (self-contained) | ~8–12 MB (static) |
| Architecture | Monolith | 7-crate Workspace |
| Concurrency | ThreadPool | Tokio async (io_uring/epoll/kqueue) |
| Deployment | Docker, bare metal | Single static binary + Docker |
- ✅ Jellyfin-compatible REST API — Works with official Jellyfin clients
- ✅ User Auth — JWT tokens, API keys, Quick Connect, Argon2 password hashing
- ✅ Library Management — Create/scan/delete libraries (Movies, Series, Music, Photos, Books)
- ✅ Media Browsing — Items, filtering, sorting, pagination, resume points
- ✅ Metadata Providers — TMDb, OMDb, local NFO files
- ✅ Image Proxy — Caching, on-the-fly resize, format conversion
- ✅ Direct Play / Direct Stream — Range requests, seeking, HLS/DASH passthrough
- ✅ SQLite Database — Zero-config, embedded, SQLx compile-time checked queries
- HLS Transcoding (FFmpeg integration)
- Playback tracking (watched, resume, favorites)
- Subtitle support (SRT, ASS, VTT, OpenSubtitles)
- Session & Device management
- Full-text & Fuzzy Search
- Collections & Playlists
- Scheduled Tasks (auto-scan, cache cleanup)
- Plugin System
- Full Jellyfin Client Compatibility (Web, Android, iOS, TV apps)
- Official Docker Image (
ghcr.io/peopleandpixel/rustyfin)
rustyfin/
├── crates/
│ ├── rustyfin-server # Entry point, config, server bootstrap
│ ├── rustyfin-api # Axum routes, handlers, OpenAPI docs
│ ├── rustyfin-auth # Argon2, JWT, API keys, Quick Connect
│ ├── rustyfin-core # Business logic: scanning, metadata, images
│ ├── rustyfin-db # SQLx + SQLite, migrations, repositories
│ ├── rustyfin-model # Shared DTOs, entities, Jellyfin API types
│ └── rustyfin-cli # CLI utilities (migrate, admin, benchmark)
├── docker/
│ ├── Dockerfile
│ └── docker-compose.yml
├── .github/workflows/ci.yml
└── Cargo.toml (workspace)
- Rust 1.85+ (2024 Edition) —
rustup update stable - SQLite3 dev headers (bundled via
sqlx)
git clone https://github.com/peopleandpixel/rustyfin.git
cd rustyfin
# Build release (optimized, static binary ~10 MB)
cargo build --release --workspace
# Run
./target/release/rustyfinDefault:
http://0.0.0.0:8096· Data dir:~/.rustyfin/
First run: Createsadmin/admin— change immediately!
| Variable | Description | Default |
|---|---|---|
RUSTYFIN_BIND |
Bind address:port | 0.0.0.0:8096 |
RUSTYFIN_DATA |
Data directory (DB, cache, config, logs) | ~/.rustyfin |
RUSTYFIN_DB |
SQLite connection string | sqlite://<data>/rustyfin.db?mode=rwc |
RUSTYFIN_SECRET |
JWT signing secret | Random UUID (regenerated each start!) |
RUSTYFIN_SERVER_ID |
Unique server identifier | Random UUID |
RUSTYFIN_API_KEY |
Static API key for integrations | Disabled |
RUST_LOG |
Log level (debug, info, rustyfin=trace) |
info |
Example (production):
RUSTYFIN_BIND=127.0.0.1:8096 \
RUSTYFIN_DATA=/srv/rustyfin \
RUSTYFIN_SECRET="$(openssl rand -base64 32)" \
RUSTYFIN_API_KEY="my-integration-key" \
./target/release/rustyfindocker build -t rustyfin .
docker run -d \
-p 8096:8096 \
-v /path/to/media:/media:ro \
-v /path/to/data:/data \
-e RUSTYFIN_DATA=/data \
-e RUSTYFIN_SECRET="$(openssl rand -base64 32)" \
rustyfin# Live reload
cargo install cargo-watch
cargo watch -x "run --release"
# Run all tests
cargo test --workspace
# Format & lint (CI checks these)
cargo fmt --all -- --check
cargo clippy --workspace --all-targets --all-features -- -D warnings
# Generate SQLx query cache (for offline builds)
cargo sqlx prepare --workspace
# Build docs
cargo doc --workspace --no-deps --open| Client | Status | Notes |
|---|---|---|
| Jellyfin Web | ✅ Works | Full browsing, playback |
| Jellyfin Android | ✅ Works | Direct play/stream |
| Jellyfin iOS/tvOS | ✅ Works | Direct play/stream |
| Jellyfin Roku | Some endpoints missing | |
| Jellyfin Kodi Addon | Auth works, browsing WIP | |
| Infuse (iOS) | ✅ Works | Via Jellyfin API |
| Swiftfin | ✅ Works | Native Jellyfin client |
| Metric | Value |
|---|---|
| Idle RAM | ~18 MB |
| Streaming 1080p (direct) | ~25 MB |
| Cold start → ready | < 300 ms |
| Library scan (10k items) | ~8 s (parallel) |
| Binary size (stripped) | 9.2 MB |
- Fork → Feature branch (
git checkout -b feat/amazing-feature) - Commit (
git commit -m 'feat: add amazing feature') - Push → Open PR
- CI must pass:
fmt,clippy,test,build
MIT License — see LICENSE for details.
- Jellyfin — The free software media system we're compatible with
- Axum — Ergonomic web framework
- SQLx — Compile-time checked SQL
- Tokio — Async runtime
- TMDb / OMDb — Metadata APIs
Jens Reinemuth — Senior Full-Stack Dev (Rust, Flutter, PHP/Symfony, DevOps, AI)
🇪🇺 EU Citizen · 🇵🇹 Portugal · 📧 jens@reinemuth.pt · GitHub · LinkedIn
💼 Open to remote roles in Germany/EU · 25+ years experience