Setting up a MongoDB replica set on Ubuntu 20.04
What is a replica set?
A MongoDB replica set is a group of mongod instances that hold the same data. It gives you high availability, redundancy, and an easy path to scale reads. If a node fails, an automatic failover elects a new primary and the cluster keeps serving traffic.
Architecture is simple: at any moment exactly one node is the primary (accepts writes), and the rest are secondaries (replicate from the primary, can serve reads). A replica set should have at least 3 nodes so a majority can elect a primary even if one is down.
For a single-node MongoDB install on Ubuntu, see my other post. This one assumes you already have it on each box.
What you'll need
- 3 Ubuntu 20.04 servers
- MongoDB installed on each (standalone, from the post above)
- Minimum 4 GB RAM, 2 CPU cores per node
- Network connectivity between the nodes on MongoDB's port (27017 by default)
Configure each node
The key edits in /etc/mongod.conf: bind the right IP and tell MongoDB it's part of a replica set.
In this guide:
node 1 = 192.168.159.135node 2 = 192.168.159.136node 3 = 192.168.159.137Edit /etc/mongod.conf on each node:
sudo vi /etc/mongod.confNode 1 — bind its own IP, set the replica set name:
net: port: 27017 bindIp: 192.168.159.135replication: replSetName: "rs1"Node 2 — same thing, but its own IP:
net: port: 27017 bindIp: 192.168.159.136replication: replSetName: "rs1"Node 3:
net: port: 27017 bindIp: 192.168.159.137replication: replSetName: "rs1"Restart MongoDB on every node so the changes take effect:
sudo systemctl restart mongodInitiate the replica set
Connect to node 1 with mongosh:
mongosh --host 192.168.159.135Initiate the replica set:
rs.initiate()Sample output:
{ info2: 'no configuration specified. Using a default configuration for the set', me: '192.168.159.135:27017', ok: 1, ...}Now add the other two nodes:
rs.add("192.168.159.136")rs.add("192.168.159.137")Each call returns { ok: 1, ... }. After this, MongoDB runs an election internally and picks a primary.
Verify the cluster
rs.status()You'll get a long object back. The interesting bits are under members[] — each node has a stateStr (PRIMARY or SECONDARY) and a health: 1. A healthy 3-node replica set looks like:
members: [ { _id: 0, name: '192.168.159.135:27017', health: 1, stateStr: 'PRIMARY', ... }, { _id: 1, name: '192.168.159.136:27017', health: 1, stateStr: 'SECONDARY', ... }, { _id: 2, name: '192.168.159.137:27017', health: 1, stateStr: 'SECONDARY', ... }]That's it — you've got a 3-node replica set. Writes go to the primary; reads can be routed to the primary or any secondary.
Smoke test: insert and read across the set
On the primary, insert a document:
use linuxpedidb.linuxpedi.insertOne({ "name": "MertYavuz" })Connect to one of the secondaries:
mongosh --host 192.168.159.136Reads on a secondary are disabled by default — you need to opt in for the session:
rs.secondaryOk()// ordb.getMongo().setReadPref('secondaryPreferred')Then query:
use linuxpedidb.linuxpedi.find().pretty()You should see the document you inserted on the primary. Replication's working.
A few production-readiness notes
This guide gets you a working replica set, but for real workloads also think about:
-
Auth: enable
security.authorization: enabledinmongod.confand create proper users. This setup is wide open by default. -
Keyfile or x.509 between members: required once auth is on, so the nodes can authenticate to each other.
-
Backups: replication is not a backup. Use
mongodumpor filesystem snapshots on a schedule. -
Monitoring: at least track replication lag, primary elections, and disk usage.
-
Connection strings: drivers expect a replica-set-aware URI like:
jsmongodb://node1:27017,node2:27017,node3:27017/?replicaSet=rs1Don't point clients at a single node — they need the full list to handle failover gracefully.