This article will guide you thru running a production ready meteor.js app on Digital Ocean with Phusion Passenger and ngnix.
- Create a droplet
- Install Phusion Passanger with NGNIX
- Install node.js
- Configure NGNIX
- Run NGNIX on server reboot
- Bundle your app a deploy for production
- Make it run!
- Check for errors
Go to your account and crate a Droplet, choose a plan, deployment infrastructure (US, EU, ASIA) and OS (we will be working with Debian 7 x64
droplet). If you are deploying a production ready app, make sure to run it with at least 1GB RAM.
Passenger is very similar to NGNIX or APACHE, it can run as a standalone server or a module to APACHE or NGNIX, we are going to use it with ngnix. Passenger also takes care of starting/restarting out app, which simplifies the setup a lot.
- To install anything on your server you have to use
ssh
. Which is present on any UNIX-like system. If you are on windows please usePUTTY
or other ssh client.
ssh root@DROPLET_IP
If this is your first time logging in to the droplet, the system will ask you to change your ssh password.
- Install passenger
Follow this tutorial up to the end of step 2.3.3.
The tutorial asks you couple of times to do some file editing, If you are not familiar with UNIX systems use
sudo nano /path/
to edit the file.nano
is a file editor.
After you are done editing with
nano
pushctr + x
to exit thany
to confirm changes andenter
to go back to ssh. Orctrl + o
to Write Out change andenter
to confirm andctrl + x
to exit.
This will install Passenger along with NGNIX. You can check that everything went fine by visiting YOUR_SERVER_IP
and you should see a ngnix welcome screen.
Passenger is just a server and it does not take care of installing node.js for you, so we'll have to do it.
- Setup system
apt-get install curl
curl -sL https://deb.nodesource.com/setup | bash -
- Install node.js
apt-get install -y nodejs
- Don't forget to install build essentials!
Build essentials come in handy when you deploy your meteor app afterwards because meteor uses bcrypt which needs to be recompiled on each system.
apt-get install -y build-essential
Since we are running NGNIX we'll have to configure it to make use of Passenger.
- Open the
sites-available/default
with nano editor
sudo nano /etc/nginx/sites-available/default
- Setup your vhost conf by editing the file
You should see that there is already a
server {}
block, scroll pass it and copy/paste the following
server {
listen 80;
server_name http://yourserver.domain.com; #same as ROOT_URL
root /var/www/YOURAPPNAME/public; #DO NOT FORGET THE CHANGE THE NAME
passenger_enabled on;
passenger_sticky_sessions on;
passenger_set_cgi_param MONGO_URL mongodb://username:[email protected]/database; #DO NOT FORGET TO CHANGE IT
passenger_set_cgi_param MONGO_OPLOG_URL mongodb://username:[email protected]/database?authSource=database; #DO NOT FORGET TO CHANGEIT
passenger_set_cgi_param ROOT_URL http://yourserver.domain.com;
passenger_set_cgi_param METEOR_SETTINGS '{}'; #If you are using 'meteor --settings settings.json' in development, copy paste your values here
passenger_app_type node;
passenger_startup_file main.js;
}
This basically tells ngnix to listen for incoming traffic at port 80
which points to your server name
and uses passenger module to handle the request. MONGO_URL
, MONGO_OPLOG_URL
and ROOT_URL
are needed by Meteor to run. The last two lines tells passenger that our app is a node
app and starts with main.js
.
After you are done editing push ctr + x
to exit than y
to confirm changes and enter
to go back to ssh. Or ctrl + o
to Write Out change and enter
to confirm and ctrl + x
to exit.
By default ngnix or passenger are not started on server boot, we have to handle that.
- Create a file in
/etc/init.d/
calledngnix.sh
sudo nano /etc/init.d/ngnix.sh
- Paste this line to the file
/etc/init.d/nginx start
After you are done editing push ctr + x
to exit than y
to confirm changes and enter
to go back to ssh. Or ctrl + o
to Write Out change and enter
to confirm and ctrl + x
to exit.
Now whenever the droplet reboots
the ngnix server will start.
Bundling meteor apps is very easy, because meteor CLI give is the great functionality of meteor bundle
- Open a new terminal Window
- Cd into your Meteor app
- Bundle your meteor app
meteor bundle bundle.tar.gz
- Upload the bundle to the server
scp bundle.tar.gz root@DROPLET_IP:
login with password
- login to your serve again via
ssh
- Create the
/var/www/
directory, cd to it, and extract the bundle
sudo mkdir /var/www/ && cd ../var/www/ #create and change directory
sudo tar xzvf ~/budnle.tar.gz #extracts the bundle to ./bundle
sudo mv bundle YOURAPPNAME #rename the bundle folder to your desired name
- Create
public
andtmp
directories which are needed by Passenger
mkdir -p YOURAPPNAME/public YOURAPPNAME/tmp
- Install dependencies
Meteor bundle
turns the meteor app in to almost standardnode
app so we have the install the dependencies.
cd YOURAPPNAME/programs/server && sudo npm install
-
Reinstall
npm-bcrypt
Unfortunately Meteor bundle also, bundlesnpm-bcrypt
which needs to be compiled on every platform, so if you bundled the app on OSX or Windows Machine the app wont start, and will give youbcrypt_lib.node: invalid ELF
error. So we need to rebuildbcrypt
. -
Delete the current
npm-directory
and recreate it a now
rm -rf npm/npm-bcrypt/ && mkdir -p npm/npm-bcrypt/node_modules/bcrypt/
- Move to the projects root directory
cd ../../
- Install
npm-bcrypt
npm install bcrypt
- Now move it to the recreated
npm-directory
cp -r node_modules/bcrypt programs/server/npm/npm-bcrypt/node_modules/
So far it everything went butter smooth you should have a working Meteor deployment on Digital Ocean and Phusion Passenger
- Restart ngnix
/etc/init.d/nginx restart
- Visit your domain name provider and create an
A
record which points to yourDROPLET_IP
- Visit
https://cloud.digitalocean.com/domains
and configure it accordingly to your DNS and ngnix default configuration - Save all of those settings
- It will take 30 min probably to synchronise DNS records
- Visit your page!
App is not running? ngnix does not want to start?
sudo nano /var/log/nginx/error.log
In fact, if you don't install nginx, but instead install passenger nginx integration mode directly, you don't need to configure nginx separately for restarts etc. Additionally, I find it easier to deploy as a meteor app instead of a node app, but just run it with the --production flag. This way, you don't have to install node separately, and you don't need to run meteor bundle for every update of your app.