Compiling MongoDB with SSL Support on Ubuntu 12.04 LTS

EDIT: After more refinement, I've turned these instructions into an executable script, which you can see here: Compile and install MongoDB with SSL support script.

Note: Originally written for Digital Ocean, this never got published. Works for me though.

Introduction

When using MongoDB on Digital Ocean Droplets, you may want your database to reside on a server separate from your application server. As soon as you do this, ensuring your database connections are encrypted is vital. Unfortunately, pre-built MongoDB binaries do not come with SSL support. For that, we have to compile it ourselves.

When you create your Droplet, make sure you select 64-bit. MongoDB will run on 32-bit operating systems, but is limited to 2 GB storage. You can choose any size Droplet. Make sure you add a swap file.

Note: You will need a hefty droplet to complete the compilation, so we will resize it up to 8 GB of RAM with 4 cores, then resize it back down once compilation is complete.

Update packages

The first thing to do is get all packages up to date. Log in as as root and type the following:

aptitude update && aptitude dist-upgrade -y && reboot

If this is your first time updating, you will get a couple of warnings saying:

A new version of -------- is available, but the version installed currently has been locally modified.

Choose install the package maintainer's version.

Install pre-requisites

We'll need the following packages installed before we can compile MongoDB. Here's what we'll install:

  • build-essential — This is the Ubuntu package that installs commonly used programs needed for building software.
  • scons — SCons is an alternate to the "Make" build tool, which is used by the MongoDB.
  • git-core — Git is a version control system that we'll use to download the MongoDB source code.
  • libssl-dev — We need the development files that go along with the SSL shared library, in order to add this support to MongoDB.
  • various boost libs — portable C++ source libraries

Which we can do with the following command:

aptitude install build-essential scons \
  git-core libssl-dev \
  libboost-filesystem-dev \
  libboost-program-options-dev \
  libboost-system-dev libboost-thread-dev -y

Resize your Droplet

Compiling MongoDB is resource intensive and can be time consuming, so to speed this up, temporarily resize your Droplet. Type the following command to shutdown your Droplet:

shutdown -t secs 0 -h -P

Then log into the Droplets Admin page, choose the correct Droplet and choose Resize.

Select the 8 GB RAM / 4 CPU option for fast compilation. Then select Boot to start the Droplet back up.

Get MongoDB source

We can use git to download the source code for MongoDB:

cd /usr/src
git clone git://github.com/mongodb/mongo.git

Choose which version to install

Now that we have the source downloaded, we need to select which version we want to compile and install. So type in:

cd mongo
git tag -l | grep -v rc

This lists the available versions of MongoDB (excluding pre-release versions). You should probably chose the highest numbered version in the current stable branch. As of this writing, it is version 2.4.9. (Note: odd numbered minor version are development versions, and should not be used for production.)

git checkout r2.4.9

Compile and install

One of the things we can do to speed up the compilation is compile multiple source code files at the same time. A general rule of thumb is add one to one and a half threads per each CPU core. So we'll add "-j 4" to the command, but feel free to adjust depending on the size of your Droplet. The "--ssl" option tells the compiler to add SSL support, and the "--prefix=/usr" says where we want the binaries installed.

scons -j 4 --64 --ssl all
scons -j 4 --64 --ssl --prefix=/usr install

The install should then fail with the following error:

scons: *** [build/linux2/ssl/mongo/lame_stacktrace_test] Error 1
scons: building terminated because of errors.

And while it would be nice to not have these errors, MongoDB is indeed installed and working.

Run post-installation script

Best practices dictates that a database run under it's own account on the system. MongoDB comes with a script to set up this account, as well as make the data and log directories. First, we have to make the script executable:

cd debian
chmod +x postinst

And then run it:

./postinst configure

Copy upstart script and blank config file

We want MongoDB to start automatically when the computer boots. In modern Ubuntu systems, this is done with a program called upstart. MongoDB comes with an upstart script, which we can copy into place with the following command:

cp mongodb.upstart /etc/init/mongodb.conf

Next is the MongoDB configuration file. Again, MongoDB comes with a pre-made config file, so copy it like this:

cp mongodb.conf /etc

Add log rotation config

Log rotation is the process of automatic archival of log files. To ensure MongoDB's log files don't get out of control, configure the program logrotate to handle MongoDB's log files. Use nano to edit the configuration file:

nano /etc/logrotate.d/mongodb-server

And paste in the following configuration:

/var/log/mongodb/*.log {
  weekly
  rotate 10
  copytruncate
  delaycompress
  compress
  notifempty
  missingok
}

Save with ctrl-w then Enter, and exit with ctrl-x.

Generate SSL key

Using SSL requires both an SSL key and certificate. We're going to generate a key and a self-signed certificate. Instructions for using a cert signed by a certificate authority, refer to these instructions.

The following commands will generate the certificate and the key. (This key will be valid for 1 year, which you can increase by changing the -days section.)

cd /etc/ssl/
openssl req -new -x509 -days 3650 -nodes -out mongodb-cert.crt -keyout mongodb-cert.key

You'll be asked for several pieces of data:

  • Country (two letters)
  • State (spelled out)
  • City
  • Company
  • Section
  • Fully qualified domain name of server
  • Email address

Example:
image

Next, combine the key and the certificate into a single file:

cat mongodb-cert.key mongodb-cert.crt > mongodb.pem

Configure MongoDB to use SSL

The next thing to do is configure MongoDB to use SSL. Edit the configuration file with the following command:

nano /etc/mongodb.conf

And add the following two lines to the configuration:

sslOnNormalPorts = prefer
sslPEMKeyFile = /etc/ssl/mongodb.pem

Save with ctrl-w then Enter, and exit with ctrl-x.

Remove unused files

The compilation takes up several gigabytes of storage, so once done remove these with the following command:

rm -rf /usr/src/mongo

Start MongoDB

And now, let's start MongoDB:

service mongodb start

Browse to https://nnn.nnn.nnn.nnn:28017 (where nnn.nnn.nnn.nnn is the IP address of your Droplet) to ensure MongoDB is running. You will get a warning because the certificate is self-signed, but continue. If successful, it should look like this:

image

If you did resize your Droplet to save time compiling, go ahead and resize it back now.

Profit!

Congratulations, you now have MongoDB up and running with built-in support for SSL encryption.


Troubleshooting

Note: if you're running into the error cc1plus: all warnings being treated as errors, find the following block (around line 710) in /usr/src/mongo/SConstruct

# -Winvalid-pch Warn if a precompiled header (see Precompiled Headers) is found in the search path but can't be use$
env.Append( CCFLAGS=["-fPIC",
                     "-fno-strict-aliasing",
                     "-ggdb",
                     "-pthread",
                     "-Wall",
                     "-Wsign-compare",
                     "-Wno-unknown-pragmas",
                     "-Winvalid-pch"] )

and add -Wno-unused-local-typedefs to the flags, then re-run scons as above.