Critical fix: - Dockerfile env var was MEDIARIP__DATABASE__PATH (ignored) — now MEDIARIP__SERVER__DB_PATH DB was landing at /app/mediarip.db (lost on restart) instead of /data/mediarip.db Persistence model: - /downloads → media files (bind mount recommended) - /data → SQLite DB, session cookies, error logs (named volume) - /themes → custom CSS themes (read-only bind mount) - /app/config.yaml → optional YAML config (read-only bind mount) Other changes: - Add server.data_dir config field (default: /data) for explicit session storage - Cookie storage uses data_dir instead of fragile path math from output_dir parent - Lifespan creates data_dir on startup - .dockerignore excludes tests, dev DB, egg-info - docker-compose.yml: inline admin/purge config examples - docker-compose.example.yml: parameterized with env vars - .env.example: session mode, clearer docs - README: Docker volumes table, admin setup docs, full config reference - PROJECT.md: reflects completed v1.0 state - REQUIREMENTS.md: all 26 requirements validated
6.3 KiB
media.rip()
A self-hostable yt-dlp web frontend. Paste a URL, pick quality, download — with session isolation, real-time progress, and a cyberpunk default theme.
Features
- Paste & download — Any URL yt-dlp supports. Format picker with live quality extraction.
- Real-time progress — Server-Sent Events stream download progress to the browser instantly.
- Session isolation — Each browser gets its own download queue. No cross-talk.
- Playlist support — Collapsible parent/child jobs with per-video status tracking.
- Three built-in themes — Cyberpunk (default), Dark, Light. Switch in the header.
- Custom themes — Drop a CSS file into
/themesvolume. No rebuild needed. - Admin panel — Session management, storage info, manual purge, error logs. Protected by bcrypt auth.
- Cookie auth — Upload cookies.txt per session for paywalled/private content.
- Auto-purge — Configurable scheduled cleanup of old downloads and logs.
- Zero telemetry — No outbound requests. No CDN, no fonts, no analytics. CSP enforced.
- Mobile-friendly — Responsive layout with bottom tabs on small screens.
Quickstart
docker compose up
Open http://localhost:8080 and paste a URL.
Downloads are saved to ./downloads/.
Docker Volumes
| Mount | Purpose | Persists |
|---|---|---|
/downloads |
Downloaded media files | ✅ Bind mount recommended |
/data |
SQLite database, session cookies, error logs | ✅ Named volume recommended |
/themes |
Custom theme CSS overrides (optional) | Read-only bind mount |
/app/config.yaml |
YAML config file (optional) | Read-only bind mount |
Important: The /data volume contains the database (download history, admin state, error logs) and session cookie files. Use a named volume or bind mount to persist across container restarts.
Configuration
All settings have sensible defaults. Override via environment variables or config.yaml:
| Variable | Default | Description |
|---|---|---|
MEDIARIP__SERVER__PORT |
8000 |
Internal server port |
MEDIARIP__SERVER__DB_PATH |
/data/mediarip.db |
SQLite database path |
MEDIARIP__SERVER__DATA_DIR |
/data |
Persistent data directory |
MEDIARIP__DOWNLOADS__OUTPUT_DIR |
/downloads |
Where files are saved |
MEDIARIP__DOWNLOADS__MAX_CONCURRENT |
3 |
Maximum parallel downloads |
MEDIARIP__SESSION__MODE |
isolated |
isolated, shared, or open |
MEDIARIP__SESSION__TIMEOUT_HOURS |
72 |
Session cookie lifetime |
MEDIARIP__ADMIN__ENABLED |
false |
Enable admin panel |
MEDIARIP__ADMIN__USERNAME |
admin |
Admin username |
MEDIARIP__ADMIN__PASSWORD_HASH |
(empty) | Bcrypt hash of admin password |
MEDIARIP__PURGE__ENABLED |
false |
Enable auto-purge of old downloads |
MEDIARIP__PURGE__MAX_AGE_HOURS |
168 |
Delete downloads older than this |
MEDIARIP__PURGE__CRON |
0 3 * * * |
Purge schedule (cron syntax) |
MEDIARIP__THEMES_DIR |
/themes |
Custom themes directory |
Session Modes
- isolated (default): Each browser session has its own private queue.
- shared: All sessions see all downloads. Good for household/team use.
- open: No session tracking at all.
Admin Panel
Enable the admin panel to manage sessions, view storage, trigger manual purge, and review error logs:
# docker-compose.yml environment section
MEDIARIP__ADMIN__ENABLED: "true"
MEDIARIP__ADMIN__USERNAME: "admin"
MEDIARIP__ADMIN__PASSWORD_HASH: "$2b$12$..." # see below
Generate a bcrypt password hash:
docker run --rm python:3.12-slim python -c \
"import bcrypt; print(bcrypt.hashpw(b'YOUR_PASSWORD', bcrypt.gensalt()).decode())"
Admin state (login, settings changes) persists in the SQLite database at /data/mediarip.db.
Custom Themes
- Create a folder in your themes volume:
./themes/my-theme/ - Add
metadata.json:{ "name": "My Theme", "author": "You", "description": "A cool theme" } - Add
theme.csswith CSS variable overrides:[data-theme="my-theme"] { --color-bg: #1a1a2e; --color-accent: #e94560; /* See base.css for all 50+ tokens */ } - Restart the container. Your theme appears in the picker.
See the built-in themes in frontend/src/themes/ for fully commented examples.
Secure Deployment
For production with TLS, use the included Caddy reverse proxy:
cp docker-compose.example.yml docker-compose.yml
cp .env.example .env
# Edit .env with your domain and admin password hash
docker compose up -d
Caddy automatically provisions Let's Encrypt TLS certificates for your domain.
Development
Backend
cd backend
python -m venv .venv
.venv/bin/pip install -r requirements.txt
.venv/bin/pip install pytest pytest-asyncio pytest-anyio httpx ruff
.venv/bin/python -m pytest tests/ -v -m "not integration"
Frontend
cd frontend
npm install
npm run dev # Dev server with hot reload
npx vitest run # Run tests
npm run build # Production build
API
| Endpoint | Method | Description |
|---|---|---|
/api/health |
GET | Health check with version + uptime |
/api/config/public |
GET | Public configuration |
/api/downloads |
GET | List downloads for current session |
/api/downloads |
POST | Start a new download |
/api/downloads/{id} |
DELETE | Cancel/remove a download |
/api/formats |
GET | Extract available formats for a URL |
/api/events |
GET | SSE stream for real-time progress |
/api/cookies |
POST | Upload cookies.txt for authenticated downloads |
/api/cookies |
DELETE | Remove cookies.txt for current session |
/api/themes |
GET | List available custom themes |
/api/admin/* |
GET/POST | Admin endpoints (requires auth) |
Architecture
- Backend: Python 3.12 + FastAPI + aiosqlite + yt-dlp
- Frontend: Vue 3 + TypeScript + Pinia + Vite
- Transport: Server-Sent Events for real-time progress
- Database: SQLite with WAL mode
- Styling: CSS custom properties (no Tailwind, no component library)
- Container: Multi-stage build, non-root user, amd64 + arm64
License
MIT