How to make a mongodb cluster with a hidden replica and secure with SSL

While hosted mongodb solutions exist, they aren’t for everyone. Scaling, security, and reliability is just one tutorial away.

Set up your primary server

In this example, the primary is Start by creating a data directory on a mounted volume. Remember, WiredTiger has the best performance on XFS.

apt update && apt upgrade

Install mongodb:

wget -qO - | sudo apt-key add -
echo "deb [ arch=amd64 ] bionic/mongodb-org/4.2 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-4.2.list
apt update
apt install -y mongodb-org

Create a data directory

mkdir /mnt/db/mongodb
chown -R mongodb:mongodb /mnt/db/mongodb

Create a bare bones configuration just to get it functioning. Edit /etc/mongod.conf.

  dbPath: /mnt/db/mongodb
  replSetName: rs0
  oplogSizeMB: 100

dbPath is now set to the path you made. makes your server accessible via the web.

Restart mongod and register it with systemctl to start when your server boots:

service mongod restart
systemctl enable mongod

Create the admin user

In this section, you will configure your database to only accept username & password authentication. Create an admin user:

use local
use admin

  user: "admin",
  pwd: "password",
  roles: [ { role: "root", db: "admin" } ]

Edit /etc/mongod.conf again! Specify a security policy. This one is absolutely required if your server is bound to! Once done, you must authenticate every time (even through localhost!)

  authorization: "enabled"

Restart mongod:

systemctl restart mongod
systemctl status mongod

Try it out! You want to make sure you can log in!

mongo mongodb://

Enable SSL

First, you need to have a minimal web server running to connect to LetsEncrypt. Install NGINX and Certbot:

apt install nginx
add-apt-repository ppa:certbot/certbot
apt update
apt install software-properties-common python-certbot-nginx

Create the certificate for this host:

certbot --nginx -d

Set up automatic creation of the SSL certificate:

cd ~

Paste in this script:


certbot renew
newestFull=$(ls -v /etc/letsencrypt/archive/"$DOMAIN"/fullchain*.pem | tail -n 1)
newestPriv=$(ls -v /etc/letsencrypt/archive/"$DOMAIN"/privkey*.pem | tail -n 1)
cat {$newestFull,$newestPriv} | tee /etc/ssl/mongo.pem
chmod 600 /etc/ssl/mongo.pem
chown mongodb:mongodb /etc/ssl/mongo.pem
service mongod restart

Make it executable

chmod +x

Enable SSL in the mongo server configuration in /etc/mongod.conf by adding this under the net declaration:

    mode: requireTLS
    certificateKeyFile: /etc/ssl/mongo.pem

Run the script for the first time:


Add the script as a cron job with crontab -e

0 0 1 * *

Reboot, and now you can connect through SSL. Note that the URL now contains the ssl param:

mongo mongodb://

Adding a secondary

Follow the same process above to get mongo installed and configured, switching out with your secondary’s hostname.

All nodes in a cluster must share the same secret key– that’s how they authenticate with each other. We’ll make that file next. Do this step on both servers!

echo "your-secret-key" > /data/key

Edit /etc/mongod.conf

> security:
>  keyFile: /data/key

Then restart the mongo server again

service mongod restart

Next, log back in to the mongo shell.

mongo mongodb://

The following mongo shell script is to have a secondary that your BI tools could beat up without affecting your primary. That’s why hidden is set to 1 and not 0. This ensures that the node can not become the primary in the event of a primary malfunction.

rs.add({host: "", priority: 0, votes: 0, hidden: 1})

If you want to provide more hosts for your app to connect to, you instead want to make them visible. The minimum number of nodes in a cluster jumps from 1 straight to 3, otherwise a cluster of 2 can not perform a vote to decide which node will become primary.