Add a MongoDB source
MongoDB support works end to end but is not yet battle-tested
across the full version and deployment matrix. Stable today:
single-replica-set sources on MongoDB 6 and 7, reachable via
mongodb:// or mongodb+srv://. What is
rough: Atlas-specific quirks (region transfer limits, IP
allowlists), sharded clusters (single-shard only), FLE
(field-level encryption) fields. Report edges via
simon@hackerman.co.
Point the agent at a MongoDB database. The shape mirrors the
Postgres
flow: a read role on the source, the URI in an env file, a
source block in config.yaml, one check, reload, first
backup.
Before you start
- An agent installed and connected, green dot in the dashboard.
- A MongoDB 6 or 7 instance (self-hosted or Atlas EU regions).
- MongoDB Database Tools installed on the agent host. Not in most distro repos; follow MongoDB's install page for your distro. Install the major version matching your source.
1. Create a backup role
The agent calls mongodump. That needs the
backup role on the database you are dumping, plus
authentication against the admin database where
MongoDB stores users by convention.
use admin
db.createUser({
user: "restorable_backup",
pwd: "generate-a-strong-one",
roles: [
{ role: "backup", db: "admin" }
]
})
If your source uses client-side field-level encryption, the
backup role is not enough to read the encrypted
fields; Restorable restores the encrypted blobs as-is and the
check sees the ciphertext unless the scratch container has the
decryption keys. Plan your checks against the visible fields
accordingly, or stage decryption keys into the scratch.
2. Put the URI in the env file
sudo tee -a /var/lib/restorable/env >/dev/null <<'EOF'
RESTORABLE_MONGO_URI=mongodb+srv://restorable_backup:PASSWORD@cluster0.xyz.mongodb.net/?authSource=admin&retryWrites=true&w=majority
EOF
sudo chmod 0600 /var/lib/restorable/env
sudo chown root:root /var/lib/restorable/env
For self-hosted MongoDB, mongodb://user:pass@host:27017/?authSource=admin.
Either scheme works with the agent.
3. Declare the source in config.yaml
sources:
- slug: prod-mongo
kind: mongodb
connection:
uri: env:RESTORABLE_MONGO_URI
checks:
- app-healthy
checks:
- id: app-healthy
summary_find:
database: app
collection: users
filter: { }
expect: "n > 0"
The summary_find block is engine-specific to Mongo.
It comes in three shapes: filter-with-implicit-count (above),
aggregate-pipeline (below), and a list-collections probe that
counts user collections in the database (the mongo equivalent of
postgres's schema-count check).
Filter form
db.collection.countDocuments(filter), wrapped so
the summary row is always { n: <count> }.
The expect expression references n.
Aggregate form
checks:
- id: orders-total
summary_find:
database: app
collection: orders
aggregate:
- { $match: { status: "open" } }
- { $group: { _id: null, n: { $sum: 1 }, total: { $sum: "$amount" } } }
- { $project: { ok: { $cond: [{ $and: [{ $gt: ["$n", 0] }, { $gt: ["$total", 10000] }] }, 1, 0] } } }
expect: "ok == 1"
The expect DSL is single-comparison only; compose
compound conditions in the pipeline (a final
$project with $cond reduces a predicate
to a 1/0 column the expect can read).
The first document of the pipeline's result becomes the summary
row. Keys in that document are what expect can
reference. Aggregate is strictly more powerful than filter; use
aggregate when you need more than a count.
List-collections form
checks:
- id: app-collections
summary_find:
database: app
list_collections: true
expect: "n >= 4"
Counts user collections in database, dropping names
that start with system., and returns
{ n: <count> }. This is the schema-
count probe the wizard auto-attaches as
<slug>-collections: it catches the failure mode
where a restore exits clean but most of the database didn't
materialize (wrong archive, partial restore, role visibility
drift). collection, filter, and
aggregate must be unset in this mode.
database is required for every shape. The scratch
container's default database is admin, which is not
where your data lives; name the database explicitly.
4. Reload the agent
sudo systemctl reload restorable.service
sudo journalctl -u restorable.service -f 5. Take the first backup and restore test
From the dashboard, run backup, then run restore test. The flow mirrors Postgres:
-
Agent runs
mongodump --uri=<source> --archiveand pipes the archive throughageencryption. - Encrypted archive uploads to the ciphertext bucket.
-
On restore test, the agent downloads and decrypts, spins up a
Mongo scratch container matching the source's major version,
runs
mongorestore, runs the check via the Node driver, signs the receipt.
Common failures
mongodump: not authorized on admin
The role needs { role: "backup", db: "admin" }.
Without it, the dump fails on the first collection that
requires elevated privileges (config or oplog collections).
Atlas transfer limits
Atlas rate-limits egress on smaller cluster tiers. A large
mongodump from an M0 or M2 cluster may throttle or
fail after a few GB. For sources that large, move to M10 or
host the source elsewhere.
Scratch image missing indexes after restore
mongorestore rebuilds indexes on the scratch by
default. On very large collections, index rebuild dominates the
restore-test time budget. If that is unacceptable, pass
--noIndexRestore via agent config
(post-beta feature) and accept that indexed queries in checks
will not use their indexes.
SRV record resolution failure
mongodb+srv:// requires DNS SRV records from the
agent's host. Corporate DNS that does not forward SRV queries
breaks Atlas connectivity. Fall back to the
mongodb://host:port/ scheme or fix DNS.
What to write in a Mongo check
Same principles as
Writing a check:
aim at a specific failure category. A bare
countDocuments() catches
"restore produced an empty collection" and not much else. Write
checks that depend on the schema you care about:
-
A filter matching "recent" documents via
$gt: ISODate(...). Catches a stale snapshot. - An aggregate summing a numeric field and asserting the total is in a realistic range. Catches a partial restore.
-
A lookup across two collections via
$lookup. The Mongo equivalent of a referential-integrity check.