Self-hosted media dashboard for Radarr, Sonarr, and Overseerr with multi-user support and MFA.
2.3K
A self-hosted media dashboard for your Radarr and Sonarr libraries. Clean dark UI with multi-user support, MFA, and invite-based registration.
1. Create a data directory:
mkdir -p /home/docker/mediahub/data
2. Create a docker-compose.yml:
services:
mediahub:
image: playeronegameover/mediahub:latest
container_name: mediahub
restart: unless-stopped
ports:
- "3333:3333"
volumes:
- /home/docker/mediahub/data:/var/data
environment:
NODE_ENV: production
HOST: 0.0.0.0
PORT: 3333
LOG_LEVEL: info
TZ: UTC
SESSION_DRIVER: cookie
COOKIE_SECURE: "false"
LIMITER_STORE: database
DB_DATABASE: /var/data/mediahub.sqlite3
UPLOADS_PATH: /var/data/uploads
APP_KEY: ${APP_KEY}
3. Create a .env file alongside your docker-compose.yml:
APP_KEY=your-secret-key-here
Generate a secure key with:
docker run --rm playeronegameover/mediahub:latest node ace generate:key
4. Start:
docker compose up -d
5. Run migrations:
docker exec -it mediahub node ace migration:run --force
6. Create the admin user:
docker exec -it mediahub node ace db:seed --files="database/seeders/admin_user_seeder.ts"
Default login:
[email protected]admin1234Change your password immediately after first login.
7. Open: http://your-server-ip:3333
After logging in, go to Settings to configure your Radarr and Sonarr API connections.
docker compose pull
docker compose up -d
docker exec -it mediahub node ace migration:run --force
| Variable | Required | Default | Description |
|---|---|---|---|
APP_KEY | ✅ | - | Encryption secret. Generate with node ace generate:key |
NODE_ENV | ✅ | - | Set to production |
HOST | ✅ | - | Set to 0.0.0.0 |
PORT | ✅ | 3333 | HTTP port |
LOG_LEVEL | ✅ | info | fatal error warn info debug trace |
SESSION_DRIVER | ✅ | cookie | Set to cookie |
COOKIE_SECURE | ✅ | false | Set to true when serving over HTTPS |
DB_DATABASE | ✅ | - | Path inside container: /var/data/mediahub.sqlite3 |
UPLOADS_PATH | ✅ | - | Path inside container: /var/data/uploads |
LIMITER_STORE | - | database | Rate-limit backend (database or memory). database recommended |
TZ | - | system | Timezone, e.g. UTC, Europe/London, America/New_York |
All API integrations are configured via the Settings page after login (stored in the database, not environment variables).
| Setting | Required | Description |
|---|---|---|
| Radarr URL | ✅ | Base URL of your Radarr instance |
| Radarr API Key | ✅ | Found in Radarr → Settings → General. Masked; click the eye icon to reveal |
| Radarr Quality Profile | - | Default quality profile for movie requests. Dynamically populated from Radarr |
| Radarr Root Folder | - | Default download location for movie requests. Dynamically populated from Radarr |
| Sonarr URL | - | Base URL of your Sonarr instance |
| Sonarr API Key | - | Found in Sonarr -> Settings -> General. Masked; click the eye icon to reveal |
| Sonarr Quality Profile | - | Default quality profile for series requests. Dynamically populated from Sonarr |
| Sonarr Root Folder | - | Default download location for series requests. Dynamically populated from Sonarr |
| Dashboard Items to Display | - | Items shown in the Recently Added, Upcoming Releases, and Trending This Week sections (default 24) |
| Sync Interval | - | Background sync frequency for Radarr/Sonarr library data (5–60 minutes, default 5) |
| Sync Log Retention | - | Days to keep sync log entries (0–14, default 0 = disabled). Enables admin-only Sync Log page when > 0 |
| TMDb API Key | - | themoviedb.org - enables cast/crew, trailers, taglines, the Trending page, and the Search page. Masked; click the eye icon to reveal |
| Overseerr URL | - | Base URL of your Overseerr/Seerr instance - used for media requests (primary), fallback trailer source, and Requested badges on trending items |
| Overseerr API Key | - | Found in Overseerr → Settings → General. Masked; click the eye icon to reveal |
Nginx:
server {
listen 80;
server_name mediahub.example.com;
location / {
proxy_pass http://127.0.0.1:3333;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache_bypass $http_upgrade;
}
}
IIS (requires URL Rewrite + ARR modules):
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="Proxy to MediaHub" stopProcessing="true">
<match url="(.*)" />
<action type="Rewrite" url="http://localhost:3333/{R:1}" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>
Set
COOKIE_SECURE=truewhen terminating HTTPS at the proxy.
| Area | Detail |
|---|---|
| Login rate limiting | 5 attempts per IP per 15 minutes on /login and /login/mfa; HTTP 429 with flash message on breach |
| Content Security Policy | Strict CSP with nonce-based inline script protection - default-src 'self', object-src 'none', frame-src restricted to youtube.com (trailer player only). No inline event handlers |
| MFA QR codes | Generated server-side - your TOTP secret is never sent to any third party |
| API call timeouts | 8 s for Radarr/Sonarr/Overseerr, 10 s for TMDb |
| API key masking | All API keys are stored and displayed masked; reveal toggle available in Settings |
Content type
Image
Digest
sha256:bc4ecc40c…
Size
113.5 MB
Last updated
5 months ago
docker pull playeronegameover/mediahub