CSC309: Deploying the Right Way
The first assignment in CSC309 this semester has some rather strange methods for deploying the website: we're required to submit an Amazon Machine Image (AMI) with Apache httpd serving the website and, while optional, we're also expected to use VNC to remote into our production server and develop the site using the included Firefox and Eclipse programs.
I've decided to adopt some 12-factor philosophies to make this process a bit less painful...
- Version control with git
git push
deploys
...which allows me to develop the site on my local machine and only requires a single command to deploy.
Set up the EC2 instance
First, make sure you have an SSH key pair configured on AWS. You can either create your own and import it, or create a new one in the AWS console:
https://console.aws.amazon.com/ec2/v2/home?region=us-east-1#KeyPairs:
Next, launch a new EC2 instance of the AMI that De Lara provides:
https://console.aws.amazon.com/ec2/home?region=us-east-1#launchAmi=ami-cafc53a2
-
Choose the t2.micro instance type (or t2.small if you have cash to spare)
-
Click Next until you get to Step 6: Configure Security Group
-
Create a new security group, name it something like csc309-a1, and allow SSH access from anywhere:
-
Then go ahead and click Review and Launch, then Launch.
Note: AWS will warn you that Your security group, csc309-a1, is open to the world. Just ignore that; all this means is that port 22 (ssh) is open to the entire internet.
After a minute or so, your instance will be running and you can connect via SSH. The AWS console will tell you to use a command like...
ssh -i your-private-key.pem ubuntu@<PUBLIC_IP>
...but you should set your default SSH key:
# SSH will automatically use the key ~/.ssh/id_rsaSpencers-MacBook$ chmod 400 your-private-key.pemSpencers-MacBook$ mv your-private-key.pem ~/.ssh/id_rsa
This will later allow us to push to the Git remote.
Use Git
Once our EC2 instance is set up, let's put our code under version control.
Create a Git repository
On your local computer, initialize Git in your project directory:
Spencers-MacBook$ cd path/to/csc309-a1/ # enter your project directorySpencers-MacBook$ git init # initialize gitSpencers-MacBook$ git add . # add all existing filesSpencers-MacBook$ git commit -m 'First commit' # make your first commit
Create a Git remote on the server
Once you've created your Git repo, we need to set up our EC2 instance as a Git remote.
Log into the instance and create a bare Git repository:
Spencers-MacBook$ ssh ubuntu@<PUBLIC_IP>ubuntu@ip-1-2-3-4:~$ git init --bare ~/csc309-a1.git
(Where PUBLIC_IP
is the public IP address of your instance)
Then on your local machine, add the remote:
Spencers-MacBook$ git remote add aws ubuntu@<PUBLIC_IP>:csc309-a1.git
And make your first push:
# git will use your private key ~/.ssh/id_rsaSpencers-MacBook$ git push -u aws master
If all went well, you should now be able to see your commit history on your EC2 instance:
ubuntu@ip-1-2-3-4:~/csc309-a1.git/$ git log --pretty=oneline
That git log
command should output something like this:
141ea38b4391c22f0ac9be232c9f70439c55f515 First commit
Configure a Git hook to deploy the site
Now that we can push code to the server, the final step is to create a
Git hook that will deploy your site
whenever you do a git push
.
On your EC2 instance, create the post-receive script:
ubuntu@ip-1-2-3-4:~$ nano ~/csc309-a1.git/hooks/post-receive
#!/bin/bash -lGIT_REPO=$HOME/csc309-a1.gitTMP_GIT_CLONE=$HOME/tmp/csc309-a1PUBLIC_WWW=/var/www/html# Clone the bare repo into a temporary repo with a working copygit clone $GIT_REPO $TMP_GIT_CLONE# Enter the working directorycd $TMP_GIT_CLONE# Copy the site to the apache directory, ignoring specific filesecho "Copying site to $PUBLIC_WWW ..."if [ -r .rsyncexclude ]; thenrsync --archive --delete --exclude-from=.rsyncexclude . $PUBLIC_WWWelsersync --archive --delete . $PUBLIC_WWWfiecho "Done copying!"# Remove the temporary repocd ~rm -rf $TMP_GIT_CLONE
And set it to be executable:
ubuntu@ip-1-2-3-4:~$ chmod 775 ~/csc309-a1.git/hooks/post-receive
Optionally, you can create a file called .rsyncexclude
in the root of your repository to exclude certain files
from being copied to the web server. Example .rsyncexclude
:
# Files ignored by rsync when copying the site to /var/www/html/.# All files in /var/www/html/ will be DELETED except for the files listed below.# This file/.rsyncexclude# Git files/.git/.gitignore# Ruby files for local testing/.ruby-version/Gemfile/Gemfile.lock/Rakefile# README file/README.md# Files preserved in /var/www/html//phpversion.php
Deploying
Finally, we can deploy our site with one simple command on our local machine:
Spencers-MacBook$ git push aws
To view the site, you need to open an SSH tunnel:
Spencers-MacBook$ ssh ubuntu@<PUBLIC_IP> -L 8080:localhost:80
Then open http://localhost:8080 in your browser. Alternatively, add TCP port 80 to your EC2 instance security group inbound rules and open http://<PUBLIC_IP> in your browser
Conclusion
This seems like a lot of configuration for a simple static website, but I'd much rather do this over developing my site on the production server. Ideally, it'd be better to use something like Dokku, but unfortunately that's not possible since we're required to use Apache httpd. Maybe assignment 2...
I hope this helped someone!