NoSQL Databases

Securing Your MongoDB Cluster with TLS/SSL: A Complete Configuration Guide

Running MongoDB without TLS exposes your data to network interception and man-in-the-middle attacks. Here's how to configure TLS/SSL across your MongoDB replica set.

JusDB Team
May 2, 2022
9 min read
150 views

Your PCI DSS assessor flagged it. Your SOC 2 auditor flagged it. Your internal security team flagged it. MongoDB running without TLS/SSL means every query, every authentication handshake, and every replication message travels across your network in plaintext — readable by anyone with access to the wire. For teams handling financial data, healthcare records, or any regulated workload, unencrypted MongoDB connections are a hard blocker for compliance sign-off. For everyone else, it is a preventable breach vector. Configuring TLS for MongoDB is not optional in 2024 — it is table stakes.

This guide walks through the complete TLS/SSL configuration lifecycle for MongoDB: generating certificates, updating mongod.conf, securing client connections, enabling x.509 internal authentication, and rotating certificates without downtime.

The commands target MongoDB 6.x and 7.x on Linux. Windows paths differ but the configuration keys are identical.

TL;DR
  • Generate a CA certificate and per-node server certificates signed by that CA.
  • Set net.tls.mode: requireTLS and point mongod.conf at the PEM files.
  • Update all client connection strings with tls=true&tlsCAFile=ca.pem.
  • Use x.509 certificates for replica set and sharded cluster internal member authentication instead of keyfiles.
  • Automate certificate rotation with mongod --tlsCertificateKeyFilePassword and a SIGHUP reload — zero downtime required.

MongoDB TLS/SSL Overview

MongoDB's documentation uses "TLS/SSL" together for historical reasons — older MongoDB versions used the now-deprecated --ssl flags. Since MongoDB 4.2, the preferred configuration keys are all prefixed with tls. The underlying protocol is TLS 1.2 or TLS 1.3 depending on your OpenSSL version and MongoDB build. The old net.ssl.* keys still work but are deprecated and will be removed in a future release. Migrate to net.tls.* now.

What TLS encrypts in MongoDB

When TLS is enabled, the following traffic is encrypted end-to-end:

  • Client-to-server connections — mongosh, application drivers, mongodump, mongorestore, all of it.
  • Replica set replication traffic — oplog entries sync between members over TLS when internal authentication is configured.
  • Sharded cluster traffic — mongos-to-config server and mongos-to-shard connections.
  • Ops Manager / Cloud Manager agent connections — monitoring and automation agents authenticate with TLS certificates.

TLS does not encrypt data at rest. For encryption at rest, use the Encrypted Storage Engine (Enterprise) or filesystem-level encryption (LUKS on Linux). TLS and encryption at rest are complementary, not substitutes for each other.

TLS modes available in mongod

MongoDB supports four TLS modes, configured via net.tls.mode:

  • disabled — No TLS. Default. Never use this in production.
  • allowTLS — Accepts both TLS and non-TLS connections. Use only during migration.
  • preferTLS — Prefers TLS but still accepts plaintext. Use only during migration.
  • requireTLS — Rejects all non-TLS connections. The only acceptable production setting.

Generating Certificates

You have two practical options: a self-signed CA (acceptable for internal clusters with controlled client environments) or certificates signed by a trusted external CA like Let's Encrypt, DigiCert, or your organization's internal PKI. PCI DSS and many SOC 2 auditors will ask about your CA trust chain — self-signed CAs are acceptable if managed properly with a documented rotation process.

Option 1: Generate a self-signed CA and server certificates with OpenSSL

Run these commands on a secure machine — ideally not on any MongoDB node itself. Store the CA private key offline or in a secrets manager.

bash
# Step 1: Generate the CA private key and self-signed certificate (10-year validity)
openssl req -newkey rsa:4096 -x509 -days 3650 -keyout ca-key.pem -out ca-cert.pem \
  -subj "/C=US/ST=California/O=YourOrg/CN=MongoDB-CA" \
  -passout pass:YOUR_CA_PASSPHRASE

# Step 2: Generate a private key for the MongoDB node
openssl genrsa -out mongodb-node1-key.pem 4096

# Step 3: Create a certificate signing request (CSR) for the node
# The CN must match the hostname or IP that clients will connect to.
openssl req -new -key mongodb-node1-key.pem -out mongodb-node1.csr \
  -subj "/C=US/ST=California/O=YourOrg/CN=mongodb-node1.internal.example.com"

# Step 4: Sign the CSR with the CA (2-year validity recommended for server certs)
openssl x509 -req -in mongodb-node1.csr -CA ca-cert.pem -CAkey ca-key.pem \
  -CAcreateserial -out mongodb-node1-cert.pem -days 730 \
  -passin pass:YOUR_CA_PASSPHRASE

# Step 5: Combine the certificate and key into a single PEM file (required by mongod)
cat mongodb-node1-cert.pem mongodb-node1-key.pem > mongodb-node1.pem

# Set strict permissions — mongod will refuse to start if the key is world-readable
chmod 600 mongodb-node1.pem
chown mongod:mongod mongodb-node1.pem

Repeat steps 2–5 for every node in your replica set or sharded cluster. Each node must have its own certificate with its correct hostname in the CN (or SAN extension).

Option 2: Add Subject Alternative Names (SANs)

Modern TLS validation requires SANs for hostnames. Add a SAN extension file for production certificates:

bash
# Create an extension file with SANs
cat > node1-ext.cnf <
Certificate management pitfalls to avoid
  • Mismatched CN/SAN and hostname — If the hostname clients use to connect does not match the certificate's CN or SAN, connections will fail with a TLS handshake error. Always verify with openssl verify -CAfile ca-cert.pem mongodb-node1-cert.pem before deploying.
  • Storing the CA private key on a MongoDB node — The CA key should be kept offline or in a secrets manager (HashiCorp Vault, AWS Secrets Manager). If a MongoDB node is compromised, your entire CA should not be at risk.
  • Forgetting to concatenate cert + key into a single PEM — MongoDB's net.tls.certificateKeyFile expects a single file containing both the certificate chain and the private key, in that order. Providing only the certificate will cause a startup failure.
  • Short certificate validity periods without rotation automation — A 90-day certificate with no rotation automation will cause a 3 AM outage. Either use longer validity (1–2 years) with scheduled rotation, or automate renewal.

Configuring TLS on mongod

Edit /etc/mongod.conf on each node. The relevant section is net. Below is a complete, production-ready configuration for a replica set member:

yaml
# /etc/mongod.conf — production TLS configuration

net:
  port: 27017
  bindIp: 0.0.0.0          # Or restrict to specific IPs / VPC CIDR
  tls:
    mode: requireTLS
    certificateKeyFile: /etc/ssl/mongodb/mongodb-node1.pem
    certificateKeyFilePassword: ""   # Leave empty if key is unencrypted
                                     # Use environment variable injection for encrypted keys
    CAFile: /etc/ssl/mongodb/ca-cert.pem
    allowInvalidHostnames: false     # Never set true in production
    allowInvalidCertificates: false  # Never set true in production
    disabledProtocols: "TLS1_0,TLS1_1"  # Enforce TLS 1.2 minimum

security:
  authorization: enabled
  clusterAuthMode: x509             # Use x.509 for internal member auth

replication:
  replSetName: "rs0"

storage:
  dbPath: /var/lib/mongo

After updating the config, restart the mongod service:

bash
sudo systemctl restart mongod
sudo systemctl status mongod

# Verify TLS is active
openssl s_client -connect mongodb-node1.internal.example.com:27017 \
  -CAfile /etc/ssl/mongodb/ca-cert.pem \
  -servername mongodb-node1.internal.example.com < /dev/null
Production TLS requirements checklist
  • net.tls.mode must be requireTLS — not allowTLS or preferTLS.
  • net.tls.allowInvalidCertificates must be false.
  • net.tls.allowInvalidHostnames must be false.
  • net.tls.disabledProtocols must include TLS1_0 and TLS1_1 at minimum.
  • Certificate files must be owned by the mongod user with mode 600.
  • CA certificate must be deployed to all client machines that connect to the cluster.

Configuring TLS on MongoDB Clients

mongosh

Connect with TLS enabled and pointing to the CA certificate:

bash
# Basic TLS connection
mongosh "mongodb://mongodb-node1.internal.example.com:27017/admin" \
  --tls \
  --tlsCAFile /etc/ssl/mongodb/ca-cert.pem \
  --username admin \
  --password

# Using a client certificate for x.509 authentication
mongosh "mongodb://mongodb-node1.internal.example.com:27017/admin" \
  --tls \
  --tlsCAFile /etc/ssl/mongodb/ca-cert.pem \
  --tlsCertificateKeyFile /etc/ssl/mongodb/client-cert.pem \
  --authenticationMechanism MONGODB-X509

Connection string URI format

For application drivers, use the URI connection string with TLS parameters. This works across all official MongoDB drivers (Node.js, Python, Go, Java, etc.):

bash
# Standard username/password auth over TLS
mongodb://appuser:password@mongodb-node1.internal.example.com:27017,mongodb-node2.internal.example.com:27017/mydb?replicaSet=rs0&tls=true&tlsCAFile=/etc/ssl/mongodb/ca-cert.pem

# x.509 client certificate auth
mongodb://mongodb-node1.internal.example.com:27017/mydb?replicaSet=rs0&tls=true&tlsCAFile=/etc/ssl/mongodb/ca-cert.pem&tlsCertificateKeyFile=/etc/ssl/mongodb/client.pem&authMechanism=MONGODB-X509

Python (PyMongo)

python
import pymongo
import ssl

client = pymongo.MongoClient(
    "mongodb://mongodb-node1.internal.example.com:27017/",
    tls=True,
    tlsCAFile="/etc/ssl/mongodb/ca-cert.pem",
    tlsCertificateKeyFile="/etc/ssl/mongodb/client.pem",
    replicaSet="rs0"
)
db = client.mydb

Node.js (MongoDB Node Driver)

javascript
const { MongoClient } = require('mongodb');

const client = new MongoClient(
  'mongodb://mongodb-node1.internal.example.com:27017/?replicaSet=rs0',
  {
    tls: true,
    tlsCAFile: '/etc/ssl/mongodb/ca-cert.pem',
    tlsCertificateKeyFile: '/etc/ssl/mongodb/client.pem',
  }
);

await client.connect();

X.509 Authentication for Internal Member Authentication

MongoDB replica sets and sharded clusters require a form of internal authentication so that members verify each other's identity before syncing data. The two options are keyfile authentication (a shared secret) and x.509 authentication (certificate-based). X.509 is significantly more secure: there is no shared secret to leak, each member has its own identity, and you can revoke individual member certificates without rotating a shared key across all nodes.

Requirements for x.509 internal auth

For internal member authentication, MongoDB requires that member certificates share the same:

  • Organization (O)
  • Organizational Unit (OU)
  • Domain Component (DC) attributes in the certificate subject

Generate member certificates with matching O and OU fields:

bash
# Generate member certificate for node1
openssl req -newkey rsa:4096 -nodes -keyout rs0-member1-key.pem \
  -out rs0-member1.csr \
  -subj "/C=US/ST=California/O=YourOrg/OU=MongoDBReplicaSet/CN=mongodb-node1.internal.example.com"

openssl x509 -req -in rs0-member1.csr -CA ca-cert.pem -CAkey ca-key.pem \
  -CAcreateserial -out rs0-member1-cert.pem -days 730 \
  -passin pass:YOUR_CA_PASSPHRASE

cat rs0-member1-cert.pem rs0-member1-key.pem > rs0-member1.pem
chmod 600 rs0-member1.pem
chown mongod:mongod rs0-member1.pem

In mongod.conf, set clusterAuthMode: x509 (as shown in the config block above). When initializing or reconfiguring the replica set, each member authenticates using its certificate rather than a keyfile.

To create a MongoDB user mapped to an x.509 client certificate, the username must be the full certificate subject in RFC 2253 format:

javascript
// Connect as admin, then create the x.509 user
db.getSiblingDB("$external").runCommand({
  createUser: "CN=app-service,OU=Applications,O=YourOrg,C=US",
  roles: [
    { role: "readWrite", db: "mydb" }
  ],
  writeConcern: { w: "majority" }
});

Enforcing TLS: Disabling Plaintext Connections

Setting net.tls.mode: requireTLS is necessary but not always sufficient if you are migrating an existing cluster. During the migration window, you may use allowTLS or preferTLS to avoid breaking existing clients. The migration sequence for a live replica set without downtime is:

bash
# Step 1: Deploy certificates to all nodes. Set mode to allowTLS.
# This allows both TLS and non-TLS connections — existing clients still work.
net:
  tls:
    mode: allowTLS

# Step 2: Rolling restart of replica set members (secondaries first, then primary).
# Verify all members are healthy: rs.status()

# Step 3: Update all application clients to connect with TLS.
# Verify no plaintext connections remain (check network firewall logs or
# use tcpdump to confirm all traffic is encrypted).

# Step 4: Change mode to requireTLS on all members (rolling restart again).
net:
  tls:
    mode: requireTLS

# Step 5: Verify with mongosh — a plaintext connection attempt should now fail.
mongosh "mongodb://mongodb-node1.internal.example.com:27017/admin"
# Expected: MongoServerError: SSL is required

To verify no plaintext connections are being accepted, test explicitly:

bash
# This should fail after enforcing requireTLS
mongosh --host mongodb-node1.internal.example.com --port 27017 --eval "db.adminCommand({ping: 1})"
# Output should be: MongoNetworkError or SSL handshake error

Certificate Rotation Without Downtime

Certificate rotation is where many teams get stuck. The good news: MongoDB supports online certificate rotation via SIGHUP (on Linux) or the rotateCertificates admin command without restarting mongod.

Online rotation procedure

bash
# Step 1: Generate new certificates using the same CA
# (repeat the OpenSSL steps from the Generating Certificates section)
# New cert file: mongodb-node1-new.pem

# Step 2: Replace the certificate file on disk
# Use an atomic rename to avoid a window where the file is partially written
cp /etc/ssl/mongodb/mongodb-node1-new.pem /etc/ssl/mongodb/mongodb-node1.pem.new
mv /etc/ssl/mongodb/mongodb-node1.pem.new /etc/ssl/mongodb/mongodb-node1.pem
chown mongod:mongod /etc/ssl/mongodb/mongodb-node1.pem
chmod 600 /etc/ssl/mongodb/mongodb-node1.pem

# Step 3: Signal mongod to reload certificates (no restart required)
# Find the mongod PID
MONGOD_PID=$(pgrep -x mongod)
sudo kill -SIGHUP $MONGOD_PID

# OR use the admin command from mongosh (MongoDB 4.4+)
db.adminCommand({ rotateCertificates: 1 })

After rotation, new connections will use the new certificate. In-flight connections continue using the old certificate until they close naturally. Verify the new certificate is active:

bash
openssl s_client -connect mongodb-node1.internal.example.com:27017 \
  -CAfile /etc/ssl/mongodb/ca-cert.pem < /dev/null 2>&1 | \
  grep -E "subject|issuer|notAfter"

For replica sets, rotate one member at a time and verify rs.status() shows all members healthy before rotating the next. For sharded clusters, rotate config server members first, then shard members, then mongos instances.

Automating rotation with a cron job

bash
#!/bin/bash
# /usr/local/bin/rotate-mongo-cert.sh
# Run 30 days before expiry via cron

set -euo pipefail

CERT_DIR="/etc/ssl/mongodb"
CA_CERT="${CERT_DIR}/ca-cert.pem"
NODE_CERT="${CERT_DIR}/mongodb-node1.pem"
MONGOD_PID=$(pgrep -x mongod)

# Generate new certificate (assumes CA key is in secrets manager)
# ... OpenSSL commands here ...

# Atomic replacement
mv "${CERT_DIR}/mongodb-node1-new.pem" "${NODE_CERT}"
chown mongod:mongod "${NODE_CERT}"
chmod 600 "${NODE_CERT}"

# Signal reload
kill -SIGHUP "${MONGOD_PID}"

echo "Certificate rotated successfully at $(date)"
Key Takeaways
  • Always use net.tls.mode: requireTLS in production. The intermediate modes (allowTLS, preferTLS) are migration tools only.
  • Each MongoDB node needs its own certificate with the correct CN/SAN matching its hostname. Wildcard certificates are valid but reduce the security isolation benefit.
  • Use x.509 for internal replica set authentication instead of keyfiles — it eliminates shared secrets and enables per-member certificate revocation.
  • Disable TLS 1.0 and 1.1 explicitly via net.tls.disabledProtocols. Enforce TLS 1.2 at minimum; prefer TLS 1.3 where supported.
  • Never set allowInvalidCertificates: true or allowInvalidHostnames: true in production. These flags defeat the purpose of TLS.
  • Certificate rotation is possible without downtime using SIGHUP or rotateCertificates. Plan rotation schedules before certificates are within 30 days of expiry.
  • Test your TLS configuration with openssl s_client before updating client applications — catch handshake errors at the infrastructure layer, not in production code.

Working with JusDB on MongoDB Security

JusDB secures MongoDB deployments for engineering teams with compliance requirements — TLS configuration, x.509 authentication, audit logging, and RBAC design. Our DBAs handle the full security hardening lifecycle so your MongoDB clusters pass security audits.

Explore JusDB MongoDB Management →  |  Talk to a DBA

Related reading:

Share this article