DEV Community

Complete Guide - Deploying Production-Ready MongoDB Replica Set on AWS

MongoDB is a leading NoSQL database trusted by organizations for its flexibility, scalability, and high availability. This guide walks you through deploying a production-ready MongoDB replica set on AWS using a self-hosted, Dockerized setup. By leveraging AWS’s robust infrastructure, such as EC2 instances, paired with cost-saving strategies like Savings Plans or Reserved Instances, you can achieve a highly available and cost-optimized database solution.

We’ll also compare this self-hosted approach to managed services like MongoDB Atlas, showcasing how you can significantly reduce costs while retaining full control over your database environment. To ensure robust security, we’ll enable authentication and implement proper role-based authorization, safeguarding your data against unauthorized access.

Whether you’re a DevOps professional or a database administrator, this guide provides practical insights and detailed steps for deploying, securing, and optimizing MongoDB replica sets in an AWS environment.

Preparation Phase: Setting Up MongoDB Replica Set Deployment on AWS

To ensure a smooth deployment of your MongoDB replica set, we will use the latest stable Debian release, Bookworm, for compatibility with the latest MongoDB version. Additionally, the Docker engine must be installed and operational. Proper internal hostnames must also be assigned to your EC2 instances for seamless replica set initialization.

Step 1 - Verify the Server Environment

  • Kernel Information:
uname -a
Enter fullscreen mode Exit fullscreen mode

Ensure the system is running the Debian Bookworm kernel.

  • Docker Installation:
docker info
Enter fullscreen mode Exit fullscreen mode

Confirm that Docker is installed and functioning correctly.

  • Resource Availability:
htop
Enter fullscreen mode Exit fullscreen mode

Check the system's resource usage, including CPU and memory, to ensure adequate capacity.

  • Disk Space:
df -h
Enter fullscreen mode Exit fullscreen mode

Verify that sufficient disk space is available for MongoDB data storage.

Step 2 (Optional) - Expand Filesystem

We'll use persistent EBS volume attached to EC2 instances to store MongoDB data. It'll be easier to manage separate EBS volume to backup and restore in case of need.

If you’ve increased the size of a persistent disk attached to your EC2 instance, grow the filesystem to utilize the expanded space:

xfs_growfs /dev/xvdp
Enter fullscreen mode Exit fullscreen mode

Step 3 - Assign Internal Hostnames

Internal hostnames are critical for MongoDB replica set configuration. Assign a unique, descriptive hostname to each machine:

hostnamectl set-hostname <hostname>.internal.company.net
Enter fullscreen mode Exit fullscreen mode

Replace "hostname" with an appropriate identifier for each instance, such as mongo1, mongo2, and mongo3.

Overview of Authentication-Enabled MongoDB Replica Set

Setting up an authentication-enabled MongoDB replica set involves securing both internal communication between replica set members and external client connections. This is achieved through the following configurations:

  • Internal Authentication:
    Members of the replica set use a keyfile for secure communication. This ensures that only trusted nodes can join and exchange data within the replica set.

  • Client Authentication with Role-Based Access Control (RBAC):
    External clients, such as the MongoDB shell or applications, must authenticate using valid credentials. Access is managed through RBAC, which assigns specific roles and permissions to each user.

This dual-layered security setup ensures robust protection for your MongoDB replica set, safeguarding both internal operations and client interactions.

 Deploying MongoDB Replica Set with Keyfile Access Control

Setting up a MongoDB replica set with keyfile-based authentication involves generating a secure keyfile, preparing Docker volumes to persist data and configurations, and setting appropriate file permissions. Additionally, a dedicated MongoDB user must be created for managing the necessary files securely.

Step 1 - Generate the Keyfile

Keyfile authentication ensures secure communication between replica set members. Each mongod instance uses the keyfile as a shared password to authenticate with other members. Only nodes with the correct keyfile can join the replica set.

To generate a secure keyfile:

openssl rand -base64 756 > prod-mongo.pem
chmod 400 prod-mongo.pem
Enter fullscreen mode Exit fullscreen mode
  • openssl rand -base64 756: Generates a 756-byte pseudo-random string encoded in Base64, creating a secure keyfile.
  • chmod 400: Restricts file access to the owner.

Step 2 - Create MongoDB Linux User and Group

On each EC2 instance, create a dedicated Linux user and group with consistent UID and GID for MongoDB:

groupadd -r mongodb && useradd -r -u 999 -g mongodb mongodb
Enter fullscreen mode Exit fullscreen mode

This ensures MongoDB processes, running with UID 999 in Docker containers, have proper access permissions.

Step 3 - Copy the Keyfile to All Replica Set Members

Distribute the prod-mongo.pem keyfile to all servers in the replica set. Ensure file permissions and ownership are correctly set:

chmod 400 prod-mongo.pem  
chown 999:999 prod-mongo.pem
Enter fullscreen mode Exit fullscreen mode

It is required to store the keyfile in the mongo-key Docker volume for use by the containers.

 Step 4 - Create Docker Volumes for Persistent Storage

Prepare Docker volumes to persistently store MongoDB data, configuration files, logs, and the keyfile for each container:

docker volume create mongo-data  
docker volume create mongo-config  
docker volume create mongo-log  
docker volume create mongo-key
Enter fullscreen mode Exit fullscreen mode

Copy the prod-mongo.pem keyfile into the mongo-key volume.

Step 5 - Configure Logging

Alongside security measures, effective logging is essential for monitoring and troubleshooting. Create a mongod.conf file and store it in the mongo-config Docker volume at /var/lib/docker/volumes/mongo-config/.

# mongod.conf

storage:  
  dbPath: /data/db  

systemLog:  
  destination: file  
  logAppend: true  
  path: /var/log/mongodb/mongod.log  

net:  
  port: 27017  
  bindIp: 0.0.0.0  

processManagement:  
  timeZoneInfo: /usr/share/zoneinfo  

Enter fullscreen mode Exit fullscreen mode

Step 6 - Start MongoDB Containers

Start each replica set member as a Docker container, ensuring the --auth and --keyFile options are enabled for secure access and communication.

Run the following command on each EC2 instance:

docker run \
--name aws-mongodb-prod \
-h aws-mongodb-prod \
--restart unless-stopped \
-v mongo-data:/data/db \
-v mongo-config:/etc/mongo-config \
-v mongo-key:/opt \
-v mongo-log:/var/log/mongodb \
-p 27017:27017 \
-d mongo:8.0.4 -f /etc/mongo-config/mongod.conf --keyFile /opt/prod-mongokey.pem --replSet awsProdRepl --auth
Enter fullscreen mode Exit fullscreen mode

Initiating the MongoDB Replica Set

After deploying MongoDB as standalone instances using Docker, the replica set is not yet active because no replica set configuration has been provided. To enable high availability and replication, you must configure and initiate the replica set.

Step 1 - Access the MongoDB Shell

First, exec into the MongoDB container to access the mongo shell:

docker exec -it aws-mongodb-prod bash
Enter fullscreen mode Exit fullscreen mode

Once inside the container, start the MongoDB shell:

mongosh
Enter fullscreen mode Exit fullscreen mode

 Step 2 - Initiate the Replica Set

Now that you have access to the mongo shell, you can initiate the replica set by passing the appropriate configuration. Replace "hostname" with the actual internal hostnames of your replica set members:

rs.initiate({  
   _id: "awsProdRepl",  
   members: [  
      { _id: 0, host: "<hostname>:27017" },  
      { _id: 1, host: "<hostname>:27017" },  
      { _id: 2, host: "<hostname>:27017" }  
   ]  
})  
Enter fullscreen mode Exit fullscreen mode

If successful, the output should include:

{ "ok" : 1 }  
Enter fullscreen mode Exit fullscreen mode

Important Notes:

  • Replica Set Name: The _id field in the configuration must match the replica set name you provided in the Docker --replSet argument (e.g., awsProdRepl).

  • Hostnames: Ensure the host field contains the correct hostnames of each replica set member, along with the MongoDB port (27017).

  • Ordering: The _id values in the members array define the priority of the nodes. Typically, the primary node has the lowest _id.

 Step 3 - Verify the Replica Set

After initiating the replica set, you can verify its status using the following command in the mongo shell:

rs.status()
Enter fullscreen mode Exit fullscreen mode

This will display details about the replica set, including the state of each member.

🎉 Congratulations!
You have successfully deployed and configured a MongoDB replica set with authentication and keyfile-based access control. Your MongoDB deployment is now highly available and ready for production.

 Post-Deployment Actions: Creating Privileged & Restricted Users

After successfully initiating the MongoDB replica set with keyfile-based internal authentication, the next step is to implement user access control. This ensures secure access to your MongoDB deployment, especially for clients like the Mongo shell or application APIs. Below are the steps to create both privileged and restricted users.

Step 1 - Access Mongo Shell

Start by accessing the Mongo shell from within the Docker container:

docker exec -it aws-mongodb-prod bash  
mongosh
Enter fullscreen mode Exit fullscreen mode

 Step 2 - Create a Privileged MongoDB User

For managing MongoDB cluster operations, you'll need a privileged user.

To create a privileged user, switch to the admin database and execute the following command:

use admin  

db.createUser(  
  {  
    user: "<user>",  
    pwd: "<password>",  
    roles: [ { role: "root", db: "admin" } ]  
  }  
)
Enter fullscreen mode Exit fullscreen mode

Replace and with the desired username and password. This user will now have full administrative privileges on the MongoDB cluster

Step 3 - Create a Restricted User for Applications and APIs

Next, create a restricted user for use by applications or APIs that need limited access. In this example, the user will have read and write access only to the user_events database.

use user_events  

db.createUser(  
  {  
    user: "prodUser",  
    pwd: "<password>",  
    roles: [ { role: "readWrite", db: "user_events" } ]  
  }  
)
Enter fullscreen mode Exit fullscreen mode

Replace with the desired password for the prodUser. This user will only have read and write access to the user_events database.

 Step 4 - Verify User Access

To verify that the prodUser has the correct access, authenticate using the newly created user:

use user_events  
db.auth("prodUser", "<password>")  
Enter fullscreen mode Exit fullscreen mode

If successful, you should see the output:

1  
Enter fullscreen mode Exit fullscreen mode

🎉 Congratulations!
You have successfully created the prodUser with restricted access and the privileged user with full administrative rights. Your MongoDB deployment now has proper user access controls, ensuring secure operations and access for different use cases.

Conclusion

Deploying a production-ready MongoDB replica set on AWS using Docker provides a robust, secure, and cost-effective solution compared to managed database services like MongoDB Atlas or AWS DocumentDB. By leveraging AWS EC2 instances and keyfile-based authentication, you achieve high availability with granular control over the deployment. This approach ensures both internal security between replica set members and external security for client connections using role-based access control.

With thoughtful configuration, including persistent Docker volumes, optimized logging, and properly defined user roles, the solution is tailored to meet enterprise requirements. The use of AWS Savings Plans or Reserved Instances further reduces operational costs, offering significant savings over managed database services while maintaining full control over your infrastructure.

This deployment model combines flexibility, performance, and security, making it an excellent choice for businesses looking to balance cost efficiency and operational excellence in their database infrastructure. By following this guide, you now have the tools to set up a scalable, secure, and cost-optimized MongoDB replica set on AWS.

References:

 MongoDB Official Documentation
AWS Resources
Docker Resources

Top comments (0)