Created
March 30, 2018 03:01
-
-
Save randika/c08e911cf7a8ed52e6642a9606ae3ea2 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"AWSTemplateFormatVersion": "2010-09-09", | |
"Description": "Launches a Jenkins server", | |
"Parameters": { | |
"InstanceType": { | |
"Description": "EC2 instance type", | |
"Type": "String", | |
"Default": "t2.small", | |
"AllowedValues": [ | |
"t1.micro", | |
"t2.small", | |
"m1.small", | |
"m1.medium", | |
"m1.large", | |
"m1.xlarge", | |
"m2.xlarge", | |
"m2.2xlarge", | |
"m2.4xlarge", | |
"m3.xlarge", | |
"m3.2xlarge", | |
"c1.medium", | |
"c1.xlarge", | |
"cc1.4xlarge", | |
"cc2.8xlarge", | |
"cg1.4xlarge" | |
], | |
"ConstraintDescription": "must be a valid EC2 instance type." | |
}, | |
"AppId": { | |
"Description": "Application Identifier", | |
"Type": "String", | |
"Default": "" | |
}, | |
"AppComponentId": { | |
"Description": "Application Component name. (ex: web, db, build)", | |
"Type": "String" | |
}, | |
"AppEnv": { | |
"Description": "Application Environment", | |
"Type": "String", | |
"Default": "dev" | |
}, | |
"SshKey": { | |
"Description": "Name of an existing EC2 keypair to enable SSH access to the instances", | |
"Default": "", | |
"Type": "AWS::EC2::KeyPair::KeyName" | |
}, | |
"IPWhitelist": { | |
"Description": "IP Address to Whitelist (your IP address followed by /32)", | |
"MinLength": "9", | |
"MaxLength": "18", | |
"Type": "String", | |
"AllowedPattern": "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})", | |
"ConstraintDescription": "must be a valid IP CIDR range of the form x.x.x.x/x.", | |
"Default": "0.0.0.0/0" | |
}, | |
"EmailAddress": { | |
"Description": "What email address will receive the default Jenkins password", | |
"Type": "String", | |
"Default": "" | |
}, | |
"S3Bucket": { | |
"Description": "Existing S3 bucket to use for Jenkins backups and restores", | |
"Type": "String" | |
}, | |
"S3Prefix": { | |
"Description": "[Optional] Key prefix to use for Jenkins backups", | |
"Type": "String", | |
"Default": "" | |
}, | |
"Subnets": { | |
"Description": "List of VPC subnet IDs for the cluster", | |
"Type": "List<AWS::EC2::Subnet::Id>" | |
}, | |
"VpcId": { | |
"Description": "VPC associated with the provided subnets", | |
"Type": "AWS::EC2::VPC::Id" | |
}, | |
"AdminSecurityGroup": { | |
"Description": "Existing security group that should be granted administrative access to Jenkins (e.g., 'sg-123456')", | |
"Default": "Primary", | |
"Type": "AWS::EC2::SecurityGroup::Id" | |
} | |
}, | |
"Mappings": { | |
"RegionMap": { | |
"us-east-1": { | |
"AMI": "ami-6869aa05" | |
}, | |
"us-west-1": { | |
"AMI": "ami-7172b611" | |
}, | |
"us-west-2": { | |
"AMI": "ami-31490d51" | |
}, | |
"eu-west-1": { | |
"AMI": "ami-f9dd458a" | |
} | |
} | |
}, | |
"Resources": { | |
"CloudFormationLogs": { | |
"Type": "AWS::Logs::LogGroup", | |
"Properties": { | |
"RetentionInDays": 7 | |
} | |
}, | |
"IamJenkinsUser": { | |
"Type": "AWS::IAM::User", | |
"Properties": { | |
"Policies": [ | |
{ | |
"PolicyName": "S3Access", | |
"PolicyDocument": { | |
"Statement": [ | |
{ | |
"Effect": "Allow", | |
"Action": "s3:*", | |
"Resource": { | |
"Fn::Join": [ | |
"", | |
[ | |
"arn:aws:s3:::", | |
{ | |
"Ref": "S3Bucket" | |
}, | |
"/*" | |
] | |
] | |
} | |
} | |
] | |
} | |
}, | |
{ | |
"PolicyName": "IAMAccess", | |
"PolicyDocument": { | |
"Statement": [ | |
{ | |
"Effect": "Allow", | |
"NotAction": "iam:*", | |
"Resource": "*" | |
} | |
] | |
} | |
}, | |
{ | |
"PolicyName": "EC2Access", | |
"PolicyDocument": { | |
"Statement": [ | |
{ | |
"Effect": "Allow", | |
"Action": "ec2:*", | |
"Resource": "*" | |
} | |
] | |
} | |
} | |
] | |
} | |
}, | |
"BuildRole": { | |
"Type": "AWS::IAM::Role", | |
"Properties": { | |
"AssumeRolePolicyDocument": { | |
"Version": "2012-10-17", | |
"Statement": [ | |
{ | |
"Effect": "Allow", | |
"Principal": { | |
"Service": [ | |
"ec2.amazonaws.com" | |
] | |
}, | |
"Action": [ | |
"sts:AssumeRole" | |
] | |
} | |
] | |
}, | |
"Policies": [ | |
{ | |
"PolicyName": "root", | |
"PolicyDocument": { | |
"Version": "2012-10-17", | |
"Statement": [ | |
{ | |
"Effect": "Allow", | |
"Action": "*", | |
"Resource": "*" | |
} | |
] | |
} | |
} | |
] | |
} | |
}, | |
"RolePolicies": { | |
"Type": "AWS::IAM::Policy", | |
"Properties": { | |
"PolicyName": "root", | |
"PolicyDocument": { | |
"Version": "2012-10-17", | |
"Statement": [ | |
{ | |
"Action": "ec2:*", | |
"Effect": "Allow", | |
"Resource": "*" | |
}, | |
{ | |
"Effect": "Allow", | |
"Action": "elasticloadbalancing:*", | |
"Resource": "*" | |
}, | |
{ | |
"Effect": "Allow", | |
"Action": "cloudwatch:*", | |
"Resource": "*" | |
}, | |
{ | |
"Effect": "Allow", | |
"Action": "autoscaling:*", | |
"Resource": "*" | |
}, | |
{ | |
"Effect": "Allow", | |
"Action": "s3:*", | |
"Resource": "*" | |
}, | |
{ | |
"Effect": "Allow", | |
"Action": "ecs:*", | |
"Resource": "*" | |
}, | |
{ | |
"Effect": "Allow", | |
"Action": "ecr:*", | |
"Resource": "*" | |
} | |
{ | |
"Effect": "Allow", | |
"Action": [ | |
"iam:PassRole", | |
"iam:ListInstanceProfiles", | |
"ec2:*" | |
], | |
"Resource": "*" | |
} | |
] | |
}, | |
"Roles": [ | |
{ | |
"Ref": "BuildRole" | |
} | |
] | |
} | |
}, | |
"BuildInstanceProfile": { | |
"Type": "AWS::IAM::InstanceProfile", | |
"Properties": { | |
"Path": "/", | |
"Roles": [ | |
{ | |
"Ref": "BuildRole" | |
} | |
] | |
} | |
}, | |
"HostKeys": { | |
"Type": "AWS::IAM::AccessKey", | |
"Properties": { | |
"UserName": { | |
"Ref": "IamJenkinsUser" | |
} | |
} | |
}, | |
"ServerGroup": { | |
"Type": "AWS::AutoScaling::AutoScalingGroup", | |
"Properties": { | |
"VPCZoneIdentifier" : { "Ref" : "Subnets" }, | |
"LaunchConfigurationName": { | |
"Ref": "LaunchConfig" | |
}, | |
"MinSize": "1", | |
"MaxSize": "1", | |
"DesiredCapacity": "1", | |
"LoadBalancerNames": [ | |
{ | |
"Ref": "ElasticLoadBalancer" | |
} | |
], | |
"Tags" : [ | |
{ | |
"Key" : "app_id", | |
"Value" : { "Ref": "AppId"}, | |
"PropagateAtLaunch" : "true" | |
}, | |
{ | |
"Key" : "env", | |
"Value" : { "Ref": "AppEnv"}, | |
"PropagateAtLaunch" : "true" | |
} | |
] | |
} | |
}, | |
"LaunchConfig": { | |
"Type": "AWS::AutoScaling::LaunchConfiguration", | |
"Metadata": { | |
"Comment": "Install a simple application", | |
"AWS::CloudFormation::Init": { | |
"configSets": { | |
"install_all": ["install_cfn", "install_base", "install_nginx", "install_logs"] | |
}, | |
"install_cfn": { | |
"files": { | |
"/etc/cfn/cfn-hup.conf": { | |
"content": { | |
"Fn::Join": ["", [ | |
"[main]\n", | |
"stack=", { | |
"Ref": "AWS::StackId" | |
}, "\n", | |
"region=", { | |
"Ref": "AWS::Region" | |
}, "\n" | |
]] | |
}, | |
"mode": "000400", | |
"owner": "root", | |
"group": "root" | |
}, | |
"/etc/cfn/hooks.d/cfn-auto-reloader.conf": { | |
"content": { | |
"Fn::Join": ["", [ | |
"[cfn-auto-reloader-hook]\n", | |
"triggers=post.update\n", | |
"path=Resources.WebServerInstance.Metadata.AWS::CloudFormation::Init\n", | |
"action=/opt/aws/bin/cfn-init -v ", | |
" --stack ", { | |
"Ref": "AWS::StackName" | |
}, | |
" --resource WebServerInstance ", | |
" --configsets install_all ", | |
" --region ", { | |
"Ref": "AWS::Region" | |
}, "\n", | |
"runas=root\n" | |
]] | |
} | |
} | |
}, | |
"services": { | |
"sysvinit": { | |
"cfn-hup": { | |
"enabled": "true", | |
"ensureRunning": "true", | |
"files": ["/etc/cfn/cfn-hup.conf", "/etc/cfn/hooks.d/cfn-auto-reloader.conf"] | |
} | |
} | |
} | |
}, | |
"install_base": { | |
"packages": { | |
"yum": { | |
"git": [], | |
"docker": [], | |
"httpd-tools": [], | |
"jq": [], | |
"java-1.8.0-openjdk.x86_64": [] | |
} | |
}, | |
"services": { | |
"sysvinit": { | |
"docker": { | |
"enabled": "true", | |
"ensureRunning": "true" | |
} | |
} | |
} | |
}, | |
"install_nginx": { | |
"packages": { | |
"yum": { | |
"nginx": [] | |
} | |
}, | |
"files": { | |
"/etc/nginx/nginx.conf": { | |
"content": { | |
"Fn::Join": ["", [ | |
"user nginx;\n", | |
"worker_processes 1;\n\n", | |
"error_log /var/log/nginx/error.log;\n", | |
"pid /var/run/nginx.pid;\n\n", | |
"events {\n", | |
" worker_connections 1024;\n", | |
"}\n\n", | |
"http {\n", | |
" include /etc/nginx/mime.types;\n", | |
" default_type application/octet-stream;\n", | |
" log_format main '$remote_addr - $remote_user [$time_local] \"$request\" '\n", | |
" '$status $body_bytes_sent \"$http_referer\" '\n", | |
" '\"$http_user_agent\" \"$http_x_forwarded_for\"';\n\n", | |
" access_log /var/log/nginx/access.log main;\n", | |
" sendfile on;\n", | |
" keepalive_timeout 65;\n", | |
" include /etc/nginx/conf.d/*.conf;\n", | |
" index index.html index.htm;\n", | |
" server {\n", | |
" listen 80;\n", | |
" server_name _;\n", | |
" location / {\n", | |
" proxy_pass http://127.0.0.1:8080;\n", | |
" proxy_set_header Host $host;\n", | |
" proxy_set_header X-Real-IP $remote_addr;\n", | |
" proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n", | |
" proxy_connect_timeout 150;\n", | |
" proxy_send_timeout 100;\n", | |
" proxy_read_timeout 100;\n", | |
" proxy_buffers 4 32k;\n", | |
" client_max_body_size 8m;\n", | |
" client_body_buffer_size 128k;\n", | |
" }\n", | |
" }\n", | |
"}\n" | |
]] | |
}, | |
"mode": "000444", | |
"owner": "root", | |
"group": "root" | |
} | |
}, | |
"services": { | |
"sysvinit": { | |
"nginx": { | |
"enabled": "true", | |
"ensureRunning": "true", | |
"files": ["/etc/nginx/nginx.conf"] | |
} | |
} | |
} | |
}, | |
"install_logs": { | |
"packages": { | |
"yum": { | |
"awslogs": [] | |
} | |
}, | |
"files": { | |
"/etc/awslogs/awslogs.conf": { | |
"content": { | |
"Fn::Join": ["", [ | |
"[general]\n", | |
"state_file= /var/awslogs/state/agent-state\n", | |
"[/var/log/cloud-init.log]\n", | |
"file = /var/log/cloud-init.log\n", | |
"log_group_name = ", { | |
"Ref": "CloudFormationLogs" | |
}, "\n", | |
"log_stream_name = {instance_id}/cloud-init.log\n", | |
"datetime_format = \n", | |
"[/var/log/cloud-init-output.log]\n", | |
"file = /var/log/cloud-init-output.log\n", | |
"log_group_name = ", { | |
"Ref": "CloudFormationLogs" | |
}, "\n", | |
"log_stream_name = {instance_id}/cloud-init-output.log\n", | |
"datetime_format = \n", | |
"[/var/log/cfn-init.log]\n", | |
"file = /var/log/cfn-init.log\n", | |
"log_group_name = ", { | |
"Ref": "CloudFormationLogs" | |
}, "\n", | |
"log_stream_name = {instance_id}/cfn-init.log\n", | |
"datetime_format = \n", | |
"[/var/log/cfn-hup.log]\n", | |
"file = /var/log/cfn-hup.log\n", | |
"log_group_name = ", { | |
"Ref": "CloudFormationLogs" | |
}, "\n", | |
"log_stream_name = {instance_id}/cfn-hup.log\n", | |
"datetime_format = \n", | |
"[/var/log/cfn-wire.log]\n", | |
"file = /var/log/cfn-wire.log\n", | |
"log_group_name = ", { | |
"Ref": "CloudFormationLogs" | |
}, "\n", | |
"log_stream_name = {instance_id}/cfn-wire.log\n", | |
"datetime_format = \n", | |
"[/var/log/nginx/access.log]\n", | |
"file = /var/log/nginx/access.log\n", | |
"log_group_name = ", { | |
"Ref": "CloudFormationLogs" | |
}, "\n", | |
"log_stream_name = {instance_id}/nginx-access.log\n", | |
"datetime_format = \n", | |
"[/var/log/nginx/error.log]\n", | |
"file = /var/log/nginx/error.log\n", | |
"log_group_name = ", { | |
"Ref": "CloudFormationLogs" | |
}, "\n", | |
"log_stream_name = {instance_id}/nginx-error.log\n", | |
"datetime_format = \n", | |
"[/var/log/jenkins/jenkins.log]\n", | |
"file = /var/log/jenkins/jenkins.log\n", | |
"log_group_name = ", { | |
"Ref": "CloudFormationLogs" | |
}, "\n", | |
"log_stream_name = {instance_id}/jenkins.log\n", | |
"datetime_format = \n" | |
]] | |
}, | |
"mode": "000444", | |
"owner": "root", | |
"group": "root" | |
} | |
}, | |
"commands": { | |
"01_create_state_directory": { | |
"command": "mkdir -p /var/awslogs/state" | |
}, | |
"02_change_log_region": { | |
"command": { | |
"Fn::Join": ["", ["sed -i 's/region = us-east-1/region = ", | |
{ "Ref": "AWS::Region" }, | |
"/g' /etc/awslogs/awscli.conf"]] | |
} | |
} | |
}, | |
"services": { | |
"sysvinit": { | |
"awslogs": { | |
"enabled": "true", | |
"ensureRunning": "true", | |
"files": ["/etc/awslogs/awslogs.conf"] | |
} | |
} | |
} | |
} | |
} | |
}, | |
"Properties": { | |
"KeyName": { | |
"Ref": "SshKey" | |
}, | |
"ImageId": { | |
"Fn::FindInMap": [ | |
"RegionMap", | |
{ | |
"Ref": "AWS::Region" | |
}, | |
"AMI" | |
] | |
}, | |
"BlockDeviceMappings": [{ | |
"DeviceName": "/dev/xvda", | |
"Ebs": { | |
"VolumeSize": "50", | |
"VolumeType": "gp2" | |
} | |
}], | |
"SecurityGroups": [{ | |
"Ref": "ServerSecurityGroup" | |
}], | |
"InstanceType": { | |
"Ref": "InstanceType" | |
}, | |
"IamInstanceProfile": { | |
"Ref": "BuildInstanceProfile" | |
}, | |
"UserData": { | |
"Fn::Base64": { | |
"Fn::Join": ["", [ | |
"#!/bin/bash -xe\n", | |
"yum update -y aws-cfn-bootstrap\n", | |
"/opt/aws/bin/cfn-init -v ", | |
" --stack ", { | |
"Ref": "AWS::StackName" | |
}, | |
" --resource LaunchConfig ", | |
" --configsets install_all ", | |
" --region ", { | |
"Ref": "AWS::Region" | |
}, "\n", | |
"yum remove -y java-1.7.0\n", | |
"# Install Jenkins\n", | |
"wget -O /etc/yum.repos.d/jenkins.repo http://pkg.jenkins-ci.org/redhat/jenkins.repo\n", | |
"rpm --import http://pkg.jenkins-ci.org/redhat/jenkins-ci.org.key\n", | |
"yum install -y jenkins\n", | |
"# Add Jenkins user to Docker group\n", | |
"usermod -a -G docker jenkins\n", | |
"service jenkins start\n", | |
"chkconfig jenkins on\n", | |
"# Update the AWS CLI to the latest version\n", | |
"yum update -y aws-cli\n", | |
"# Wait 30 seconds to allow Jenkins to startup\n", | |
"echo \"Waiting 30 seconds for Jenkins to start.....\"\n", | |
"sleep 30\n", | |
"# Install the required plugins\n", | |
"cd /var/lib/jenkins/plugins\n", | |
"curl -O -L https://updates.jenkins-ci.org/latest/token-macro.hpi\n", | |
"curl -O -L https://updates.jenkins-ci.org/latest/docker-build-publish.hpi\n", | |
"curl -O -L https://updates.jenkins-ci.org/latest/multiple-scms.hpi\n", | |
"curl -O -L https://updates.jenkins-ci.org/latest/github-api.hpi\n", | |
"curl -O -L https://updates.jenkins-ci.org/latest/scm-api.hpi\n", | |
"curl -O -L https://updates.jenkins-ci.org/latest/git-client.hpi\n", | |
"curl -O -L https://updates.jenkins-ci.org/latest/github.hpi\n", | |
"curl -O -L https://updates.jenkins-ci.org/latest/git.hpi\n", | |
"curl -O -L https://updates.jenkins-ci.org/latest/dockerhub.hpi\n", | |
"chown jenkins:jenkins *.hpi\n", | |
"# Restarting Jenkins\n", | |
"service jenkins restart\n", | |
"/opt/aws/bin/cfn-signal -e $? ", | |
" --stack ", { | |
"Ref": "AWS::StackName" | |
}, | |
" --resource WebServerGroup ", | |
" --region ", { | |
"Ref": "AWS::Region" | |
}, "\n" | |
]] | |
} | |
}, | |
} | |
}, | |
"LbSecurityGroup": { | |
"Type": "AWS::EC2::SecurityGroup", | |
"Properties": { | |
"GroupDescription": "Jenkins LBs", | |
"VpcId": { | |
"Ref": "VpcId" | |
}, | |
"SecurityGroupIngress": [ | |
{ | |
"IpProtocol": "tcp", | |
"FromPort": "80", | |
"ToPort": "80", | |
"CidrIp": "0.0.0.0/0" | |
} | |
], | |
"Tags" : [ | |
{ | |
"Key" : "app_id", | |
"Value" : { "Ref": "AppId"} | |
}, | |
{ | |
"Key" : "env", | |
"Value" : { "Ref": "AppEnv"} | |
} | |
] | |
} | |
}, | |
"ServerSecurityGroup": { | |
"Type": "AWS::EC2::SecurityGroup", | |
"Properties": { | |
"GroupDescription": "Jenkins servers", | |
"VpcId": { | |
"Ref": "VpcId" | |
}, | |
"SecurityGroupIngress": [ | |
{ | |
"IpProtocol": "tcp", | |
"FromPort": "8080", | |
"ToPort": "8080", | |
"CidrIp": "0.0.0.0/0" | |
}, | |
{ | |
"IpProtocol": "tcp", | |
"FromPort": "22", | |
"ToPort": "22", | |
"CidrIp": {"Ref" : "IPWhitelist"} | |
} | |
], | |
"Tags" : [ | |
{ | |
"Key" : "app_id", | |
"Value" : { "Ref": "AppId"} | |
}, | |
{ | |
"Key" : "env", | |
"Value" : { "Ref": "AppEnv"} | |
} | |
] | |
} | |
}, | |
"ElasticLoadBalancer": { | |
"Type": "AWS::ElasticLoadBalancing::LoadBalancer", | |
"Properties": { | |
"SecurityGroups": [ | |
{ | |
"Ref": "LbSecurityGroup" | |
}, | |
{ | |
"Ref": "AdminSecurityGroup" | |
} | |
], | |
"Subnets": { | |
"Ref": "Subnets" | |
}, | |
"Listeners": [ | |
{ | |
"LoadBalancerPort": "80", | |
"InstancePort": "8080", | |
"Protocol": "HTTP" | |
} | |
], | |
"HealthCheck": { | |
"Target": "TCP:8080", | |
"HealthyThreshold": "3", | |
"UnhealthyThreshold": "5", | |
"Interval": "30", | |
"Timeout": "5" | |
}, | |
"LoadBalancerName": { | |
"Fn::Join": [ | |
"-", | |
[ | |
{"Ref": "AppEnv"},{"Ref": "AppId"},{"Ref": "AppComponentId"} | |
] | |
] | |
}, | |
"Tags" : [ | |
{ | |
"Key" : "app_id", | |
"Value" : { "Ref": "AppId"} | |
}, | |
{ | |
"Key" : "env", | |
"Value" : { "Ref": "AppEnv"} | |
} | |
] | |
} | |
}, | |
"WaitHandle": { | |
"Type": "AWS::CloudFormation::WaitConditionHandle" | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment