MongoDB running without TLS sends documents, queries, and authentication tokens over the network in plaintext. This is the default for self-managed MongoDB, even on versions 5, 6, and 7. This article walks through enabling TLS on mongod, connecting the mongo shell and drivers with certificate verification, enabling mutual TLS for x.509 client authentication, and configuring TLS for replica sets.
MongoDB TLS modes
MongoDB supports four TLS modes, configured via net.tls.mode (or --tlsMode on the command line):
| Mode | Incoming connections | Details |
|---|---|---|
disabled | Plaintext only | No TLS |
allowTLS | Plaintext and TLS | Clients can use either |
preferTLS | Prefer TLS, allow plaintext | Transition mode |
requireTLS | TLS only | Production mode |
Start with allowTLS to migrate clients gradually, then switch to requireTLS.
Step 1: Prepare the certificate
MongoDB requires a PEM file that contains both the certificate and the private key concatenated together — this is different from most other services that use separate files.
# From Let's Encrypt
cat /etc/letsencrypt/live/mongo.example.com/fullchain.pem \
/etc/letsencrypt/live/mongo.example.com/privkey.pem \
> /etc/mongodb/mongod.pem
# Set permissions
chown mongodb:mongodb /etc/mongodb/mongod.pem
chmod 600 /etc/mongodb/mongod.pem
For an internal CA-signed certificate:
# Generate key and CSR
openssl genrsa -out /tmp/mongo.key 4096
openssl req -new -key /tmp/mongo.key \
-out /tmp/mongo.csr \
-subj "/CN=mongo.example.com"
# Sign with your CA
openssl x509 -req -in /tmp/mongo.csr \
-CA /etc/pki/ca/ca.crt -CAkey /etc/pki/ca/ca.key \
-CAcreateserial -out /tmp/mongo.crt -days 365 \
-extfile <(echo "subjectAltName=DNS:mongo.example.com")
# Combine into a single PEM file
cat /tmp/mongo.crt /tmp/mongo.key > /etc/mongodb/mongod.pem
chown mongodb:mongodb /etc/mongodb/mongod.pem
chmod 600 /etc/mongodb/mongod.pem
# Copy the CA cert separately (for client verification)
cp /etc/pki/ca/ca.crt /etc/mongodb/ca.pem
chown mongodb:mongodb /etc/mongodb/ca.pem
Step 2: Configure mongod.conf
Open /etc/mongod.conf:
sudo nano /etc/mongod.conf
net:
port: 27017
bindIp: 0.0.0.0
tls:
mode: requireTLS
certificateKeyFile: /etc/mongodb/mongod.pem
CAFile: /etc/mongodb/ca.pem
# Disable older TLS versions
disabledProtocols: TLS1_0,TLS1_1
# Allow invalid hostnames — set to false in production
allowInvalidHostnames: false
allowInvalidCertificates: false
Restart MongoDB:
sudo systemctl restart mongod
sudo systemctl status mongod
sudo tail -50 /var/log/mongodb/mongod.log
Look for:
{"t":...,"s":"I","c":"NETWORK","id":23015,"ctx":"listener","msg":"Listening on","attr":{"address":"0.0.0.0:27017"}}
Without any TLS error messages.
Step 3: Verify TLS is active
openssl s_client -connect mongo.example.com:27017 \
-servername mongo.example.com \
-starttls mongodb \
-CAfile /etc/mongodb/ca.pem </dev/null 2>&1 \
| openssl x509 -noout -subject -dates
Note: MongoDB 4.x+ no longer requires -starttls mongodb — TLS is negotiated directly.
Step 4: Connect with mongosh
mongosh "mongodb://mongo.example.com:27017/admin" \
--tls \
--tlsCAFile /etc/mongodb/ca.pem \
--username admin \
--password
Or using the connection string:
mongosh "******mongo.example.com:27017/admin?tls=true&tlsCAFile=/etc/mongodb/ca.pem"
Step 5: Configure application drivers
Python (PyMongo)
from pymongo import MongoClient
import certifi
# Using Let's Encrypt CA (already in certifi):
client = MongoClient(
"mongodb://mongo.example.com:27017/",
tls=True,
tlsCAFile=certifi.where()
)
# Using a private CA:
client = MongoClient(
"******mongo.example.com:27017/mydb",
tls=True,
tlsCAFile='/etc/app/mongo-ca.pem',
tlsAllowInvalidHostnames=False,
tlsAllowInvalidCertificates=False
)
db = client.mydb
print(db.list_collection_names())
Node.js (mongodb driver)
const { MongoClient } = require('mongodb');
const fs = require('fs');
const client = new MongoClient('******mongo.example.com:27017/mydb', {
tls: true,
tlsCAFile: '/etc/app/mongo-ca.pem',
// tlsCertificateKeyFile: '/etc/app/client.pem', // for mutual TLS
});
async function run() {
await client.connect();
const db = client.db('mydb');
console.log(await db.listCollections().toArray());
await client.close();
}
run();
Java (MongoDB Java Driver)
MongoClientSettings settings = MongoClientSettings.builder()
.applyConnectionString(new ConnectionString(
"******mongo.example.com:27017/mydb"
))
.applyToSslSettings(builder -> {
builder.enabled(true);
builder.invalidHostNameAllowed(false);
// Set system trust store or custom trust store
})
.build();
MongoClient mongoClient = MongoClients.create(settings);
For a custom CA, create a JKS truststore:
keytool -import -alias mongo-ca -file /etc/app/mongo-ca.pem \
-keystore /etc/app/mongo.truststore.jks \
-storepass trustpass -noprompt
Then add JVM system properties:
-Djavax.net.ssl.trustStore=/etc/app/mongo.truststore.jks
-Djavax.net.ssl.trustStorePassword=trustpass
Step 6: x.509 client authentication (mutual TLS)
MongoDB supports authenticating clients by their certificate’s DN (Distinguished Name) instead of username/password. This is the MONGODB-X509 authentication mechanism.
Enable x.509 authentication
In mongod.conf:
security:
authorization: enabled
net:
tls:
mode: requireTLS
certificateKeyFile: /etc/mongodb/mongod.pem
CAFile: /etc/mongodb/ca.pem
Create a client certificate
openssl genrsa -out /tmp/app-client.key 4096
openssl req -new -key /tmp/app-client.key \
-out /tmp/app-client.csr \
-subj "/CN=myapp/OU=apps/O=example/C=US"
openssl x509 -req -in /tmp/app-client.csr \
-CA /etc/mongodb/ca.pem -CAkey /etc/pki/ca/ca.key \
-CAcreateserial -out /tmp/app-client.crt -days 365
# Combine for MongoDB
cat /tmp/app-client.crt /tmp/app-client.key > /etc/app/mongo-client.pem
Create the MongoDB user for the certificate
Connect to MongoDB and create a user whose username exactly matches the certificate’s subject DN:
db.getSiblingDB('$external').createUser({
user: "CN=myapp,OU=apps,O=example,C=US",
roles: [{ role: "readWrite", db: "mydb" }]
});
Connect using the client certificate
mongosh "mongodb://mongo.example.com:27017/mydb" \
--tls \
--tlsCAFile /etc/mongodb/ca.pem \
--tlsCertificateKeyFile /etc/app/mongo-client.pem \
--authenticationMechanism MONGODB-X509 \
--authenticationDatabase '$external'
Step 7: TLS for Replica Sets
Each member of a replica set needs its own certificate. The members authenticate each other using TLS (and optionally keyfile or x.509 internal authentication).
For each replica set member’s mongod.conf:
net:
tls:
mode: requireTLS
certificateKeyFile: /etc/mongodb/member1.pem
CAFile: /etc/mongodb/ca.pem
clusterAuthX509:
extensionValue: ""
replication:
replSetName: "rs0"
security:
clusterAuthMode: x509
Copy the CA to all members. All member certificates must be signed by the same CA.
Initiate the replica set:
rs.initiate({
_id: "rs0",
members: [
{ _id: 0, host: "mongo1.example.com:27017" },
{ _id: 1, host: "mongo2.example.com:27017" },
{ _id: 2, host: "mongo3.example.com:27017" }
]
});
Certificate renewal
sudo nano /etc/letsencrypt/renewal-hooks/deploy/mongodb.sh
#!/bin/bash
DOMAIN=mongo.example.com
DEST=/etc/mongodb
cat /etc/letsencrypt/live/${DOMAIN}/fullchain.pem \
/etc/letsencrypt/live/${DOMAIN}/privkey.pem \
> ${DEST}/mongod.pem
cp /etc/letsencrypt/live/${DOMAIN}/chain.pem ${DEST}/ca.pem
chown mongodb:mongodb ${DEST}/mongod.pem ${DEST}/ca.pem
chmod 600 ${DEST}/mongod.pem
chmod 644 ${DEST}/ca.pem
systemctl restart mongod
sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/mongodb.sh
MongoDB does not support hot TLS certificate reload — a restart is required. For replica sets, do a rolling restart to avoid downtime.
Troubleshooting
| Error | Cause | Fix |
|---|---|---|
SSL peer certificate validation failed | CA not trusted | Provide tlsCAFile pointing to the correct CA |
MongoServerError: x509 auth error: X509 name mismatch | Certificate DN does not match the user in $external | Ensure the user’s name exactly matches the cert subject |
Error: ENOENT: no such file or directory | Certificate path wrong | Verify file exists and permissions are correct |
SSL_ERROR_RX_RECORD_TOO_LONG | Client connecting to non-TLS port | Use port 27017 with tls=true |
| Replica set members cannot communicate | Member certs signed by different CAs | All members must share the same CA in CAFile |
Summary
MongoDB TLS requires concatenating the certificate and private key into a single .pem file, setting net.tls.mode: requireTLS in mongod.conf, and providing the CA file for client verification. Clients must pass tls=true and tlsCAFile in their connection strings. For stronger authentication, use x.509 client certificates (MONGODB-X509) so applications connect without passwords. Replica set members use the same CA to verify each other. Certificate renewal requires a restart, which should be performed as a rolling restart on replica sets.