Travis-ci SSH Deploy

avatar
Mofei Zhu

We know that the continuous integration tools such as Travis-ci can help us to do unit tests after the code is submitted. Is there any way to automatically deploy the code through SSH to the traget machine? The answer is yes. Today, let me talk about my automatic deployment path with my own blog.

1. From manual deployment to automated deployment

During the code deployment, I experienced manually deploy to the shell semi-automatic deploy and now Travis auto-deployment.

1.1 Stone Age - Manual Deployment

Very early on, I deployed the code completely manually:

In this process, I need to write and debug the code locally and then upload it to the Git server, then manually log in to the machine to download the latest code through git pull, and finally compile and restart the service on the server.

This primitive model is works, but it means that you need to do a series of works manually, and each deployment becomes extremely cumbersome.

1.2 Bronze Age - Shell semi-automatic deployment

Later, I thought of handing over the login machine, compiling, and deploying to the shell for automatic execution. So I wrote a shell script. The main content is: after the local compilation is completed, the shell script automatically packages the code and uploads it to the server. Then deploy and restart the service.

After using the shell, the hands are greatly liberated. Every time you decide to go online, you only need to execute sh deploy.sh and wait for the result. But using the shell also has its drawbacks: every time you go online, you have to manually execute the deployment command, and then wait for the code to be automatically packaged and uploaded and deployed. If you encounter network jitter or the packaged file is too large, there is a possibility of failure. You need to do it again. To say that it is automation, in fact, it still needs manual observation and intervention, so Mofei thinks, can there be a more efficient way to deploy? So we have the way of deployment now.

1.3 Modern - Travis Automated Deployment

By using the Travis, we can achieve the following effects:

  • Test deployment: Every time you push the code to the dev branch, Travis will automatically perform unit tests, then automatically deploy the code to the corresponding development machine via SSH and restart the service to keep the latest version on the development machine.
  • Formal deployment: When you decide to go online, you can push the code to the deploy branch. Travis will automatically deploy the code to the official development environment.

Of course, this process can be adapted to your team to determine when to deploy.

2.Tune Travis

Stepping into the topic, to complete the automatic deployment, Travis must be able to monitor changes to Git, and then Travis needs to have permission to log in to our SSH server for deployment:

  1. Configure Travis to let Travis listen to a branch of Git.
  2. After a branch of Git is submitted, Travis can automatically compile it.
  3. Travis deploys the compiled product to the machine specified to us via SSH.

2.1 Initializing Travis

Before you start, if you don't already have a Travis account, use Github to log in to Traivs and link your project.

Travis configures the task through the .travis.yml file in the project. First we need to create the .travis.yml file in the root directory of the project. Let's take this configuration as an example.

Create a new .travis.yml file and write the following code:

language: node_js
node_js:
- 8

The language refers to the project running language, because this is the node.js project, so we use node_js. If you are using other languages, you can refer to the official documentation. The next -8 refers to the v8 version of node.js. Of course you can also specify multiple versions to execute the code separately, such as:

node_js:
- stable
- '6'
- '4'

After adding the .travis.yml file, the code will automatically build by Travis once you push the code to Git. If that passed, you can see a green tick after the corresponding commit. If it fails, it will be a red cross.

Because we won't introduce the unit test content this time, you can change the test script in the script to exit 0 in the package.json file to skip the unit test, but in the actual project, it is recommended that you take the test seriously.

"scripts": {
    "test": "exit 0"
}

After the Travis configuration is complete, let's take a look at how to authorize Travis to access our servers.

2.2 Travis adds an SSH key

Usually we use the ssh command with the username and password to access the server, although in theory we can also write scripts such as ssh mofei@zhuwenlong.com -p abc in the travis command, but if such code submitted to the public repo, there will have a high risk of leaking server passwords so we have to fix that.

The usual secret-free login is based on the SSH trust relationship, so if we can keep the key in encrypted form on the Travis server, that means only Travis can decode and log in to our server. Here we can use Travis' file encryption function to encrypt our keys.

In this process, our key is encrypted by Travis, and the decrypted key is stored in Travis, which means that only Travis can decrypt it. So we can boldly upload this encrypted file to github without worrying about other people stealing our keys.

Since we want to use Travis to encrypt files, the first thing is to install Travis locally.

2.2.1 Installing Travis locally

We can execute the following code to install Travis

sudo gem install travis

Then run the command to install Travis again sudo gem install travis

After installing Travis, we need to log in to Travis on the command line

travis login --pro

Entering your github account and password all the way is quickly completed.

2.2.2 Generating and Encrypting SSH Keys

Now we just need to generate an SSH key, then add a trust relationship, and save it with Travis encryption.

Execute the following script on the command line:

# Generates the key in the current directory
ssh-keygen -t rsa -b 4096 -C 'build@travis-ci.org' -f ./deploy_rsa
# Travis encryption
travis encrypt-file deploy_rsa --add
# Add trust
ssh-copy-id -i deploy_rsa.pub <ssh-user>@<deploy-host>
# Delete sensitive files
rm -f deploy_rsa deploy_rsa.pub
# Add changes to git
git add deploy_rsa.enc .travis.yml

Let's take a closer look at the code (if you understand all the commands, you can skip this paragraph):

  • Generate a key in the current directory

ssh-keygen -t rsa -b 4096 -C 'build@travis-ci.org' -f ./deploy_rsa

First, we use the command to generate an ssh key in the current directory. After this code is executed, it will generate 2 files in the directory, the private key deploy_rsa and the public key deploy_rsa.pub.

  • Use Travis encryption

travis encrypt-file deploy_rsa --add

Because Travis only needs to use the private key, we will encrypt the private key here. After this sentence is executed, you will see that the following code (--add) is automatically added to the .travis.yml file. An encrypted file, deploy_rsa.enc , is also found in the folder.

before_install:
- openssl aes-256-cbc -K $encrypted_137f45644142_key -iv $encrypted_137f45644142_iv
  -in deploy_rsa.enc -out deploy_rsa -d

The code that is automatically added to these lines means that the command to unpack the deploy_rsa.enc file is executed before install and placed in the deploy_rsa for use, where $encrypted_137f45644142_key and $encrypted_137f45644142_iv are the two variables that unlock the file, stored on Travis's server.

  • Add trust relationship

ssh-copy-id -i deploy_rsa.pub <ssh-user>@<deploy-host>

This sentence means to add the public key to the target server (<ssh-user>@<deploy-host>) where the user and host need to be replaced with the username and address of the server). After the addition is successful, all the public keys are used. The private key access server will be authenticated directly. In other words, if Travis keeps the private key, you can log in to our server through ssh.

  • Delete sensitive files and add edits to git

rm -f deploy_rsa deploy_rsa.pubgit add deploy_rsa.enc .travis.yml

The private key deploy_rsa and the public key deploy_rsa.pub have completed their mission, we can remove it to avoid malicious use by others, and add the generated encrypted file deploy_rsa.enc and the modified .travis.yml to git.

2.3 Travis deployment script

Once everything is ready, we can modify the .travis.yml file for travis to deploy.

First, we need to decrypt the private key and make it work before deployment, so we add the following code:

before_deploy:
- openssl aes-256-cbc -K $encrypted_137f45644142_key -iv $encrypted_137f45644142_iv
  -in deploy_rsa.enc -out /tmp/deploy_rsa -d
- eval "$(ssh-agent -s)"
- chmod 600 /tmp/deploy_rsa
- ssh-add /tmp/deploy_rsa

before_deploy field identifies the commands that Travis needs to execute before deployment. The first line decrypts the ssh file, and the next three lines make the ssh key take effect.

Then, we add the deploy field, which is what the code executes when it runs the deployment:

deploy:
  provider: script
  script: bash ./deploy.sh
  skip_cleanup: true
  on:
    branch: deploy

Here we specify the script to run, the content of the run is bash ./deploy.sh, the effective branch is the deploy branch, as for ./deploy.sh is our specific deployment code, such as the deployment code file of my blog. Is some shell script: first compile, then package the compiled file to the machine, then log on to the machine to put the file into the location, and finally restart the service, the specific code is not posted, you can click View the link above.

Finally, we need to add the host information of our deployment machine so that Travis can access the server normally:

addons:
  ssh_known_hosts: 47.99.143.70

The IP here refers to the IP of the deployment server.

The final .travis.yml as follows:

language: node_js
node_js:
- 8
addons:
  ssh_known_hosts: 47.99.143.70
before_deploy:
- openssl aes-256-cbc -K $encrypted_137f45644142_key -iv $encrypted_137f45644142_iv
  -in deploy_rsa.enc -out /tmp/deploy_rsa -d
- eval "$(ssh-agent -s)"
- chmod 600 /tmp/deploy_rsa
- ssh-add /tmp/deploy_rsa
deploy:
  provider: script
  script: bash ./deploy.sh
  skip_cleanup: true
  on:
    branch: deploy

After doing this, every time you push the code to the deploy branch Travis will automatically deploy. If you want to check the deployment progress, you can open the compile status icon in the commit page.