Deploying Jenkins to AWS
Table of Contents
Configure EC2 #
I opted for an t2.small
Ubuntu 14.04 EC2 instance. This gives us two gigs of RAM and a single core for about .02 cents an hour. This should serve our purposes for a personal CI server.
Elastic IP Address #
I elected to not assign a public IP address / Amazon DNS as this will change everytime the server reboots. Instead I allocated an Elastic IP address (under Network & Security). This allows Rotue 53 to properly route to the EC2 instance even after a reboot or completely different instance.
Securing a Linux box #
Codelitt’s excellent article on securing a Linux server proves useful here: My First Ten Minutes on a Server
Jenkins User #
For the purposes of this deployment I created a jenkins user but you can create whatever user you’d like, so long as it as SSH and SUDOer powers.
Security Groups #
One point where I differed from the above guide was that rather than having ufw
handle the firewall, I opted for AWS security groups instead. This way I can monitor my open ports directly from EC2, rather than logging into individual machines. We also need to give Github access so Webhooks work:
Github Security Group #
Jenkins Security Group #
VPN and Security Groups #
You’ll note the IP address for the source is not 0.0.0.0/0
(which allows anyone to access those ports). I created a personal VPN to give me a secure and static IP address (sorry, not the actual VPN server address 😉). This is important since my ISP only hands out dynamic IP addresses and I don’t want the whole world gunning for my server.
DigitalOcean wrote a great guide on getting one setup: How to setup a VPN server
An interesting side note about VPN, the IP address of the VPN server itself is the one AWS sees.
Now that we’ve deployed and secured our webserver, lets install Jenkins.
Installing Jenkins #
1. Install Oracle Java 8
sudo add-apt-repository ppa:webupd8team/java
sudo apt-get update && sudo apt-get install oracle-java8-installer
java -version
java version "1.8.0_91"
Java(TM) SE Runtime Environment (build 1.8.0_91-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.91-b14, mixed mode)
2. Install Jenkins
I recommend using a 2.x build of Jenkins to get Pipelines support but the LTS (1.651.3 LTS as of this writing) should work as well.
Installing Jenkins on Ubuntu: instructions
Copied here for prosperity:
wget -q -O - http://pkg.jenkins.io/debian/jenkins.io.key | sudo apt-key add -
# add to /etc/apt/sources.list
deb http://pkg.jenkins.io/debian binary/
# update and install
sudo apt-get update
sudo apt-get install jenkins
If everything went according to plan you’ll find Jenkins on port :8080
of your EC2 instance. Make sure 8080 is open in your
security group.
I found the wizard at :8080
NOT :8080/jenkins
as would be the case if we installed the WAR on a tomcat.
Follow the initial setup instructions in the 2.x setup wizard.
Plugins I selected:
- Pipeline
- GitHub Organization Folder Plugin
- Git plugin
- GitHub plugin
- Credentials
- Credentials binding
as well as the default Dashboard and email plugins.
Configure Nginx #
You’ll have noticed by now that the packaged Jenkins needs that 8080 port. Lets fix that with a reverse proxy.
sudo apt-get update
sudo apt-get install nginx
Make sure to add port 80
to your security group and you should see the Nginx landing page by browsing to your EC2 instance:
Let’s configure Nginx to route to Jenkins on port 80
:
cd /etc/nginx/sites-available
sudo vi jenkins
server {
listen 80;
server_name elastic.ip.address jenkins.server.tld
access_log /var/log/nginx/jenkins.server.tld/access.log;
error_log /var/log/nginx/jenkins.server.tld/error.log info;
location / {
proxy_pass http://localhost:8080;
}
}
#create the logs folder
sudo mkdir -p /var/log/nginx/jenkins.{{ hostname }}/
# remove default and add the jenkins site
sudo rm /etc/nginx/sites-enabled/default
# enable an nginx site with a syslink
sudo ln -s /etc/nginx/sites-available/jenkins /etc/nginx/sites-enabled/
# restart nginx
sudo service nginx restart
Configure Github plugin #
Create an RSA keypair for jenkins
:
ssh-keygen -t rsa
Note: don’t specify a password as it apparantly breaks Jenkins’ daemon - Jenkins and private repos
If you added a password, you can remove it with ssh-keygen -p
Assign your id_rsa.pub
to your Github account #
Browse to https://github.com/settings/ssh
and copy your password-less id_rsa.pub
as a new SSH key. This will allow two-way communication between Github and Jenkins.
You can verify the SSH connection with:
ssh -T [email protected]
jenkins@jenkins:~/.ssh$ ssh -T [email protected]
Hi github user! You've successfully authenticated, but GitHub does not provide shell access.
Note: no password should be prompted for
Not sure why this is the case since Jenkins’ credentials page specifes an SSH user and password combo. Make sure the password field is blank:
Create a pipeline #
Add the HTTPS url to the Jenkins build to listen for commits:
Once you’ve configured SSH credentials for both Jenkins and Github we can verify git checkout works by creating a simple Pipeline:
node {
stage 'Checkout'
git credentialsId: 'jenkins.mblum.me', url: '[email protected]:mikeblum/mblum.me.git'
}
It’s import to note here we use the SSH repo adddress, not the HTTPS version so our SSH keys we’ve configured allow for password-less deployments.
The credentialsId matches the ID speciifed in the Jenkins Global Credentials.
Kick off a test build with Build Now
.
Deploying this blog #
In our previous post: Deploying to S3 we configured Gitlab to deploy our site to Amazon S3. We’ll want to replicate the same behavior using Jenkins pipelines and Docker in the next post: Docker Pipelines.