So, you’ve created a great Meteor app and now you want to deploy it? There are several options to do this:
- Use a NodeJS hosting provider like Modulus.io, Heroku or NodeChef.
- Host on Meteor’s own Galaxy.
- Deploy on your own server.
For a quick overview of MUPX, read the documentation here.
Now having to type
mupx deploy after every major change to your app can get a pain in the ass. Maybe we should automate this.
I assume you use Git. Personally I use the Gitflow model to keep my code clean. All my development is done on feature branches, and when I create a release, this is merged with my master branch. The image below illustrates this (source).
Enter Jenkins. Jenkins is an open source automation sever or continuous integration tool. In this tutorial I’ll show you how to set up a DigitalOcean droplet, that builds your code every time you push your changes to master.
There are some really cool services for continuus integration like Travis CI, CodeShip and others, but they are rather expensive. They are however, much easier to use. Jenkins can be daunting, so if money is not an issue I suggest you try a hosted service.
- A Meteor project, configured for MUPX (or MUP). So, a mup.json must be present.
- A DigitalOcean account (or Vultr or any other VPS – but I’ll use DigitalOcean in this post)
- A Github or BitBucket account you push your code to (I’ll use BitBucket in this tutorial)
- Basic Bash and terminal knowledge
Step 1: create a DigitalOcean droplet
The first step is creating a new Droplet. Just visit this link and enter the details below:
- Distribution: Ubuntu 14.04 x64 (or whatever the latest Ubuntu Long Term Support release is when you read this).
- Size: more means faster build times. I choose the $10/mo 1GB RAM droplet.
- Location: choose the one closest to your target server.
- Hostname: something you can remember (like Jenkins)
Step 2: install Jenkins
Go check your mailbox and you should’ve received an e-mail containing the root password and IP-address of your Droplet.
Open a terminal (or a terminal emulator when you’re on Windows) and type the following command:
You will now be asked to change your password. Once you’ve done this you will get a command prompt.
Let’s install Jenkins. Enter these commands, and answer Y (yes) when asked:
wget -q -O - http://pkg.jenkins-ci.org/debian/jenkins-ci.org.key | apt-key add -
echo deb http://pkg.jenkins-ci.org/debian binary/ > /etc/apt/sources.list.d/jenkins.list
apt-get install jenkins
Optional: make Jenkins run on port 80
If you don’t have access to port 8080 (because of a firewall or proxy) or you think the URL is ugly this way, you can change this with some simple iptables magic.
Enter these commands:
iptables -I INPUT 1 -p tcp --dport 8080 -j ACCEPT iptables -I INPUT 1 -p tcp --dport 80 -j ACCEPT
iptables -A PREROUTING -t nat -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 8080
apt-get install iptables-persistent
iptables-save > /etc/iptables/rules.v4
This will configure iptables to map port 80 to 8080, and will reapply these rules when you reboot.
Optional: don’t make Jenkins speak your language
If your browser language is anything other than English, Jenkins will try to speak your language. The translations for my language are a bit weird. If yours are too fix this by installing the locale plugin.
Go to http://your-ip:8080 and select Manage Jenkins > Manage plugins, click available and search for the Locale plugin. Install it and restart Jenkins (by checking the checkbox during install).
When Jenkins has restarted select Manage Jenkins > Configure System and set default language to en. Make sure to check the checkbox below, save the settings and voila … your Jenkins is now in English.
Optional, but recommended: don’t store passwords in your Git.
It’s not a very good idea to keep passwords in your
mup.json file. MUP allows you to specify a private key instead of a password. I strongly advise you to use this.
My workflow is to put this key in
/usr/local/keys on my Mac and copy the key to the same location on the Jenkins server. This way I can both run mupx locally and when building through Jenkins.
Step 3: secure Jenkins
You don’t want anyone to be able to administer your Jenkins installation. So let’s tighten the security a little bit. Select Manage Jenkins > Configure Global Security.
Click the checkbox Enable security, choose Jenkins own database as Security Realm, and check Matrix-based security.
Next, this is very important, make sure anonymous user has the read permission for the view property. If you don’t enable this, you won’t be able to log in.
Add a user with the username you desire and give it all permissions.
Click save, and you’ll be presented with a sign up form. Register using the username you picked and click save. You’ll be logged in and will be able to do everything.
Step 4: install Meteor & Git on your server
In the terminal (connected to your server) type:
apt-get install git curl
curl https://install.meteor.com/ | sh
Step 5: install some plugins.
Let’s install some plugins, so we’ll be able to work with NodeJS and Git.
Click Manage Jenkins > Manage Plugins > Available and select these plugins:
- NodeJS plugin: this will allow us to set up a NodeJS environment for our builds.
- Git plugin: allows us to work with Git (duh).
Download and restart Jenkins (restarting should not be necessary, but it is safer). Meteor and Git will now be available to your projects.
Step 6: configure the NodeJS plugin
Go (once again) back to Manage Jenkins > Configure system and scroll down to NodeJS.
Enter a name for your installation and click the “Install automatically” checkbox.
Choose 0.10.41 (or whatever version is required for Meteor when you read this) as version , and enter mupx in the global npm packages list.
If for some reason this dropdown list is empty (happened to me and took a long time to debug): go to Manage Jenkins > Manage Plugins, click the Advanced tab and then click Submit beneath Update Site and also Check now next to Update information. Go back and the list should be populated.
Step 7: setting up your Git credentials
We’ll be using a private key to access our Git repository. I’ll explain this for BitBucket, but it should be almost the same for Github.
First, in a terminal on your server run:
Press enter when it asks you for keyphrase, and type:
Copy this to your clipboard and go to Bitbucket. Click on your profile pic on the right and choose Settings. Next click SSH-keys beneath Security. Click Add key, choose a nice name and paste your public key.
Go back to Jenkins and click Credentials on the left side. Click Global credentials (unrestricted) and click the link saying you don’t have any credentials.
You want to add a SSH Username with private key so enter your Bitbucket username and select that you want to load it from Jenkin’s home directory.
Step 8: add a project
Finally. We can start adding projects and forget about the previous steps. The screenshots below can be a little different of your screen because I disabled some plugins like Maven support.
Go home and select New Item. Enter a project name and select Freestyle project.
Beneath Source Code Management select Git, enter your repository URL (the SSH-version)x and select the credentials you’ve just entered. Check Poll SCM (this will make sure builds only trigger on push to master) but do not enter a schedule.
Provide the NodeJS path under Build Environment.
Now we have our build checking out, let’s add our build step to deploy it.
Click Add build step and choose Execute shell. Enter:
And Save! Time to test this. Click Build Now on the left side and when the build shows up under Build History click it and choose Console Output.
The first time this will take a little bit longer, because it has to check out your entire tree, configure NodeJS, install Meteor and mupx, but after a little while you should see mupx deploying your project. Next builds will be way faster.
If all goes well you can move on to the next step.
Step 9: notify Jenkins about pushes to Git.
Open BitBucket again, go to your repository and click Settings. Select Webhooks and add a new one.
Choose a nice name, and enter this as URL:
Replace the URL with your Git URL (the same one used when setting up your project) and the ip-of-jenkins with your IP or hostname.
Now whenever you push, Jenkins will see if anything has changed on your master branch and build your project.
Hope you enjoy this approach!