How do I host multiple Meteor apps on one DigitalOcean Droplet

18 March 2016

I know that there are plenty of articles about hosting Meteor apps on DigitalOcean. I’m not a specialist in this area, but I thought that I could write down some of my experiences related to that kind of work, which should be done from time to time and sometimes there just is no other way. I must confess that I don't find it super exciting, but that’s just me. You can treat this article as another way to achieve it and it is for sure for beginners. Of course, I assume that you know how to use command line and Ubuntu OS. Ok let's take a look at the problem and the solution.

What I wanted was one cheap DigitalOcean droplet which can handle 2-3 rather simple and not very demanding Meteor apps at once. There is no simple way to do this on DigitalOcean and, with Meteor, it is super complicated, at least for me. Fortunately there are many smarter people than me out there. People who have built some cool tools and write a bunch of helpful articles. Some of these articles will be linked here and without some of these tools, I won't be able to achieve my goals for sure.

You’re probably asking yourselves why you would use DigitalOcean when there are plenty of simpler solutions for Meteor. Yes, you’re right, there are many simpler solutions, but DigitalOcean is very good, has never disappointed me, is very cheap. You can of course use Galaxy, which is great, or Modulus or many others. I use Galaxy too, but I have some apps and websites built with Meteor which don't need such hosting and don't earn money so for such apps DigitalOcean is the best for me right now.

What you need to know is that we need Ubuntu distribution. This is because of the tools which we will be using here. So you should check this option in the 'Choose an image' section. Next you can choose a droplet size. I am interested in the cheapest option, so I've chosen the 5$/mo option. You can also choose a dataset region. It's better to have your hosting machines as close to your major users as possible. I’m in Poland so I've chosen the Frankfurt region, but you can also choose other regions in Europe, in the USA, or Singapore. Next you’ll be able to set up some additional features as backups or SSH keys. You'll find the tutorials in linked article above.

When you create your droplet, you'll be able to login with SSH to your server, but for now, let's leave it.

You need domains for your Meteor apps. Let's assume that we want to host two Meteor apps which will have two separated domains. You can also host them under subdomains of one domain. Configuration is the same. In fact, let’s assume that you want to host one Meteor app under one new domain and one Meteor app under the subdomain of another domain. Let's say that one Meteor app will be hosted under www.meteor-app-1.com and the second one will be awesome.meteor-app-2.com.

You'll also find many tutorials on how to configure your domains in DigitalOcean. For example, this one: How To Set Up a Host Name with DigitalOcean. All you need to know is that you need to set up DigitalOcean's domain nameservers in your domains provider admin panel. The DNS server names are: ns1.digitalocean.com, ns2.digitalocean.com, ns3.digitalocean.com. Next, in the DigitalOcean's admin panel in the Networking/Domains section, you need to provide two domains and choose the droplet that you created previously. You need to provide your domains names. In our case, we need to provide meteor-app-1.com and metepr-app-2.com names. Then for the second one, we will create a subdomain. You need to go to the details of the meteor-app-2.com domain and create an A record for a subdomain. You need to select 'A' record and then write the subdomain name which is 'awesome' in that case. You need to choose the same droplet in the field next to it or you can also paste doplet's IP here. This is it, we have our domains configured. Ok, so when we have basic work done, we can take a look at our new server insights.

Initial server setup

You can log in through SSH into your server. You just need to use your IP and your password which should be sent to your e-mail address. You can also change the main password in DigitalOcean's admin panel. To log in, you just need to write in your console:

$ ssh root@YOUR_SERVER_IP_HERE

After this you can start configuring your initial server setup. It’s good to create another user with all the necessary rights. You can find some awesome guides here: Initial Server Setup with Ubuntu 14.04. For me, it was very helpful. Basically, you can go through all steps described there.

Next you'll need a Swap File space. This is an essential part. DigitalOean's docs says that on SSD discs it's better not to create a Swap File, but in our case it’s mandatory. This is because we want to host a couple Meteor apps on one droplet and one droplet in our case has a small amount of memory. It’s only 512 MB so we need a Swap File because sometimes it could not be enough and without it our server could crash. Moreover, we wouldn’t be able to recover our data, so this is very important if you want to host a couple of apps on a small droplet. In my case, I've created a 4GB Swap File and it seems to be ok for now.

How do you create a Swap File? Here is a great tutorial: Create a Swap File. You can also go through the whole article and use other guides too.

Nginx installation and simple configuration for Meteor instances

When you want to use a couple Meteor apps on one DigitalOcean droplet, you should have Nginx installed. This is quite simple. You can check another great article from DigitalOcean's knowledge base: How To Install Nginx on Ubuntu 14.04 LTS, but all you need to do is just:

$ sudo apt-get update
$ sudo apt-get install nginx

Ok, after installation we can configure Nginx for our two Meteor apps.

Go and change directory to /etc/nginx/sites-available/ Here we need to create our config file. Let's name it after the first domain name so: meteor-app-1.com.conf. Example content of this file could be something like:

As you can see, everything is almost the same. We don't need the non-www redirects part here and we also need to change the app's port to 3002 because 3000 is occupied and we don't want any possible collisions with MongoDB, so it is 3002 and not 3001.

Once you have your two configuration files in the /etc/nginx/sites-available directory we need to run a couple commands. First is the link command. We need to link the configuration files to the sites-enabled folder. We can do this like

And that's it! You have your configuration. Of course there aren't any files deployed. We’ll take care of that soon.

Mup – Meteor deployment tool

Mup is a tool created by Arunoda Susiripala, but not it is maintained by @zodern What it does is basically preparation and deployment of a Meteor app. With this tool, deployment is really simple. It uses Docker behind the scenes so you need to install it on your server. If you are still logged in to your DigitalOcean droplet, just run the command:

$ sudo wget -qO- https://get.docker.com/ | sudo sh

Then you can install the mup tool locally. Open another terminal window and install mup. This is a standard Npm tool. Install it by:

$ sudo npm install -g mup

When the installation is over, go to your Meteor app (locally, not on the server) and run:

$ mup init

This command should create two files in your app's folder: mup.js and settings.json (if you don't have one). The first file is the most important because here you'll provide configuration needed to set up your Meteor app on the server which you've just configured. The mup.js file for our first app should look like: https://github.com/zodern/meteor-up#example-file.

As you can see, we can provide the login and password for our SSH access here, so it’s very important not to include mup.js in your public repositories on GitHub or Bitbucket. You can add this file to your .gitignore file.

We can also provide the app name and special environment variables. We need to provide a port number, in this case 3000 (remember that the second app runs on 3002). We also need to provide ROOT_URL, which is our host name (www.meteor-app-1.com).

Mup is also capable of creating and setting up your MongoDB instance which will run on the same DigitalOcean droplet. You can use it this way, but the better option is to use services like Compose.io or mLab.com. You can provide MONGO_URL in the mup.js file. You'll read more about the configuration under the link provided at the beginning of this chapter.

Ok, so we have our mup.js file with the needed configuration. It’s time to set up our app on the server. To do this, you just need to run:

$ mup setup

If the mup.js file is configured properly, this command should log in to your SSH account on the server and prepare the environment for our Meteor app. You only need to run the setup command once. After it’s done, we need to deploy our app to the server. There is also a very simple command to do this:

$ mup deploy

This will deploy all files to the server and run the app. You should be able to run the app under the configured domain.

We can do the same with the second app. Remember to change the appName, env.ROOT_URL and env.PORT variables in the mup.js file.

Final words

This is a really basic DigitalOcean droplet configuration guide for hosting more than one Meteor app. There are many other great resources about this topic on the Internet. DigitalOcean has a very well prepared knowledge base too.

We don't cover SSL usage here, but Mup tool has support for it. All you need to do is to generate your files with keys and provide paths to them in the mup.js file. You can use Let's Encrypt, for example, which is really great.

As I said at the beginning, I'm not an expert in this area, but the path described here let's me run some of my simple Meteor apps in one place and, most importantly, it’s very cheap.

So please take a look at the Mup tool. It's awesome. Many thanks to Arunoda for creating it and @zodern for maintaining it. Mup can do many cool things so it's worth learning.

Let me know if I should do something in different or better way or if you have any questions about this topic. I'll try to answer everything.