MongoDB User Isolation — Playbook
Created: 2026-07-05 (feat/#2728) Scope: MongoDB rs0 (bms-2 PRIMARY / bms-3 SECONDARY / bms-4 arbiter)
Current user map
| User | Roles | Auth DB | Credential DB | SOPS file | Consumer |
|---|---|---|---|---|---|
admin | root | admin | admin | bms-servers.env.sops + mongodb-bms.env.sops | maintenance, backups, p24-status.py |
et_oper | readWrite | admin | w4_db | et-operational-platform.env.sops | et-operational-platform Vercel |
w3_app | readWrite | w3_db | w3_db | pinbox24-w3.env.sops | v32-prod (bms-1) |
w4_app | readWrite | w4_db | w4_db | pinbox24-w4.env.sops | v42-prod (bms-1) |
pinbox_production | readWrite | w3_db | w3_db (legacy) | n/a — not referenced by any tracked SOPS key (verified 2026-07-11, #3754) | unknown / dormant — do not reuse without confirming live usage first |
w3_read_v42 | read | w3_db | w3_db | pinbox24-w4.env.sops (V42_v3MongoUrl) | v42-prod legacy mongojs compat path (reads W3 data only — .aggregate(), never a write; see #3754) |
prometheus | clusterMonitor | admin | admin | mongodb-bms.env.sops + n8n-bms4.env.sops (dup) | mongodb-exporter on bms-4 |
Note: prometheus credentials are temporarily in both mongodb-bms.env.sops and n8n-bms4.env.sops.
Cleanup tracked in issue #2732.
Adding a new MongoDB user
Step 1 — Identify PRIMARY
ssh -i ~/.ssh/id_ed25519 root@145.239.133.104 "mongosh admin -u admin -p '\$ADMIN_PW' \
--authenticationDatabase admin --quiet --eval \"rs.isMaster().primary\""Step 2 — Create user on PRIMARY
Write a shell script (avoids SSH quoting issues):
#!/bin/bash
mongosh admin \
-u admin -p "$MONGO_ADMIN_PW" \
--authenticationDatabase admin \
--quiet \
--eval "db.createUser({user:'NEW_USER',pwd:'NEW_PW',roles:[{role:'readWrite',db:'TARGET_DB'}]});"SCP the script to PRIMARY, execute, delete:
scp -i ~/.ssh/id_ed25519 script.sh root@145.239.133.104:/tmp/create_user.sh
ssh -i ~/.ssh/id_ed25519 root@145.239.133.104 "bash /tmp/create_user.sh && rm /tmp/create_user.sh"Step 3 — Test connection
ssh -i ~/.ssh/id_ed25519 root@145.239.133.104 \
"mongosh 'mongodb://NEW_USER:NEW_PW@145.239.133.104:27017/TARGET_DB?authSource=admin&replicaSet=rs0' \
--eval 'db.collectionName.countDocuments({})'"Step 4 — Add to SOPS
Add NEW_USER_MONGODB_URI=mongodb://NEW_USER:PW@... to the correct SOPS file.
Use explicit dotenv flags:
$env:SOPS_AGE_KEY_FILE = "C:\Users\konar\.age\p24-infra-keys.txt"
# 1. Decrypt to variable (never print)
$plain = sops --decrypt --input-type dotenv --output-type dotenv secrets\<file>.env.sops
# 2. Append new key (value from $env:NEW_VALUE — never hardcoded)
$content = ($plain -join "`n") + "`nNEW_KEY=$env:NEW_VALUE`n"
# 3. WriteAllText (no BOM, LF)
[System.IO.File]::WriteAllText("$PWD\secrets\<file>.env.sops", $content, [System.Text.UTF8Encoding]::new($false))
# 4. Encrypt in-place
sops --encrypt --in-place --input-type dotenv --output-type dotenv secrets\<file>.env.sops
# 5. Canary
sops --decrypt --input-type dotenv --output-type dotenv secrets\<file>.env.sops | Out-Null
$env:NEW_VALUE = ""Step 5 — Update infrastructure-overview.md
Add row to §MongoDB user map with: user, roles, db, SOPS file, consumer.
Rollback procedure
If a new user causes authentication failures:
- Identify affected service in Vercel/PM2 logs
- Revert SOPS: restore previous value of the connection URI
- Update Vercel env var via API (see Vercel API pattern in secrets-sync.yml)
- Trigger service redeploy
- The MongoDB user can remain (harmless) while root cause is investigated
Notes on authSource
- Users created in
admindb:authSource=adminin connection string - Current convention: create all users in
admindb for consistency
Connection string format
mongodb://<user>:<password>@145.239.133.104:27017,51.68.155.224:27017/<database>?authSource=admin&replicaSet=rs0
Generate URL-safe passwords (no special chars that need encoding):
$pw = -join ((65..90)+(97..122)+(48..57) | Get-Random -Count 32 | ForEach-Object { [char]$_ })