MongoDB TLS Configuration: Encrypting Connections and Requiring Client Certificates

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):

ModeIncoming connectionsDetails
disabledPlaintext onlyNo TLS
allowTLSPlaintext and TLSClients can use either
preferTLSPrefer TLS, allow plaintextTransition mode
requireTLSTLS onlyProduction 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

ErrorCauseFix
SSL peer certificate validation failedCA not trustedProvide tlsCAFile pointing to the correct CA
MongoServerError: x509 auth error: X509 name mismatchCertificate DN does not match the user in $externalEnsure the user’s name exactly matches the cert subject
Error: ENOENT: no such file or directoryCertificate path wrongVerify file exists and permissions are correct
SSL_ERROR_RX_RECORD_TOO_LONGClient connecting to non-TLS portUse port 27017 with tls=true
Replica set members cannot communicateMember certs signed by different CAsAll 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.

Scroll to Top