
MongoDB is a popular NoSQL database, widely used for its flexibility and scalability. This guide demonstrates how to set up a 3-node MongoDB replica set with a Primary-Secondary-Arbiter (PSA) configuration on Ubuntu 24.04 LTS, securing node communication with Let's Encrypt TLS certificates.
Prerequisites
Three Ubuntu 24.04 LTS servers, each with a unique hostname:
mongo-01.db.domain.commongo-02.db.domain.commongo-03.db.domain.com
All hostnames must resolve correctly via DNS (A and/or AAAA records) to their respective servers for proper replica set functionality.
1. Initial Server Setup
Log into each server and update packages:
sudo apt update && sudo apt dist-upgrade -y
Create a non-root user with sudo privileges:
adduser mongoadm
adduser mongoadm sudo
2. Install MongoDB 8.0
On each server, perform the following:
- Install prerequisites:
sudo apt-get install gnupg curl
- Import MongoDB public GPG key and add the official MongoDB repository:
curl -fsSL https://www.mongodb.org/static/pgp/server-8.0.asc | sudo gpg -o /usr/share/keyrings/mongodb-server-8.0.gpg --dearmor
echo "deb [ arch=amd64,arm64 signed-by=/usr/share/keyrings/mongodb-server-8.0.gpg ] https://repo.mongodb.org/apt/ubuntu noble/mongodb-org/8.2 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-8.2.list
- Update and install MongoDB:
sudo apt-get update && sudo apt-get install -y mongodb-org
3. Setup Key File for Internal Authentication
Generate a key file for encrypted node-to-node communication:
sudo mkdir /etc/mongodb
sudo openssl rand -base64 756 | sudo tee /etc/mongodb/mongo.key
sudo chmod 600 /etc/mongodb/mongo.key
sudo chown mongodb:mongodb /etc/mongodb/mongo.key
Important: Copy this key file identically to all three servers with identical permissions.
4. Install and Configure Let's Encrypt Certbot TLS
Install Certbot and your required DNS plugin to obtain certificates for each node's hostname.
Create a renewal hook script at /etc/letsencrypt/renewal-hooks/deploy/reload-mongodb.sh:
sudo tee /etc/letsencrypt/renewal-hooks/deploy/reload-mongodb.sh > /dev/null <<'EOF'
#!/bin/bash
cat /etc/letsencrypt/live/YOUR_HOST_NAME/fullchain.pem \
/etc/letsencrypt/live/YOUR_HOST_NAME/privkey.pem \
> /etc/mongodb/mongodb.pem
chown mongodb:mongodb /etc/mongodb/mongodb.pem
chmod 600 /etc/mongodb/mongodb.pem
# Reload TLS certs in running mongod instances without restart
ps aux | grep mongod | grep -v grep | awk '{print $2}' | xargs -I{} kill -SIGUSR2 {}
EOF
sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/reload-mongodb.sh
Replace YOUR_HOST_NAME with each server's hostname.
We will execute /etc/letsencrypt/renewal-hooks/deploy/reload-mongodb.sh only once on each servers to generate /etc/mongodb/mongodb.pem
5. MongoDB Configuration
Replace the default config at /etc/mongod.conf on all nodes (do not start services yet):
storage:
dbPath: /var/lib/mongodb
systemLog:
destination: file
logAppend: true
path: /var/log/mongodb/mongod.log
net:
port: 27017
bindIp: localhost,mongo-01.db.domain.com
ipv6: true
tls:
mode: requireTLS
certificateKeyFile: /etc/mongodb/mongodb.pem
allowConnectionsWithoutCertificates: true
allowInvalidCertificates: false
processManagement:
timeZoneInfo: /usr/share/zoneinfo
security:
authorization: enabled
clusterAuthMode: keyFile
keyFile: /etc/mongodb/mongo.key
javascriptEnabled: false
replication:
replSetName: rs0
setParameter:
tlsUseSystemCA: true
Note: Update bindIp with each node's respective hostname.
6. Initialize the Replica Set (First Node Only)
On the first node, temporarily comment out the security and replication sections in /etc/mongod.conf, then start the service:
sudo systemctl start mongod.service
Connect to the first node:
mongosh --host mongo-01.db.domain.com --tls
Create the root admin user:
use admin
db.createUser({
user: "admin",
pwd: "SafeASCIIpassword123!",
roles: ["root"]
})
Exit the shell and uncomment the security and replication sections. Restart MongoDB:
sudo systemctl restart mongod.service
7. Start Services on Remaining Nodes
Start MongoDB on nodes 2 and 3:
sudo systemctl start mongod.service
Verify all services are active:
sudo systemctl status mongod.service
8. Configure the Replica Set
Log back into the first node as the admin user:
mongosh --host mongo-01.db.domain.com --tls --authenticationDatabase admin -u admin -p
Initialize the replica set:
rs.initiate({
_id: "rs0",
members: [
{ _id: 0, host: "mongo-01.db.domain.com:27017" },
{ _id: 1, host: "mongo-02.db.domain.com:27017" },
{ _id: 2, host: "mongo-03.db.domain.com:27017" }
]
})
You should receive { ok: 1 } upon success. After a few seconds, one node will be elected as primary.
9. Configure MongoDB Atlas-Like Connection URL (Optional)
To enable connection strings like mongodb+srv://username:[email protected]/database, configure DNS records:
TXT Record on
mongo.db.domain.com:- Content:
authSource=admin&replicaSet=rs0
- Content:
SRV Records on
_mongodb._tcp.mongo.db.domain.com:
| Priority | Weight | Port | Target |
|---|---|---|---|
| 0 | 0 | 27017 | mongo-01.db.domain.com |
| 0 | 0 | 27017 | mongo-02.db.domain.com |
| 0 | 0 | 27017 | mongo-03.db.domain.com |
Conclusion
Your MongoDB PSA replica set is now fully operational with TLS encryption and automatic certificate renewal!
Note: The primary purpose of this post is for my future reference. AI was used to format the post and generate the thumbnail.