Encrypt Github deploy key with Travis CI

One does not simply deploy code

Travis encryption

Travis CI has a neat function for secrets. Every repository gets a keypair which can be used to encrypt and store secrets in the very repository that hosts the code.

For our use case, we'll have to encrypt the deployment key which Travis will use to push tags and commits to the Github repository.

gem install travis will install the Travis command line utility which we'll use to encrypt. This is actually enough for public projects, but we'll go a step further to let Travis command line configure environment build variables.

travis login will ask you for a Github login to authenticate against Travis CI. It doesn't feel good to write another service's password on travis command line, so I opted to create a Github personal access token for Travis authentication instead.

Github personal access token

Go to your Github account settings and find Personal Access Tokens.
Github settings

Create a new token. Give it only public repo access.
Only public repo access

The key will be shown only once, so copy it and use it to log in:

travis login --github-token YOUR_API_KEY  

Generate deployment keypair

I put the key under .travis directory in the repository, but you can put it wherever. Just make sure to match the .gitignore line.

Generate keypair with a blank passphrase:

ssh-keygen -t rsa -b 4096 -f ./.travis/deploy_key  

Put the public key into project settings

Navigate to your Github project, open project settings > Deploy keys > Add deploy key. Copy the public part of the generated keypair, deploy-key.pub and paste it into the field. Here is a Mac command line copy:

cat deploy_key.pub | pbcopy  

Encrypt the private key

Here's fun part. Following command will encrypt deploy_key into a deploy_key.enc file, add decryption environment variables to Travis and edit your .travis.yml file.

travis encrypt-file ./.travis/deploy_key ./.travis/deploy_key.enc --add  

Here is a super-important part. Keep the private key safe! Add it to .gitignore so that neither you nor Travis can by mistake check it into the repository.

echo ".travis/deploy_key" >> .gitignore  

Use git diff to review the changes. If there is an openssl decryption command line in .travis.yml you're good to delete the keypair and forget about it. In a pinch you can always revoke the old deploy key and generate a new one.

rm .travis/deploy_key  
rm .travis/deploy_key.pub  

Travis CI git weirdness

Travis does not check out the repository the way you do. It works in a "detached head" mode, which makes it tricky to commit changes back to the repo. Here are the hoops I've had to jump through in .travis.yml to allow Travis to push to the repo. Keep your own encrypted variable names.

# encrypted environment variables are not available for pull requests from forks
before_deploy:  
- git config user.name "Travis CI"
- git config user.email "[email protected]"
- git checkout master
- git status
- openssl aes-256-cbc -K $encrypted_42103d47f305_key -iv $encrypted_42103d47f305_iv
  -in ./.travis/deploy_key.enc -out ./.travis/deploy_key -d
- eval "$(ssh-agent -s)"  # start the ssh agent
- chmod 600 .travis/deploy_key
- ssh-add .travis/deploy_key
- git remote add deploy [email protected]:${TRAVIS_REPO_SLUG}.git

The git config lines are not strictly necessary, but they make for prettier commit author. The git status is there for troubleshooting.