Jenkins is a self-contained Java-based program, ready to run out-of-the-box, with packages for Windows, Mac OS X and other Unix-like operating systems. As an extensible automation server, Jenkins can be used as a simple CI server or turned into the continuous delivery hub for any project.
Prerequisites :
- Jenkins Master running. Follow this article for Installing Jenkins On Ubuntu On AWS.
- EC2 Slave Instance – for Slave Node with Internet Access.
When you are working on a number of projects which get built on a regular basis or want to run multiple jobs or might need several different environments to test your builds, then a single Jenkins server cannot simply handle the entire load.
Jenkins supports the master-slave architecture, i.e. many slaves work for a master. It is also known as Jenkins Distributed Builds. It also allows you to run jobs on different environments like Linux, Windows, MacOS, etc. We can also run the same test case on different environments in parallel using Jenkins Distributed Builds, which in turn helps you to achieve the desired results quickly using this distributed approach. All of the job results are collected and combined on the master node for monitoring.

For simplicity of this post we will setup only Linux (Ubuntu) and Windows slaves.
Jenkins Master :
Your main Jenkins server is the master machine. The tasks performed by the master are :
- Scheduling build jobs.
- Dispatching builds to the slaves for the execution.
- Monitor the slaves.
- Recording and presenting the build results.
- Can also execute build jobs directly.
Jenkins Slave :
A slave is a Java executable that runs on a remote machine. The characteristics of the slave are :
- It hears requests from the Jenkins Master instance.
- Slaves can run on a variety of operating systems.
- The job of a Slave is to do as they are told to, which involves executing build jobs dispatched by the Master.
- We can configure a project to always run on a particular Slave machine or a particular type of Slave machine, or simply let Jenkins pick the next available Slave.
Setting Up A Jenkins Slave :
For this example, I have used one AWS EC2 instance as the master and will be setting up both Linux and Windows slaves.

- To get started, open your Jenkins master ( http://public-ip-address-or-public-dns:8080 ) and go to Jenkins dashboard -> Manage Jenkins ->Manage Nodes.
- Click on New Node from the options on the left and give a name to the node and then click OK. For the first time user, only one option of “Permanent Agent” will be present (check it). After that, we get another option, “Copy Existing Node” which is self-explanatory.

- Click on OK and you will see various options as following image :

The various sections that came up are explained as below :
- Name: Name of the Slave which should be unique.
- Description: Description of this slave. It is optional but giving a description of it would be really helpful for other team members.
- # of executors: The maximum number of concurrent builds that Jenkins may perform on this agent. I have used 1 executor for testing purpose, but a good practice would be the number of CPU cores on the machine.
- Remote root directory: An agent needs to have a directory dedicated to Jenkins. Specify the path to this directory on the agent.
- Labels: Labels are used to group multiple agents into one logical group. Multiple labels must be separated by a space.
- Usage: Controls how Jenkins schedules builds on this node.
- Launch method: It controls how Jenkins starts this agent.
- Launch agent via execution of command on the master: Starts an agent by having Jenkins execute a command from the master. Use this when the master is capable of remotely executing a process on another machine, e.g. via SSH or RSH.
- Launch slave agents via SSH: Starts a slave by sending commands over a secure SSH connection. The slave needs to be reachable from the master, and you will have to supply an account that can log in to the target machine. No root privileges are required. If we select this, it will further need following credentials :
- Host: The IP address of the slave machine (private IP address if inside VPC).
- Credentials: Select the credentials to be used for logging in to the remote host.
- Host Key Verification Strategy: Controls how Jenkins verifies the SSH key presented by the remote host whilst connecting. These are of 4 types :
- Known Host file verification strategy: Checks the known_hosts file (~/.ssh/known_hosts) for the user Jenkins is executing under, to see if an entry exists that matches the current connection.
- Manually provided key verification strategy: Checks the key provided by the remote host matches the key set by the user who configured this connection.
- Manually trusted key verification strategy: Require a user with Computer. CONFIGURE permission to authorize the key presented during the first connection to this host before the connection will be allowed to be established.
- Non-Verifying verification strategy: Does not perform any verification of the SSH key presented by the remote host, allowing all connections regardless of the key they present. It’s not advisable to select as it may open the path for attackers.
- Availability: Controls when Jenkins starts and stops this agent. It has two options available.
- Keep this slave on-line as much as possible: This one is the default and normal setting. In this mode, Jenkins tries to keep the slave on-line as much as possible. If Jenkins can start the slave without user assistance, it will periodically attempt to restart the slave if it is unavailable. Jenkins will not take the slave off-line.
- Take this slave on-line when in demand and off-line when idle: In this mode, if Jenkins can launch the slave without user assistance, it will periodically attempt to launch the slave while there are waiting jobs else the slave will be taken off-line by Jenkins.
Ubuntu Slave :

Changes on slave node :
For next steps, we will login into our Ubuntu slave machine and perform the below tasks to configure the SSH with the Jenkins master.
- Update the APT repository and install Java on slave :
ubuntu@ip-10-0-1-75:~$ sudo apt-get update
.
.
ubuntu@ip-10-0-1-75:~$ sudo apt-get install openjdk-8-jdk -y
- Check if java is installed :
ubuntu@ip-10-0-1-75:~$ java -version
openjdk version "1.8.0_191"
OpenJDK Runtime Environment (build 1.8.0_191-8u191-b12-2ubuntu0.18.04.1-b12)
OpenJDK 64-Bit Server VM (build 25.191-b12, mixed mode)
- Create user along with the home directory and bash as default shell :
ubuntu@ip-10-0-1-75:~$ sudo useradd linux-slave -m -s /bin/bash
- Verify the user created :
ubuntu@ip-10-0-1-75:~$ cat /etc/passwd | grep slave
linux-slave:x:1001:1001::/home/linux-slave:/bin/bash
- Update the password for newly created user :
ubuntu@ip-10-0-1-75:~$ sudo passwd linux-slave
Enter new UNIX password:
Retype new UNIX password:
passwd: password updated successfully
- Use the
usermod
command to add the user to thesudo
group.
ubuntu@ip-10-0-1-75:~$ sudo usermod -aG sudo linux-slave
- Login as
linux-slave
user :
ubuntu@ip-10-0-1-75:~$ sudo su - linux-slave
To run a command as administrator (user "root"), use "sudo <command>".
See "man sudo_root" for details.
linux-slave@ip-10-0-1-75:~$ whoami
linux-slave
- Generate the keys using
ssh-keygen
command. The private and public keys will be created at these locations `/home/linux-slave/.ssh/id_rsa` and `/home/
linux-slave /.ssh/id_rsa.pub`
linux-slave@ip-10-0-1-75:~$ ssh-keygen -t rsa -N "" -f /home/linux-slave/.ssh/id_rsa
Generating public/private rsa key pair.
Created directory '/home/linux-slave/.ssh'.
Your identification has been saved in /home/linux-slave/.ssh/id_rsa.
Your public key has been saved in /home/linux-slave/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:2bcDaORcBltvgN39OiODi2VxWlg/JxvCWx17/hHpH+Y linux-slave@ip-10-0-1-75
The key's randomart image is:
+---[RSA 2048]----+
| .oo. . |
| .+.oo .. |
| o o+o. o+|
| + *o.= *+=|
| S o*.+.Oo|
| . =o+.==.|
| + .oooo=|
| . . . Eo|
| |
+----[SHA256]-----+
- Change directory to .ssh and copy the public key (.pub) to authorized_keys file :
linux-slave@ip-10-0-1-75:~$ cd .ssh
linux-slave@ip-10-0-1-75:~/.ssh$ ls
authorized_keys id_rsa id_rsa.pub
linux-slave@ip-10-0-1-75:~/.ssh$ cat id_rsa.pub > authorized_keys
- Provide permissions only to owner (linux-slave) of the authorized_keys file :
linux-slave@ip-10-0-1-75:~/.ssh$ chmod 700 authorized_keys
CHANGES ON Master NODE :
We are done with the configurations on the Ubuntu slave machine, now we will configure our Jenkins master by remoting into it :
- Make sure
jenkins
user is there on the master machine and its part of thesudo
group :
ubuntu@ip-10-0-1-171:~$ cat /etc/passwd | grep jenkins
jenkins:x:111:115:Jenkins,,,:/var/lib/jenkins:/bin/bash
ubuntu@ip-10-0-1-171:~$ sudo usermod -aG sudo jenkins
ubuntu@ip-10-0-1-171:~$ groups jenkins
jenkins : jenkins sudo
- Here, we can see that the home directory of
jenkins
user is/var/lib/jenkins
and default shell isbash
. - Login as jenkins user in your master machine :
ubuntu@ip-10-0-1-171:~$ sudo su - jenkins
To run a command as administrator (user "root"), use "sudo <command>".
See "man sudo_root" for details.
jenkins@ip-10-0-1-171:~$
- Create the
.ssh
directory if it doesn’t exist and change the current directory to.ssh
.
jenkins@ip-10-0-1-171:~$ mkdir -p ~/.ssh
jenkins@ip-10-0-1-171:~$ cd ~/.ssh
- Tell Jenkins master to grab the public key of slave machine (using its private IP address) and add it to its
known_hosts
file for connection to take place every time seamlessly.
jenkins@ip-10-0-1-171:~/.ssh$ ssh-keyscan -H 10.0.1.75 >>/var/lib/jenkins/.ssh/known_hosts
# 10.0.1.75:22 SSH-2.0-OpenSSH_7.6p1 Ubuntu-4ubuntu0.2
# 10.0.1.75:22 SSH-2.0-OpenSSH_7.6p1 Ubuntu-4ubuntu0.2
# 10.0.1.75:22 SSH-2.0-OpenSSH_7.6p1 Ubuntu-4ubuntu0.2
- Finally, make
jenkins
user as owner of it and remove other user’s access to it.
jenkins@ip-10-0-1-171:~/.ssh$ chown jenkins:jenkins known_hosts
jenkins@ip-10-0-1-171:~/.ssh$ chmod 700 known_hosts
jenkins@ip-10-0-1-171:~/.ssh$ ls -l
total 4
-rwx------ 1 jenkins jenkins 2418 Mar 14 10:26 known_hosts
Changes on Jenkins Master :
We are done with the changes in master node as well. Now, lets open the Jenkins master (UI) and complete the setup :
- Open the new node configurations again and fill the sections as below :

- To add credentials, click on Add drop down and then on Jenkins Credential Provider icon. It will show a pop up to create the credential that will be used to SSH on slave node, hence we will select our pre-configured SSH username and private key of slave node.
- While setting up our slave node earlier, we gave the username as
linux-slave
and private key was generated at~/.ssh
folder. So, to fetch the private key we will run below commands on slave node :
linux-slave@ip-10-0-1-75:~$ cd .ssh
linux-slave@ip-10-0-1-75:~/.ssh$ ls -l
total 12
-rwx------ 1 linux-slave linux-slave 406 Mar 14 09:55 authorized_keys
-rw------- 1 linux-slave linux-slave 1675 Mar 14 09:53 id_rsa
-rw-r--r-- 1 linux-slave linux-slave 406 Mar 14 09:53 id_rsa.pub
linux-slave@ip-10-0-1-75:~/.ssh$ cat id_rsa
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEA4aj4TH/W2/SkqrK26OuWddnzGPaiD3dcL/bRPP5Z2cN5he8e
hfAVpx22ImnvZbtWLaAtbZzPBtULCRSVHyeQwyYzzymV4dRLu986PUMbIJk4lTI8
.
.
.
RBvteF/8QJDp/gqJG0j0OG1PKj1XiOeVrJfsbLYakKFCX6l5Qqfr0Cx5gLB3lB7X
clrc3H5gd6Rvs93NlOEWvjhxKBrN6zkn39zeGWOKjGpoimjITDsn
-----END RSA PRIVATE KEY-----
- Copy the private key from slave node and paste it on the Private Key (Enter directly) section of the pop up as below :

- Finally click on Add and our credentials will be added. Then select our added credential in the Credentials section of the Launch method and click on Save.

- Once the Save button is clicked we will be directed back to Manage Nodes page and we can see our newly added
linux-slave
, but it is offline :

- Don’t loose patience and simply press Refresh status button :

- We can now see our
linux-slave
is online. Click on thelinux-slave
to get more info about our Agent:

- We are done successfully setting up our Linux Slave, let’s create a job and give it a test.
Test linux slave :
- To test our
linux-slave
we will create a freestyle job :

- In the General section of the configuration, we will setup Restrict where this project can be run to
linux
label :

- Scroll down to Build section and add an Execute shell build step. Provide any linux specific command to test our
linux-slave
:

- Finally click on Apply and Save. Then go ahead and trigger the job with Build Now option, after few seconds we should get the following Console Output :

Yayy! We have successfully added and tested our Linux Slave on Jenkins.
Windows Slave :

We will now add another slave having Windows OS which can be used to build .NET applications and some other windows specific purposes :
- To create a new Slave – Click on New Node, name the node and click OK .
- Fill all the required details, if needed check the above sections for information on the various options.
- Choose the appropriate Launch method – Launch agent via Java Web Start.

- If you are missing this option, you might not be able to start/configure the Jenkins slave because, by default Jenkins disabled the TCP Port for JNLP agents. We can set this up in Configure global security option in Manage Jenkins .

- And then change the TCP port for JNLP agents to Fixed (8888) from Disabled.

- Since we are using port 8888 for incoming agent connections through JNLP, we need to expose the same in our AWS Security group for Jenkins Master instance.

- Once the new node is created, it will be in Offline mode with instructions on some ways to connect this slave to master.

Changes on slave :
- Install JRE on the windows slave machine, a comprehensive tutorial on installing JRE on Windows 10 can be found here.
- Open the Jenkins master URL from Windows slave machine and navigate to
windows-slave
Configuration page. - Once done, just click on Launch Button – You will see a new popup which confirms the Jenkins Master-Slave Connection.

- Refresh the Agent
windows-slave
page to see the node online.

- Lets now create and install this as a Windows service which will avoid the hassle to go to url and perform the same operation every time.
- Once you create the service it will always be up & running and then you can manage it through Windows Services.
- Don’t close the pop-up, instead just click on File Menu – If its not visible just maximise the popup window – and click on Install as a service option.

- It will prompt you for the confirmation, click on OK.

- Go to Windows Settings and then to check the Windows Services.

- You can see the Jenkins Windows Slave is successfully configure and running (If not then just Start the Service)
- Go back to your Jenkins Slave Page and now you will see that Agent is Successfully Running and ready to build your project.
That’s it. You have successfully configured the Jenkins Slave on Windows Machine and Installed it as a Windows Service.
Test windows slave :
- To test our
windows-slave
we will create a freestyle job :

- In the General section of the configuration, we will setup Restrict where this project can be run to
windows
label :

- Scroll down to Build section and add an Execute windows batch command build step. Provide any windows specific command to test our
windows-slave
:

- Finally click on Apply and Save. Then go ahead and trigger the job with Build Now option, after few seconds we should get the following Console Output :

Yayy! We have successfully added and tested our Windows Slave on Jenkins as well.
To sum up, we have successfully spun up two AWS instances (Ubuntu and Windows), configured them as Jenkins Slaves and finally tested them separately by running a test job.
Thanks for reading the article, let me know what you think of this and feel free to contact in case anything bothers.
hello
I have a question.
The private IP of EC2 will change after reboot.
Will the “known_hosts” you set will work after reboot?
LikeLike
Once an EC2 instance is launched, it’s assigned a private IP address at boot time. An instance’s private IP address will never change during the lifetime of that instance. Private IP addresses do not change in EC2 with a simple restart. As per AWS, when an instance is launched in EC2-Classic, it is automatically assigned a public IP address to the instance from the EC2-Classic public IPv4 address pool. This behaviour cannot be modified. When an instance is launched in a VPC, you control whether it receives a public IP or not. The public IP address can change under certain circumstances.
LikeLike
Hi
I followed the steps described to create the slave node.
But when trying to connect to the slave node amd getting below shown error.
Can you help me on this.
[SSH] The SSH key presented by the remote host does not match the key saved in the Known Hosts file against this host. Connections to this host will be denied until the two keys match.
LikeLike
Hello ANANDASOKANVIT,
I have verified the steps above and it works fine, please make sure the key pairs are rightly set and within proper linux users.
Thanks for the comment and let me know if the problem persists.
LikeLike
Hi All,
Might be a dumb question, but want to know, can I connect AWS machine as client to jenkins which is hosted on my local. I’ll keep AWS VPN connected.
Thanks in Anticipation
LikeLike
Honestly I haven’t tried it, but it should work if your are connected via AWS VPN, all it takes it ssh connection to internal hosts. Give it a try and let us know as well 🙂
LikeLike