Get masqueradarr running
masqueradarr ships as Docker images. Pick a deployment shape, set a handful of environment variables, then walk the first-run wizard from first admin to first playlist.
Two ways to run it
Both are official Docker images. Reach for the compose stack for a normal deployment; reach for the all-in-one for a quick trial or a small home server with nothing external to manage.
App + MongoDB, two services
The standard image (iflip721/masqueradarr) plus a mongo service, wired by docker-compose.yml. The app self-provisions its config from your .env on every boot — there's no host config file to manage.
App + MongoDB in one container
A second image (the AIO variant of iflip721/masqueradarr) bundles app + mongod + config bootstrap, so the whole stack runs from a single docker run with no external database. One /data volume persists everything.
Option A — bring up the compose stack
# 1 · copy the env template and fill it in (see the .env table below) cp .env.example .env # 2 · bring the stack up — app + MongoDB docker compose up -d # 3 · open the app → http://localhost:3000 (or your DOMAIN)
At minimum set MONGO_ROOT_USER / MONGO_ROOT_PASS, your DOMAIN, and the host volume paths (COMPOSE_PATH, BACKUPS_PATH, MONGO_DATA_PATH). To publish on a host port other than 3000, set MASQUERADARR_PORT and update DOMAIN to match.
Option B — run the all-in-one
# one container — app + MongoDB + config bootstrap, no external database
docker run -d \
-p 3000:3000 \
-v masqueradarr-data:/data \
iflip721/masqueradarr:latest
On amd64 the bundled MongoDB 7.0 needs a CPU with AVX. On hosts without it (some older or low-power boxes), use the compose stack with an external Mongo instead. To publish on a different host port, change the left side of the -p mapping — e.g. -p 8080:3000 (the container always serves on 3000 internally).
.env fileWhat each variable does
All runtime settings live in MongoDB and are editable on the Settings screen. The .env only bootstraps infrastructure on first boot — most values are seeded with $setOnInsert, so they apply on the first provision only. Change them in the UI afterward; a redeploy won't clobber your UI changes.
| Variable | Purpose |
|---|---|
| MASQUERADARR_PORT | Host port mapped to masqueradarr (default 3000). |
| MONGO_ROOT_USER MONGO_ROOT_PASS | MongoDB root credentials; also assemble the app's mongoUri. |
| DOMAIN | Public base URL written into composed playlist / guide links. Set it correctly up front — changing it later rewrites every playlist's URL. |
| DISPLAY_NAME | App display name. |
| TZ | Container timezone (used by the scheduler). |
| COMPOSE_PATH | Host dir for composed .m3u + XMLTV exports (uid-1000 writable). |
| BACKUPS_PATH | Host dir for scheduled backups (uid-1000 writable). |
| MONGO_DATA_PATH | Host dir for persistent MongoDB data. |
| MONGO_HOST_PORT | Host port mapped to mongod (default 27017). |
| MONGO_URI MONGO_HOST | Optional — point the app at an external / Atlas MongoDB instead of the compose mongo service. |
| DNS_LOG_LEVEL | Outbound-DNS trace verbosity (1–3); seeds the setting on first boot. |
| MASQ_EDGE | Optional (default off). 1 inverts the topology so the Rust proxy owns the public port — see the topology section. |
Host directories must be writable by the container users
The compose stack bind-mounts three host directories so your exports, backups and database survive a rebuild. Create each one before composing the stack, and make it writable by the right uid — the app's node user is uid 1000; mongod runs as uid 999.
# create the host volume dirs and grant the container users write access mkdir compose && chown -R 1000:1000 ./compose && chmod -R 777 ./compose # node (uid 1000) mkdir backups && chown -R 1000:1000 ./backups && chmod -R 777 ./backups # node (uid 1000) mkdir mongo && chown -R 999:999 ./mongo && chmod -R 777 ./mongo # mongod (uid 999)
You never manage a config.json by hand. The app writes /app/config/config.json inside the container from your .env on every boot (creds URL-encoded into the mongoUri) — it's image-internal and regenerated each start. Point at an external Mongo with MONGO_URI / MONGO_HOST if you'd rather not run the bundled one.
MASQ_EDGEThe default topology — and the opt-in inversion
masqueradarr runs two processes: the Node control plane and the Rust data-plane (masq-proxy). Which one owns the public socket is a single switch, MASQ_EDGE. Leave it off unless you have a reason. Same public port and DOMAIN either way; fully reversible.
The whole idea of edge mode is to take Node's single-threaded event loop out of the video byte path. Turn it on for many concurrent or high-bitrate viewers, to keep the management UI snappy under streaming load, or on constrained hardware (Pi / small VPS). Leave it off for a personal setup with a handful of viewers — the default sidecar path is simpler, more battle-tested, and keeps strictly per-request token revocation. Rust's loopback :8787 listener is unchanged in both modes, so the channel-probe scheduler always works.
The one-time setup wizard
On first launch there are no users — the app reports needsSetup and the SPA walks you through creating the first admin account. On a fresh install the database starts empty; built-in sources appear as zero-channel shells and only populate after your first Sync now. Here's the order.
https://tv.example.com). It's woven into every published playlist URL. changing it later rewrites every playlist's URL.m3u + XMLTV guide URL from their Dashboard. Paste the M3U into TiviMate / VLC / Plex / Jellyfin — the download is token-free, but the stream is token-gated to that user.There is no in-place upgrade path — masqueradarr is a new application with a new data model (MongoDB instead of flat files). Stand it up fresh and re-add your sources through the UI.