Deploying a Meteor app on a Digital Ocean production server
with Passenger in Nginx mode on Ubuntu 17.10 (with APT)
On this page you will learn how you can deploy your app to a server that is running Passenger. You can either follow these instructions with your own app, or you can use the sample Meteor app we prepared.
Table of contents
- Loading...
1 Transferring the Meteor package to the server
1.1 Build package
To deploy your Meteor app to production, we need to create a packaged version of it. A packaged Meteor app contains the Meteor runtime and various other necessary things for running a Meteor app in production.
In order to provide you appropriate instructions, please choose your Meteor version:
Inside your application's code directory, on your local computer, use the meteor bundle
meteor build
command to create a Meteor package tarball.
$ meteor bundle package.tar.gz
$ meteor build --server-only ../new_package && mv ../new_package/*.tar.gz package.tar.gz
Why create a package?
Wondering why we instruct you to create a package, instead of just using the Meteor app in unpackaged form? Learn more at About Meteor support.
"meteor bundle" deprecated?
Meteor will probably tell you that meteor bundle
is deprecated in favor of meteor build
. Please ignore that message, because for the purpose of running a Meteor web application on Passenger, only meteor bundle
does what we want.
meteor bundle
creates a packaged web application, in the form of a Node.js web app with the Meteor runtime included. meteor build
is a more comprehensive tool that not only does what meteor bundle
does, but also builds iOS and Android app packages. However, Passenger is a web application server, so iOS and Android packages are not relevant to us, which is why we recommend using meteor bundle
instead of meteor build
.
1.2 Upload package to the server
Copy the package to your production server, for example using scp
:
local-computer$ scp package.tar.gz adminuser@yourserver.com:
Replace adminuser
with the name of an account with administrator privileges or sudo privileges.
1.3 Login to your server, create a user for the app
Login to your server with SSH:
$ ssh adminuser@yourserver.com
Replace adminuser
with the name of an account with administrator privileges or sudo privileges.
Now that you have logged in, you should create an operating system user account for your app. For security reasons, it is a good idea to run each app under its own user account, in order to limit the damage that security vulnerabilities in the app can do. Passenger will automatically run your app under this user account as part of its user account sandboxing feature.
You should give the user account the same name as your app. But for demonstration purposes, this tutorial names the user account myappuser
.
$ sudo adduser myappuser
We also ensure that that user has your SSH key installed:
$ sudo mkdir -p ~myappuser/.ssh $ touch $HOME/.ssh/authorized_keys $ sudo sh -c "cat $HOME/.ssh/authorized_keys >> ~myappuser/.ssh/authorized_keys" $ sudo chown -R myappuser: ~myappuser/.ssh $ sudo chmod 700 ~myappuser/.ssh $ sudo sh -c "chmod 600 ~myappuser/.ssh/*"
1.4 Extract package
You need extract the package to a permanent location on the server. A good location is /var/www/APP_NAME
. Let us create that directory.
$ sudo mkdir -p /var/www/myapp
Replace myapp
and myappuser
with your app's name and your app user account's name.
Now let us extract the package:
$ cd /var/www/myapp $ tar xzf ~/package.tar.gz $ chown -R myappuser: .
Your extract app package directory now lives on the server at /var/www/myapp/bundle
.
2 Preparing the app's environment
2.1 Install MongoDB
During development, the Meteor runtime takes care of starting MongoDB for you. MongoDB is the database engine that Meteor uses. But a packaged Meteor app does not start MongoDB for you. Instead, a packaged Meteor app expects that MongoDB is already running somewhere, and that you tell the app where that MongoDB instance is.
You can install MongoDB from www.mongodb.org. While you can also install MongoDB via a package manager (apt-get), please note that this might be an outdated or even unsupported version.
2.2 Login as the app's user
All subsequent instructions must be run under the application's user account. While logged into your server, login under the application's user account as follows:
$ sudo -u myappuser -H bash -l
2.3 Install app dependencies
Your application has various dependencies.
They must be installed. Most of these dependencies are Javascript libraries, managed by npm. You can install them by running npm install
in your app's package directory, under the programs/server
subdirectory:
$ cd /var/www/myapp/bundle/programs/server $ npm install --production
Your app may also depend on services, such as Redis etc. With the exception of MongoDB, installing services that your app depends on is outside of this tutorial's scope.
3 Configuring Nginx and Passenger
Now that you are done with transferring your app's code to the server and setting up an environment for your app, it is time to configure Nginx so that Passenger knows how to serve your app.
3.1 Go back to the admin account
You have previously logged into your app's user account in order to prepare the app's environment. That user does not have sudo access. In the next steps, you need to edit configuration files, for which sudo access is needed. So you need to switch back to the admin account.
This can be done by simply exiting the shell that was logged into the app's user account. You will then be dropped back to the admin account. For example:
# This is what you previously ran: admin$ sudo -u myappuser -H bash -l myappuser$ ... # Type `exit` to go back to the account you were before myappuser$ exit admin$ _
3.2 Edit Nginx configuration file
We need to create an Nginx configuration file and setup a virtual host entry that points to your app. This virtual host entry tells Nginx (and Passenger) where your app is located.
$ sudo nano /etc/nginx/sites-enabled/myapp.conf
Replace myapp
with your app's name.
Put this inside the file:
server { listen 80; server_name yourserver.com; # Tell Nginx and Passenger where your app's 'public' directory is root /var/www/myapp/bundle/public; # Turn on Passenger passenger_enabled on; # Tell Passenger that your app is a Meteor app passenger_app_type node; passenger_startup_file main.js; # Tell your app where MongoDB is passenger_env_var MONGO_URL mongodb://localhost:27017/myappdb; # Tell your app what its root URL is passenger_env_var ROOT_URL http://yourserver.com; }
Replace yourserver.com
with your server's host name and replace /var/www/myapp/bundle
with your application's package directory path. Replace myappdb
with an appropriate MongoDB database name. Also be sure to set ROOT_URL
to an appropriate value.
When you are done, restart Nginx:
$ sudo service nginx restart
3.3 Test drive
You should now be able to access your app through the server's host name! Try running this from your local computer. Replace yourserver.com
with your server's hostname, exactly as it appears in the Nginx config file's server_name
directive.
$ curl http://yourserver.com/ ...your app's front page HTML...
If you do not see your app's front page HTML, then these are the most likely causes:
- You did not correctly configure your
server_name
directive. Theserver_name
must exactly match the host name in the URL. For example, if you use the commandcurl http://45.55.91.235/
to access your app, then theserver_name
must be45.55.91.235
. - You did not setup DNS records. Setting up DNS is outside the scope of this tutorial. In the mean time, we recommend that you use your server's IP address as the server name.
Next step
Congratulations, you have successfully deployed your app!
Continue: Deploying updates »