Documentation Persistent Storage

Persistent Storage

Without volumes, all BunkerM data is stored inside the container and is lost when you stop or remove it. Mounting Docker volumes keeps your MQTT clients, ACLs, configuration, and agent data safe across restarts and upgrades.

What Data BunkerM Stores

  • MQTT clients and ACLs - every client, role, and group you have created
  • Broker configuration - Mosquitto settings and options
  • Dynamic security - the full Mosquitto dynamic security JSON
  • Web UI users - BunkerM admin and user accounts
  • BunkerAI settings - API keys, integration tokens, and configuration
  • Agents - Watchers and Scheduled Jobs
  • Anomaly history - detected anomalies and their status
  • Topic annotations - AI context hints for your topics
  • Client logs - connection event history

Volume Paths

  • /nextjs/data - web UI users, BunkerAI settings, agents, anomalies, annotations, client logs
  • /var/lib/mosquitto - MQTT persistence (retained messages, QoS queues), dynamic security (clients/ACLs)
  • /etc/mosquitto - Mosquitto configuration files

Docker Run with Volumes

docker run -d \
  -p 1900:1900 \
  -p 2000:2000 \
  -v bunkerm_data:/nextjs/data \
  -v mosquitto_data:/var/lib/mosquitto \
  -v mosquitto_conf:/etc/mosquitto \
  --name bunkerm \
  --restart unless-stopped \
  bunkeriot/bunkerm:latest

Docker creates the named volumes automatically on first run. On subsequent starts, the same data is mounted back into the container.

Docker Compose Setup

version: "3.8"
services:
  bunkerm:
    image: bunkeriot/bunkerm:latest
    ports:
      - "1900:1900"
      - "2000:2000"
    volumes:
      - bunkerm_data:/nextjs/data
      - mosquitto_data:/var/lib/mosquitto
      - mosquitto_conf:/etc/mosquitto
    restart: unless-stopped

volumes:
  bunkerm_data:
  mosquitto_data:
  mosquitto_conf:
docker compose up -d      # start
docker compose down       # stop (data preserved)
docker compose down -v    # stop AND delete volumes
Only use down -v if you intentionally want to wipe all data and start fresh.

Named Volumes vs Bind Mounts

Named volumes (recommended)

Docker manages the storage location. Volumes are portable, easy to back up, and work the same on any Docker host.

-v bunkerm_data:/nextjs/data

Bind mounts

The container writes directly to a directory on your host. Useful for direct file access or integration with other tools.

mkdir -p /opt/bunkerm/data /opt/bunkerm/mosquitto/data /opt/bunkerm/mosquitto/conf

docker run -d \
  -p 1900:1900 -p 2000:2000 \
  -v /opt/bunkerm/data:/nextjs/data \
  -v /opt/bunkerm/mosquitto/data:/var/lib/mosquitto \
  -v /opt/bunkerm/mosquitto/conf:/etc/mosquitto \
  --name bunkerm --restart unless-stopped \
  bunkeriot/bunkerm:latest

Backup

# Back up a named volume
docker run --rm \
  -v bunkerm_data:/source:ro \
  -v $(pwd):/backup \
  alpine tar czf /backup/bunkerm_data_$(date +%Y%m%d).tar.gz -C /source .

For bind mounts, simply copy the directories:

cp -r /opt/bunkerm/data /opt/bunkerm/data.backup.$(date +%Y%m%d)

Upgrading BunkerM

Because data lives in volumes outside the container, upgrades are safe:

  1. docker pull bunkeriot/bunkerm:latest
  2. docker compose down (data stays in volumes)
  3. docker compose up -d (new container mounts the same volumes)
  4. Open the web UI and verify your clients and settings are intact.