Note: While MediaRSS is primarily designed and tested for audio files
(MP3, M4A, M4B, etc.), video files should also work. However, video support
is not the primary focus and may have limitations (especially with regard to
performance) with certain formats.
Remix Version Notes
MediaRSS currently targets remix@3.0.0-alpha.4.
For migration details (including import rules, package adoption decisions, and
router behavior expectations), see
docs/remix/README.md.
Development Tooling
Runtime: Node.js 24
Package manager: npm
Linter: oxlint
Formatter: Biome
Common commands:
npm run dev
npm run lint
npm run format
npm run validate
Screenshots
Dashboard
Feed Details
Create Feed
Media Library
Media Details
Analytics
MediaRSS includes built-in feed and media analytics in the admin dashboard:
Feed analytics (per feed + per token):
RSS fetches
media requests
download starts
bytes served
unique clients
top media items
top clients
daily activity trends
Media analytics (aggregated across all feed tokens):
requests/download starts
bytes served
unique clients
per-feed/per-token breakdowns
top clients
daily activity trends
Time windows: switch between 7d / 30d / 90d directly in the UI
Self-Hosting
Prerequisites
Docker
A server or machine to host the application
Basic understanding of Docker volumes for data persistence
Media files organized in one or more directories on your host machine
Format: name:path,name:path (comma-separated, each with a name and
path)
The rest of the standard instructions apply for managing the container.
Quick Start Script
For the easiest setup, use the provided NAS setup script:
Copy scripts/nas-setup.sh to your NAS
Edit the configuration section at the top of the script
Run it:
bash
chmod +x nas-setup.sh./nas-setup.sh
The script will pull the latest image, set up the container with your media
directories, and configure automatic restarts.
Manual Setup (Non-Synology)
Pull the Docker image:
bash
docker pull [your-image-name]
Create directories for persistent storage and ensure your media directories
exist:
bash
# Create directories for database and artwork storagemkdir -p /path/to/your/datamkdir -p /path/to/your/data/artwork# Your media directories should already exist
Important: Without this mount, uploaded artwork will be lost on container
restart
Media Volumes (any number allowed):
Purpose: Access to your audio files
Mount point pattern: /media/[your-name]
Examples:
-v /path/to/audiobooks:/media/audiobooks:ro
-v /path/to/audio-series:/media/audio-series:ro
Mount read-only (:ro) if you only need to serve existing files
For media uploads: Mount read/write (without :ro) to enable uploading
files via the admin dashboard
Name the mount points anything that makes sense for your use case
Media Directory Structure
You can organize your media directories however you prefer. Here's an example
structure for audiobooks and audio series:
plaintext
/media/audiobooks/├── fiction/│ ├── Harry Potter Series/│ └── Lord of the Rings/└── non-fiction/ ├── Atomic Habits/ └── Deep Work//media/audio-series/├── podcasts/│ ├── show1/│ └── show2/└── courses/ ├── course1/ └── course2/
Environment Variables
The following environment variables can be configured:
PORT: Server port (default: 22050)
NODE_ENV: Environment mode (production, development, or test)
DATABASE_PATH: Path to the main SQLite database (default: ./data/sqlite.db)
CACHE_DATABASE_PATH: Path to the cache SQLite database (default:
./data/cache.db)
MEDIA_PATHS: Named media roots in format name:path,name:path
Each media root has a name (used in URLs) and a path (filesystem location)
Names must be unique - duplicate names are not allowed
Names should be URL-safe (alphanumeric, hyphens, underscores)
ANALYTICS_RETENTION_DAYS: Number of days to retain feed analytics events
(default: 180)
Older analytics events are pruned automatically on startup
Securing the Admin Dashboard
MediaRSS has two types of routes:
Public routes (/feed/*, /media/*, /art/*) - These are accessed by RSS
readers and podcast apps. They use secret tokens in URLs for access control.
Admin routes (/) - The dashboard for managing feeds. This should be
protected.
Since RSS readers need direct access to feed URLs without authentication prompts,
we recommend using Cloudflare Tunnel to secure the admin dashboard rather
than app-level authentication.
Why Cloudflare Tunnel?
Free HTTPS - Automatic SSL certificates, no configuration needed
No port forwarding - Outbound-only connection, your router stays locked down
Hidden IP - Your home IP address is never exposed
Access policies - Add authentication at the edge (email OTP, SSO, etc.)
Works with any DNS - You don't need to move your domain to Cloudflare
Setting Up Cloudflare Tunnel
Create a free Cloudflare account and add your domain (you can use the free
plan).
Create a tunnel in the Zero Trust dashboard:
Go to Networks → Tunnels → Create a tunnel
Name it (e.g., "mediarss")
Choose Docker as the connector
Copy the tunnel token
Run cloudflared alongside MediaRSS on your NAS/server:
bash
docker run -d \ --name cloudflared \ --restart unless-stopped \ --network host \ cloudflare/cloudflared:latest \ tunnel run --token YOUR_TUNNEL_TOKEN
Note: The --network host flag is required so that cloudflared can reach
MediaRSS via localhost. Without it, localhost would refer to the
cloudflared container itself, not your NAS.
Configure the public hostname in the tunnel settings:
Hostname: media.yourdomain.com (a domain name you control)
Service: http://localhost:22050 (or your MediaRSS port)
Add an Access policy to protect the admin dashboard:
Go to Access → Applications → Add an application
Choose "Self-hosted"
Set the domain to media.yourdomain.com
Set the path to /admin (just the admin pages)
Add an authentication method (email OTP is easiest)
Important: Don't protect /feed/*, /media/*, or /art/* paths
Using Cloudflare Tunnel Without Moving DNS
If your domain's DNS is managed elsewhere (not Cloudflare), you can still use
Cloudflare Tunnel with a CNAME record:
Complete steps 1-4 above
Find your tunnel's hostname in the Cloudflare dashboard - it looks like:
a1b2c3d4-e5f6-7890-abcd-ef1234567890.cfargotunnel.com
Note: This only works for subdomains (e.g., media.yourdomain.com), not the
root domain.
Alternative: Local Network Only
If you only access MediaRSS from your local network and don't need remote
access, you can skip Cloudflare Tunnel entirely. The token-based URLs for feeds
provide sufficient security for trusted networks.
Data Persistence
The application stores persistent data in two locations:
Databases (in /data):
Main database: /data/sqlite.db
Cache database: /data/cache.db
Uploaded Artwork (in /app/data/artwork):
Feed cover images uploaded through the admin dashboard
To ensure your data persists between container restarts and updates, you
must mount volumes to both /data and /app/data/artwork as shown in the
run command above.
Backup and Restore
To backup your data, simply copy the files from your mounted data directory. For
example:
bash
# Stop the container before backupdocker stop mediarss# Backup the databases and artworkcp /path/to/your/data/sqlite.db /path/to/backup/sqlite.dbcp /path/to/your/data/cache.db /path/to/backup/cache.dbcp -r /path/to/your/data/artwork /path/to/backup/artwork# Restart the containerdocker start mediarss
To restore from backup:
bash
# Stop the containerdocker stop mediarss# Restore the databases and artworkcp /path/to/backup/sqlite.db /path/to/your/data/sqlite.dbcp /path/to/backup/cache.db /path/to/your/data/cache.dbcp -r /path/to/backup/artwork /path/to/your/data/artwork# Restart the containerdocker start mediarss
Upgrading
To upgrade to a new version:
bash
# Pull the new imagedocker pull [your-image-name]# Stop the current containerdocker stop mediarss# Remove the old containerdocker rm mediarss# Run the new container (using the same data directory and media mount)# Note: Remove :ro from media volumes if you need to upload media filesdocker run -d \ --name mediarss \ -p 22050:22050 \ -v /path/to/your/data:/data \ -v /path/to/your/data/artwork:/app/data/artwork \ -v /path/to/audiobooks:/media/audiobooks:ro \ -v /path/to/audio-series:/media/audio-series:ro \ -e MEDIA_PATHS=audiobooks:/media/audiobooks,audio-series:/media/audio-series \ [your-image-name]
Your data will be preserved as long as you use the same volume mount points.
Alternatives
Audiobookshelf is a fully featured
audio media server. It doesn't support private RSS feeds and it's a little too
much for what I want, so I built my own thing. But you might like it.