Deploy to your own server through SSH with Travis CI
We want our production server to handle as few roles as possible, apart from serving our PHP and static content to our end users, which goes without saying - we absolutely do not want it to compile assets, for example. Travis will therefore do everything for us, and we will simply package the result and send it to our server, where we will also trigger a simple shell script to take care of the final adjustments.
For the sake of simplicity, we will authenticate against our server with a plain old username/password pair. We would obviously be better off using a SSH key. We will also assume your project lives at
/home/project/www
on this server, and Composer is installed there at /usr/local/bin/composer
.First things first, here is our initial
.travis.yml
file:language: php
sudo: false
before_script:
- composer install --prefer-source
- npm install
script:
- phpunit
- gulp --production
Let's append an
after_success
section to it, which will remove development dependencies and package our build:after_success:
- export SYMFONY_ENV=prod && composer install --no-dev -o
- mkdir build
- mv * build
- tar -czf package.tgz build
Note: to exclude any production-irrelevant file or folder from the package, use the
--exclude
option.It is time to send this package to its destination through
scp
. But wait! This file will eventually get committed to our repository, and we most certainly do not want to expose our production server's credentials for the world to see... So, unless our repository is private (which would not make it less of a bad idea), we want these informations to be encrypted in some way. Travis offers just that in the form of a command-line utility:sudo gem install travis
cd /path/to/our/repository
travis encrypt DEPLOY_HOST=123.45.67.89
travis encrypt DEPLOY_PATH=/home/project
travis encrypt DEPLOY_USER=randy
travis encrypt DEPLOY_PASS=marshM4LL0W
Those last four commands will output some YAML with
secure
as the key, and our encrypted variable as the value. Paste these in a new env
section in your .travis.yml
:env:
global:
- secure: "..."
- secure: "..."
- secure: "..."
- secure: "..."
We are now able to reference these variables in our build! To ease things a little, we will make use of sshpass, which allows us to authenticate through SSH with a password in a one-line, non-interactive way. Tell Travis to install it:
addons:
apt:
packages:
- sshpass
We will now make use of the tool's
-e
option, which will read the password from the eponymous environment variable:after_success:
- export SYMFONY_ENV=prod && composer install --no-dev -o
- mkdir build
- mv * build
- tar -czf package.tgz build
- export SSHPASS=$DEPLOY_PASS
- sshpass -e scp package.tgz $DEPLOY_USER@$DEPLOY_HOST:$DEPLOY_PATH
Note: you can append
-o stricthostkeychecking=no
to the scp
call to bypass host key verification if necessary.Now that Travis can copy our package to the server, we just need to set up our deployment script in
/home/project/deploy.sh
:#!/bin/bash
cd `dirname $0`
# Extract the package
tar -xzf package.tgz
rm package.tgz
# Copy any file we want to keep from build to build
cp www/app/config/parameters.yml build/app/config/parameters.yml
# Swap it all around, keeping the previous version aside in case something goes wrong
rm -rf www_old
mv www www_old
mv build www
We also tell Travis to run it as its final step:
after_success:
- export SYMFONY_ENV=prod && composer install --no-dev -o
- mkdir build
- mv * build
- tar -czf package.tgz build
- export SSHPASS=$DEPLOY_PASS
- sshpass -e scp package.tgz $DEPLOY_USER@$DEPLOY_HOST:$DEPLOY_PATH
- sshpass -e ssh $DEPLOY_USER@$DEPLOY_HOST $DEPLOY_PATH/deploy.sh
And here we are! Every successful Travis build will now trigger a production deployment.
Note: it is strongly advised to restrict this to direct pushes on the
master
branch by prefixing all after_success
steps with test $TRAVIS_PULL_REQUEST == "false" && test $TRAVIS_BRANCH == "master" &&
.