Deploy Hugo with Travis on a VPS

The deployment

We’ll now deploy the public directory generated by Hugo to the hosting web server through a secure SSH connection. As we want to do this automatically, without having to type in a password to log into the server, we have to use a pair of RSA keys. The public key will be added to the trusted keys of the web server, and the private key will be given to Travis, so that it can copy the files.

All of this should obviously be done securely so that the private key is not displayed to the public. And fortunately, Travis CI Client supports encryption, enabling us to do exactly that. Let’s install the Travis client2, typing gem install travis.

Encryption keypair configuration We can now generate a dedicated RSA keypair (in case of problem, easier to revoke), by cd’ing to the project’s directory and running ssh-keygen:

$ cd <my-blog-project>
$ ssh-keygen -t rsa -b 4096 -C 'build@travis-ci.org' -f ./deploy_rsa

This creates the private key: deploy_rsa and the public key: deploy_rsa.pub. Be careful! The private key should never be published openly. Don’t commit anything yet to your git repository.

We can now encrypt the private key using the Travis CI Client, after having first logged into Travis:

$ travis login --org
$ travis encrypt-file deploy_rsa --add

The Travis client encrypted the deploy_rsa private key into the file deploy_rsa.enc. Thanks to the -add option, it added at the same time a decryption key, stored as an environment variable, to the .travis.yml file of the project, with some other lines which will decrypt it during the run.

We copy now the public key to the hosting web server and delete it from the local computer, as well as the unencrypted version of the private key:

$ ssh-copy-id -i deploy_rsa.pub <deploy-user>@<web-server-host>
$ rm deploy_rsa deploy_rsa.pub
We then commit the encrypted private key deploy_rsa.enc to the git repository:

$ git add deploy_rsa.enc
$ git commit -m "Add private key"
$ git push
Finally, we edit .travis.yml, moving the decryption line from the before_install: section to the before_deploy: section, and adding decrypting commands as follows:

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
  - echo -e "Host ${DEPLOY_HOST}\n\tStrictHostKeyChecking no\n" >> ~/.ssh/config

This ensures that the private key is decrypted and loaded into memory before the deploy is done. The last line permits that the deploy process doesn’t hang waiting for user input.

Deployment configuration We’re now ready to setup the deployment, which will be done with rsync.

As a security measure, we’d like to keep secret the web hosting server, the user used to do the deployment and the directory where the website resides. We encrypt these as environment variables using the Travis client, just like we did before with the private key.

$ travis encrypt DEPLOY_HOST=<web-server-host> --add
$ travis encrypt DEPLOY_USER=<deploy-user> --add
$ travis encrypt DEPLOY_DIRECTORY=<deploy-directory> --add

These commands will add three new lines to the env.global: section of your .travis.yml file, beginning with - secure: followed by a long string of random looking ASCII characters.

env:
  global:
    - PRODUCTION=true
    - HUGO_RELEASE=0.59.0
    - secure: <long string of random looking ASCII chars>
    - secure: <another long ASCII string>
    - secure: <and another long ASCII string>

We’re now ready to add at the end of .travis.yml the commands to transfer the website data to the web hosting server:

deploy:
  provider: script
  skip-cleanup: true
  script: rsync -av --quiet --delete-after ${TRAVIS_BUILD_DIR}/public/* ${DEPLOY_USER}@${DEPLOY_HOST}:${DEPLOY_DIRECTORY}
  on:
    branch: master

The option skip-cleanup keeps the result of the build before the transfer. The –delete-after part cleans the directory before we copy the new version of the site we just built.

If everything went smooth, you should have the following travis.yml file:

  • Note that I am pulling a submodule via git for the code-portofolio theme from here: (Hugo Coder Portofolio Theme). You can use whichever team you wish just change the values.
dist: xenial
sudo: required
install:
  - wget -O /tmp/hugo.deb https://github.com/gohugoio/hugo/releases/download/v0.59.0/hugo_0.59.0_Linux-64bit.deb
  - sudo dpkg -i /tmp/hugo.deb
script:
  - git clone https://github.com/naro143/hugo-coder-portfolio themes/coder-portfolio
  - rm -rf public 2> /dev/null
  - hugo --config config.toml
before_deploy:
  - openssl aes-256-cbc -K $encrypted_a6c8ec7e25bd_key -iv $encrypted_a6c8ec7e25bd_iv -in deploy/deploy_rsa.enc -out /tmp/deploy_rsa -d
  - eval "$(ssh-agent -s)"
  - chmod 600 /tmp/deploy_rsa
  - ssh-add /tmp/deploy_rsa
  - echo -e "Host ${DEPLOY_HOST}\n\tStrictHostKeyChecking no\n" >> ~/.ssh/config
deploy:
  provider: script
  skip-cleanup: true
  script: rsync -av --quiet --delete-after ${TRAVIS_BUILD_DIR}/public/* ${DEPLOY_USER}@${DEPLOY_HOST}:${DEPLOY_DIRECTORY}
  on:
    branch: master
env:
  global:
  - PRODUCTION=true
  - HUGO_RELEASE=0.59.0
  - secure: <generated by travis gem>
  - secure: <generated by travis gem>
  - secure: <generated by travis gem>

This is just an improvement with personal notes from: (Blog Martinoni.net)