---
title: "How to Install Jenkins on AWS EC2 Instance"
description: "In this post, I will show you how to Create an EC2 Instance on AWS and install Jenkins on it."
author: "Mohammad Abu Mattar"
canonical: https://mkabumattar.com/blog/post/install-jenkins-on-aws-ec2-instance
---

# How to Install Jenkins on AWS EC2 Instance

## Introduction

In this post, I will show you how to Create an EC2 Instance on AWS and install Jenkins on it.

## Prerequisites

- AWS CLI installed and configured
- IAM user with the following permissions:
  - AmazonVPCFullAccess
  - AmazonEC2FullAccess

## Create a VPC

### Step 1: Create a VPC

To create a VPC, run the following command:

```shell
# Create a VPC
AWS_VPC=$(aws ec2 create-vpc \
  --cidr-block 15.0.0.0/16 \
  --query 'Vpc.VpcId' \
  --output text)

# Add a name tag to the VPC
aws ec2 create-tags \
  --resources $AWS_VPC \
  --tags Key=Name,Value=jenkins-vpc
```

Explanation:

- `AWS_VPC` is a variable that holds the VPC ID.
- `--cidr-block` The IPv4 network range for the VPC, in CIDR notation.
- `--query` The JMESPath query that is used to extract data from the output.
- `--output` The output format of the command.

### Step 2: Modify your custom VPC and enable DNS hostname support, and DNS support

To modify your custom VPC and enable DNS hostname support, and DNS support, run the following command:

```shell
# Modify your custom VPC and enable DNS hostname support, and DNS support
# Enable DNS hostnames
aws ec2 modify-vpc-attribute \
  --vpc-id $AWS_VPC \
  --enable-dns-hostnames "{\"Value\":true}"

# Enable DNS support
aws ec2 modify-vpc-attribute \
  --vpc-id $AWS_VPC \
  --enable-dns-support "{\"Value\":true}"
```

Explanation:

- `--enable-dns-hostnames` Indicates whether the instances launched in the VPC get DNS hostnames.
- `--enable-dns-support` Indicates whether DNS resolution is supported for the VPC.

### Step 3: Create a Public Subnet

To create a public subnet, run the following command:

```shell
# Create a public subnet
AWS_PUBLIC_SUBNET=$(aws ec2 create-subnet \
  --vpc-id $AWS_VPC \
  --cidr-block 15.0.1.0/24 \
  --query 'Subnet.SubnetId' \
  --output text)

# Add a name tag to the public subnet
aws ec2 create-tags \
  --resources $AWS_PUBLIC_SUBNET \
  --tags Key=Name,Value=jenkins-public-subnet
```

Explanation:

- `AWS_PUBLIC_SUBNET` is a variable that holds the public subnet ID.
- `--vpc-id` The ID of the VPC.
- `--cidr-block` The IPv4 network range for the subnet, in CIDR notation.
- `--query` The JMESPath query that is used to extract data from the output.
- `--output` The output format of the command.

### Step 4: Enable Auto-assign Public IP on the subnet

To enable auto-assign public IP on the subnet, run the following command:

```shell
# Enable auto-assign public IP on the subnet
aws ec2 modify-subnet-attribute \
  --subnet-id $AWS_PUBLIC_SUBNET \
  --map-public-ip-on-launch
```

Explanation:

- `--subnet-id` The ID of the subnet.
- `--map-public-ip-on-launch` Indicates whether to assign a public IPv4 address to instances launched in the subnet.

### Step 5: Create an Internet Gateway

To create an internet gateway, run the following command:

```shell
# Create an internet gateway
AWS_INTERNET_GATEWAY=$(aws ec2 create-internet-gateway \
  --query 'InternetGateway.InternetGatewayId' \
  --output text)

# Add a name tag to the internet gateway
aws ec2 create-tags \
  --resources $AWS_INTERNET_GATEWAY \
  --tags Key=Name,Value=jenkins-internet-gateway
```

Explanation:

- `AWS_INTERNET_GATEWAY` is a variable that holds the internet gateway ID.
- `--query` The JMESPath query that is used to extract data from the output.
- `--output` The output format of the command.

### Step 6: Attach the Internet Gateway to the VPC

To attach the internet gateway to the VPC, run the following command:

```shell
# Attach the internet gateway to the VPC
aws ec2 attach-internet-gateway \
  --internet-gateway-id $AWS_INTERNET_GATEWAY \
  --vpc-id $AWS_VPC
```

Explanation:

- `--internet-gateway-id` The ID of the internet gateway.
- `--vpc-id` The ID of the VPC.

### Step 7: Create a Route Table

To create a route table, run the following command:

```shell
# Create a route table
AWS_ROUTE_TABLE=$(aws ec2 create-route-table \
  --vpc-id $AWS_VPC \
  --query 'RouteTable.RouteTableId' \
  --output text)

# Add a name tag to the route table
aws ec2 create-tags \
  --resources $AWS_ROUTE_TABLE \
  --tags Key=Name,Value=jenkins-route-table
```

Explanation:

- `AWS_ROUTE_TABLE` is a variable that holds the route table ID.
- `--vpc-id` The ID of the VPC.
- `--query` The JMESPath query that is used to extract data from the output.
- `--output` The output format of the command.

### Step 8: Create a custom route table association

To create a custom route table association, run the following command:

```shell
# Create a custom route table association
aws ec2 associate-route-table \
  --subnet-id $AWS_PUBLIC_SUBNET \
  --route-table-id $AWS_ROUTE_TABLE
```

Explanation:

- `--subnet-id` The ID of the subnet.
- `--route-table-id` The ID of the route table.

### Step 9: Associate the subnet with route table, making it a public subnet

To associate the subnet with route table, making it a public subnet, run the following command:

```shell
# Associate the subnet with route table, making it a public subnet
aws ec2 create-route \
  --route-table-id $AWS_ROUTE_TABLE \
  --destination-cidr-block 0.0.0.0/0 \
  --gateway-id $AWS_INTERNET_GATEWAY
```

Explanation:

- `--route-table-id` The ID of the route table.
- `--destination-cidr-block` The IPv4 CIDR address block used for the destination match.
- `--gateway-id` The ID of an internet gateway or virtual private gateway attached to your VPC.

### Step 10: Create a Security Group

To create a security group, run the following command:

```shell
# Create a security group
AWS_SECURITY_GROUP=$(aws ec2 create-security-group \
  --group-name aws-security-group \
  --description "AWS Security Group" \
  --vpc-id $AWS_VPC \
  --query 'GroupId' \
  --output text)

# Add a name tag to the security group
aws ec2 create-tags \
  --resources $AWS_SECURITY_GROUP \
  --tags Key=Name,Value=jenkins-security-group
```

Explanation:

- `AWS_SECURITY_GROUP` is a variable that holds the security group ID.
- `--group-name` The name of the security group.
- `--description` A description for the security group.
- `--vpc-id` The ID of the VPC.
- `--query` The JMESPath query that is used to extract data from the output.
- `--output` The output format of the command.

### Step 11: Add a rule to the security group

To add a rule to the security group, run the following command:

```shell
# Add a rule to the security group

# Add SSH rule
aws ec2 authorize-security-group-ingress \
  --group-id $AWS_SECURITY_GROUP \
  --protocol tcp \
  --port 22 \
  --cidr 0.0.0.0/0 \
  --output text

# Add HTTP rule
aws ec2 authorize-security-group-ingress \
  --group-id $AWS_SECURITY_GROUP \
  --protocol tcp \
  --port 80 \
  --cidr 0.0.0.0/0 \
  --output text

# Add HTTPS rule
aws ec2 authorize-security-group-ingress \
  --group-id $AWS_SECURITY_GROUP \
  --protocol tcp \
  --port 443 \
  --cidr 0.0.0.0/0 \
  --output text

# Add Jenkins rule
aws ec2 authorize-security-group-ingress \
  --group-id $AWS_SECURITY_GROUP \
  --protocol tcp \
  --port 8080-8090 \
  --cidr 0.0.0.0/0 \
  --output text
```

Explanation:

- `--group-id` The ID of the security group.
- `--protocol` The IP protocol name or number.
- `--port` The port number or range of port numbers.
- `--cidr` The IPv4 CIDR range.
- `--output` The output format of the command.

## Create an EC2 Instance

### Step 1: Get the latest AMI ID

To get the latest AMI ID, run the following command:

```shell
# Get the latest AMI ID
AWS_AMI=$(aws ec2 describe-images \
  --owners 'amazon' \
  --filters 'Name=name,Values=amzn2-ami-hvm-2.0.*' \
  'Name=state,Values=available' \
  --query 'sort_by(Images, &CreationDate)[-1].[ImageId]' \
  --output 'text')
```

Explanation:

- `AWS_AMI` is a variable that holds the AMI ID.
- `--owners` The AWS account ID of the owner.
- `--filters` The filters.
- `--query` The JMESPath query that is used to extract data from the output.
- `--output` The output format of the command.

### Step 2: Create a Key Pair

To create a key pair, run the following command:

```shell
# Create a key pair
aws ec2 create-key-pair \
  --key-name aws-key-pair \
  --query 'KeyMaterial' \
  --output text > aws-key-pair.pem

# Change the permission of the key pair
chmod 400 aws-key-pair.pem
```

Explanation:

- `--key-name` The name of the key pair.
- `--query` The JMESPath query that is used to extract data from the output.
- `--output` The output format of the command.
- `>` The output is redirected to a file.
- `aws-key-pair.pem` The name of the file.
- `chmod 400 aws-key-pair.pem` Change the permission of the key pair, so that only the owner can read and write.

### Step 3: Create a User Data Script

To create a user data script, run the following command:

```shell
# Create a user data script
cat << EOF > user-data.sh
#!/bin/bash

# update the system
sudo yum update -y

# add the jenkins repo
sudo wget -O /etc/yum.repos.d/jenkins.repo https://pkg.jenkins.io/redhat-stable/jenkins.repo
sudo rpm --import https://pkg.jenkins.io/redhat-stable/jenkins.io.key
sudo yum upgrade

# install java
sudo amazon-linux-extras install java-openjdk11 -y

# install jenkins
sudo yum install jenkins -y

# start jenkins
sudo systemctl start jenkins

# enable jenkins
sudo systemctl enable jenkins

# install git
sudo yum install git -y
EOF
```

Explanation:

- `cat << EOF > user-data.sh` The output is redirected to a file.
- `user-data.sh` The name of the file.
- `#!/bin/bash` The shebang line.
- `sudo yum update -y` Update the system.
- `sudo wget -O /etc/yum.repos.d/jenkins.repo https://pkg.jenkins.io/redhat-stable/jenkins.repo` Add the Jenkins repo.
- `sudo rpm --import https://pkg.jenkins.io/redhat-stable/jenkins.io.key` Import the Jenkins repo key.
- `sudo yum upgrade` Upgrade the system.
- `sudo amazon-linux-extras install java-openjdk11 -y` Install Java.
- `sudo yum install jenkins -y` Install Jenkins.
- `sudo systemctl start jenkins` Start Jenkins.
- `sudo systemctl enable jenkins` Enable Jenkins.

### Step 4: Create an EC2 Instance

To create an EC2 instance, run the following command:

```shell
# Create an EC2 instance
AWS_INSTANCE=$(aws ec2 run-instances \
--image-id $AWS_AMI \
--instance-type t2.micro \
--key-name aws-key-pair \
--monitoring "Enabled=false" \
--security-group-ids $AWS_SECURITY_GROUP \
--subnet-id $AWS_PUBLIC_SUBNET \
--user-data file://user-data.sh \
--query 'Instances[0].InstanceId' \
--output text)

# add a name tag to the instance
aws ec2 create-tags \
  --resources $AWS_INSTANCE \
  --tags Key=Name,Value=jenkins-server
```

Explanation:

- `AWS_INSTANCE` is a variable that holds the instance ID.
- `--image-id` The ID of the AMI.
- `--instance-type` The instance type.
- `--key-name` The name of the key pair.
- `--monitoring` The monitoring for the instance.
- `--security-group-ids` The IDs of the security groups.
- `--subnet-id` The ID of the subnet.
- `--user-data` The user data to provide when launching the instance.
- `--query` The JMESPath query that is used to extract data from the output.
- `--output` The output format of the command.

### Step 5: Create an Elastic IP

To create an Elastic IP, run the following command:

```shell
# Create an Elastic IP
AWS_ELASTIC_IP=$(aws ec2 allocate-address \
  --domain vpc \
  --query 'AllocationId' \
  --output text)

# add a name tag to the Elastic IP
aws ec2 create-tags \
  --resources $AWS_ELASTIC_IP \
  --tags Key=Name,Value=jenkins-server-elastic-ip
```

Explanation:

- `AWS_ELASTIC_IP` is a variable that holds the Elastic IP ID.
- `--domain` The domain name.
- `--query` The JMESPath query that is used to extract data from the output.
- `--output` The output format of the command.

### Step 6: Associate the Elastic IP with the EC2 Instance

To associate the Elastic IP with the EC2 instance, run the following command:

```shell
# Associate the Elastic IP with the EC2 instance
aws ec2 associate-address \
  --allocation-id $AWS_ELASTIC_IP \
  --instance-id $AWS_INSTANCE
```

Explanation:

- `--allocation-id` The allocation ID.
- `--instance-id` The ID of the instance.

## Connect to the Jenkins Server, and Setup Jenkins

### Step 1: Connect to the Jenkins Server

To connect to the Jenkins server, run the following command:

```shell
# Get the public IP address of the Jenkins server
AWS_PUBLIC_IP=$(aws ec2 describe-instances \
  --instance-ids $AWS_INSTANCE \
  --query 'Reservations[0].Instances[0].PublicIpAddress' \
  --output text)

# Connect to the Jenkins server
ssh -i aws-key-pair.pem ec2-user@$AWS_PUBLIC_IP
```

Explanation:

- `AWS_PUBLIC_IP` is a variable that holds the public IP address of the Jenkins server.
- `ssh -i aws-key-pair.pem ec2-user@$AWS_PUBLIC_IP` Connect to the Jenkins server.

### Step 2: Setup Jenkins

To setup Jenkins, run the following command:

```shell
# Get the initial admin password
sudo cat /var/lib/jenkins/secrets/initialAdminPassword
```

Explanation:

- `sudo cat /var/lib/jenkins/secrets/initialAdminPassword` Get the initial admin password.

### Step 3: Configuring Jenkins

To configure Jenkins:

1. Go to `http://<public-ip-address>:8080/`.

![jenkins-1](/assets/blog/0031-install-jenkins-on-aws-ec2-instance/jenkins-1.png)

2. Enter the initial admin password.

![jenkins-2](/assets/blog/0031-install-jenkins-on-aws-ec2-instance/jenkins-2.png)

3. Select the recommended plugins.

![jenkins-3](/assets/blog/0031-install-jenkins-on-aws-ec2-instance/jenkins-3.png)

4. Create the first admin user.

![jenkins-4](/assets/blog/0031-install-jenkins-on-aws-ec2-instance/jenkins-4.png)

5. Jenkins is ready.

![jenkins-5](/assets/blog/0031-install-jenkins-on-aws-ec2-instance/jenkins-5.png)

## Conclusion

In this tutorial, you learned how to install Jenkins on an AWS EC2 instance.

## References

- [Jenkins Official Website](https://www.jenkins.io/)
- [Jenkins User Documentation](https://www.jenkins.io/doc/)
- [Installing Jenkins on Linux](https://www.jenkins.io/doc/book/installing/linux/)
- [AWS Command Line Interface (CLI) User Guide](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-welcome.html)
- [Amazon EC2 User Guide for Linux Instances](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/concepts.html)
- [Amazon VPC User Guide](https://docs.aws.amazon.com/vpc/latest/userguide/what-is-amazon-vpc.html)
- [AWS Identity and Access Management (IAM) User Guide](https://docs.aws.amazon.com/IAM/latest/UserGuide/introduction.html)
- [AWS Key Pairs and Amazon EC2 Instances](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-key-pairs.html)
- [Security Groups for your VPC - Amazon VPC](https://docs.aws.amazon.com/vpc/latest/userguide/VPC_SecurityGroups.html)
- [User data and shell scripts for EC2 instances](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/user-data.html)
- [Elastic IP addresses - Amazon EC2](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/elastic-ip-addresses-eip.html)
- [Connect to your Linux instance using SSH - Amazon EC2](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AccessingInstancesLinux.html)
- [Managing Jenkins Plugins](https://www.jenkins.io/doc/book/managing/plugins/)
- [Getting started with Jenkins](https://www.jenkins.io/doc/pipeline/tour/getting-started/)
