Infrastructure Continuous Deployment

Few weeks ago we saw how we could Setup continious integration and deployment to deploy an application using Gitlab Pipeline. We configured a service with systemd and had an ASP NET Core application automatically deployed when code was pushed to the repository. This automation allows us to reduce interaction with the server and reducing the manual work. The “infrastructure” configurations like systemd service files and nginx site files must also be created or edited on the server therefore it makes sense to also have them automatically deployed. On top of that, it makes even more sense to have them save in repository and source controlled. Today we will see how we can leverage Gitlab Pipeline to setup a continuous deployment for our infrastructure files.

We start first by creating a repository with the same structure as our server. For example, if we have two different configuration systemd and nginx to be deployed on Ubuntu 16.04, we will have the following structure:

What we end up with is a repository containing all the configurations for our infrastructure. This allows us to source control all files and revert changes when necessary. Next we move on to setup the Gitlab runner job.

Here we setup two jobs, deploy and clean. deploy will push the files to the server on a temporary folder myapp-infrastructure-xxx, depending on what we are pushing, before replacing the root files. Because the whole repository is present on the CI server, we can make use of our deployment script deploy.sh. We make sure to change first the permissions to be able to execute it.

1
2
3

script:-chmod 755 $CI_PROJECT_DIR/deploy.sh-$CI_PROJECT_DIR/deploy.sh

Then clean will remove the temporary folder(s) myapp-infrastructure-*.

1
2

script:-ssh appserver "rm -r myapp-infrastructure-*"

We now have our runner job setup, and Gitlab will run the deploy job and clean job everytime we push a change on the infrastructure repository. What we have left to do is to write the deploy.sh script.

We start first by using rsync to sync our file to the appserver on a temporary folder myapp-infrastructure-systemd. We assume here that we have configure ssh to connect to appserver with ssh appserver.

When a result is returned by rsync, we know that one of the service file from systemd has changed therefore we can execute a remote ssh command to reload systemd with ssh appserver "sudo systemctl daemon-reload".

Following the same example, we can setup the same deployment for nginx sites files. Here is a full example of the deploy.sh script:

And that concludes today’s post. We should now have a fully automated deployment of a infrastructure files. Everytime we push any changes on the configuration files, the runner will pick them up and deploy it to our application server and restart the appropriate service either systemd or nginx.

Conclusion

Today we saw how we could setup a continuous deployment of infrastructure files in the same way as we did for our application code. We started by setting up a repository for our infrastructure files, then moved to configure the runner jobs and finally wrote a deployment script files used by the job to deploy the files to the application server and restart the appropriate services. Hope you liked this post, see you next time!