My FeedDiscussionsHeadless CMS
New
Sign in
Log inSign up
Learn more about Hashnode Headless CMSHashnode Headless CMS
Collaborate seamlessly with Hashnode Headless CMS for Enterprise.
Upgrade ✨Learn more
How to configure MongoDB 5 for TLS/SSL Connections on Debian/Ubuntu

How to configure MongoDB 5 for TLS/SSL Connections on Debian/Ubuntu

Learn how to configure MongoDB connections over TLS/SSL the easy way, even when using self-signed certificates. No hacks required!

Deactivated User's photo
Deactivated User
·Sep 22, 2021·

8 min read

In this tutorial, you'll learn how to:

  • Install MongoDB 5 on Debian/Ubuntu
  • Create the required root CA and (self-signed) TLS/SSL certificates
  • Configuring the MongoDB server and client to communicate over TLS/SSL

All without using hacks such as --tlsAllowInvalidCertificates or --tlsAllowInvalidCertificates that present significant security risks to applications in production.

You'll also see how a secrets manager (Doppler in this case) can be used to securely store and restrict access to the MongoDB TLS/SSL keys and certificates. Installing Doppler is not required for this tutorial, but it might give you some ideas for secrets automation that you can integrate into your CI/CD workflows.

Finally, this post assumes that you understand how TLS/SSL certificates and the chain of trust works. If you need a good introduction, check out this How HTTPS works YouTube video, which explains what a Certificate Authority is and how self-signed certificates work.

Let's get started!

Required System Dependencies

Install the required system dependencies for this tutorial:

apt-get update
apt install -y apt-transport-https ca-certificates curl wget gnupg

Install MongoDB 5

As MongoDB 5 isn't yet available from Debian/Ubuntu's provided repositories, Mongo's custom apt repository will be used instead:

# Install MonogDB 5 for Debian/Ubuntu
wget -qO - https://www.mongodb.org/static/pgp/server-5.0.asc | apt-key add -
echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu focal/mongodb-org/5.0 multiverse" | tee /etc/apt/sources.list.d/mongodb-org-5.0.list
apt-get update
apt-get install -y mongodb-org
mongod --version

If using a Virtual Machine, start and configure the MongoDB service to launch on machine boot automatically:

systemctl start mongod
systemctl status mongod
systemctl enable mongod

Creating a Root CA and MongoDB Server TLS/SSL Certificate Using mkcert

To have a complete working example, the mkcert CLI will be used to establish a new Certificate Authority (CA) to then create the MongoDB server TLS/SSL certificate and key.

The mkcert CLI makes creating locally trusted certificates a breeze and is especially useful in development environments or where getting a certificate from a trusted external Certificate Authority isn't feasible.

Before using in production, check if your DevOps/SecOps team has an existing process for managing TLS/SSL certificates.

Let's start by installing mkcert:

wget -O /usr/local/bin/mkcert "https://github.com/FiloSottile/mkcert/releases/download/v1.4.3/mkcert-v1.4.3-linux-$(dpkg --print-architecture)"
chmod +x /usr/local/bin/mkcert
mkcert --version

Then generate the CA:

You can view the root CA certificate and key mkcert created by running:

With a Certificate Authority (CA) in place, mkcert can now generate the MongoDB server TLS/SSL certificate and key, capable of supporting multiple DNS names (including wildcards):

# Replace the doppler.university with your own internal domains
mkcert \
    -cert-file mongo-tls.crt \
    -key-file mongo-tls.key \
    doppler.university *.doppler.university localhost 127.0.0.1 ::1

The final step is to create a file containing the certificate and key as this is the format the MongoDB server requires:

cat mongo-tls.crt mongo-tls.key > mongo-tls.pem

Note that even though a self-signed certificate is used (as it's not from a globally trusted CA), as long as the hostname used by the client to connect to the server matches one of these domains, you won't need workarounds such as --tlsAllowInvalidCertificates or --tlsAllowInvalidCertificates.

These flags should never be used in production as it makes the client susceptible to man-in-the-middle attacks because the Mongo client is essentially saying, "I don't know who you are, but you accept TLS so good enough for me!".

These hacks are unnecessary as the root CA certificate will be used by the Mongo client to verify the server is who it claims to be, e.g., mongo.doppler.university.

Using Doppler to Manage MongoDB TLS/SSL Certificates

While this step is optional, it highlights the advantages of using a centralized and access-controlled secrets manager that provides encrypted storage and handy features such as version history and rollbacks.

Doppler is free to get started and doesn't require any credit card details to sign up.

The first step is to install the Doppler CLI on the MongoDB server:

# Debian/Ubuntu install instructions. See docs for other Operating Systems.
curl -sLf --retry 3 --tlsv1.2 --proto "=https" 'https://packages.doppler.com/public/cli/gpg.DE2A7741A397C129.key' | apt-key add -
echo "deb https://packages.doppler.com/public/cli/deb/debian any-version main" | tee /etc/apt/sources.list.d/doppler-cli.list
apt-get update
apt-get -y install doppler
doppler --version

Storing MongoDB TLS/SSL Certificates in Doppler

The fastest and easiest way to import the certificates and keys into Doppler is via the CLI, which saves us from manually copying and pasting the values into the Doppler dashboard.

To achieve this, the Doppler CLI will need temporary write access to your account:

Next, create a Doppler project to store the certificates and keys:

doppler projects create mongodb

Then select the production (prd) environment:

doppler setup --project mongodb --config prd

For an actual application, you would create different certificates for each environment (e.g. development and staging) and restrict production secrets access to specific staff members such as the DevSecOps team.

First, add the CA root certificate and key created by mkcert:

doppler secrets set ROOT_CA_CERT="$(cat "$(mkcert -CAROOT)/rootCA.pem")"
doppler secrets set ROOT_CA_KEY="$(cat "$(mkcert -CAROOT)/rootCA-key.pem")"

Then add the server TLS certificate and key:

doppler secrets set MONGO_TLS_CERT="$(cat ./mongo-tls.crt)"
doppler secrets set MONGO_TLS_KEY="$(cat ./mongo-tls.key)"

Next is the combined server certificate and key file. Instead of storing a duplicate of the certificate and key, Doppler secret referencing will be used:

doppler secrets set MONGO_TLS_PEM="$(cat <<'EOF'
${MONGO_TLS_CERT}
${MONGO_TLS_KEY}
EOF
)"

The output from this command may give the impression that Doppler stored the values of the certificate and key, but that's because you're viewing the computed output of that secret.

The actual raw value can be verified by running:

doppler secrets get MONGO_TLS_PEM --raw --plain

Because the certificates and keys are in Doppler, they can be deleted from the server as you'll now access them using the Doppler CLI.

To remove the current certificate and keys, run:

rm "$(mkcert -CAROOT)/rootCA.pem"
rm "$(mkcert -CAROOT)/rootCA-key.pem"
rm mongo-tls*

The final step is revoking the CLI's write access by running:

Access MongoDB TLS/SSL Certificates using the Doppler CLI

Secrets access is restricted to a single config in read-only mode for production environments using a Doppler Service Token.

Create a Service Token for the mongodb project in the Doppler dashboard and copy the value.

Then, back on the MongoDB server terminal, scope the Service Token to the /root directory so only the root user in the /root directory can use the Doppler CLI commands to access secrets:

# Replace 'dp.st.prd.xxx' with your Service Token value
doppler configure set token dp.st.prd.xxx --scope /root

In more permissive environments where any user can access secrets (e.g. a non-root application user), the scope could be set to the root of the file system:

doppler configure set token dp.st.prd.xxxx --scope /

Verify the CLI has access to the MongoDB project's secrets by running:

Imagining that TLS/SSL for MongoDB is being configured for the first time, the Doppler CLI will be used to extract the required certificates.

First, get the combined certificate and key file for the server:

doppler secrets get MONGO_TLS_PEM --plain > /etc/ssl/mongo.tls.pem

Then the CA certificate for the client:

doppler secrets get ROOT_CA_CERT --plain > /etc/ssl/mongo.caroot.crt

If the MongoDB client and server are on different machines, the client machine only needs the CA root certificate to verify the TLS/SSL certificate presented by the server.

Did you notice the root CA private key was not accessed? That's because the root CA private key is only required for generating a new TLS certificate and key for the server.

Providing centralized, encrypted, and accessed controlled storage for critical secrets such as a private key is a primary benefit of using a secrets manager. Without one, it's unclear where to store secrets in line with best-practice security standards.

In other words, Doppler implements the principle of least privilege by restricting who and what machines are allowed to access specific secrets.

Configuring MongoDB Server to Accept TLS/SSL Connections

The MongoDB server can now be configured to accept TLS/SSL connections.

It will need to be decided whether clients can optionally upgrade to a TLS/SSL connection or if only TLS/SSL connections will be accepted. MongoDB provides two logical options: preferTLS and requireTLS.

The recommended approach is to start with preferTLS and move to requireTLS once all clients have upgraded.

To configure MongoDB to accept TLS/SSL connections, a tls section under net: is required in MongoDB's conf file at /etc/mongod.conf:

# etc/mongod.conf
net:
  port: 27017
  # Important! These hostnames match the valid DNS names for the TLS certificate
  bindIp: mongo.doppler.university, localhost 127.0.0.1
  tls:
    mode: preferTLS
    certificateKeyFile: /etc/ssl/mongo.tls.pem

Once /etc/mongod.conf is updated, either relaunch the mongod process or restart the mongod service to apply the changes:

systemctl restart mongod
systemctl status mongod

If you receive an error, check the MongoDB logs (by default at /var/log/mongodb/mongod.log) to determine the cause.

Configuring a MongoDB Client to use TLS/SSL Mode

The final step is configuring your MongoDB client to connect in TLS/SSL mode which requires two TLS parameters:

mongosh \
    --tls \
    --tlsCAFile /etc/ssl/mongo.caroot.crt \
    --quiet \
    --eval 'db.runCommand({ connectionStatus: 1 })'

Well done! You've successfully connected to your MongoDB server using TLS/SSL!

Note that roughly the same method of supplying the relevant TLS/SSL flags applies to any MongoDB client, just with different parameter names.

For example, Mongoose on Node.js:

const mongoose = require('mongoose');

async function connect() {
  try {
    await mongoose.connect('mongodb://localhost:27017/', {
      ssl: true,
      sslValidate: true,
      sslCA: '/etc/ssl/mongo.caroot.crt',
    });

    console.log('[info]: TLS connection established');
  } catch (error) {
    console.log(`[error]: TLS connection failed: ${error}`);
  }
}

connect();

Summary

Awesome work!

Now you know how to configure MongoDB 5 for TLS/SSL on Debian/Ubuntu! And without resorting to hacks such as --tlsAllowInvalidCertificates or --tlsAllowInvalidCertificates, even when using self-signed certificates.

We'd love for you to give Doppler a test drive for securely storing and managing Mongo's TLS/SSL certificates and if you need help, ask a question in the Doppler Community Forum.

Feedback is welcome and you can find me on Twitter or send me an email at .