It's been a while since I last wrote here, hopefully I could get back to my weekly routine.

In the last month or so I've been working heavily with Meteor.

When it came to the stage of deploying to a test server, I decided to use a simple node server, without an extra layer of Nginx/Apache. Normally, to build a Meteor application, you run:

1 meteor build This generates a tar.gz file with your compiled (-ish) application, which you could later extract to your production server.

After extracting, you'll have to run node main.js to start the application. This approach has 2 problems:

Dependencies - Some npm packages will have to be installed via running npm install under programs/server, this adds yet another step that has to be done for deployment.

- Some npm packages will have to be installed via running npm install under programs/server, this adds yet another step that has to be done for deployment. No Logs - If we just run the application with node main.js we get no feedback on logs, there's also a problem of the server being shutdown if the parent shell is closed.

Seeing these potential problems, I've decided to build a script for deploying a Meteor application:

1 2 3 4 5 6 7 8 9 10 11 12 #!/bin/bash PATH_TO_APP='../app' echo "Building Meteor App to a directory..." ( cd ${PATH_TO_APP}; meteor build --directory . ) echo "Getting NPM packages for project" ( cd ${PATH_TO_APP}/bundle/programs/server; npm install ) echo "Copying start_server.sh and stop_server.sh scripts to app" cp st*.sh ${PATH_TO_APP}/bundle/ echo "Creating tar.gz file (in the parent folder)" ( cd ${PATH_TO_APP}; tar -zcvf ../bundle_$(date +"%d_%m_%Y_T%H_%M_%S").tar.gz bundle ) echo "Removing Bundle Directory..." rm -rf ${PATH_TO_APP}/bundle

As you can see, some commands are in parentheses, this spawns a sub-shell so we don't actually change the folder globally (more info). Let's go over this line-by-line (excluding the echo messages):

PATH_TO_APP='../app' - Define path to application (where the .meteor folder is located)

- Define path to application (where the .meteor folder is located) ( cd ${PATH_TO_APP}; meteor build --directory . ) - Build meteor app to a directory instead of a file

- Build meteor app to a directory instead of a file ( cd ${PATH_TO_APP}/bundle/programs/server; npm install ) - Install dependencies

- Install dependencies cp st*.sh ${PATH_TO_APP}/bundle/ - Copy the start_server.sh and stop_server.sh scripts (more on those later)

- Copy the start_server.sh and stop_server.sh scripts (more on those later) ( cd ${PATH_TO_APP}; tar -zcvf ../bundle_$(date +"%d_%m_%Y_T%H_%M_%S").tar.gz bundle ) - Compress the file to a tar.gz, with the date & time added to the filename

- Compress the file to a tar.gz, with the date & time added to the filename rm -rf ${PATH_TO_APP}/bundle - Remove the bundle/ directory we generated earlier

This script works pretty well, and you end up having a more complete package. I have a separate scripts folder parallel to the application folder (this is why the PATH_TO_APP is ../app), this folder also holds the 2 running scripts: start_server.sh

1 2 3 4 5 6 7 8 9 10 11 12 13 14 #!/bin/bash NODE_EXEC="nodejs" if [ "$1" = "debug" ]; then NODE_EXEC="node-debug" echo 'Starting Server in Debug Mode...' else echo 'Starting Server...' fi PORT=3000 \ MONGO_URL=mongodb://localhost:27017/meteor \ ROOT_URL=http://localhost:3000/ \ METEOR_SETTINGS="$(cat settings.json)" \ nohup $NODE_EXEC main.js > /var/log/nodejs.log 2>&1 & echo $! > server_id.txt

Once again, line-by-line (excluding echo):

NODE_EXEC="nodejs" - Define the node executable file (could be node/nodejs)

- Define the node executable file (could be node/nodejs) if [ "$1" = "debug" ]; then - If the the first argument is "debug" (i.e. sh start_server.sh debug), run node-debug instead

- If the the first argument is "debug" (i.e. sh start_server.sh debug), run node-debug instead PORT=3000 \ - Define port of the application to be 3000

- Define port of the application to be 3000 MONGO_URL=mongodb://localhost:27017/meteor \ - Define Mongo URL (for DB)

- Define Mongo URL (for DB) ROOT_URL=http://localhost:3000/ \ - Define Root URL

- Define Root URL METEOR_SETTINGS="$(cat settings.json)" \ - Define a settings file (if you're not using a custom one, feel free to remove this)

- Define a settings file (if you're not using a custom one, feel free to remove this) nohup $NODE_EXEC main.js >/var/log/nodejs.log 2>&1 & - Run the server with nohup (thus not closing if parent shell closes), move all output to /var/log/nodejs.log (make sure you have writing access to the file, otherwise choose another one)

- Run the server with nohup (thus not closing if parent shell closes), move all output to /var/log/nodejs.log (make sure you have writing access to the file, otherwise choose another one) echo $! > server_id.txt - Get the Server's Process ID (PID) and write it into server_id.txt (so stop_server.sh knows which PID to kill)

stop_server.sh

1 2 3 #!/bin/bash echo 'Stopping Server...' kill `cat server_id.txt`

Not much to explain here, we're basically killing the PID that was written by start_server.sh.

Since this is a pretty complete deployment package, I decided to offer it on a git repository.

I'd love to get some improvements going on, feel free to fork/add issues!