MongoDB security.

Enable auth

security:
  authorization: enabled

Create admin

use admin
db.createUser({
    user: "admin",
    pwd: passwordPrompt(),
    roles: [{ role: "userAdminAnyDatabase", db: "admin" }],
})

App user (least priv)

use myapp
db.createUser({
    user: "appuser",
    pwd: "...",
    roles: [{ role: "readWrite", db: "myapp" }],
})

Built-in roles

  • read, readWrite
  • dbAdmin, userAdmin
  • clusterAdmin, clusterManager, clusterMonitor
  • backup, restore
  • readAnyDatabase, readWriteAnyDatabase
  • root

Custom role

db.createRole({
    role: "readUsers",
    privileges: [
        { resource: { db: "myapp", collection: "users" }, actions: ["find"] }
    ],
    roles: [],
})

TLS

net:
  tls:
    mode: requireTLS
    certificateKeyFile: /etc/ssl/mongodb.pem
    CAFile: /etc/ssl/ca.pem

Connection with TLS

mongodb://...?tls=true&tlsCAFile=ca.pem

Encrypt at rest (Enterprise / WT)

security:
  enableEncryption: true
  encryptionKeyFile: /etc/mongo/keyfile

For Community: use disk encryption (LUKS).

Network

net:
  bindIp: 127.0.0.1,10.0.0.5

Don’t bind 0.0.0.0 on public IP. Use firewall.

Auth mechanisms

  • SCRAM-SHA-256 (default, strong).
  • MONGODB-X509 (cert-based).
  • MONGODB-AWS (IAM auth).
  • LDAP (Enterprise).

Field-level encryption (Client-Side)

Encrypt sensitive fields client-side before storing. Mongo doesn’t see plaintext. Requires keyVault.

from pymongo.encryption import AutoEncryptionOpts
opts = AutoEncryptionOpts(kms_providers={"local": {"key": local_key}}, ...)
client = MongoClient(uri, auto_encryption_opts=opts)

Audit log (Enterprise)

auditLog:
  destination: file
  format: JSON
  path: /var/log/mongo/audit.log

Rate limiting / connection cap

net:
  maxIncomingConnections: 5000

Hide commands

setParameter:
  authenticationMechanisms: SCRAM-SHA-256

Run as non-root user

# /etc/systemd/system/mongod.service
User=mongodb
Group=mongodb

Disable JS in server

security:
  javascriptEnabled: false

Common mistakes

  • Auth disabled (default if no config) → world-readable.
  • bindIp: 0.0.0.0 + no firewall.
  • App user with root role.
  • Plaintext passwords in connection strings.
  • No TLS in production.

Read this next

If you want my hardening playbook, it’s at rajpoot.dev .


Building something AI-, backend-, or data-heavy and want a second pair of eyes? I do consulting and freelance work — see my projects and ways to reach me at rajpoot.dev .