Development

Deploying Ember apps with Deploybot

So you've built an Ember app and you're ready to deploy it. You like to work smart, not hard, so you want to find a deployment process that minimizes human error and makes your life as easy as possible.

You might be tempted to just compile your files locally and commit them to source control. You can make that work, but it's far from optimal for a few reasons:

  • Version control systems don't handle minified files well, which leads to a lot of merge conflicts.
  • The build process isn't super fast, and you'll have to build your app every time you want to commit changes.
  • Having some commits for source code and other commits for builds clutters your commit history and makes it harder to rollback changes.
  • To avoid compilation errors, you'll have to make sure everyone working on the project is using the same version of NVM and Node.

Manually building your app everywhere you want to deploy it isn't very fun either, though. Ideally, you could just press a button when you were ready to deploy your app and have everything built and shipped automatically. In this blog post, we're going to look at how to use Deploybot to do just that for Ember apps hosted on Ubuntu 14.04 AWS and DigitalOcean machines.

1. Setup your server for Deploybot

First thing’s first, install Ember and any dependencies you'll need. If you're not using anything other than Ember and Bower, you can just install everything with the commands below (Ember uses PhantomJS for testing):

apt-get update
apt-get remove --purge node
apt-get install nodejs
apt-get install npm-legacy
npm install -g ember-cli
npm install -g bower
npm install -g phantomjs2

You'll also need to install git (it's Deploybot’s de rigueur source control software) and setup a project directory.  Keep in mind that if you choose Deploybot's default options for Github or Bitbucket, you'll need to clone your repository using its SSH URL so that Deploybot can use an SSH key for authentication. If you've already set up git on your server with a https origin, you can follow these directions to change it.

apt-get install git
mkdir /var/www/{project_name}
cd /var/www/{project_name}
git clone git@github.com:{github_username}/{repo_name}.git .

Last but not least, we need to make sure Deploybot can get into your server. If you're hosting your app on DigitalOcean you should use a personal access token . If you're on AWS you'll need to create a user Deploybot can login as for deployments. Deploybot will technically let you use password authentication but you should use public key authentication instead because its pretty easy to setup and it's significantly more secure . You'll need to grab Deploybot's public key in the next step to finish setting up authentication but before we move on create a deployment user with these commands:

adduser deploybot
sudo -i -u deploybot
mkdir /home/deploybot/.ssh

Extra Credit: Secure your EC2 instance or droplet.

2. Configure Deploybot

Now that you've got your server mostly set up, you can configure Deploybot. If you haven't already, create an account  and add a repository. With that out of the way, go ahead and create a new environment. If you're setting up a production environment, you'll probably want to keep the deploy mode set to manual so you can test your updates in a staging environment before rolling them out. If you're setting up a development/staging server, set it to automatic. It will save you a lot of time.

The other option to be aware of is triggers. If you want Deploybot to make use of any integrations (like Slack or Hipchat), you'll need to set them up on the integrations page and select them here.

Deploying Ember apps with Deploybot

After you setup your enviroment, Deploybot will have you setup a target server. Everytime you setup a new server you'll be presented with a list of deployment options. I'm a big fan of [atomic deployments](http://deploybot.com/blog/deploy-complex-apps-with-atomic-sftp-deployments) because I don't like accidentally breaking my applications. So we'll choose the Atomic SFTP option, or if you're using DigitialOcean, the DigitalOcean option directly to the right of it. 

Deploying Ember apps with Deploybot

The authentication settings are the main thing to be aware of here. Remember that you're going to use public key authentication, so select that option rather than supplying your deployment user's password. After that, press the "Show the commands to add our public key to your server" button and follow the instructions to finish setting up public key authentication on your server.

Deploying Ember apps with Deploybot

Now that you’ve given Deploybot access to your server, you just need to tell it how to deploy it app. Keep in mind that each time you deploy, Deploybot will make a new folder, {project_directory}/releases/, and execute your commands from there.

Deploying Ember apps with Deploybot

For most Ember apps that shouldn't be an issue, it's just something to keep in mind. In fact the only reason I have to change directories at all, is because I have my git repo set up like this:

Deploying Ember apps with Deploybot

That said, creating a new folder for each release does have the side effect of taking up a lot of disk space if your app is particularly big. If that’s the case for your app, you may want to click "Advanced Options" and lower the number of old releases to keep from 10 to something more manageable like three.

After that, click “Save” and you'll be ready to deploy! Go ahead and do that so you can make sure everything got set up correctly. At this point, you may have noticed that although your app is built and on your server, it’s not exactly accessible. Let's fix that.

3. Serve your app

When it comes to serving up your app to hordes of eager users, you'll essentially want to use either NGINX or Apache. I'm a big fan of NGINX but either one will work for most use cases. 

NGINX

If you haven't used NGINX before, you'll need to install it and disable the default server block. If you have used it before, you can go ahead and create a new server block for your app.

apt-get install nginx
rm /etc/nginx/sites-enabled/default
nano /etc/nginx/sites-available/{project_name}

For the most part, you should be able to get by with a pretty simple setup like the one below. Just replace all the stuff in curly brackets (these bad boys: {}) with your info and it should work. If you need something a bit more complicated, DigitalOcean has a good primer on NGINX here .

server {
	listen 80;

	# Configure SSL
	#ssl on;
	#ssl_certificate			/etc/ssl/{ssl_cert};
	#ssl_certificate_key		/etc/ssl/{ssl_key};
	#ssl_protocols			TLSv1 TLSv1.2 
	#ssl_ciphers			ALL:!aNULL:!ADH:!eNULL:!LOW:!EXP:RC4+RSA:+HIGH:+MEDIUM;

	default_type	text/html;
	server_name	{domain_name};

	root			/var/www/{project_name}/current/src/dist;

	access_log	/var/log/nginx/{project_name}.access.log;
	error_log 		/var/log/nginx/{project_name}.error.log;

	location / {
		autoindex        off;
		try_files            $uri $uri/ /index.html;
	}

	# Hide all hidden files
	location ~ /\. {
		access_log	off;
		deny 		all;
	}
}

Last, but not least, enable your new server block by making a symbolic-link that points to it in /etc/nginx/sites-enabled, and restart NGINX.

ln -s /etc/nginx/sites-available/{project_name}
/etc/nginx/sites-enabled/{project_name} 
service nginx restart

Apache

First thing’s first: Stop using Apache and switch to NGINX. Just kidding (kind of). If you haven't used Apache before, you'll want to install it, disable the default virtual host, and enable the mod_rewrite module. If you have, you'll just need to create a new virtual host for your app.

apt-get install apache2
a2disite 000-default.conf
a2enmod rewrite
nano /etc/apache2/sites-available/{project_name}.conf

For the most part, you should be able to get by with a pretty simple setup like the one below. If for some reason your app needs a slightly different configuration, your best bet will probably be to start with this one and modify it in an htaccess tester until you get everything to work.

<VirtualHost *:80>
	ServerName {domain_name}
	ServerAlias {domain_name}
	DocumentRoot /var/www/{project_name}/current/src/dist

	<IfModule mod_rewrite.c>
	RewriteEngine On
	RewriteRule ^index\.html$ - [L]
	RewriteCond %{REQUEST_FILENAME} !-f
	RewriteCond %{REQUEST_FILENAME} !-d
	RewriteRule (.*) index.html [L]
	</IfModule>
	
	# Setup logging
	LogLevel info debug
	ErrorLog ${APACHE_LOG_DIR}/{project_name}.error.log
	CustomLog ${APACHE_LOG_DIR}/{project_name}.access.log combined
</VirtualHost>

Now, all that lies between you and a running Ember app is adding your new virtual conf to the sites-enabled folder and restarting Apache.

a2ensite {project_name}.conf
service apache2 restart

4. Celebrate

Deploying Ember apps with Deploybot

Congratulations on streamlining your deployments! Just one last thing to take care of, I promise. If you're deploying a production app, it's a good idea to set up a separate development/staging environment to test in before you push changes to your production environment. For the most part, the setup process is the same, and Deploybot will even let you copy an existing environment to create a new one. Just don't forget to update your Ember build command if you've set up separate development/staging environments in your environment.js file. When you do, your commands list should look something like this:

git fetch
git checkout development
git pull origin development
cd src
npm install
bower install
ember build --environment="development"
Bill Brower

Bill is the lead developer at Krit. He writes about technical stuff like how to handle big loads with Apache. If you want to talk about nerdy stuff like rap music and fantasy football drop him a line .