Quite recently, I decided to jump ship to Mongodb after years of web development using MySQL database. The one thing that attracted me the most to Mongodb is that you can start pushing data to the database without first defining a schema. This means you can spend more time iterating app code without lifting a finger managing the database schema.

Mongodb is a very mature platform with about 10 years in development and is being used by big name companies that handle data for millions of customers everyday. It has a huge community behind it and is currently ranked fourth as the most popular database.

This post is an extended getting start guide for ** Ubuntu & Linux Mint** users on how to properly set up a ** secure Mongodb server** and how to solve common configuration issues. The information provided here is as a result of knowledge gained through researching the official doc guides and experimenting to validate the concepts learned.

I've provided this knowledge here to make it easy for beginners to transition to the Mongo database on the Linux platform.

Before installing Mongodb, make sure you have purged all previous versions of mongodb. The mongodb version that is currently available in the official ubuntu repositories is outdated and has an issue where large amounts of disk space are consumed by its journal. To purge the outdated version, just execute the following:

sudo apt-get purge mongo* sudo rm -R /var/lib/mongo

Next, you'll need to add the official mongodb repository that contains the latest community version.

sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 0C49F3730359A14518585931BC711F9BA15703C6 echo "deb [ arch=amd64,arm64 ] http://repo.mongodb.org/apt/ubuntu xenial/mongodb-org/3.4 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-3.4.list echo "deb [ arch=amd64 or Linux Mint 17] http://repo.mongodb.org/apt/ubuntu trusty/mongodb-org/3.4 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-3.4.list echo "deb [ arch=amd64 ] http://repo.mongodb.org/apt/ubuntu precise/mongodb-org/3.4 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-3.4.list sudo apt-get update

Once the repository cache is updated, run the install command:

sudo apt-get install -y mongodb-org

Ensure you typed mongodb-org, and not mongodb, otherwise you'll install the old version.

The next obvious step after finishing installation is to start the mongo shell, right?

Unfortunately, you will encounter connection errors. This is because Mongodb does not start automatically on boot or after installation. To fix this, run the following commands that will start the mongodb service and enable it to auto-start on boot.

sudo systemctl start mongod sudo systemctl enable mongod

To confirm that mongodb server has successfully started, execute either of the following commands:

netstat -plntu | grep 27017 // Check service status sudo service mongod status

27017 is the default port used by Mongodb server to listen for connections. I prefer the second command for checking status as it displays more information such as if its enabled to run on boot and if there are errors in its configuration file if they are any.

Now that the Mongodb service is running, you can now use mongo shell to access the server by executing mongo in the terminal.

The mongo shell starts successfully, however, you get hit by several warning messages. Despite the warnings, you can create new databases and add documents to the collections. However, I recommend that we first resolve the warning messages.

Let's start with these warning messages that are in regards to performance:

** WARNING: /sys/kernel/mm/transparent_hugepage/enabled is 'always' . ** We suggest setting it to 'never' ** WARNING: /sys/kernel/mm/transparent_hugepage/defrag is 'always' . ** We suggest setting it to 'never'

According to the official docs, Mongo recommends that you disable a Linux Memory Management feature called Transparent Huge Pages as it causes databases workloads to perform poorly.

To fix this, create a new file at /etc/init.d/disable-transparent-hugepages and paste this content. After saving the file, execute the following commands:

sudo chmod 755 /etc/init.d/disable-transparent-hugepages sudo update-rc.d disable-transparent-hugepages defaults

Since the above commands affect the Linux kernel, you'll have to restart the entire machine for the changes to take effect.

After restarting the machine, simply type mongo and you should connect to the mongodb server. The shell no longer displays the warning messages regarding the 'transparent-hugepages.

However, there are two more warnings that still need to be solved which we shall look at in the next step.

By default, mongodb is insecure. The reason for this, I believe, is to make it easy for new users to try out Mongodb comfortably, and hence increase adoption. Security is left at the hands of the users to implement when they are ready.

When you access the mongo shell like this...

mongo

...you get logged in as default user. In this account you are free to perform any CRUD operation you feel like provided authentication hasn't been set up. Lets try some basic commands in the mongo shell to confirm this:

use twist db . users . insert ( { name : "mike" , email : "mike@example.com" } ) db . users . find ( )

All the above operations should execute with no problem whatsoever. Now lets proceed with securing our mongodb server in order to protect our data from anonymous users.

First, we need to turn on the 'auth' setting for mongodb. There are several ways of doing it, but the method I prefer is by editing the /etc/mongod.conf file.

Using administrative privileges, edit the file /etc/mongod.conf using your favorite text editor:

sudo nano /etc/mongod.conf sudo pluma /etc/mongod.conf sudo xed /etc/mongod.conf

Look for the commented out section called security and edit as follows:

security : authorization : enabled

Save the changes above, close the file and restart mongodb service for the changes to take effect.

sudo service mongod restart sudo service mongod status mongo

You'll notice that the remaining warning messages have now disappeared. Mongodb is now running in auth mode, therefore the 'access control' warning should disappear. The 'XFS file system' warning too also disappears mysteriously after enabling authentication. Currently, I don't know why this happens. However, I'll be sure to use XFS file system when installing Mongodb in production servers since it comes highly recommended.

Let's now confirm that default users can't read or write to any database. Inside the mongo shell, execute the following:

use twist db . users . insert ( { name : "maggie" , email : "maggie@example.com" } )

As expected, the default user is prevented from accessing documents from any collection. Now we can proceed with creating an authenticated user.

The way authentication works in Mongodb is that you need to save user accounts in a special database called admin. Within this database you will need to create an admin user who will be responsible for creating new user accounts and assigning roles.

As an admin user, you can create more users within the admin database, or you can switch to a new database and create them there. However, during login authentication, you will have to specify which database is holding the user credentials you want to login.

As demonstrated earlier, the default user currently has no privileges. However, since no users have been created, an exemption will be made to allow the default user to create an admin user.

use admin db . createUser ( { user : "admin" , pwd : "abc123" , roles : [ { role : "userAdminAnyDatabase" , db : "admin" } ] } ) exit

After the admin user has been created, the default user account won't be allowed again to create any user.

To log in as the admin user, do...

mongo -u admin --authenticationDatabase admin -p

... you will be prompted to enter the password for the newly created admin user. The flag --authenticationDatabase is used to pass the name of the database holding user credentials.

As the new mongodb admin, you can now create new users for other databases. Let's create one for the database twist:

use admin db . createUser ( { user : "twister" , pwd : "xyz123" , roles : [ { role : "readWrite" , db : "twist" } ] } )

Exit the mongo shell and now login back with the new user credentials within the shell.

mongo -u twister --authenticationDatabase admin -p

Enter the password as prompted. Next, switch to the twist database and add some data.

use twist show collections db . users . insert ( { name : "maggie" , email : "maggie@example.com" } ) db . users . find ( )

As expected you now have access to read and write capability in the twist database. As a simple exercise, try switching to another database, say library and try adding documents and see what happens.

As expected you will get authorization errors informing you that you lack the permission to perform the operation.

If you would like to update a user account, say change password, you normally have to logout and login as the admin user to be able to do that. Alternatively, you can do this while still logged in as another user:

use admin db . auth ( "admin" , "abc123" ) db . updateUser ( "twister" , { pwd : "zyx123" } ) exit

You will need to exit the mongo shell in order for the password change to take effect. You can now log in back again using either mongo shell parameters or log in as default user then use db.auth() function to login as 'twister'. When using db.auth() function, make sure you switch to the admin database first since this is where the user accounts are stored. When it returns '1', it means you are authenticated and you can now switch to the twist database to perform some data manipulation.

So far you have learned how to secure your Mongodb server. You can go over the official security checklist if you want to further enhance your database security.

So far, I have shown you how to insert data. Here are other common operations that you need to learn.

Insert Documents

Lets first create a new collection with data that we shall manipulate with using other operations. But before we get started, here are some naming conventions suggested for Mongodb collections:

Use lower case names

Use plural

Avoid word separators such as '-' or '_'

Use dot notation to indicate relation e.g. users users.pagevisits



Lets now create a collection called pets and populate it with data. Below you will see the different ways of inserting data into a collection.

db . pets . insert ( { name : "Fluffy" , owner : "Harold" , speices : "cat" , sex : "F" , birth : "2013-02-04" } ) db . pets . insertOne ( { name : "Claws" , owner : "Gwen" , speices : "cat" , sex : "M" , birth : "2014-03-17" } ) db . pets . insert ( [ { name : "Buffy" , owner : "Harold" , speices : "dog" , sex : "F" , birth : "2009-05-13" } , { name : "Fang" , owner : "Benny" , speices : "dog" , sex : "M" , birth : "2010-08-27" } , { name : "Bowser" , owner : "Diane" , speices : "dog" , sex : "M" , birth : "2014-08-31" } ] ) db . pets . insertMany ( [ { name : "Chirpy" , owner : "Gwen" , speices : "bird" , sex : "F" , birth : "2009-09-11" } , { name : "Whistler" , owner : "Gwen" , speices : "bird" , sex : "M" , birth : "2007-12-09" } , { name : "Slim" , owner : "Benny" , speices : "snake" , sex : "M" , birth : "2016-04-29" } ] ) db . pets . find ( ) db . pets . find ( ) . count ( )

Query

Executing queries in mongodb is fairly simple. If you are familiar with SQL, then you'll understand the following operations.

db . pets . find ( ) db . pets . find ( { owner : "Gwen" } ) db . pets . find ( { sex : "M" } ) db . pets . find ( { sex : "M" , speices : "dog" } ) db . pets . find ( { $or : [ { speices : "cat" , sex : "F" } , { speices : "bird" } ] } ) db . pets . find ( { birth : { $gt : "2010-01-01" } } )

Now that there is some data to manipulate, lets do an update operation

db . pets . update ( { name : "Slim" } , { $ set : { owner : "Ben" , speices : "Lizard" } } ) db . pets . find ( )

In the above update() function, I have provided 2 parameters

filter (similar to WHERE clause)

update data

You can also provide a third parameter called options. Examples of options are:

{ multi:true } allows update operation to affect more than one matching rows

allows update operation to affect more than one matching rows { upsert:true} if the filter specified doesn't match a document, a new document is created

There are more variations of the update() function you can have a look at them here

Remove Documents

Let's first create a new collection for demonstration

db . jets . insert ( { name : "Lockheed Martin F-22" } )

The remove() function, just like the SQL 'DELETE' command, is a dangerous function that should be handled with care. Simply executing something like this...

db . jets . remove ( { } )

... will delete all documents in a collection. Once a document is deleted, it doesn't go to trash, it goes away forever. There is no undo operation or rollback function you can use to recover the deleted data. If you did this accidentally on a production database, the ramifications can be pretty serious. This happened at work to a colleague of mine. Luckily he was able to restore the data from the daily backups.

However, if you really wanted to delete all documents from a collection, this is the recommended way

show collections db . jets . drop ( ) show collections

By using drop() function, the indexes get deleted too and completely gets rid of the collection. Using just remove({}) will just delete the documents and retain the indexes, hence the collection will still exist despite not containing any data.

Now , let's delete a single document from the pets collection

db . pets . find ( ) db . pets . remove ( { name : "Bowser" } ) db . pets . find ( )

The remove() function works as expected, however, its still risky as it will delete all documents matching the filter. A better way is to use the deleteOne() function and pass it the _id value of a document. This way you will be 100% sure that you are deleting the correct document.

db . pets . find ( ) db . pets . deleteOne ( { _id : ObjectId ( "58b51bfb54deb7f848d5310a" ) } ) db . pets . find ( )

Mongodb doesn't come packaged with a GUI administration interface, however there are plenty of third-party GUI interfaces available. Some are commercial, and some are open-source. They are all listed on the Mongo docs site. They don't all provide the same features, you may have to dig a bit deeper to determine if the tool meets your project requirements.

I can't say for sure which is the most popular Mongo GUI tool available, but I have found that RoboMongo and Studio-3T(formerly MongoChef) seem to be the most popular. Personally, I would recommend Studio-3T as it does appear to provide all features available in RoboMongo plus a lot more including user administration. Studio-3T also comes in three flavours, you can view the comparison here.

For this guide I'll just show you how to install Studio-3T. Head over to the site and click the Download for Linux button. After download is complete, use the extraction tool to uncompress it in your Downloads folder.

Open your terminal and navigate to your downloads folder. Move the robomongo folder to the /opt folder. You'll probably need root permission to do that.

sudo mv studio-3t-5.0.1-linux-x64/ /opt/studio3t/ cd /opt/studio-3t sudo wget http://cdn-web.3t.io/wp-content/uploads/logo_pro_256.png cd /usr/bin sudo ln -s /opt/studio3t/bin/studio-3t.sh studio3t

Let's create a menu entry for Studio-3T using the menu editor. Just place your mouse cursor over the your Desktop Menu and right-click, select Edit Menus. Then select Programming. Click on new item and enter the path to Studio-3t executable. Also select the icon that we downloaded in the /opt/studio3t folder.

Now that we have finished installing, lets start the application. You can either start it from the menu or in the terminal. Once the app starts, you will be given three options. You can choose either the free version or the 14 day pro trial.

After you have chosen you will be provided with the connection dialogue.

Let's first create a connection for the admin user, then the twister user. Click New Connection, specify 'Admin' as the name of connection. Make sure sure connection type is set to 'Direct Connection'. Click the Authentication Tab, under mode select Basic, then provide the admin credentials. For the authentication DB, set it to 'admin'. Click save to close the dialogue.

To create a connection for the user 'twister', just repeat the same steps. The authentication DB will remain 'admin'. When you connect as a certain user, Studio-3T will only show you databases that you have access to. After you have saved the new connection, you can go ahead and connect to both 'Admin' and 'Twist'.

As you can see, the Admin user can see all the databases but the Twist user can only see admin & twist database. Although the Admin user can see twist database, the collections are not accessible. Let's see if we can correct this.

Right click on the admin database under Admin connection, then choose manage users. Select the admin user, then click on Grant Roles Button. Choose 'readWriteAnyDatabase' then click Grant.

Right click on th Admin connection and select Refresh All. Now under the Admin connection, access pets data.

Studio 3T has quite a list of features that are beyond the scope of this guide. I'll leave you to it exploring both Mongodb and the Studio 3T tool.

I hope you have enjoyed learning how to setup and configure a secure Mongodb database. You have simply scratched the surface of the many possibilities and great projects you can come up with this awesome database platform. Despite what you have learned today, you will still need to do a bit more research on how to become an effective Mongodb user.

Like this article? Follow @myxsys on Twitter