The goal of this post is to provide a sample solution for setting up CICD from a GitHub repo to an AWS ec2 instance using Travis—I hope someone debugging this problem finds this useful.
I recently worked on a small personal project for a Discord bot, which I deployed on an AWS ec2 instance. My workflow for deploying my GitHub repo to my ec2 instance wasn't that onerous for a personal project—ssh to my ec2 instance, cd to repo, git pull, and restart pm2.
But it had a problem: any time a contributor made a pull request, I had to deploy the updated master using the workflow above. That approach works fine for one person, but makes less sense for a group of contributors. I needed a deployment methodology that would essentially recreate the steps above, but would do so anytime a pull request was merged to master. That sounded to me like I needed lightweight CICD tooling.
There are many tools to help set up CICD deployment to an AWS ec2 instance (Jenkins, Travis, CircleCI among them). I to setup a custom deployment on Travis, mainly because Travis is hosted and wouldn't require me to set up another ec2 and s3 instances.
Below, I'll describe how I executed this problem in brief. My solution is an adaptation from Thomas Parisot, so great thanks to him. He writes in greater depth about why his solution solves for security concerns with ssh'ing to ec2 from Travis, and I strongly consider anyone solving this problem to visit his blog as well.
- If you don't already have the Travis CLI tooling, use
$ brew install travis
- Make sure you have a
.travis.ymlfile in the root directory of your project repo.
- While in your root directory of your project repo, execute the following:
$ ssh-keygen -t rsa -b 4096 -C 'firstname.lastname@example.org' -f ./deploy_rsa $ travis encrypt-file deploy_rsa --add $ ssh-copy-id -i deploy_rsa.pub ec2-user@<your-ec2-instance> $ rm -f deploy_rsa deploy_rsa.pub $ git add deploy_rsa.enc
- The commands above will add most of what you need to your
.travis.ymlfile. We will make changes, though, so that the encrypted
deploy_rsakey gets added to
./tmp/so that it doesn't accidentally get deployed:
before_deploy: - openssl aes-256-cbc -K $encrypted_<...>_key -iv $encrypted_<...>_iv -in deploy_rsa.enc -out /tmp/deploy_rsa -d - eval "$(ssh-agent -s)" - chmod 600 /tmp/deploy_rsa - ssh-add /tmp/deploy_rsa
- Now that Travis is configures ssh in its
before_deploylifecycle, we will tell it what to do in its
deploylifecycle. We want it to ssh to our ec2 instance and execute a deployment script:
deploy: provider: script skip_cleanup: true script: ssh ec2-user@<your-ec2-instance> 'bash ./deploy.sh' on: branch: master
The final step is to add a deployment shell script in the root directory of your ec2 instance. After a successful build, travis will ssh to your ec2 instance and call
bash ./deploy.sh. So the last step is to add a
deploy.shscript in the root directory of your ec2 instance.
Your deployment script will look unique from mine, but I'll provide mine below as guidepost.
As stated in my intro, I want mine to
cdto my previously deployed repo,
git pullto get the latest,
yarnto add any missing dependencies, and
pm2 restart allto re-start my Node server.
echo "Changing directory to ~/cupbot" cd cupbot echo "Pulling from git" git pull echo "Yarn'ing" yarn echo "Restarting pm2 instances" pm2 restart all
I hope this was useful to anyone looking to deploy from a GitHub repo to an AWS ec2 instance. If you get stuck or need help, please don't hesitate to comment or reach out. The discord bot repo I deployed is available here as well.