DEV Community

Jack Keck
Jack Keck

Posted on • Edited on

Setting up MongoDB Locally

A SIMPLE MONGO DATABASE

I've used MongoDB quite a bit and wanted to share how I usually approach building a quick instance locally. If you know me, you know that I enjoy when things are broken down Barney-style.

gif of Barney the purple dinosaur singing "I love you, you love me..."

So this should be easy to follow whether you're new to all this or a seasoned vet. With that said, we'll walk through:

I relied on MongoDB's installation instructions and their core documentation for the installation. Additional sources are noted inline as appropriate. If at any time you need to start over from scratch, you can use the Helpful Scraps section at the bottom. There are commands to clean up the database as well as how to perform a clean uninstall. Additionally, you can find the specifics of my local setup below.



MY LOCALHOST

In the interest of transparency and sanity when debugging, these are the relevant details of my local environment.

Local Setup
OS: macOS Mojave 10.14.4
HOMEBREW: Homebrew 2.1.9
GIT: git version 2.22.0
MONGODB: MongoDB Community 4.0


INSTALL

gif of mongodb being installed in a terminal
Installing and starting MongoDB is simple. Open your terminal and use the below commands:

brew tap mongodb/brew
brew install mongodb-community@4.0 
mongod --config /usr/local/etc/mongod.conf &
Enter fullscreen mode Exit fullscreen mode

Homebrew's tap command creates a shallow clone of MongoDB's formulae. This means that it adds a reference/link to that GitHub repository in your Homebrew for future use.

We run install knowing that it is using the MongoDB formulae we specified before. In addition to the MongoDB binaries, Homebrew creates your configuration file (mongod.conf) and necessary paths.

Despite using Homebrew for installation, we will not be using their services command. This is because brew services uses launchctl's plist files. Consequently, it does not pull in a fresh copy of your configuration file on each startup.

Instead, we're directly invoking mongod, MongoDB's parent process, with a reference to our 'mongod.conf' using the --config flag. In Linux, the & is a control operator. It allows your shell to manage the command(s) issued in the background; this outputs the process identifier (PID). If you want to verify, you can use jobs -l to print the process running background and its PID. You can also use ps (with a | grep mongo* in this case).



LOAD

gif of mongodb being loaded with a json dataset in a terminal
Now that we've installed and started our MongoDB, we need to populate it with data. We'll be using the dataset from the mongo-pokemon repository provided by ALT-WDI. To keep this simple, I've forked this repo and trimmed it down to the single dataset file we'll need.

Make sure you have started your MongoDB instance then open your terminal, navigate to a clean directory, and run the following:

git clone https://github.com/jackkeck/pokemonDataSet
cd pokemonDataSet
mongoimport -d pokemon -c pokemons --jsonArray < pokemon.json
mongo
show dbs
use pokemon
show collections
db.pokemons.find().pretty()
Enter fullscreen mode Exit fullscreen mode

Git's clone command will copy my forked repository to your local machine. Once it's downloaded, you use cd to drop down into the repository.

MongoDB's mongoimport command allows us to bulk load data. In this case, we're using flags to accomplish a few things. We're creating a database called "pokemon" using the -d flag. We're creating a collection called "pokemons" using the -c flag. We're telling the import command to treat the data file as a JSON Array. Finally, we're specifying pokemon.json as our import file.

MongoDB provides a Javascript-based shell through it's mongo command. Once we pop a shell, we're using the show dbs command to list all available databases to verify we've created the pokemon database. We use the pokemon database then list its collections using show collections. We can see the "pokemons" collection was created so we use db.pokemons.find().pretty() to check that the data was imported. I like to add the .pretty() method to make the output easier to read. For those of you who are familiar with relational databases and sql, this is the mongo equivalent of select * from pokemon.pokemons.



SECURITY

MongoDB and the security community have had an interesting relationship. Up until version 3.6, MongoDB used to allow any connection on port 27017 by default (meaning if you weren't behind a firewall, anyone could pop into your database). Even now, it still doesn't ship with any kind of access control or authentication enabled by default unless you have an enterprise-licensed version 💰. This section will walk through some basic steps we can take to protect our instance.



ROLE-BASED ACCESS CONTROL

As a rule, we should try to adhere to the principle of least privilege (PoLP). By applying this principle now, we're ensuring that we build our application with a level of access that we'll have in a production environment.

MongoDB uses role-based access control (RBAC) to allow for the governance (er.... control) of access. There is a ton of material available on what RBAC is. If you're interested, here is the definition from David Ferraiolo's and Richard Kuhn's conference paper "Role-Based Access Controls":

A role-based access control (RBAC) policy bases access control decisions on the functions a user is allowed to perform within an organization. The users cannot pass access permissions on to other users at their discretion.

MongoDB does not ship with this enabled by default. In order to enable this, we need to:

  1. Create a superuser.
  2. Enable authorization in our mongod.conf.
  3. Create a user with Read and Write (RW) access, but only to the pokemon database.

CREATE ADMIN USER

gif of creating an admin user for mongodb in terminal
A superuser has access to do anything and everything. You've been operating with this access this whole time by default. So let's create a dedicated admin user with a password. In your terminal, open a mongo shell and run the following:

use admin

db.createUser(
  { 
    user: "admin",  
    pwd: "doNotEatThat", 
    roles: 
      [
        {role: "userAdminAnyDatabase", db: "admin"},
        {role: "dbAdminAnyDatabase",   db: "admin"},
        {role: "readWriteAnyDatabase", db: "admin"}
      ]
  }
)
Enter fullscreen mode Exit fullscreen mode


ENABLE AUTHORIZATION

gif of editing mongodb configuration to enable security authorization
Once the admin user is created, we need to enable the security.authorization setting in MongoDB.

  1. Stop MongoDB Run pkill -f mongod to stop the database. You can confirm it has stopped using jobs -l.
  2. Update mongod.conf I used sudo vi. For reference, use your arrow keys to get to the end of the file, press "i" on the keyboard to type, add the security block below, press "esc" on the keyboard, then type ":wq" then hit enter to save and exit.
/:~$ sudo vi /usr/local/etc/mongod.conf

systemLog:
  destination: file
  path: /usr/local/var/log/mongodb/mongo.log
  logAppend: true
storage:
  dbPath: /usr/local/var/mongodb
net:
  bindIp: 127.0.0.1
security:
   authorization: enabled
Enter fullscreen mode Exit fullscreen mode

CREATE BASIC USER

gif of creating a basic user for mongodb in terminal
The basic user will have read and write access for only the pokemon database. In your terminal, open a mongo shell and run the following:

db.auth("admin", "doNotEatThat")

use pokemon

db.createUser(
  { 
    user: "misty",  
    pwd: "godDamitPsyduck", 
    roles: 
      [
        {role: "readWrite", db: "pokemon"}
      ]
  }
)
Enter fullscreen mode Exit fullscreen mode


TRUST, BUT VERIFY

gif showing inability to perform actions mongodb without first authenticating
To verify your database is now governed using RBAC, try to connect and view something. You'll notice that when you initiate a connection using the mongo shell, there is no longer a warning message stating "Access Control is not enabled for this database". Additionally, we're unable to view or edit anything until we authenticate using db.auth("user","pwd").



CHANGE DEFAULT PORT

gif of editing the default port in mongod.conf using terminal
Starting in MongoDB 3.6, mongod is now configured to allow connections only from localhost. This means that you can only access your instance from your laptop. That's excellent however IP's can be spoofed, etc. One extra step we'll take is to change the default MongoDB's default port. Similar to how we enabled security.authorization, we'll update our mongod.conf.

  1. Stop MongoDB Run pkill -f mongod to stop the database. You can confirm it has stopped using jobs -l.
  2. Update mongod.conf I used sudo vi. For reference, use your arrow keys to get to the end of the file, press "i" on the keyboard to type, add the port setting below, press "esc" on the keyboard, then type ":wq" then hit enter to save and exit.
/:~$ sudo vi /usr/local/etc/mongod.conf

systemLog:
  destination: file
  path: /usr/local/var/log/mongodb/mongo.log
  logAppend: true
storage:
  dbPath: /usr/local/var/mongodb
net:
  port: 23456
  bindIp: 127.0.0.1
security:
   authorization: enabled
Enter fullscreen mode Exit fullscreen mode

Now start your database back up. Please keep in mind that you will need to run `mongo --port 23456' when you launch you connect now.



HELPFUL SCRAPS

DATABASE CLEANUP
To quickly wipe all databases except admin, please use this nifty one-liner from the user kev as part of the MongoDB drop every database thread on Stack Overflow:
bash
mongo --quiet --eval 'db.getMongo().getDBNames().forEach(function(i){db.getSiblingDB(i).dropDatabase()})'

CLEAN UNISTALLL
To completely uninstall MongoDB and delete all of its tertiary data, please run the following commands:
bash
pkill -f mongod
launchctl unload ~/Library/LaunchAgents/homebrew.mxcl.mongodb.plist
rm -f ~/Library/LaunchAgents/homebrew.mxcl.mongodb.plist
launchctl remove homebrew.mxcl.mongodb
brew uninstall --force mongodb-community
brew untap mongodb/brew
rm -rf /usr/local/etc/mongo*
rm -rf /usr/local/bin/mong*
rm -rf /usr/local/var/mongodb
rm -rf /Users/$USER/Library/Caches/Homebrew/downloads/*mongodb*



Top comments (6)

Collapse
 
sinni800 profile image
sinni800

It's probably important to mention in either the TITLE or at least one of the first sentences of the guide that it's supposed to be for Mac.

Not everyone uses an Apple computer. They might be strangely common among developers but no, you still need to mention it.

Collapse
 
jackkeck profile image
Jack Keck • Edited

I initially provided a link to my local setup at the beginning of this post where I explicitly listed my operating system, however, those actual details were at the bottom of the post.

I've now moved this section up and it is now located after the introductory section.

Are you installing on a different system? I'm happy to lend a hand if you have any questions. For what it's worth, installation details for other operating systems can be found on MongoDB's site including Windows, RHEL, CentOS, Ubuntu, Debian, SUSE, and Amazon Linux. The process for loading a data set and setting up basic security should remain the same.

Collapse
 
sinni800 profile image
sinni800

Thank you for moving it up. It helps to bail out early enough when you don't even use that kind of system.

Though I was going to why it should say so in the title, I skimmed through the rest of the article and have to agree that actually most of it does apply to the other operating systems too.

So I have to say I am sorry I stopped reading in 1/3rd of the article.

Thank you for the offer of helping with setting up MongoDB, but I'm good. I have no issues doing the first few steps myself without guidance

Thread Thread
 
jackkeck profile image
Jack Keck

100% understand. I know it can be super frustrating. I used Windows as an OS for the first few years when I started out and I hated getting 3/4 of the way through something only to realize there was no easy translation; even side booting Ubuntu only got me so far.

I’ll make a point to call out my local specs more prominently and higher up in future posts. I’ll also try to offer curl options, etc, when appropriate. Do you think it’s fair to ask readers to have a Linux-style terminal at their disposal? Like a Cygwin or Git-bash on Windows? I know Win10 is offering a Linux shell off-the-shelf.

Thread Thread
 
sinni800 profile image
sinni800

I think that's very fair. On Windows 10, at least, a Linux side-install is very easy nowadays using "Windows Subsystem for Linux". That, or git-bash would work excellently.

I do think the bash is so standard that you could expect that even from a Windows user.

Thread Thread
 
jackkeck profile image
Jack Keck

Thanks for the feedback. I’m going to do a follow up to this post on how to put this into a docker container and I’ll be sure to include options besides brew installs :)