« Previous Tutorial Wrapup »

Well, here we are at last … the final tutorial in the Five Minute React series. I’m going to do a follow-up video, so I won’t reflect too much here except to say that if you’ve stuck with me all this way, thanks, and I hope you’ve learned a ton. If you were starting from zero, you’ve definitely learned a ton, and should now be well-equipped to start experimenting on your own in the Node/React ecosystem.

We’re almost to the finish line, but to get there we’ll need to secure MongoDB by creating an admin user. This is a straightforward process, but it does mean generating yet another username and password. Security’s important, but also a pain in the ass. I once again strongly recommend a password manager like LastPass or 1Password.

Once again, a lot of this information is coming right from DigitalOcean’s own docs / tutorials. Look, there’s a reason I not only recommend these guys but use them myself to host CloseBrace. They’re good!

So let’s do this. We’re going to start by doing something that should feel familiar: using the MongoDB console. We do this by logging into our SSH session (if you haven’t already) and then typing:

mongo

Once in the console, you’ll see two warnings. The first you can ignore because it’s mainly relevant if you’re serving a lot of documents, which you won’t be unless you build this project out into something much larger. The second, though, is one we’re going to address: access control is not enabled for this database.

So let’s create a user. We do that by first switching to the admin db, which was auto-generated when we installed MongoDB. We do that by typing:

use admin

Now that we’re working in the admin database, we want to create a user. We do that with the following code:

db.createUser({ user: "administrator", pwd: "yourchosenpasswordgoeshere", roles: [ { role: "root", db: "admin" } ] })

Obviously, “yourchosenpasswordgoeshere” should be the actual password you want associated with this admin account. Warning: do not use a password with an @ sign in it, or it’ll break your MongoDB connection string later. Found that out the hard way! Additionally, you don’t have to use the name “administrator” … that can be whatever you want.

Hit enter and create that user. They’re now a part of MongoDB, but not a required part. To make them required, we need to head back to the command line, so type exit and press enter to exit the Mongo terminal. Now we’re going to use nano again to edit our config file, with this command:

sudo nano /etc/mongod.conf

You will, of course, need your sudo password for this. Head down to the section marked #security and, first things first, delete that hashmark, which will uncomment the section. Then add the following code on the line directly below:

  authorization: "enabled"

The indentation is important here. Two spaces for the setting, no spaces for the header, so your whole block should look like this:

security:
  authorization: "enabled"

Hit ctrl-x to exit and answer yes that you want to save the file. Now we need to restart MongoDB to get this change applied, so do that with the following command:

sudo systemctl restart mongod

Now let’s do a quick check with

sudo systemctl status mongod

And make sure that the “active since” date is, well, a few seconds ago.

We can check that regular users no longer have access by returning to the MongoDB console (using mongo), and then trying the show dbs command again. Instead of showing the available databases, this will now throw an error, which is what we want. Quit out of the console (exit), and then log in using your newly created administrative user, like this:

mongo -u administrator -p --authenticationDatabase admin

Obviously, if you used a different username, put that in there instead. You’ll be asked for your password, so enter that, and then run show dbs again. If all has gone well, you’ll see your databases. Success!

Quit out one more time. We’re done setting up authentication, but now we have a problem: we’ve broken our MusicList app! Oh, it would launch just fine at this point, but the minute we went to do anything that interacted with the database, it would break like a glass dropped onto a stone floor. We need to fix that.

To do that, we need to make some quick code changes. We’re going to be a bit unorthodox here, mostly for the sake of speed, and edit directly on the server in the master branch, and then commit from there. I won’t tell anyone if you won’t.

Just cd to /var/www/musiclist and then type the following:

sudo nano config.json

Important: you need to add a comma after the close brace for the mailgun line or, to quote the South Park meme, you’re gonna have a bad time. So add that first, and then below it, add the following:

"mongodb": {
    "user": "administrator",
    "password": "yourpasswordgoeshere"
  },

Again, if you used a different username, then put that in, and obviously put your correct password in there as well. While we’re here, let’s add a port setting so we can run this on the regular http port of 80. We could also do that by editing environment variables, but again, we’re being speedy here. Just below the code you added, add this line:

"port": "80"

Now save the file—you know the drill by now, ctrl-x and then y and then enter. Then type:

sudo nano config.js

And between the “mailgun” and “port” exports at the bottom (see? That port export seemed superfluous for a long time, but we’re finally using it!), add this line:

exports.mongodb = parsed.mongodb;

Save and exit this file, and then type:

sudo nano app.js

Find your Mongoose connection line and change it to the following:

mongoose.connect(`mongodb://${appConfig.mongodb.user}:${appConfig.mongodb.password}@localhost/musiclist?authSource=admin`, { useMongoClient: true });

We need to make one more change, because we’re not using HTTPS for this tutorial, but we added a line for express-session that requires it to work properly. So find this line:

    sessionValues.cookie.secure = true;

and just comment it out, like this:

  // sessionValues.cookie.secure = true;

Save and exit that file, and then we have just one more change to make. Type:

sudo nano bin/www

Find this line:

var app = require('../app');

Then just below it, add this code:

var appConfig = require('../config.js');

Next, jump down a couple of lines to this one:

var port = normalizePort(process.env.PORT || '3000');

And change it to this:

var port = normalizePort(process.env.PORT || appConfig.port);

Save the file and exit nano. Before we can put this all together and see our app running, we’ll need to fix a few issues. To see one of them, let’s try to run our production build script, so type:

sudo yarn run build-prod

Let that do its thing, and you’ll see there’s a problem. Our 512 MB of memory is not enough to run our build script. D’oh! There’s two solutions to this: the first is to increase the size of your droplet. The second is to add some temporary virtual memory. Let’s allocate 4 GB, which should be plenty, and is only a fifth of the disk space we have available. Type the following:

sudo fallocate -l 4G /swapfile && sudo chmod 600 /swapfile

Now enable the swapfile with this command:

sudo mkswap /swapfile && sudo swapon /swapfile

And finally, confirm it worked with this command:

sudo swapon --show

Cool, were all set. Now we can re-run our build script.

sudo yarn run build-prod

It will take a long time again, possibly even longer than before, but it should finish.

Now we have to do one last thing, because by default Ubuntu doesn’t like to give Node access to port 80, so run this command:

sudo apt-get install libcap2-bin

And then this one:

sudo setcap cap_net_bind_service=+ep `readlink -f `which node``

And finally, to head off an annoying error, type this:

sudo chmod 777 ~/.babel.json

With that done, we’re ready to launch. This is it … the big moment. Type the following:

sudo pm2 start --name musiclist npm -- run start-prod --

You’ll get some nice output from PM2, which you can bring back up at any time with

sudo pm2 list

Now head for a browser. Navigate to the IP associated with your droplet (it’s listed on your DigitalOcean control panel). If all’s gone well, you should see your app up and running! You can create a user, add albums and artists, and all that good stuff.

So, there you go! Basic setup and deployment for an app. The world of server administration is, of course, very complicated and there’s still a lot more to learn, but that’s going to have to happen in some other tutorial series … because this one. Is. Done!

I’ll be working on new tutorials very soon! Stay tuned for my wrapup video next week, and thanks again for taking this journey with me.

« Previous Tutorial Wrapup »