Documentation

Storage Mapping

OpenNVR writes recordings to a directory that is mounted into its containers. This build has no in-app storage settings page — you choose where recordings land by mapping a host path into the containers with a Docker volume, then let MediaMTX write segments there.

[!NOTE] Storage mapping is a deployment task done on the host (in docker-compose.yml / .env), not from the web UI. It requires shell access to the machine running the stack. Retention (auto-delete) is configured separately in Media Server Config via the Retention (Delete After) field.

Mapped recordings directory on the host, showing per-camera segment folders

What you can do here

  • Map recordings to a dedicated disk, NAS, or RAID array instead of the default folder.
  • Verify that segments are actually being written to your target.
  • Understand the on-disk layout so you can migrate or back up recordings.

How the mapping works

Both the mediamtx and opennvr-core services mount the same host directory to /app/recordings inside the container. The host side is driven by the RECORDINGS_PATH variable:

services:
  opennvr-core:
    volumes:
      - ${RECORDINGS_PATH:-./recordings}:/app/recordings

  mediamtx:
    volumes:
      - ${RECORDINGS_PATH:-./recordings}:/app/recordings

When RECORDINGS_PATH is unset it defaults to ./recordings (a folder next to docker-compose.yml). The container-side path is fixed — opennvr-core also carries these environment values:

Variable Example Notes
RECORDINGS_PATH /mnt/nas/nvr_recordings Host directory to store recordings; set in .env or the shell
RECORDINGS_HOST_BASE ${RECORDINGS_PATH:-./recordings} Host base path (informational)
RECORDINGS_CONTAINER_BASE /app/recordings Where the volume is mounted inside the container
RECORDINGS_BASE_PATH /app/recordings Base path the recorder writes under

Map recordings to a dedicated path

  1. Stop the stack:

    docker compose down
  2. Set RECORDINGS_PATH to your host directory. The simplest way is your .env file:

    # .env
    RECORDINGS_PATH=/mnt/nas/nvr_recordings

    (Windows example: RECORDINGS_PATH=D:/Surveillance/Recordings)

    Or edit the volumes entry directly in docker-compose.yml for both opennvr-core and mediamtx:

    - /mnt/nas/nvr_recordings:/app/recordings
  3. Make sure the host directory exists and the container user can read/write it.

  4. Start the stack again:

    docker compose up -d

[!WARNING] Map the same host path into both opennvr-core and mediamtx. mediamtx writes the segments; opennvr-core reads them back for playback. If the two point at different directories, recordings won’t play back.

Verify writes

Once a camera is recording, confirm segments are landing on your target by listing the directory inside the running container:

docker compose exec opennvr-core ls -lah /app/recordings

Recordings are organized per camera and date. Each recording path follows the pattern cam-<id>/%Y/%m/%d/%H-%M-%S-%f, so you’ll see subfolders like cam-3/2026/07/10/ fill with segment files. The default retention when recording is enabled is 168h (7 days); change or disable it from Media Server Config → Path Defaults.

[!WARNING] Binding a new empty directory to a running instance means OpenNVR immediately loses access to previously stored video. Migrate existing recordings to the new path first (for example with rsync) before switching the mount.

📸 Screenshots to capture

Save this to opennvr-site/public/screenshots/ with the exact filename below:

  • storage-settings.png — a host or docker compose exec file listing of the mapped recordings directory, showing the cam-<id>/YYYY/MM/DD/ segment folder structure.