AWSTemplateFormatVersion: "2010-09-09" Description: >- PagerBeauty: PagerDuty on-call widget for your monitoring dashboard # ------- Mappings ----------------------------------------------------------- # Mappings: AWSInstanceType2Arch: m4.large: Arch: HVM64 m4.xlarge: Arch: HVM64 m4.2xlarge: Arch: HVM64 m4.4xlarge: Arch: HVM64 m4.10xlarge: Arch: HVM64 m4.16xlarge: Arch: HVM64 m5.large: Arch: HVM64 m5.xlarge: Arch: HVM64 m5.2xlarge: Arch: HVM64 m5.4xlarge: Arch: HVM64 m5.8xlarge: Arch: HVM64 m5.12xlarge: Arch: HVM64 m5.16xlarge: Arch: HVM64 m5.24xlarge: Arch: HVM64 m5.metal: Arch: HVM64 m5d.large: Arch: HVM64 m5d.xlarge: Arch: HVM64 m5d.2xlarge: Arch: HVM64 m5d.4xlarge: Arch: HVM64 m5d.8xlarge: Arch: HVM64 m5d.12xlarge: Arch: HVM64 m5d.16xlarge: Arch: HVM64 m5d.24xlarge: Arch: HVM64 m5d.metal: Arch: HVM64 t2.nano: Arch: HVM64 t2.micro: Arch: HVM64 t2.small: Arch: HVM64 t2.medium: Arch: HVM64 t2.large: Arch: HVM64 t2.xlarge: Arch: HVM64 t2.2xlarge: Arch: HVM64 AWSRegionArch2AMI: # https://aws.amazon.com/amazon-linux-ami/2018.03-release-notes/ ap-east-1: HVM64: ami-f3e19982 ap-northeast-1: HVM64: ami-03170618b41df9458 ap-northeast-2: HVM64: ami-0761fc884501dd08f ap-northeast-3: HVM64: ami-06f86eac01b79c18d ap-south-1: HVM64: ami-0d2e8ef01c8b6708d ap-southeast-1: HVM64: ami-0131c0c47922b4c1e ap-southeast-2: HVM64: ami-081790451483a9fec ca-central-1: HVM64: ami-00a6bab89074a4d9e cn-north-1: HVM64: ami-00076fc62e7f14ef8 cn-northwest-1: HVM64: ami-09405a182abd40504 eu-central-1: HVM64: ami-0a0f438792b407c3d eu-north-1: HVM64: ami-bf4bc3c1 eu-west-1: HVM64: ami-0dc9a8d2479a3c7d7 eu-west-2: HVM64: ami-0e9a26a04cf77de3b eu-west-3: HVM64: ami-0f606357fbf7be639 sa-east-1: HVM64: ami-0d532fdce993b9c55 us-east-1: HVM64: ami-0e05097610fae5559 us-east-2: HVM64: ami-0b00e7f461c40ed19 us-gov-east-1: HVM64: ami-7db0510c us-gov-west-1: HVM64: ami-fb4d319a us-west-1: HVM64: ami-0b4a9c56e9f69e9f8 us-west-2: HVM64: ami-0d1d9e1864d1494b6 # ------- Parameters --------------------------------------------------------- # Parameters: KeyName: Description: The EC2 Key Pair to allow SSH access to the instance Type: 'AWS::EC2::KeyPair::KeyName' InstanceType: Description: WebServer EC2 instance type Type: String Default: t2.micro AllowedValues: # https://aws.amazon.com/amazon-linux-ami/instance-type-matrix/ # https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-types.html - m4.large - m4.xlarge - m4.2xlarge - m4.4xlarge - m4.10xlarge - m4.16xlarge - m5.large - m5.xlarge - m5.2xlarge - m5.4xlarge - m5.8xlarge - m5.12xlarge - m5.16xlarge - m5.24xlarge - m5.metal - m5d.large - m5d.xlarge - m5d.2xlarge - m5d.4xlarge - m5d.8xlarge - m5d.12xlarge - m5d.16xlarge - m5d.24xlarge - m5d.metal - t2.nano - t2.micro - t2.small - t2.medium - t2.large - t2.xlarge - t2.2xlarge ConstraintDescription: must be a valid EC2 instance type. SSHLocation: Description: | The IP address range that can be used to SSH to the EC2 instances. To allow connections from all IPs, enter 0.0.0.0/0 Type: String MinLength: '9' MaxLength: '18' 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. PagerbeautyPdApiKey: Description: | Prefer Read-Only key. Docs: https://support.pagerduty.com/docs/using-the-api Type: String NoEcho: True PagerbeautyPdSchedules: Description: | Comma-separated list of PagerDuty schedule ids. You can find schedule id in the URL of the schedule on PagerDuty website after symbol #. For example, schedule https://example.pagerduty.com/schedules#PJ1P5JQ has id PJ1P5JQ Type: CommaDelimitedList PagerbeautyHTTPUser: Description: (optional) Type: String PagerbeautyHTTPPassword: Description: (optional) Type: String NoEcho: True PagerbeautyHTTPAccessToken: Description: | (optional) Random characters and digits of your choice. Makes possible embedding PagerBeauty in browsers that don't support iframes with basic HTTP authentication enabled Type: String NoEcho: True # ------- Metadata ----------------------------------------------------------- # Metadata: 'AWS::CloudFormation::Interface': ParameterGroups: - Label: default: "EC2 Configuration" Parameters: - InstanceType - KeyName - SSHLocation - Label: default: "Pager Beauty: Settings" Parameters: - PagerbeautyPdApiKey - PagerbeautyPdSchedules - Label: default: "Pager Beauty: Enable HTTP Authentication (Optional)" Parameters: - PagerbeautyHTTPUser - PagerbeautyHTTPPassword - PagerbeautyHTTPAccessToken ParameterLabels: InstanceType: default: Instance Type KeyName: default: Key Name SSHLocation: default: SSH Location # Pagerbeauty: PagerDuty settings PagerbeautyPdApiKey: default: PagerDuty REST API v2 Access Key PagerbeautyPdSchedules: default: PagerDuty Schedule ids # Pagerbeauty HTTP Authentication PagerbeautyHTTPUser: default: "HTTP authentication: user name" PagerbeautyHTTPPassword: default: "HTTP authentication: password" PagerbeautyHTTPAccessToken: default: HTTP authentication access token # ------- Resources ---------------------------------------------------------- # Resources: # ------ Security Group ------ PagerBeautySecurityGroup: Type: 'AWS::EC2::SecurityGroup' Properties: GroupDescription: Enable HTTP 80 and SSH 22 SecurityGroupIngress: - IpProtocol: tcp FromPort: 80 ToPort: 80 CidrIp: 0.0.0.0/0 - IpProtocol: tcp FromPort: 22 ToPort: 22 CidrIp: !Ref SSHLocation # ------ Elastic IP ------ PagerBeautyEIP: Type: AWS::EC2::EIP Properties: InstanceId: !Ref PagerBeautyEC2 # ------ PagerBeauty App Server ------ PagerBeautyEC2: Type: AWS::EC2::Instance Properties: InstanceType: !Ref InstanceType SecurityGroups: - !Ref PagerBeautySecurityGroup KeyName: !Ref KeyName ImageId: !FindInMap - AWSRegionArch2AMI - !Ref 'AWS::Region' - !FindInMap - AWSInstanceType2Arch - !Ref InstanceType - Arch UserData: Fn::Base64: !Sub | #!/bin/bash -ex yum update -y aws-cfn-bootstrap # Install the files and packages from the metadata /opt/aws/bin/cfn-init -v \ --stack ${AWS::StackName} \ --resource PagerBeautyEC2 \ --region ${AWS::Region} \ --configsets install_pagerbeauty /opt/aws/bin/cfn-signal -e $? \ --stack ${AWS::StackName} \ --resource PagerBeautyEC2 \ --region ${AWS::Region} Metadata: 'AWS::CloudFormation::Init': configSets: install_pagerbeauty: - install_cfn - add_nodejs_official_repos - install_nodejs - download_pagerbeauty - config_pagerbeauty - install_pagerbeauty # ------ CFN ----------------------------------------------------------- install_cfn: files: /etc/cfn/cfn-hup.conf: content: !Sub | [main] stack=${AWS::StackId} region=${AWS::Region} interval=1 mode: '000400' owner: root group: root /etc/cfn/hooks.d/cfn-auto-reloader.conf: content: !Sub | [cfn-auto-reloader-hook] triggers=post.update path=Resources.LaunchConfig.Metadata.AWS::CloudFormation::Init action=/opt/aws/bin/cfn-init -v --stack ${AWS::StackName} --resource LaunchConfig --configsets wordpress_install --region ${AWS::Region} runas=root mode: "000400" owner: "root" group: "root" services: sysvinit: cfn-hup: enabled: true ensureRunning: true files: - /etc/cfn/cfn-hup.conf - /etc/cfn/hooks.d/cfn-auto-reloader.conf # ------ Nodejs -------------------------------------------------------- add_nodejs_official_repos: # https://nodejs.org/en/download/package-manager -> # https://github.com/nodesource/distributions/blob/master/README.md commands: 00_nodejs_repo: command: curl -sL https://rpm.nodesource.com/setup_12.x | bash - 01_yarn_repo: command: curl -sL https://dl.yarnpkg.com/rpm/yarn.repo | tee /etc/yum.repos.d/yarn.repo install_nodejs: # Must be executed after add_nodejs_official_repos packages: yum: nodejs: [] yarn: [] # ------ Pagerbeauty --------------------------------------------------- download_pagerbeauty: # Run the app as a user with minimal privileges users: pagerbeauty: homeDir: /opt/pagerbeauty # Download pagerbeauty build from github sources: /opt/pagerbeauty: https://github.com/sergiitk/pagerbeauty/archive/v1.1.1.tar.gz commands: # Link pagerbeauty versioned folder to app path ans # setup pagerbeauty user permissions to its home 00_setup_home_folder: command: | ln -nvsf /opt/pagerbeauty/pagerbeauty-1.1.1 /opt/pagerbeauty/app chown -R pagerbeauty:pagerbeauty /opt/pagerbeauty config_pagerbeauty: files: '/opt/pagerbeauty/app/.env': mode: "000640" owner: "pagerbeauty" group: "pagerbeauty" context: PagerbeautyPdApiKey: !Ref 'PagerbeautyPdApiKey' PagerbeautyPdSchedules: !Join - ',' - !Ref 'PagerbeautyPdSchedules' PagerbeautyHTTPUser: !Ref 'PagerbeautyHTTPUser' PagerbeautyHTTPPassword: !Ref 'PagerbeautyHTTPPassword' PagerbeautyHTTPAccessToken: !Ref 'PagerbeautyHTTPAccessToken' content: | # For Docker compatibility, do not placed quotation marks around the values. # https://docs.docker.com/compose/env-file/ # PagerDuty REST API v2 Access Key (Read-only) # Docs: https://support.pagerduty.com/docs/using-the-api PAGERBEAUTY_PD_API_KEY={{PagerbeautyPdApiKey}} # Comma-separated list of PagerDuty schedule ids # You can find schedule id in the URL of the schedule on PagerDuty website after symbol # # For example, schedule https://example.pagerduty.com/schedules#PJ1P5JQ has id PJ1P5JQ PAGERBEAUTY_PD_SCHEDULES={{PagerbeautyPdSchedules}} # (Optional) How often to refresh the schedules, in minutes. # Default: 10. # PAGERBEAUTY_REFRESH_RATE_MINUTES=10 # (Optional) Disable polling for active incidents. # Default: false # PAGERBEAUTY_INCIDENTS_DISABLE=true # (Optional) How often to refresh active incidents, in minutes. # Default: 1 # PAGERBEAUTY_INCIDENTS_REFRESH_RATE_MINUTES=5 # (Optional) Highest logging level to include into application logs. # One of: error, warn, info, verbose, debug, silly # Default: info # PAGERBEAUTY_LOG_LEVEL=verbose PAGERBEAUTY_LOG_LEVEL=verbose # (Optional) Log format. One of: # machine - Machine-readable JSON format # human - Human-readable colorized format # Default: resolved to `human` for development and `machine` for production. # PAGERBEAUTY_LOG_FORMAT=machine PAGERBEAUTY_LOG_FORMAT=human # (Optional) The port for HTTP server to listen on. # Default: 8080 # PAGERBEAUTY_HTTP_PORT=80 # (Optional) Enable basic HTTP authentication # Default: disabled # PAGERBEAUTY_HTTP_USER=basic_username # PAGERBEAUTY_HTTP_PASSWORD=basic_password PAGERBEAUTY_HTTP_USER={{PagerbeautyHTTPUser}} PAGERBEAUTY_HTTP_PASSWORD={{PagerbeautyHTTPPassword}} # (Optional) Enable authentication access token (RFC6750) # Note: embedding iframes that link to a page with basic HTTP name/password # authentication is not supported by most modern browsers. To bypass it, you # can set random access_token and append it to schedule URL. For example, if you can't embed schedule # https://pb.example.com/v1/schedules/P538IZH.html, you can append your access token like so: # https://pb.example.com/v1/schedules/P538IZH.html?acccess_token=your_token # This link is embeddable now. Please use HTTPS. # Default: disabled # PAGERBEAUTY_HTTP_ACCESS_TOKEN=your_token PAGERBEAUTY_HTTP_ACCESS_TOKEN={{PagerbeautyHTTPAccessToken}} commands: # Redirect port 80 to port 8080 to avoid granting unprivileged users low ports binding 00_redirect_port_80: command: | iptables -A PREROUTING -t nat -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 8080 iptables -t nat -A OUTPUT -o lo -p tcp --dport 80 -j REDIRECT --to-port 8080 service iptables save install_pagerbeauty: commands: 00_install_modules: command: | cd /opt/pagerbeauty/app sudo -u pagerbeauty yarn install --prod --frozen-lockfile sudo -u pagerbeauty yarn cache clean 01_start_and_setup_sysvinit_script: command: | npm install -g pm2 cd /opt/pagerbeauty/app sudo -u pagerbeauty pm2 start "yarn app:prod" --name "pagerbeauty" sudo -u pagerbeauty pm2 save env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 startup systemv -u pagerbeauty --hp /opt/pagerbeauty services: sysvinit: pm2-pagerbeauty: enabled: true ensureRun: true