Skip to main content
CI Modules 0.53.1Last updated in version 0.52.17

Jenkins server

View SourceRelease Notes

This module can be used to deploy Jenkins CI server in AWS. It creates the following resources:

  • An ASG to run Jenkins and automatically redeploy it if it crashes
  • An EBS volume for the Jenkins data directory that persists between redeploys
  • An ALB to route traffic to Jenkins
  • A Route 53 DNS A record for Jenkins pointing at the ALB

Under the hood, we are using the server-group module to run an ASG for Jenkins that can correctly reattach an EBS volume.

Example code

  • Check out the jenkins example for working sample code.
  • See vars.tf for all parameters you can configure on this module.

Jenkins AMI

See the install-jenkins module for a way to create an AMI with Jenkins installed and a script you can run in User Data to start Jenkins while the server is booting.

Backing up Jenkins

See the ec2-backup module for an automatic way to take scheduled backups of Jenkins and its EBS volume.

IAM permissions

This module assigns an IAM role to the Jenkins server and exports the ID of the IAM role. To give your Jenkins server IAM permissions—e.g., so you can use the server to automatically deploy changes into your AWS account—you can attach inline permissions to the IAM role using the aws_iam_role_policy resource:

module "jenkins" {
source = "git::git@github.com:gruntwork-io/terraform-aws-ci.git//modules/jenkins-server?ref=v1.0.8"

# ... (params ommitted) ...
}

resource "aws_iam_role_policy" "example" {
role = "${module.jenkins.jenkins_iam_role_id}"
policy = "${data.aws_iam_policy_document.example.json}"
}

data "aws_iam_policy_document" "example" {
statement {
effect = "Allow"
actions = ["s3:*"]
resources = "*"
}
}

You can also attach managed policies (not inline) to the IAM role using the aws_iam_role_policy_attachment resource:

module "jenkins" {
source = "git::git@github.com:gruntwork-io/terraform-aws-ci.git//modules/jenkins-server?ref=v1.0.8"

# ... (params ommitted) ...
}

resource "aws_iam_policy" "example" {
name_prefix = "example-iam-policy"
policy = "${data.aws_iam_policy_document.example.json}"
}

resource "aws_iam_role_policy_attachment" "example" {
role = "${module.jenkins.jenkins_iam_role_id}"
policy_arn = aws_iam_policy.example.arn
}

data "aws_iam_policy_document" "example" {
statement {
effect = "Allow"
actions = ["s3:*"]
resources = "*"
}
}

Sample Usage

main.tf

# ------------------------------------------------------------------------------------------------------
# DEPLOY GRUNTWORK'S JENKINS-SERVER MODULE
# ------------------------------------------------------------------------------------------------------

module "jenkins_server" {

source = "git::git@github.com:gruntwork-io/terraform-aws-ci.git//modules/jenkins-server?ref=v0.53.1"

# ----------------------------------------------------------------------------------------------------
# REQUIRED VARIABLES
# ----------------------------------------------------------------------------------------------------

# The domain name for which there is an ACM cert in this region that can be
# used to do SSL termination for the Jenkins ALB (e.g. *.foo.com).
acm_cert_domain_name = <string>

# The IDs of the subnets where the Jenkins ALB should be deployed (e.g.,
# subnet-abcd1234).
alb_subnet_ids = <list(string)>

# The ID of the Amazon Machine Image (AMI) to run for Jenkins (e.g.,
# ami-abcd1234).
ami_id = <string>

# The AWS region to deploy to (e.g. us-east-1).
aws_region = <string>

# The type of EC2 Instance to run (e.g. t2.micro).
instance_type = <string>

# The ID of the subnet where Jenkins should be deployed (e.g.,
# subnet-abcd1234).
jenkins_subnet_id = <string>

# The name for the Jenkins ASG and to namespace all the resources created by
# this module.
name = <string>

# The id of the VPC where Jenkins should be deployed (e.g. vpc-abcd1234).
vpc_id = <string>

# ----------------------------------------------------------------------------------------------------
# OPTIONAL VARIABLES
# ----------------------------------------------------------------------------------------------------

# A list of additional ALB target group ARNs. The Jenkins server will be
# registered in these groups, in addition to the ALB created by this module.
# Allows for custom and specialised routing of certain Jenkins paths, for
# example WebHooks.
additional_target_group_arns = []

# If true, the ALB will drop invalid headers. Elastic Load Balancing requires
# that message header names contain only alphanumeric characters and hyphens.
alb_drop_invalid_header_fields = false

# The port the Jenkins ALB should listen on for HTTP requests.
alb_http_port = 80

# The port the Jenkins ALB should listen on for HTTPS requests.
alb_https_port = 443

# The CIDR blocks from which the Jenkins ALB will allow HTTP/HTTPS requests.
# At least one of allow_incoming_http_from_cidr_blocks or
# allow_incoming_http_from_security_group_ids must be non-empty, or the ALB
# won't be able to receive any requests!
allow_incoming_http_from_cidr_blocks = []

# The Security Group IDs from which the Jenkins ALB will allow HTTP/HTTPS
# requests. At least one of allow_incoming_http_from_cidr_blocks or
# allow_incoming_http_from_security_group_ids must be non-empty, or the ALB
# won't be able to receive any requests!
allow_incoming_http_from_security_group_ids = []

# A list of IP address ranges in CIDR format from which SSH access will be
# permitted. Attempts to access the bastion host from all other IP addresses
# will be blocked.
allow_ssh_from_cidr_blocks = []

# The IDs of security groups from which SSH connections will be allowed.
allow_ssh_from_security_group_ids = []

# If set to true, create a DNS A Record for the Jenkins ALB. Make sure to set
# var.hosted_zone_id and var.domain_name as well.
create_route53_entry = false

# A list of custom tags to apply to Jenkins and all other resources.
custom_tags = {}

# How many servers to deploy at a time during a rolling deployment. For
# example, if you have 10 servers and set this variable to 2, then the
# deployment will a) undeploy 2 servers, b) deploy 2 replacement servers, c)
# repeat the process for the next 2 servers.
deployment_batch_size = 1

# The maximum number of times to retry the Load Balancer's Health Check before
# giving up on a rolling deployment of Jenkins. Only used if
# var.skip_health_check is false.
deployment_health_check_max_retries = 60

# The amount of time in seconds to wait between checking the status of the
# Load Balancer's Health Check status for a Jenkins instance that is being
# deployed or redeployed. Only used if var.skip_health_check is false
deployment_health_check_retry_interval_in_seconds = 10

# The domain name for which to create a DNS A Record (e.g., foo.jenkins.com).
# Only used if var.create_route53_entry is true.
domain_name = "replace-me"

# Set to true to make Jenkins EBS-optimized.
ebs_optimized = false

# Set to true to use an encrypted EBS volume for the Jenkins data dir.
ebs_volume_encrypted = true

# The amount of provisioned IOPS for the EBS volume to use for the Jenkins
# data dir. If ebs_volume_type is set to io1, you must set this parameter; if
# ebs_volume_type is set to anything else, you must NOT set this parameter.
ebs_volume_iops = null

# The size, in GB, of the EBS volume to use for the Jenkins data dir.
ebs_volume_size = 100

# The ID of an EBS snapshot to base the volume off of. This is used to restore
# from an existing EBS volume rather than launching from scratch.
ebs_volume_snapshot_id = null

# The type of EBS volume to use for the Jenkins data dir. Must be one of:
# standard, gp2, or io1.
ebs_volume_type = "gp2"

# If true, deletion of the ALB will be disabled via the AWS API. This will
# prevent Terraform from deleting the load balancer.
enable_alb_deletion_protection = false

# How long, in seconds, to wait after Jenkins deploys before checking its
# health.
health_check_grace_period = 120

# How many load balancer health checks Jenkins must pass before it is
# considered healthy.
health_check_healthy_threshold = 2

# How often, in seconds, the load balancer should conduct health checks on
# Jenkins.
health_check_interval = 15

# The path on the Jenins server the ALB should use for health checks.
health_check_path = "/login"

# The status code the ALB should expect for health checks.
health_check_status_code = "200"

# The maximum time, in seconds, Jenkins has to respond to a load balancer
# health check before it times out.
health_check_timeout = 10

# How many load balancer health checks Jenkins must fail before it is
# considered unhealthy.
health_check_unhealthy_threshold = 10

# The ID of the Route 53 Hosted Zone in which to create a DNS A Record. Only
# used if var.create_route53_entry is true.
hosted_zone_id = "replace-me"

# Set to true to make the Jenkins ALB an internal ALB that cannot be accessed
# from the public Internet. We strongly recommend setting this to true to keep
# Jenkins more secure.
is_internal_alb = true

# The amount time for the load balancer will wait between changing Jenkins'
# status from draining to unused when redeploying.
jenkins_deregistration_delay = 10

# The port Jenkins should listen on for HTTP requests.
jenkins_http_port = 8080

# The protocol the load balancer should use when talking to Jenkins.
jenkins_protocol = "HTTP"

# The name of an EC2 Key Pair to associate with each server for SSH access.
# Set to an empty string to not associate a Key Pair.
key_pair_name = null

# After this number of days, Jenkins ALB access logs should be transitioned
# from S3 to Glacier. Enter 0 to never archive log data.
num_days_after_which_archive_log_data = 30

# After this number of days, Jenkins ALB access logs should be deleted from
# S3. Enter 0 to never delete log data.
num_days_after_which_delete_log_data = 0

# Set to true to enable redirect of all requests from http to https. Ideally,
# this variable wouldn't be necessary, but because Terraform can't interpolate
# dynamic variables in counts, we must explicitly include this. Enter true or
# false.
redirect_http_to_https = false

# Whether the root volume for Jenkins should be encrypted.
root_block_device_encrypted = true

# The name of the root volume
root_block_device_name = "/dev/sda1"

# The size, in GB, of the root volume for Jenkins.
root_block_device_volume_size = 100

# The type of the root volume for Jenkins. Must be one of: standard, gp2, or
# io1.
root_block_device_volume_type = "standard"

# The log level to use with the rolling deploy script. It can be useful to set
# this to DEBUG when troubleshooting Jenkins redeploys.
script_log_level = "INFO"

# If set to true, skip the health check, and start a rolling deployment of
# Jenkins without waiting for it to initially be in a healthy state. This is
# primarily useful if the server group is in a broken state and you want to
# force a deployment anyway.
skip_health_check = false

# The aws predefined policy for alb. A List of policies can be found here:
# https://docs.aws.amazon.com/elasticloadbalancing/latest/application/create-https-listener.html#describe-ssl-policies
ssl_policy = "ELBSecurityPolicy-TLS-1-1-2017-01"

# The tenancy to use for Jenkins. Must be one of: default, dedicated, or host.
tenancy = "default"

# Set this variable to true to enable the use of Instance Metadata Service
# Version 1 in this module's aws_launch_template. Note that while IMDsv2 is
# preferred due to its special security hardening, we allow this in order to
# support the use case of AMIs built outside of these modules that depend on
# IMDSv1.
use_imdsv1 = true

# The User Data script to run on the Jenkins server when it is booting. If you
# need to pass gzipped, base64-encoded data (e.g., for a cloud-init script),
# use var.user_data_base64 instead.
user_data = null

# The base64-encoded User Data script to run on the Jenkins server when it is
# booting. This can be used to pass binary User Data, such as a gzipped
# cloud-init script. If you wish to pass in plain text (e.g., typical Bash
# Script) for User Data, use var.user_data instead.
user_data_base64 = null

# A maximum duration to wait for each server to be healthy before timing out
# (e.g. 10m). Valid units of time are: s, m, h.
wait_for_capacity_timeout = "10m"

}


Reference

Required

acm_cert_domain_namestringrequired

The domain name for which there is an ACM cert in this region that can be used to do SSL termination for the Jenkins ALB (e.g. *.foo.com).

alb_subnet_idslist(string)required

The IDs of the subnets where the Jenkins ALB should be deployed (e.g., subnet-abcd1234).

ami_idstringrequired

The ID of the Amazon Machine Image (AMI) to run for Jenkins (e.g., ami-abcd1234).

aws_regionstringrequired

The AWS region to deploy to (e.g. us-east-1).

instance_typestringrequired

The type of EC2 Instance to run (e.g. t2.micro).

jenkins_subnet_idstringrequired

The ID of the subnet where Jenkins should be deployed (e.g., subnet-abcd1234).

namestringrequired

The name for the Jenkins ASG and to namespace all the resources created by this module.

vpc_idstringrequired

The id of the VPC where Jenkins should be deployed (e.g. vpc-abcd1234).

Optional

additional_target_group_arnslist(string)optional

A list of additional ALB target group ARNs. The Jenkins server will be registered in these groups, in addition to the ALB created by this module. Allows for custom and specialised routing of certain Jenkins paths, for example WebHooks.

[]

If true, the ALB will drop invalid headers. Elastic Load Balancing requires that message header names contain only alphanumeric characters and hyphens.

false
alb_http_portnumberoptional

The port the Jenkins ALB should listen on for HTTP requests.

80
alb_https_portnumberoptional

The port the Jenkins ALB should listen on for HTTPS requests.

443

The CIDR blocks from which the Jenkins ALB will allow HTTP/HTTPS requests. At least one of allow_incoming_http_from_cidr_blocks or allow_incoming_http_from_security_group_ids must be non-empty, or the ALB won't be able to receive any requests!

[]

The Security Group IDs from which the Jenkins ALB will allow HTTP/HTTPS requests. At least one of allow_incoming_http_from_cidr_blocks or allow_incoming_http_from_security_group_ids must be non-empty, or the ALB won't be able to receive any requests!

[]
allow_ssh_from_cidr_blockslist(string)optional

A list of IP address ranges in CIDR format from which SSH access will be permitted. Attempts to access the bastion host from all other IP addresses will be blocked.

[]

The IDs of security groups from which SSH connections will be allowed.

[]

If set to true, create a DNS A Record for the Jenkins ALB. Make sure to set hosted_zone_id and domain_name as well.

false
custom_tagsmap(string)optional

A list of custom tags to apply to Jenkins and all other resources.

{}
deployment_batch_sizenumberoptional

How many servers to deploy at a time during a rolling deployment. For example, if you have 10 servers and set this variable to 2, then the deployment will a) undeploy 2 servers, b) deploy 2 replacement servers, c) repeat the process for the next 2 servers.

1

The maximum number of times to retry the Load Balancer's Health Check before giving up on a rolling deployment of Jenkins. Only used if skip_health_check is false.

60

The amount of time in seconds to wait between checking the status of the Load Balancer's Health Check status for a Jenkins instance that is being deployed or redeployed. Only used if skip_health_check is false

10
domain_namestringoptional

The domain name for which to create a DNS A Record (e.g., foo.jenkins.com). Only used if create_route53_entry is true.

"replace-me"
ebs_optimizedbooloptional

Set to true to make Jenkins EBS-optimized.

false

Set to true to use an encrypted EBS volume for the Jenkins data dir.

true
ebs_volume_iopsstringoptional

The amount of provisioned IOPS for the EBS volume to use for the Jenkins data dir. If ebs_volume_type is set to io1, you must set this parameter; if ebs_volume_type is set to anything else, you must NOT set this parameter.

null
ebs_volume_sizenumberoptional

The size, in GB, of the EBS volume to use for the Jenkins data dir.

100

The ID of an EBS snapshot to base the volume off of. This is used to restore from an existing EBS volume rather than launching from scratch.

null
ebs_volume_typestringoptional

The type of EBS volume to use for the Jenkins data dir. Must be one of: standard, gp2, or io1.

"gp2"

If true, deletion of the ALB will be disabled via the AWS API. This will prevent Terraform from deleting the load balancer.

false

How long, in seconds, to wait after Jenkins deploys before checking its health.

120

How many load balancer health checks Jenkins must pass before it is considered healthy.

2
health_check_intervalnumberoptional

How often, in seconds, the load balancer should conduct health checks on Jenkins.

15
health_check_pathstringoptional

The path on the Jenins server the ALB should use for health checks.

"/login"

The status code the ALB should expect for health checks.

"200"
health_check_timeoutnumberoptional

The maximum time, in seconds, Jenkins has to respond to a load balancer health check before it times out.

10

How many load balancer health checks Jenkins must fail before it is considered unhealthy.

10
hosted_zone_idstringoptional

The ID of the Route 53 Hosted Zone in which to create a DNS A Record. Only used if create_route53_entry is true.

"replace-me"
is_internal_albbooloptional

Set to true to make the Jenkins ALB an internal ALB that cannot be accessed from the public Internet. We strongly recommend setting this to true to keep Jenkins more secure.

true

The amount time for the load balancer will wait between changing Jenkins' status from draining to unused when redeploying.

10
jenkins_http_portnumberoptional

The port Jenkins should listen on for HTTP requests.

8080
jenkins_protocolstringoptional

The protocol the load balancer should use when talking to Jenkins.

"HTTP"
key_pair_namestringoptional

The name of an EC2 Key Pair to associate with each server for SSH access. Set to an empty string to not associate a Key Pair.

null

After this number of days, Jenkins ALB access logs should be transitioned from S3 to Glacier. Enter 0 to never archive log data.

30

After this number of days, Jenkins ALB access logs should be deleted from S3. Enter 0 to never delete log data.

0

Set to true to enable redirect of all requests from http to https. Ideally, this variable wouldn't be necessary, but because Terraform can't interpolate dynamic variables in counts, we must explicitly include this. Enter true or false.

false

Whether the root volume for Jenkins should be encrypted.

true

The name of the root volume

"/dev/sda1"

The size, in GB, of the root volume for Jenkins.

100

The type of the root volume for Jenkins. Must be one of: standard, gp2, or io1.

"standard"
script_log_levelstringoptional

The log level to use with the rolling deploy script. It can be useful to set this to DEBUG when troubleshooting Jenkins redeploys.

"INFO"
skip_health_checkbooloptional

If set to true, skip the health check, and start a rolling deployment of Jenkins without waiting for it to initially be in a healthy state. This is primarily useful if the server group is in a broken state and you want to force a deployment anyway.

false
ssl_policystringoptional
"ELBSecurityPolicy-TLS-1-1-2017-01"
tenancystringoptional

The tenancy to use for Jenkins. Must be one of: default, dedicated, or host.

"default"
use_imdsv1booloptional

Set this variable to true to enable the use of Instance Metadata Service Version 1 in this module's aws_launch_template. Note that while IMDsv2 is preferred due to its special security hardening, we allow this in order to support the use case of AMIs built outside of these modules that depend on IMDSv1.

true
user_datastringoptional

The User Data script to run on the Jenkins server when it is booting. If you need to pass gzipped, base64-encoded data (e.g., for a cloud-init script), use user_data_base64 instead.

null
user_data_base64stringoptional

The base64-encoded User Data script to run on the Jenkins server when it is booting. This can be used to pass binary User Data, such as a gzipped cloud-init script. If you wish to pass in plain text (e.g., typical Bash Script) for User Data, use user_data instead.

null

A maximum duration to wait for each server to be healthy before timing out (e.g. 10m). Valid units of time are: s, m, h.

"10m"