Deploying to a custom hosted environment
When you are ready to actually deploy your app to a production environment, you will need to convert your Meteor application to a straight up Node application. There are multiple methods to do this, all of which are (currently) manual processes and not for the beginner. A lot can go wrong. This recipe will show you how to manually deploy your Meteor application to a production server as a Node application.
Getting ready
As mentioned, there are multiple methods and server configurations that can successfully host a Node application. There are, however, some commonalities, all of which you will need for this recipe.
First, you will need a hosted MongoDB database.
Your MongoDB database can be hosted remotely or on the same machine from where you will deploy your Node application. For this recipe, we have deployed a default MongoDB database to the same machine where we will host the app. Our MONGO_URL
value will therefore be:
MONGO_URL=mongodb://localhost:27017
Tip
Installation instructions (and tutorials) for MongoDB can be found at http://docs.mongodb.org/manual/installation/.
Free or cheap but dedicated MongoDB service hosting also exists. Run a quick Internet search for MongoDB hosting or visit http://www.mongodb.com/partners/cloud for a list of providers.
Next, your hosting environment will need the latest stable Node and npm modules.
Installation instructions for each of these programs are beyond the scope of this book. For installation instructions and advice on how to get started, visit the following:
- Node (http://nodejs.org)
- npm (https://www.npmjs.com/)
Tip
The latest or nightly builds of these programs will likely cause you problems in a production environment. Be sure to use the stable versions, unless you have thoroughly tested a different version.
Lastly, you will need the forever
npm module installed in your hosting environment. From a terminal window on your hosted environment, run the following command:
$ npm install –g forever
Note that you may need to use the sudo
command to install the package globally. This will depend on how npm was installed on your server. The preceding command will install forever
on your machine, and you are now ready to prepare and deploy your application to production.
How to do it…
To deploy to a custom hosted environment, proceed with the following steps:
- Open a terminal window in your development environment and navigate to the root folder of your Meteor project. In this root folder, execute the following command:
$ meteor build [your-build-location] --architecture [x]
Replace the placeholders in the preceding line of code with your build location (for example:
~/Documents/builds/mybuild
) and an architecture (the options areos.osx.x86_64
,os.linux.x86_64
, andos.linux.x86_32
). The--architecture
option is optional if you are building this on the same server where you will deploy your app. - Meteor will bundle, extract, and repackage a clean production copy of your Meteor project, preparing it to be used in your hosting environment. While it is being built, Meteor will update you with the status in the terminal window.
- Once the build is finished, navigate to the build folder you specified, for example, if you specified
~/Documents/builds/mybuild
as your build location, you would need to enter the following command:$ cd ~/Documents/builds/mybuild
- In the build folder, you will see a
tarball
file with a name similar to[your-project-name].tar.gz
.So, for example, if the name of my project was
leaderboard
, the name of thetarball
file would beleaderboard.tar.gz
. - Make a note of the name and location because you'll need it when you copy and extract the build to your server.
- For this recipe, let's assume you're using a Linux server to host your production application. Let's create a
meteorapps
folder using the following terminal command:$ mkdir /home/meteorapps
- Next, copy the
tarball
file from your development environment to the/home/meteorapps/
folder in your production-hosted environment.If you build your application on a different machine, you can transfer it via SCP, FTP, a common file server, a Git repository, and so on. It really doesn't matter how you copy it over, as long as a copy of the
tarball
file is now in your hosted environment. - Once it's copied over, run the following command on the
tarball
file:$ tar –xf [your-tarball-name].tar.gz
This will extract the file to a folder named
bundle
. If you navigate to thebundle
folder, you will find aREADME
file. The next steps in this recipe are taken from thisREADME
file, so feel free to check them out for a more concise set of instructions. If you check the contents of the folder, you should see something similar to the following:README main.js programs server star.json
- We will now install the npm packages needed to run our application. Navigate to
bundle/programs/server
and execute the following command:$ npm install
Note
Note that we did not use the
–g
argument, as we are only installing the local npm packages specified in the bundled folder. - Next, we will need to set the
PORT
andMONGO_URL
export arguments so that Node knows how to host our application. Enter the following commands in the terminal window:$ export PORT=8080 $ export MONGO_URL=mongodb://localhost:27017
These two export commands tell your Node server what port to listen on, and where to find the
mongodb
hosted instance (we're using a local instance in this example).You will also want to configure the
ROOT_URL
andMAIL_URL
environment variables. The syntax to enter them is similar to the following export commands:$ export ROOT_URL='http://[your-hostname.com]' $ export MAIL_URL='smtp://user:password@mailhost:port/'
Now, we can run our application. Instead of using the default node
command, remember that we installed the npm forever
package. The forever
package allows us to run our Node application and will automatically restart it if we encounter an error. Run the following command in the terminal window:
$ forever start main.js
This command instructs Node to start main.js
as a node application, and to restart it if there are any issues.
Tip
You can stop the application later on by issuing the following command from the bundle/
directory:
$ forever stop main.js
Now it's time to test whether your application is successfully running by opening a browser and pointing it to your host environment, on the port you specified, for example, if our production environment was hosting the meteorapp.packtpub.com
subdomain, and we specify port 8080
, as shown in the preceding example, we would navigate to http://meteorapp.packtpub.com:8080
in a browser.
Your app should be up and serving pages.
How it works…
Node is built to run as quickly as possible. To do so, it will run a little differently on different hardware and software configurations. This means that the Node and npm packages you use in your development environment (for example, on MAC OS X) are slightly different than the corresponding Node and npm packages in your production environment (for example, Linux Ubuntu 12.4 LTS Precise). This is especially true for foundational packages, such as the npm fibers package.
Also, although Meteor is built on top of Node, it isn't a native Node application. There are some additional layers of abstraction and processing that make your life easier as a developer, but they don't make for the prettiest native Node production environment.
The meteor build
command takes care of this for us and creates a build without the npm packages installed. Instead, it lists any of the npm packages as dependencies. Because the specific npm packages aren't included (Meteor listed them in a package manifest file instead), there are no compatibility issues. We simply tell Node to find and install the packages specific to the current environment, using the package manifest file as a sort of a laundry list. We did this when we issued the npm install
command.
Once npm has read the manifest file, retrieved and installed all the needed packages, and informed us that the installation was completed correctly, we can run our new native Node application.
We then set some export variables (PORT
, MONGO_URL
, ROOT_URL
, and MAIL_URL
) and ran our application using the forever
npm package, rather than the normal node command. Using forever
helps us with not having to go back to the server every time it crashes. Ideally, we would never have an application crash, but we live in the real world, and forever
is a huge time saver when an app restart is needed.
There's more…
If our application is truly production-ready, we also want it to start automatically whenever the server reboots. There are various ways to do this, depending on the operating system your production server is running on, and we won't cover all of them.
We will give an example script and instructions on how to do this on Ubuntu and let you modify the script as needed for other environments.
Whenever an Ubuntu server restarts, it runs any *.conf scripts
script found in the /etc/init/
folder. We'll assume that our application is located at /home/meteorapps/prodapp/bundle/
, that we are going to listen on port 8080
, and that we are using the local MongoDB service (feel free to adjust these settings as appropriate).
Using a terminal window with sudo
privileges, add the following meteorapp.conf
script to /etc/init/
to your production server:
# prodapp configuration file # /etc/init/meteorapp.conf start on (local-filesystems) stop on shutdown script cd /home/meteorapps/prodapp/bundle/ export MONGO_URL=mongodb://localhost:27107 PORT=8080 export ROOT_URL='http://example.com' export MAIL_URL='smtp://user:password@mailhost:port/' exec forever start main.js end script
Let's break down what this script does.
The first two lines (start on
and stop on
) tell the OS when to run this script. In this case, we run it as soon as the local file systems are ready, and we stop it as soon as a shutdown request comes in.
We then have our script that will be run. We navigate to our application folder using cd /home/meteorapps/prodapp/bundle
.
Then, we declare the location of our MongoDB service and the port we would like the Node to listen on.
Finally, we execute the forever
command, asking it to start main.js
as a Node application.
The Meteor Group is currently working on a project called Galaxy, which will make deployment to custom servers as easy as deployment to their test servers. Once Galaxy is available, it will make this recipe obsolete, but that's a good thing! As mentioned, this recipe covers only one way of deploying to production. You may find another, easier method just by browsing https://forums.meteor.com or visiting other sources for Meteor information.
See also
- The Getting help with questions recipe in this chapter
- The Deploying with Meteor Up (MUP) recipe in this chapter
- The Deploying apps to mobile devices recipe in Chapter 12, Creating Useful Projects