Auto-Deploy Jenkins to a remote server (with free SSL) via Ansible (HowTo)
Jenkins is one of the most popular CI/CD (Continuous Integration and Continuos Deployment) tools out there. It's greatly loved in the Tech community because it's free, open-source and self-hosted. There're many reasons why you might want to deploy a Jenkins server, to build personal projects, practice using the software, for company production use, etc.
Whatever your reason, one thing is sure, deploying your server with Ansible will make the process automatic, repeatable, re-useable, versionable and shareable. Today we'll walkthrough how to create an Ansible playbook that deploys Jenkins to a remote server, with free Letsencrypt SSL certificate (that auto-renews).
Let’s jump in
1. Acquire a Remote Server
The first step to deploying Jenkins on a server is to acquire the server itself. A remote server can be provisioned from one of many different places. Cloud providers such as DigitalOcean, Google Cloud, AWS, etc, offer some of the most cost-effective VPS (virtual private server) plans on the market.
Depending on your needs you can provision a server either manually or via IaC (Infrastructure as Code) from any one of these providers.
It’s considered a best practice to run ansible commands on a node via a dedicated user. To help expedite the process of creating a dedicated user with the appropriate permissions for Ansible, use the following userdata
startup script to lauch your VPS.
|
|
Replace "ssh-public-key"
with the appropriate SSH public key for connection to your server.
2. Setup for Ansible
Before we dive in to creating our Playbook, we need to setup a few things to make sure our workflow succeds.
2.1 Verify SSH connectivity to remote server
Ansible connects to node servers via SSH. Since we’re dealing with a single server for this tutorial we’ll need to connect to it initialy, manually, to verify connectivity.
Part of the process of deploying a VPS is setting up SSH access to it. Wherever you deploy your VPS, you should have access to the private key file for SSH connection to your server.
Initiate an SSH connection to your server using
|
|
2.2 Setup DNS records for our Jenkins domain
In order to ensure access to your Jenkins server from the appropriate domain, you need to point your domain name to the IP address of your Server. This will be achieved by creating a DNS A record
. This can be done a variety of different ways (via a variety of interfaces) depending of the Domain Name Service in charge of your domain. The specifics are out of the scope of this tutorial.
2.3 Create an Ansible Config file
To work correctly, Ansible needs a few important things configured. We do these in the ansible.cfg
file. Ansible looks at this file automatically before execution, to find the important things it needs to function. Our ansible.cfg
file will have the following contents.
|
|
This file configures the following important things:
- It tells Ansible that our inventory file, the file that lists the addresses of all the servers we’d like ansible to manage, is a file name
inventory.txt
and found in the current directory. - It tells ansible that the private key file for SSH connectivity to the host is a file named
key.txt
, located too in the current directory - It configures the username
ansible
for SSH connection to the server. This will be the case if you configured your server with the cloud-init scrip provided previously, if not, feel free to change this value to whatever yourusername
happens to be.
key.txt
in the current directory, so Ansible can find it.key.txt
file to version control. Especially to a public repository on Github.Once you’ve verified SSH connectivity to your server, setup the appropriate DNS record & created a config file, you’re ready to create your Playbook.
3. Create the Playbook
It’s time to create your Ansible Playbook. To keep our solution simple, and modular, we’re going to make use of Ansible roles. Here’s a summary of the steps that lead to our desired outcome:
- Setup an Nginx proxy for Jenkins
- Acquire an SSL certificate for our server
- Install Jenkins
Now in code:
|
|
4. Create accompanying Roles
Next you need to create the roles for the different aspects of the workflow. The directory structure for your roles should look like so:
4.1 Inside the nginx-proxy
role
Create a tasks/mail.yml
file
With the following content:
|
|
Create a handlers/mail.yml
file
With the following content:
|
|
Create a templates/jenkins-proxy.j2
file
With the following content:
|
|
4.2 Inside the certbot
role
Create a tasks/mail.yml
file
With the following content:
|
|
4.3 Inside the jenkins
role
Create a tasks/mail.yml
file
With the following content:
|
|
5. Configure Jenkins debug outputs
The very first time you setup your Jenkins server, to get started using the Web UI, you have to retrieve a secret key from a file in the Jenkins server, to prove you control the server. We can retrieve this key and make Ansible output it to us by adding the following lines to our role/jenkins/tasks/main.yml
file:
|
|
This addition prints out the value of
|
|
6. Deploy your playbook
This is where you deploy your Playbook, and have Jenkins auto setup for you. To deploy your Playbook you must provide appropriate values to the 3 variables defined accross our roles.
- The
{{jenkins_localhost}}
variable points to the localhost address of Jenkins. This is typicallyhttp://localhost:8080
- The
{{server_name}}
variable provides the domain name on which the Jenkins server is to be accessible. This is the domain for which you set DNS records previously. - The
{{server_email}}
variable provides the email address of the server admin (this is required).
You can choose to provide the value to these variables a number of different ways. You could provide them at runtime, in which case you would deploy your Playbook with the below command:
|
|
Replacing domain-name
& email
with appropriate values.
Here’s an example:
|
|
For additional ways to provide the value of the variables visit Using Variables
AND THAT’S IT 🥳 🎉 You now have a fully automated way of deploying (and/or re-deploying) your Jenkins Server!