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
Ensure the system is running the Debian Bookworm kernel.
- Docker Installation:
docker info
Confirm that Docker is installed and functioning correctly.
- Resource Availability:
htop
Check the system's resource usage, including CPU and memory, to ensure adequate capacity.
- Disk Space:
df -h
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
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
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
- 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
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
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
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
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
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
Once inside the container, start the MongoDB shell:
mongosh
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" }
]
})
If successful, the output should include:
{ "ok" : 1 }
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()
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
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" } ]
}
)
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" } ]
}
)
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>")
If successful, you should see the output:
1
🎉 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
Replica Set Configuration
https://www.mongodb.com/docs/manual/replication/Authentication and Security
https://www.mongodb.com/docs/manual/core/security/Role-Based Access Control
https://www.mongodb.com/docs/manual/core/authorization/
AWS Resources
AWS EC2 Pricing
https://aws.amazon.com/ec2/pricing/Savings Plans
https://aws.amazon.com/savingsplans/Amazon EBS Persistent Storage
https://aws.amazon.com/ebs/
Docker Resources
Docker Volume Management
https://docs.docker.com/storage/volumes/MongoDB Official Docker Image
https://hub.docker.com/_/mongo
Top comments (0)