Jenkins CI Server
Overview
This service contains code to deploy Jenkins CI Server on AWS.
Jenkins architecture
Features
- Deploy Jenkins CI Server
- Run Jenkins in an Auto Scaling Group for high availability
- Store the
JENKINS_HOME
directory in an EBS Volume - Take nightly snapshots of the EBS Volume using the
ec2-backup
scheduled Lambda function - Run an ALB in front of Jenkins so it’s not accessible directly to users
- Configure DNS in Route 53 and TLS in AWS Certificate Manager (ACM)
- Send all logs and metrics to CloudWatch
- Configure alerts in CloudWatch for CPU, memory, and disk space usage
- Manage SSH access with IAM groups using
ssh-grunt
- Manage deployment permissions for the server using IAM roles
- OS hardening, including
fail2ban
,ntp
,auto-update
,ip-lockdown
, and more
Learn
note
This repo is a part of the Gruntwork Service Catalog, a collection of reusable, battle-tested, production ready infrastructure code. If you’ve never used the Service Catalog before, make sure to read How to use the Gruntwork Service Catalog!
CI/ CD Core Concepts: An overview of the core concepts you need to understand what a typical CI/CD pipeline entails for application and infrastructure code, including a sample workflow, infrastructure to support CI/CD, an threat models to consider to protect your infrastructure.
Jenkins Documentation: The official documentation for Jenkins.
Deploy
Non-production deployment (quick start for learning)
If you just want to try this repo out for experimenting and learning, check out the following resources:
- examples/for-learning-and-testing folder: The
examples/for-learning-and-testing
folder contains standalone sample code optimized for learning, experimenting, and testing (but not direct production usage).
Production deployment
If you want to deploy this repo in production, check out the following resources:
examples/for-production folder: The
examples/for-production
folder contains sample code optimized for direct usage in production. This is code from the Gruntwork Reference Architecture, and it shows you how we build an end-to-end, integrated tech stack on top of the Gruntwork Service Catalog.How to configure a production-grade CI/CD workflow for application and infrastructure code: step-by-step guide on how to configure CI / CD for your apps and infrastructure.
Reference
- Inputs
- Outputs
Required
acm_ssl_certificate_domain
string(required)The domain name used for an SSL certificate issued by the Amazon Certificate Manager (ACM).
alb_subnet_ids
list(required)The IDs of the subnets in which to deploy the ALB that runs in front of Jenkins. Must be subnets in vpc_id
.
list(string)
ami
string(required)The ID of the AMI to run on the Jenkins server. This should be the AMI build from the Packer template jenkins-ubuntu.json. One of var.ami or ami_filters
is required. Set to null if looking up the ami with filters.
ami_filters
object(required)Properties on the AMI that can be used to lookup a prebuilt AMI for use with Jenkins. You can build the AMI using the Packer template jenkins-ubuntu.json. Only used if var.ami is null. One of var.ami or ami_filters
is required. Set to null if passing the ami ID directly.
object({
# List of owners to limit the search. Set to null if you do not wish to limit the search by AMI owners.
owners = list(string)
# Name/Value pairs to filter the AMI off of. There are several valid keys, for a full reference, check out the
# documentation for describe-images in the AWS CLI reference
# (https://docs.aws.amazon.com/cli/latest/reference/ec2/describe-images.html).
filters = list(object({
name = string
values = list(string)
}))
})
domain_name
string(required)The domain name for the DNS A record to add for Jenkins (e.g. jenkins.foo.com). Must be in the domain managed by hosted_zone_id
.
hosted_zone_id
string(required)The ID of the Route 53 Hosted Zone in which to create a DNS A record for Jenkins.
instance_type
string(required)The instance type to use for the Jenkins server (e.g. t2.medium)
jenkins_subnet_id
string(required)The ID of the subnet in which to deploy Jenkins. Must be a subnet in vpc_id
.
memory
string(required)The amount of memory to give Jenkins (e.g., 1g or 512m). Used for the -Xms and -Xmx settings.
vpc_id
string(required)The ID of the VPC in which to deploy Jenkins
Optional
alarms_sns_topic_arn
list(optional)The ARNs of SNS topics where CloudWatch alarms (e.g., for CPU, memory, and disk space usage) should send notifications. Also used for the alarms if the Jenkins backup job fails.
list(string)
[]
allow_incoming_http_from_cidr_blocks
list(optional)The IP address ranges in CIDR format from which to allow incoming HTTP requests to Jenkins.
list(string)
[]
allow_incoming_http_from_security_group_ids
list(optional)The IDs of security groups from which to allow incoming HTTP requests to Jenkins.
list(string)
[]
allow_ssh_from_cidr_blocks
list(optional)The IP address ranges in CIDR format from which to allow incoming SSH requests to Jenkins.
list(string)
[]
allow_ssh_from_security_group_ids
list(optional)The IDs of security groups from which to allow incoming SSH requests to Jenkins.
list(string)
[]
backup_job_alarm_period
number(optional)How often, in seconds, the backup job is expected to run. This is the same as backup_job_schedule_expression
, but unfortunately, Terraform offers no way to convert rate expressions to seconds. We add a CloudWatch alarm that triggers if the value of backup_job_metric_name
and backup_job_metric_namespace
isn't updated within this time period, as that indicates the backup failed to run.
86400
backup_job_metric_name
string(optional)The name for the CloudWatch Metric the AWS lambda backup job will increment every time the job completes successfully.
jenkins-backup-job
backup_job_metric_namespace
string(optional)The namespace for the CloudWatch Metric the AWS lambda backup job will increment every time the job completes successfully.
Custom/Jenkins
backup_job_schedule_expression
string(optional)A cron or rate expression that specifies how often to take a snapshot of the Jenkins server for backup purposes. See https://docs.aws.amazon.com/AmazonCloudWatch/latest/events/ScheduledEvents.html for syntax details.
rate(1 day)
backup_using_dlm
bool(optional)Set to true to backup the Jenkins Server using AWS Data Lifecycle Management Policies.
true
backup_using_lambda
bool(optional)Set to true to backup the Jenkins Server using a Scheduled Lambda Function.
false
build_permission_actions
list(optional)The list of IAM actions this Jenkins server should be allowed to do: e.g., ec2:, s3:, etc. This should be the list of IAM permissions Jenkins needs in this AWS account to run builds. These permissions will be added to the server's IAM role for all resources ('*').
list(string)
[]
cloud_init_parts
map(optional)Cloud init scripts to run on the Jenkins server when it is booting. See the part blocks in https://www.terraform.io/docs/providers/template/d/cloudinit_config.html for syntax.
map(object({
filename = string
content_type = string
content = string
}))
{}
cloudwatch_log_group_kms_key_id
string(optional)The ID (ARN, alias ARN, AWS ID) of a customer managed KMS Key to use for encrypting log data.
null
cloudwatch_log_group_retention_in_days
number(optional)The number of days to retain log events in the log group. Refer to https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group#retention_in_days for all the valid values. When null, the log events are retained forever.
null
cloudwatch_log_group_tags
map(optional)Tags to apply on the CloudWatch Log Group, encoded as a map where the keys are tag keys and values are tag values.
map(string)
null
custom_tags
map(optional)A list of custom tags to apply to Jenkins and all other resources.
map(string)
{}
default_user
string(optional)The default OS user for the Jenkins AMI. For AWS Ubuntu AMIs, which is what the Packer template in jenkins-ubunutu.json uses, the default OS user is 'ubuntu'.
ubuntu
dlm_backup_job_schedule_interval
number(optional)How often this lifecycle policy should be evaluated, in hours.
24
dlm_backup_job_schedule_name
string(optional)The name of the data lifecyle management schedule
daily-last-two-weeks
dlm_backup_job_schedule_number_of_snapshots_to_retain
number(optional)How many snapshots to keep. Must be an integer between 1 and 1000.
15
dlm_backup_job_schedule_times
list(optional)A list of times in 24 hour clock format that sets when the lifecyle policy should be evaluated. Max of 1.
list(string)
[ '03:00'
]
ebs_kms_key_arn
string(optional)The ARN of the KMS key used for encrypting the Jenkins EBS volume. The module will grant Jenkins permission to use this key.
null
ebs_kms_key_arn_is_alias
bool(optional)Whether or not the provide EBS KMS key ARN is a key alias. If providing the key ID, leave this set to false.
false
enable_cloudwatch_alarms
bool(optional)Set to true to enable several basic CloudWatch alarms around CPU usage, memory usage, and disk space usage. If set to true, make sure to specify SNS topics to send notifications to using alarms_sns_topic_arn
.
true
enable_cloudwatch_log_aggregation
bool(optional)Set to true to add AIM permissions to send logs to CloudWatch. This is useful in combination with https://github.com/gruntwork-io/terraform-aws-monitoring/tree/master/modules/logs/cloudwatch-log-aggregation-scripts to do log aggregation in CloudWatch.
true
enable_cloudwatch_metrics
bool(optional)Set to true to add IAM permissions to send custom metrics to CloudWatch. This is useful in combination with https://github.com/gruntwork-io/terraform-aws-monitoring/tree/master/modules/agents/cloudwatch-agent to get memory and disk metrics in CloudWatch for your Jenkins server.
true
enable_ip_lockdown
bool(optional)Enable ip-lockdown to block access to the instance metadata. Defaults to true.
true
enable_ssh_grunt
bool(optional)Set to true to add IAM permissions for ssh-grunt (https://github.com/gruntwork-io/terraform-aws-security/tree/master/modules/ssh-grunt), which will allow you to manage SSH access via IAM groups.
true
external_account_auto_deploy_iam_role_arns
list(optional)A list of IAM role ARNs in other AWS accounts that Jenkins will be able to assume to do automated deployment in those accounts.
list(string)
[]
external_account_ssh_grunt_role_arn
string(optional)If you are using ssh-grunt and your IAM users / groups are defined in a separate AWS account, you can use this variable to specify the ARN of an IAM role that ssh-grunt can assume to retrieve IAM group and public SSH key info from that account. To omit this variable, set it to an empty string (do NOT use null, or Terraform will complain).
""
is_internal_alb
bool(optional)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
jenkins_device_name
string(optional)The OS device name where the Jenkins EBS volume should be attached
xvdh
jenkins_mount_point
string(optional)The OS path where the Jenkins EBS volume should be mounted
/jenkins
jenkins_user
string(optional)The OS user that should be used to run Jenkins
jenkins
jenkins_volume_encrypted
bool(optional)Set to true to encrypt the Jenkins EBS volume.
true
jenkins_volume_size
number(optional)The amount of disk space, in GB, to allocate for the EBS volume used by the Jenkins server.
200
jenkins_volume_type
string(optional)The type of volume to use for the EBS volume used by the Jenkins server. Must be one of: standard, gp2, io1, sc1, or st1.
gp2
keypair_name
string(optional)The name of a Key Pair that can be used to SSH to the Jenkins server. Leave blank if you don't want to enable Key Pair auth.
null
name
string(optional)Enter the name of the Jenkins server
jenkins
root_block_device_volume_type
string(optional)The type of volume to use for the root disk for Jenkins. Must be one of: standard, gp2, io1, sc1, or st1.
gp2
root_volume_size
number(optional)The amount of disk space, in GB, to allocate for the root volume of this server. Note that all of Jenkins' data is stored on a separate EBS Volume (see jenkins_volume_size
), so this root volume is primarily used for the OS, temp folders, apps, etc.
100
should_create_cloudwatch_log_group
bool(optional)When true, precreate the CloudWatch Log Group to use for log aggregation from the EC2 instances. This is useful if you wish to customize the CloudWatch Log Group with various settings such as retention periods and KMS encryption. When false, the CloudWatch agent will automatically create a basic log group to use.
true
skip_health_check
bool(optional)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
ssh_grunt_iam_group
string(optional)If you are using ssh-grunt, this is the name of the IAM group from which users will be allowed to SSH to this Jenkins server. This value is only used if enable_ssh_grunt=true.
ssh-grunt-users
ssh_grunt_iam_group_sudo
string(optional)If you are using ssh-grunt, this is the name of the IAM group from which users will be allowed to SSH to this Jenkins server with sudo permissions. This value is only used if enable_ssh_grunt=true.
ssh-grunt-sudo-users
tenancy
string(optional)The tenancy of this server. Must be one of: default, dedicated, or host.
default
use_managed_iam_policies
bool(optional)When true, all IAM policies will be managed as dedicated policies rather than inline policies attached to the IAM roles. Dedicated managed policies are friendlier to automated policy checkers, which may scan a single resource for findings. As such, it is important to avoid inline policies when targeting compliance with various security standards.
true
The ARN of the ALB deployed in front of Jenkins
The DNS name of the ALB deployed in front of Jenkins
The hosted zone ID of the ALB deployed in front of Jenkins
The ARNs of just the HTTP ALB listeners of the ALB deployed in front of Jenkins
The ARNs of just the HTTPS ALB listeners that usse ACM certs of the ALB deployed in front of Jenkins
The ARNs of just the HTTPS ALB listeners that use non-ACM certs of the ALB deployed in front of Jenkins
The ARNs of the ALB listeners of the ALB deployed in front of Jenkins
The name of the ALB deployed in front of Jenkins
The ID of the security group attached to the ALB deployed in front of Jenkins
The name of the Auto Scaling Group in which Jenkins is running
The public domain name configured for Jenkins
The ID of the EBS Volume that will store the JENKINS_HOME directory
The ARN of the IAM role attached to the Jenkins EC2 Instance
The ID of the IAM role attached to the Jenkins EC2 Instance
The ID of the Security Group attached to the Jenkins EC2 Instance