/ MongoDB

How to create MongoDB Replica Set with Authentication Ubuntu 16.04

How to make a MongoDB replica set

A three member mongodb replica set on three separate hosts with authentication. Also see official docs.

In this tutorial we're putting MongoDB on three different hosts. We generate and use keyfile. The keyfile gets used as part of a Salted Challenge Response Authentication Mechanism (SCRAM) Mechanism.

If the members of your deployment are run on different hosts or if you wish remote clients to connect to your deployment, you must specify --bind_ip or net.bindIp.

First see:

Here's a referral link to create three VPS instances on Vultr which is cheaper than Digital Ocean (select Miami location). Annoyingly, you'll have to create two $2.50 instances by selecting Miami location and one $5 instance because Vultr doesn't allow the account to spin up 3 $2.50 instances...and imho Vultr should make this clearer in their on-boarding.

Enter each instances ip address here and the tutorial will be easier:

1. Create a keyfile

On one of your instances, create a key file.

openssl rand -base64 756 > /var/lib/mongodb/keyfile &&
chmod 400 /var/lib/mongodb/keyfile &&
chown mongodb:mongodb /var/lib/mongodb/keyfile

The chmod is needed because "the keyfile must not have group or world permissions".

2. Copy keyfile to each replica set member

rsync -av /var/lib/mongodb/keyfile [email protected]:/var/lib/mongodb

..and on the third instance

rsync -av /var/lib/mongodb/keyfile [email protected]:/var/lib/mongodb

Note that we're using rsync which allows us to preserve the ownership permissions of the file. You have rsync installed by default on Ubuntu 16.04, woopie!

3. Restart each member of the replica set with access control enabled

By default your MongoDB instances are only binding (listening) on localhost (127.0.0.1) and listening on all interfaces 0.0.0.0 without authentication would be dangerous (you'd be hacked within a day, if not less).

Running mongod with the --keyFile command-line option or the security.keyFile configuration file setting enforces both Internal Authentication and Role-Based Access Control.

Create a mongod config file

Do this on each of your instances.

Stop mongod

sudo service mongod stop

Update a config file

sudo vim /lib/systemd/system/mongod.conf
Enter the following:

Un-comment out the security section, and enter:

security:
  keyFile: /var/lib/mongodb/keyfile

Un-comment-out the replication section, and enter:

replication:
  replSetName: replicaSetOne

Edit the net section by removing bindIp line and update it to:

net:
  bindIpAll: true

Leave the port default to 27017.

Warning: Do not set bindIpAll: true without setting a keyFile. Doing so would leave your replica set open on all interfaces without authentication!

Start mongod with authentication

sudo mongod --config /var/lib/mongodb/config&

Because we're passing in the config file, and we've specified the path of a keyFile, mongod will not enforce both Internal Authentication and Role-Based Access Control which is doesn't do by default.

Complete the above steps for each instance.

4. Connect to a member of the replica set over the localhost interface.

Connect to your first mongo instance via ssh. We're going to create a user on the initial instance.

$ mongo <Press ENTER>

This will give you the mongo shell.

The localhost interface is only available since no users have been created for the deployment. The localhost interface closes after the creation of the first user.

5. Initiate the replica set.

Finally!

Only run this on one mondod instance!

rs.initiate(
  {
    _id : 'replicaSetOne',
    members: [
      { _id : 0, host : "ip-of-instance-1:27017" },
      { _id : 1, host : "ip-of-instance-2:27017" },
      { _id : 2, host : "ip-of-instance-3:27017" }
    ]
  }
)

MongoDB will then try and:

  • Communicate to all members of the replica set
  • Attempt a dry run an election
  • Run an election to select a primary node out of the three instances. Cool!

Run rs.status() from the mongo shell if you want to find out which of your nodes was selected as primary.

6. Create the user administrator

IMPORTANT
After you create the first user, the localhost exception is no longer available.

The first user must have privileges to create other users, such as a user with the userAdminAnyDatabase. This ensures that you can create additional users after the Localhost Exception closes.

If at least one user does not have privileges to create users, once the localhost exception closes you may be unable to create or modify users with new privileges, and therefore unable to access necessary operations!

You **must** be connected to the primary to create users. Remember, run rs.status() from the mongo shell to find out which instance is the primary.

Choose a username and strong password. Then, from the mongo shell on your primary run:

admin = db.getSiblingDB("admin")
admin.createUser(
  {
    user: "admin",
    pwd: "changeme1",
    roles: [ { role: "userAdminAnyDatabase", db: "admin" } ]
  }
)

You should see "Successfully added user" as the response.

Verify your admin user

Exit out of the mongo sell (Ctrl+c).

Log into your mongo instance:

$ mongo

Try and show all databases:

show dbs

This should fail.

Authenticate:

db.getSiblingDB("admin", "password");
show dbs

The above should succeed showing you three default databases:

admin   0.000GB
config  0.000GB
local   0.000GB

Optional

You may want to now