AWSTemplateFormatVersion: 2010-09-09 Description: >- concerto-ec2-basic (2020-09-02): Standalone Concerto, everything on one instance, no TLS Metadata: AWS::CloudFormation::Interface: ParameterGroups: - Label: default: Concerto Parameters: - ConcertoVersion - ConcertoPassword - ConcertoContentURL - ConcertoSessionLimit - ConcertoTimezone - ConcertoStorage - Label: default: Web Parameters: - KeyName - WebServerInstanceType - Label: default: Database Parameters: - DBPassword - Label: default: Network Parameters: - CIDR - CIDRA ParameterLabels: ConcertoVersion: default: Tag ConcertoPassword: default: Password ConcertoContentURL: default: URL ConcertoSessionLimit: default: Session limit ConcertoTimezone: default: Timezone ConcertoStorage: default: Storage KeyName: default: Key pair WebServerInstanceType: default: Instance type DBPassword: default: Password CIDRA: default: CIDR for Subnet A Parameters: ConcertoVersion: Description: Concerto version to use. Can be any tag from https://github.com/campsych/concerto-platform Type: String Default: 5.0 ConcertoPassword: Description: Concerto admin account password (recommended to generate a random one) Type: String NoEcho: true MinLength: 8 ConstraintDescription: min. 8 characters. ConcertoContentURL: Description: URL with Concerto content backup to preload (optional) Type: String Default: . ConcertoSessionLimit: Description: How many concurrent sessions to allow (unlimited if 0 or not set) Type: Number Default: 0 ConcertoTimezone: Description: Timezone to use, see https://en.wikipedia.org/wiki/List_of_tz_database_time_zones Type: String Default: UTC ConcertoStorage: Default: 8 Description: The size of the storage volume (Gb) Type: Number MinValue: 8 MaxValue: 1024 ConstraintDescription: must be between 8 and 1024Gb. KeyName: Description: Name of an existing EC2 KeyPair to enable SSH access to the instance Type: AWS::EC2::KeyPair::KeyName ConstraintDescription: must be the name of an existing EC2 KeyPair WebServerInstanceType: Description: Web server instance type Type: String Default: t2.micro AllowedValues: - t2.micro - t3.micro - t2.small - t3.small - t2.medium - t3.medium - t2.large - t3.large ConstraintDescription: must be a valid EC2 instance type DBPassword: Description: Database admin account password (recommended to generate a random one, different than Concerto's) Type: String NoEcho: true MinLength: 8 ConstraintDescription: min. 8 characters CIDR: Description: The private IP address range to be used for VPC Type: String MinLength: 9 MaxLength: 18 Default: 10.10.0.0/16 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 CIDRA: Description: Address range within the VPC to be used for the subnet Type: String MinLength: 9 MaxLength: 18 Default: 10.10.0.0/24 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 Mappings: RegionMap: us-east-1: ami: ami-0b898040803850657 us-east-2: ami: ami-0d8f6eb4f641ef691 us-west-1: ami: ami-056ee704806822732 us-west-2: ami: ami-082b5a644766e0e6f eu-west-1: ami: ami-0bbc25e23a7640b9b eu-west-2: ami: ami-0d8e27447ec2c8410 eu-west-3: ami: ami-0adcddd3324248c4c eu-central-1: ami: ami-0cc293023f983ed53 eu-north-1: ami: ami-3f36be41 ap-east-1: ami: ami-570c7726 ap-northeast-1: ami: ami-0c3fd0f5d33134a76 ap-northeast-2: ami: ami-095ca789e0549777d ap-southeast-1: ami: ami-01f7527546b557442 ap-southeast-2: ami: ami-0dc96254d5535925f ap-south-1: ami: ami-0d2692b6acea72ee6 ca-central-1: ami: ami-0d4ae09ec9361d8ac sa-east-1: ami: ami-058943e7d9b9cabfb InstanceTypeMap: t2.micro: MaxChildren: 5 t3.micro: MaxChildren: 5 t2.small: MaxChildren: 20 t3.small: MaxChildren: 20 t2.medium: MaxChildren: 50 t3.medium: MaxChildren: 50 t2.large: MaxChildren: 100 t3.large: MaxChildren: 100 Resources: VPC: Type: AWS::EC2::VPC Properties: CidrBlock: !Ref CIDR Tags: - Key: Name Value: !Ref AWS::StackName SubnetA: Type: AWS::EC2::Subnet Properties: VpcId: !Ref VPC CidrBlock: !Ref CIDRA Tags: - Key: Name Value: !Ref AWS::StackName InternetGateway: Type: AWS::EC2::InternetGateway Properties: Tags: - Key: Name Value: !Ref AWS::StackName AttachGateway: Type: AWS::EC2::VPCGatewayAttachment Properties: VpcId: !Ref VPC InternetGatewayId: !Ref InternetGateway RouteTable: Type: AWS::EC2::RouteTable Properties: VpcId: !Ref VPC Tags: - Key: Name Value: !Ref AWS::StackName Route: Type: AWS::EC2::Route DependsOn: AttachGateway Properties: RouteTableId: !Ref RouteTable DestinationCidrBlock: 0.0.0.0/0 GatewayId: !Ref InternetGateway SubnetRouteTableAssociation: Type: AWS::EC2::SubnetRouteTableAssociation Properties: SubnetId: !Ref SubnetA RouteTableId: !Ref RouteTable NetworkAcl: Type: AWS::EC2::NetworkAcl Properties: VpcId: !Ref VPC Tags: - Key: Name Value: !Ref AWS::StackName InboundHTTPNetworkAclEntry: Type: AWS::EC2::NetworkAclEntry Properties: NetworkAclId: !Ref NetworkAcl RuleNumber: 100 Protocol: 6 RuleAction: allow Egress: false CidrBlock: 0.0.0.0/0 PortRange: From: 80 To: 80 InboundSSHNetworkAclEntry: Type: AWS::EC2::NetworkAclEntry Properties: NetworkAclId: !Ref NetworkAcl RuleNumber: 101 Protocol: 6 RuleAction: allow Egress: false CidrBlock: 0.0.0.0/0 PortRange: From: 22 To: 22 InboundResponsePortsNetworkAclEntry: Type: AWS::EC2::NetworkAclEntry Properties: NetworkAclId: !Ref NetworkAcl RuleNumber: 102 Protocol: 6 RuleAction: allow Egress: false CidrBlock: 0.0.0.0/0 PortRange: From: 1024 To: 65535 OutBoundHTTPNetworkAclEntry: Type: AWS::EC2::NetworkAclEntry Properties: NetworkAclId: !Ref NetworkAcl RuleNumber: 100 Protocol: 6 RuleAction: allow Egress: true CidrBlock: 0.0.0.0/0 PortRange: From: 80 To: 80 OutBoundHTTPSNetworkAclEntry: Type: AWS::EC2::NetworkAclEntry Properties: NetworkAclId: !Ref NetworkAcl RuleNumber: 101 Protocol: 6 RuleAction: allow Egress: true CidrBlock: 0.0.0.0/0 PortRange: From: 443 To: 443 OutBoundResponsePortsNetworkAclEntry: Type: AWS::EC2::NetworkAclEntry Properties: NetworkAclId: !Ref NetworkAcl RuleNumber: 102 Protocol: 6 RuleAction: allow Egress: true CidrBlock: 0.0.0.0/0 PortRange: From: 1024 To: 65535 SubnetNetworkAclAssociation: Type: AWS::EC2::SubnetNetworkAclAssociation Properties: SubnetId: !Ref SubnetA NetworkAclId: !Ref NetworkAcl WebServerSecurityGroup: Type: AWS::EC2::SecurityGroup Properties: VpcId: !Ref VPC GroupDescription: Allow ingress via SSH, HTTP ports SecurityGroupIngress: - IpProtocol: tcp FromPort: 22 ToPort: 22 CidrIp: 0.0.0.0/0 - IpProtocol: tcp FromPort: 80 ToPort: 80 CidrIp: 0.0.0.0/0 Tags: - Key: Name Value: !Ref AWS::StackName WebServerInstance: Type: AWS::EC2::Instance CreationPolicy: ResourceSignal: Count: 1 Timeout: PT15M Metadata: AWS::CloudFormation::Init: configSets: default: - cfn - updates - docker - concerto 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.WebServerInstance.Metadata.AWS::CloudFormation::Init action=/opt/aws/bin/cfn-init -v --stack ${AWS::StackName} --resource WebServerInstance --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 updates: packages: yum: yum-cron: [] commands: 01_config: command: | sed -ri 's/^(.*update_cmd\s*=).*$/\1 security/' yum-cron.conf sed -ri 's/^(.*apply_updates\s*=).*$/\1 yes/' yum-cron.conf cwd: /etc/yum services: sysvinit: yum-cron: enabled: true ensureRunning: true docker: commands: 01_user: command: usermod -a -G docker ec2-user 02_docker_compose: command: | curl -L https://github.com/docker/compose/releases/download/1.25.5/docker-compose-Linux-x86_64 -o /usr/local/bin/docker-compose chmod +x /usr/local/bin/docker-compose services: sysvinit: docker: enabled: true ensureRunning: true concerto: files: /home/concerto/docker-compose.yml: content: !Sub - | version: '3' services: database: image: mysql:5.7 container_name: database restart: unless-stopped volumes: - ./data/mysql:/var/lib/mysql environment: - MYSQL_DATABASE=concerto - MYSQL_USER=concerto - MYSQL_PASSWORD=${DBPassword} - MYSQL_ROOT_PASSWORD=${DBPassword} - TZ=${ConcertoTimezone} concerto: image: campsych/concerto-platform:${ConcertoVersion} container_name: concerto restart: unless-stopped volumes: - ./data/concerto:/data ports: - "80:80" environment: - CONCERTO_PASSWORD=${ConcertoPassword} - CONCERTO_CONTENT_URL=${ConcertoContentURL} - CONCERTO_PLATFORM_URL=/ - CONCERTO_GIT_REPOSITORY_PATH=/data/git - CONCERTO_SESSION_LIMIT=${ConcertoSessionLimit} - DB_HOST=database - DB_PASSWORD=${DBPassword} - PHP_FPM_PM=static - PHP_FPM_PM_MAX_CHILDREN=${MaxChildren} - TZ=${ConcertoTimezone} - MaxChildren: !FindInMap - InstanceTypeMap - !Ref WebServerInstanceType - MaxChildren commands: start: command: /usr/local/bin/docker-compose up -d --remove-orphans --force-recreate cwd: /home/concerto Properties: ImageId: !FindInMap - RegionMap - !Ref AWS::Region - ami InstanceType: !Ref WebServerInstanceType KeyName: !Ref KeyName UserData: Fn::Base64: !Sub | #!/usr/bin/env bash yum update --security -y yum update aws-cfn-bootstrap -y amazon-linux-extras install -y docker /opt/aws/bin/cfn-init -v --stack ${AWS::StackId} --resource WebServerInstance --region ${AWS::Region} /opt/aws/bin/cfn-signal -e $? --stack ${AWS::StackId} --resource WebServerInstance --region ${AWS::Region} BlockDeviceMappings: - DeviceName: /dev/xvda Ebs: DeleteOnTermination: false VolumeSize: !Ref ConcertoStorage NetworkInterfaces: - AssociatePublicIpAddress: true DeleteOnTermination: true DeviceIndex: 0 SubnetId: !Ref SubnetA GroupSet: - !Ref WebServerSecurityGroup Tags: - Key: Name Value: !Ref AWS::StackName Outputs: URL: Value: !Sub - http://${PublicIp}/admin - PublicIp: !GetAtt WebServerInstance.PublicIp Description: Concerto administration panel URL ServerIP: Value: !GetAtt WebServerInstance.PublicIp Description: IP address to point your domain to (i.e. with A record) ConcertoVersion: Value: !Ref ConcertoVersion Description: Concerto version being used ConcertoPassword: Value: !Ref ConcertoPassword Description: Concerto admin password DBPassword: Value: !Ref DBPassword Description: Database password