Setup MongoDB for Laravel on ploi.io

Alex Renoki
Jan 2 · 5 min read

This post has an audio version thanks to Miguel Piedrafita’s Blogcast app.

In case you want to deploy your Laravel app (or any kind of PHP-based application), ploi.io is a service that helps you with that with a minimum of Sysadmin knowledge. It helps you spin up your own VPS or Bare Metal instance on Vultr, DigitalOcean, Linode or Scaleway, UpCloud and Hetzner.

To deploy the app, you need to store it on a git-based platform. You can choose from GitHub, Gitlab or Bitbucket. Ploi also comes with monitoring through Servitor and supports Cloudflare management and automatic backups using DropBox, so your data will be safe!

It comes with a ton of out-of-the-box features for your PHP application: PHP 7.0+, NGINX, MySQL/MariaDB, Supervisor (to daemonize your applications) and supports even one-click app installs for Wordpress, OctoberCMS or Nextcloud.

Basically, what you need to do is to code. The rest of it — is Ploi’s job.


What’s MongoDB?

MongoDB is an object, document-oriented kind of database. It’s like a normal MySQL database but it has a few pros and cons compared to it. The advantages of using MongoDB are:

  • flexibility (we don’t have to define a schema using migrations, unless we want to set indexes or unique keys)
  • speed (since we do not rely on tables and we rely on JSON-encoded files that are written on disk, we get high I/O)
  • scalability (we can create replicas, just like in MySQL, but we can shard, or “split” the database content, and we can scale it across multiple regions without cutting off speed or availability)

However, most of the time, Mongo isn’t a great choice. One downside is consistency. Not all content you’ll store will have the same fields. While SQL relies on tables with strict fields (id, username, password, etc.), on MongoDB, each document (the equivalent of a row in SQL) can have, or not, all the fields. For example, we can have users that have the password field, but some that did not set a password may not have it stored. In SQL, we must define the password field and set it to null by default if we don’t want to have a value. In Mongo, it simply won’t exist.

Another downside, especially when it comes to Laravel, is that morphToMany does work, and the belongsToMany is a little bit different. So, in technical words, we do not have joins in NoSQL.

When should I use MongoDB over SQL?

Whenever you need to have better speed than consistency. Even if MongoDB is a great choice due to high I/O and scalability, SQL and NoSQL are two different things and one of them beats the other one on certain aspects, not every single one. MongoDB is great if you plan to have a lot of reading and writing while keeping a simple structure. SQL is good for deep querying or many-to-many relationships like having multiple tables. Sometimes, you might want to use both of them at the same time, that might solve all your problems regarding the structure.


Installing MongoDB on your server!

Since Ploi doesn’t come with one-click MongoDB installation, we have to do some scripting to make this work. This works only with Ubuntu 18.04, so make sure you have it before jumping and breaking things.

We’ll install the MongoDB using Ubuntu repo:

apt-get install mongodb

Let’s enable a service for it, so it will start at each boot, and let’s restart it:

systemctl enable mongodb.service
systemctl restart mongodb.service

We don’t have an admin user, for now, so we’ll have to get into Mongo’s terminal and create one:

mongo

And now, while in terminal:

> use admin;

This next command creates an admin user:

> db.createUser({ user: 'admin', pwd: 'your_password', roles: [{ role: 'userAdminAnyDatabase', db: 'admin' }] });

This can also be done in only one command:

mongo admin --eval "db.createUser({user:'root',pwd:'your_password',roles:[{role:'userAdminAnyDatabase',db:'admin'}]});"

Instead of your_password, just set a password that your admin user will have. If port 27017 is available to the internet, make sure you set a good password, otherwise, anyone can connect to it. If the firewall blocks that port, you can use any password, but remember that it can be accessed if someone accesses the SSH and tries to log in using the same mongo terminal.

Using the same command, it’s possible to create users for your databases in a fast way, but we need another role:

mongo [database_name] --eval "db.createUser({user:'user_name',pwd:'user_password',roles:[{role:'readWrite',db:'database_name'}]});"

Installing MongoDB extension for PHP

To make MongoDB run in PHP, we have to set the extension. In Ubuntu 18.04, we can acheive this using bare minimum:

pecl install mongodb

And now attach the extension name to your php.ini:

echo "extension=mongodb.so" >> `php -i | grep "Loaded Configuration" | sed -e "s|.*:\s*||"`

We have configured this for the cli, but not for the PHP-FPM. To do this, we’ll have to add the mongodb.so extension to our PHP-FPM configuration:

echo "extension=mongodb.so" >> /etc/php/[php-version]/fpm/php.ini

The php-version is our actually PHP version. In my case, it’s 7.2:

echo "extension=mongodb.so" >> /etc/php/7.2/fpm/php.ini

All you need to do is to restart your PHP-FPM service using this command. This service name varies with the version of PHP you’re using, so replace your PHP version in the command:

systemctl restart php[your_version_here]-fpm.service

For example, for PHP 7.2:

systemctl restart php7.2-fpm.service

Now you’re ready, you have a fully functional MongoDB database! You can see it running:

systemctl status mongodb.service

It will output something like this:

● mongodb.service - An object/document-oriented databaseLoaded: loaded (/lib/systemd/system/mongodb.service; enabled; vendor preset: enabled)Active: active (running) since Wed 2018-12-26 08:20:42 UTC; 1 weeks 0 days agoDocs: man:mongod(1)Main PID: 13667 (mongod)Tasks: 26 (limit: 4636)CGroup: /system.slice/mongodb.service└─13667 /usr/bin/mongod --unixSocketPrefix=/run/mongodb --config /etc/mongodb.conf

Configuring Laravel with MongoDB

To implement MongoDB in your Laravel application, you have to use Jens Segers’ MongoDB package. It gives you the right information about connecting the Eloquent Models to your MongoDB database and use them the way they also work with SQL.

To connect to your MongoDB database on your server, you have to set up this in your .env file:

DB_CONNECTION=mongodbDB_HOST=127.0.0.1DB_PORT=3306DB_DATABASE=any_database_nameDB_USERNAME=adminDB_PASSWORD=your_admin_password

Since the admin we created has role set to userAdminAnyDatabase, it doesn’t matter what name we set to the database. In case it does not exist, it will create one for us, automatically.

In case you’re using an user that does not have a userAdminAnyDatabase role, you have to add an env variable for the options field in the mongodbdriver from your config/database.php :

'mongodb' => [   'driver' => 'mongodb',   'host' => env('DB_CONNECTION', 'localhost'),   'port' => env('DB_PORT', 27017),   'database' => env('DB_DATABASE'),   'username' => env('DB_USERNAME'),   'password' => env('DB_PASSWORD'),   'options' => [      'database' => env('DB_ADMIN_DATABASE', 'admin'),   ],],

As DB_ADMIN_DATABASE, you’ll set up what is the admin database for the user. For the admin user that we created with userAdminAnyDatabase, it will be admin but for the user we just created, it will be the database name we created for it.

Too hard to understand? Reach me!

If you have more questions about Laravel, if you need help with MongoDB or any kind of question which is related to DevOps or simply want to say a Thank you!, you can find me on Twitter @rennokki!

Alex Renoki

Written by

Certified Laravel Developer. Working with full-stack web applications, AWS, Kubernetes and buzzwords like cloud computing.