Stash is the self-hosted media server that MR Stash streams from. If you don't already run it, this guide gets a clean instance up with Docker and your library scanned in. If you already have Stash running, skip straight to adding the plugins.
You'll need: a machine (or NAS/home server) with Docker and Docker Compose installed, and a folder of media you want to serve.
What Stash is
Stash is an open-source organizer and streaming server for your personal media. It scans folders you point it at, builds a browsable library with metadata, and serves everything over your network. MR Stash connects to that server and plays titles inside a mixed-reality scene on your headset.
Everything stays on your own hardware - Stash runs locally and nothing about your library leaves your network unless you choose to expose it.
Before you start
- Docker & Docker Compose installed on the host machine. On Windows or macOS, Docker Desktop includes both.
- A media folder on the host you want Stash to serve.
- The host and your headset on the same local network (or a route between them).
Create your docker-compose file
Make a folder to hold Stash's configuration and data, then create a docker-compose.yml inside it. Pick one of the two setups below.
Setting up for MR Stash? Use the DeviceAuth setup. It's identical to plain Stash plus the sidecar port and dependencies you'd otherwise add in Guide 2 - starting here means you won't have to edit and recreate the container later.
Recommended for MR Stash. The highlighted lines are what makes device pairing work - Guide 2 explains each, but you don't need to touch them again if you start here.
version: '3.4'
services:
stash:
image: stashapp/stash:latest
container_name: stash
restart: unless-stopped
# lets the plugin manage its sidecar service
privileged: true
ports:
# Stash web UI
- "9999:9999"
# sidecar port for MR Stash device communication
- "9997:9997"
logging:
driver: "json-file"
options:
max-file: "10"
max-size: "2m"
environment:
- STASH_STASH=/data/
- STASH_GENERATED=/generated/
- STASH_METADATA=/metadata/
- STASH_CACHE=/cache/
- STASH_PORT=9999
# install sidecar deps on start, then run Stash
entrypoint:
- /bin/sh
- -c
- |
python3 -c "import flask, requests, yaml, PIL" 2>/dev/null \
|| pip3 install --break-system-packages --root-user-action=ignore --quiet flask requests pyyaml Pillow
exec stash
volumes:
- /etc/localtime:/etc/localtime:ro
- ./config:/root/.stash
- ${STASH_PATH}:/data
- ./metadata:/metadata
- ./cache:/cache
- ./blobs:/blobs
- ./generated:/generated
Stock Stash with no MR Stash additions. Choose this only if you're not pairing a headset yet - you'll add the sidecar port and dependencies in Guide 2 and recreate the container then.
version: '3.4'
services:
stash:
image: stashapp/stash:latest
container_name: stash
restart: unless-stopped
ports:
# Stash web UI
- "9999:9999"
logging:
driver: "json-file"
options:
max-file: "10"
max-size: "2m"
environment:
- STASH_STASH=/data/
- STASH_GENERATED=/generated/
- STASH_METADATA=/metadata/
- STASH_CACHE=/cache/
- STASH_PORT=9999
volumes:
- /etc/localtime:/etc/localtime:ro
- ./config:/root/.stash
- ${STASH_PATH}:/data
- ./metadata:/metadata
- ./cache:/cache
- ./blobs:/blobs
- ./generated:/generated
The ${STASH_PATH} volume is where your actual media lives. Set it with a .env file next to your compose file:
# .env - point this at your media folder on the host
STASH_PATH=/path/to/your/media
The ./config, ./metadata, and other relative folders are created next to your compose file the first time you start the container.
Start the server
From the folder containing your compose file, bring it up:
docker compose up -d
Docker pulls the Stash image and starts the container in the background. Confirm it's running:
docker compose ps
- The stash container shows a status of Up.
Run first-time setup
Open the web UI in a browser on the same network:
http://your-stash-host:9999
Stash walks you through a short setup wizard on first launch:
- Confirm the library path (inside the container this is /data, which maps to your media folder).
- Optionally set a username and password to protect the server. Recommended if it's reachable beyond your machine.
Replace your-stash-host with the machine's LAN IP (for example 192.168.1.50) or hostname. You'll use this same address later when pairing your headset.
Add & scan your library
With setup done, tell Stash to index your media:
- Go to Settings → Library and confirm your media path is listed.
- Run a Scan (Settings → Tasks → Scan). Stash walks the folder and adds what it finds.
- Browse to confirm titles now appear in your library.
Once you can see and play a title from the Stash web UI, the server side is ready.