Mirra
Function Client (self-host)

Backup and restore

A Function Client server keeps its state in four places. Back up all four together:

WhatWhereWhy it matters
.env.selfhostthe repository's top directoryholds ENCRYPTION_MASTER_KEY. Without that exact key, every connected integration's stored credentials are unreadable after a restore, and every person has to connect them again.
MongoDBthe mongo-data volume, database mirraaccounts, spaces, messages, flows, everything but the graph
Neo4jthe neo4j-data volumethe memory graph
Object storagethe s3-data volumeuploaded files, images, recordings

Redis holds only caches and can be left out. The edge-data volume holds the edge's certificates, which it obtains again by itself.

.env.selfhost alone lets its holder sign in as anyone on the live server (JWT_SECRET), and with the data it unlocks every stored integration credential. Keep the backup readable only by you, and encrypt it before it leaves the machine.

The commands below run from the repository's top directory and write to backup/. Compose names the volumes mirra_<name> (the compose file's project name; with docker compose -p <project> they are <project>_<name>, so change the docker run lines to match). Each backup overwrites the last, so copy backup/ somewhere else, off the machine.

Back up

umask 077    # backup/ holds every secret: readable by you only
mkdir -p backup && chmod 700 backup
 
# 1. The settings, and with them the encryption key.
cp .env.selfhost backup/
 
# 2. MongoDB, while it runs.
docker compose --env-file .env.selfhost exec -T mongo mongodump --db mirra --archive --gzip > backup/mongo.archive.gz
 
# 3. Neo4j. Community edition dumps only a stopped database.
docker compose --env-file .env.selfhost stop neo4j
docker compose --env-file .env.selfhost run --rm --no-deps -T --user neo4j --entrypoint neo4j-admin neo4j \
  database dump neo4j --to-stdout > backup/neo4j.dump
docker compose --env-file .env.selfhost start neo4j
 
# 4. Object storage, stopped so the files are consistent.
docker compose --env-file .env.selfhost stop s3
docker run --rm -v mirra_s3-data:/data:ro busybox tar cz -C /data . > backup/s3-data.tgz
docker compose --env-file .env.selfhost start s3

To copy it off the machine, encrypt it first, for example tar -C backup -cz . | gpg --symmetric --cipher-algo AES256 -o ~/client-backup-$(date +%F).tgz.gpg, and keep the passphrase somewhere other than the backup.

While Neo4j and object storage are stopped, the app keeps running, but memory and uploads fail for those minutes.

The database's name is DB_NAME, which compose sets to mirra. It never comes from the connection string's path. Outside compose, the MongoDB step is mongodump --uri "$DB_CONNECTION_STRING" --db "$DB_NAME" --archive --gzip.

Restore

On a new machine, or after down -v: check out the same release you backed up, and put the backup in backup/.

cp backup/.env.selfhost .env.selfhost
chmod 600 .env.selfhost
 
# Object storage, into a new volume.
docker compose --env-file .env.selfhost up --no-start s3
docker run --rm -i -v mirra_s3-data:/data busybox tar xz -C /data < backup/s3-data.tgz
 
# Neo4j, before it first starts.
docker compose --env-file .env.selfhost run --rm --no-deps -T --user neo4j --entrypoint neo4j-admin neo4j \
  database load neo4j --from-stdin --overwrite-destination=true < backup/neo4j.dump
 
# MongoDB, once it is up.
docker compose --env-file .env.selfhost up -d --wait mongo
docker compose --env-file .env.selfhost exec -T mongo mongorestore --archive --gzip --drop < backup/mongo.archive.gz
 
# Everything else.
docker compose --env-file .env.selfhost up -d --build

Try a restore on a spare machine before you need one.

On this page