Simple Jenkins EC2 Server deployment with AWS CloudFormation
By: Carlos Garcia
Tags: Jenkins, Cloudformation, AWS, Cloud Computing, Ec2

If you read’ve the previous post…

…you probably were expecting a Jenkins build and to be honest It is supposed to be in the initial IaC setup with CloudFormation.. but I forgot to include it (I limit the creation of these posts to 30 minutes per day… sorry).

Now with that being water under the bridge, let’s get started with the Jenkins build but first here are a few questions + answers for you…

Why are we using Cloudformation and not Packer or Terraform?

Really is just me wanting to keep as much Terraform / Packer code off my machine. Imagine that our environment is centered around the publishing/central IT cross-account AWS setup and any new changes should be pushed through IaC stacks and not by admins assuming roles and deploying stuff from their machines.

CFT Instance Resource for Jenkins

Cool! with that being the scenario, let’s include our Jenkins instance AND Security Group resources in the CloudFormation template for IaC prep!

EC2InstanceJenkins: Type: AWS::EC2::Instance Properties: IamInstanceProfile: !Ref "IAMInstanceProfileJenkins" ImageId: "ami-062f7200baf2fa504" KeyName: !Ref "KeyPair" InstanceType: "t2.micro" SecurityGroupIds: - ! Fn::GetAtt "SecurityGroupID" SubnetId: !Ref "SubnetID"

*I used a direct reference to the ami ID but you can always follow AWS suggestions to always have the latest ami using SSM Parameters.

** notice how I used parameter references for values that will change for your acct, make sure you include those parameters in the cloudformation

now for the fun part (userdata script):

1) Basic Tools and Dependencies

UserData: Fn::Base64: !Sub | #!/bin/bash -xe sudo yum update -y sudo amazon-linux-extras install corretto8 sudo yum install jq unzip git -y

Firstly, we want to make sure all is up to date and that we enable corretto8 . Also, we have some of the basic tools eg: unzip, jq, git…

note: at the moment of this article v8 of corretto was the only one that worked for Jenkins.

2) Jenkins Installation

sudo wget -O /etc/yum.repos.d/jenkins.repo http://pkg.jenkins-ci.org/redhat/jenkins.repo sudo rpm --import https://pkg.jenkins.io/redhat/jenkins.io.key sudo yum install jenkins -y sudo service jenkins start

3) Install Packer and Terraform

NOTE: Some may prefer to actually install the plugins. through the Jenkins console — I actually think that’s better too.

sudo wget https://releases.hashicorp.com/terraform/0.12.24/terraform_0.12.24_linux_amd64.zip -O terraform.zip sudo unzip terraform.zip && rm terraform.zip -f && sudo mv terraform /bin/terraform sudo wget https://releases.hashicorp.com/packer/1.5.5/packer_1.5.5_linux_amd64.zip -O packer.zip sudo unzip packer.zip && rm packer.zip -f && sudo mv packer /bin/packer.io

Please notice that we renamed the packer binary to “packer.io” if not renamed you’ll encounter conflict with the preexisting packer command

4) Generate SSH Key and SSM Parameters

sudo ssh-keygen -t rsa -f /home/ec2-user/.ssh/id_rsa -q -P "" sudo chmod 775 /home/ec2-user/.ssh/id_rsa && sudo chmod 775 /home/ec2-user/.ssh/id_rsa JenkinsPWD="/var/lib/jenkins/secrets/initialAdminPassword" PrvKey="/home/ec2-user/.ssh/id_rsa" PubKey="/home/ec2-user/.ssh/id_rsa.pub" aws ssm put-parameter --region us-east-1 --name /jenkins/initialAdminPassword --value file://$JenkinsPWD --type String --overwrite aws ssm put-parameter --region us-east-1 --name /jenkins/SSH-Git-PrivateKey --value file://$PrvKey --type String --overwrite aws ssm put-parameter --region us-east-1 --name /jenkins/SSH-Git-PublicKey --value file://$PubKey --type String --overwrite

NOTE: Remember to encrypt the parameter or better yet, use Secrets Manager!

Awesome, now your Jenkins server is ready for you to set it up using the parameters we just generated. No need to SSH and cat the values when you can access the console and view the parameters. Additionally, you can now add the SSH credentials to both Jenkins and Github and start building pipelines with Github as SCM