AWSTemplateFormatVersion: 2010-09-09 Description: AWS CloudFormation Template for doccano. Resources: AppSG: Type: 'AWS::EC2::SecurityGroup' Properties: GroupDescription: 'for the app nodes that allow ssh, http and docker ports' SecurityGroupIngress: - IpProtocol: tcp FromPort: '80' ToPort: '80' CidrIp: 0.0.0.0/0 - IpProtocol: tcp FromPort: '443' ToPort: '443' CidrIp: 0.0.0.0/0 - IpProtocol: tcp FromPort: '22' ToPort: '22' CidrIp: 0.0.0.0/0 Metadata: 'AWS::CloudFormation::Designer': id: 116a7f7b-14c5-489a-a3c8-faf276be7ab0 App: Type: 'AWS::EC2::Instance' Properties: InstanceType: !Ref InstanceType ImageId: !Ref Ubuntu16Ami KeyName: !Ref KeyName SecurityGroups: - !Ref AppSG UserData: !Base64 'Fn::Join': - '' - - | #!/usr/bin/env bash - | sudo apt update - > sudo apt install -y apt-transport-https ca-certificates curl software-properties-common - > curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - - > sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu bionic stable" - | sudo apt update - | apt-cache policy docker-ce - | sudo apt install -y docker-ce - | sudo usermod -aG docker ${USER} - | touch /env.list - sudo tee -a /env.list <<< ADMIN= - !Ref AdminUserName - |+ - sudo tee -a /env.list <<< EMAIL= - !Ref AdminEmail - |+ - sudo tee -a /env.list <<< PASSWORD= - !Ref AdminPassword - |+ - sudo tee -a /env.list <<< DEBUG= - !Ref Debug - |+ - sudo tee -a /env.list <<< SECRET_KEY= - !Ref SecretKey - |+ - sudo tee -a /env.list <<< EMAIL_USE_TLS= - !Ref EMailUseTSL - |+ - sudo tee -a /env.list <<< EMAIL_HOST= - !Ref EMailHost - |+ - sudo tee -a /env.list <<< EMAIL_PORT= - !Ref EMailHostPort - |+ - sudo tee -a /env.list <<< EMAIL_HOST_USER= - !Ref EMailHostUser - |+ - sudo tee -a /env.list <<< EMAIL_HOST_PASSWORD= - !Ref EMailHostPassword - |+ - sudo tee -a /env.list <<< WORKERS= - !Ref WorkersCount - |+ - sudo tee -a /env.list <<< DEFAULT_FROM_EMAIL= - !Ref FromEmail - |+ - sudo tee -a /env.list <<< DOCKER_IMAGE= - !Ref DockerImageName - |+ - | set -a - | source /env.list - | set +a - | sudo docker pull ${DOCKER_IMAGE} - > sudo docker run -d --name doccano --env-file /env.list -p 80:8000 ${DOCKER_IMAGE} - > sleep 3 && sudo docker exec doccano tools/create-admin.sh ${ADMIN} ${EMAIL} ${PASSWORD} Metadata: 'AWS::CloudFormation::Designer': id: 3547c02e-5393-4b26-a9af-6f00dc2cbcdb DescribeImagesRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Action: sts:AssumeRole Effect: Allow Principal: Service: lambda.amazonaws.com ManagedPolicyArns: - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole Policies: - PolicyName: DescribeImages PolicyDocument: Version: '2012-10-17' Statement: - Action: ec2:DescribeImages Effect: Allow Resource: "*" GetLatestAMI: Type: AWS::Lambda::Function Properties: Runtime: python3.6 Handler: index.handler Role: !Sub ${DescribeImagesRole.Arn} Timeout: 60 Code: ZipFile: | import boto3 import cfnresponse import json import traceback def handler(event, context): try: response = boto3.client('ec2').describe_images( Owners=[event['ResourceProperties']['Owner']], Filters=[ {'Name': 'name', 'Values': [event['ResourceProperties']['Name']]}, {'Name': 'architecture', 'Values': [event['ResourceProperties']['Architecture']]}, {'Name': 'root-device-type', 'Values': ['ebs']}, ], ) amis = sorted(response['Images'], key=lambda x: x['CreationDate'], reverse=True) id = amis[0]['ImageId'] cfnresponse.send(event, context, cfnresponse.SUCCESS, {}, id) except: traceback.print_last() cfnresponse.send(event, context, cfnresponse.FAIL, {}, "ok") Ubuntu16Ami: Type: Custom::FindAMI Properties: ServiceToken: !Sub ${GetLatestAMI.Arn} Owner: "099720109477" Name: "ubuntu/images/hvm-ssd/ubuntu-xenial-16.04-amd64-server-20190913" Architecture: "x86_64" Metadata: 'AWS::CloudFormation::Designer': 116a7f7b-14c5-489a-a3c8-faf276be7ab0: size: width: 60 height: 60 position: x: 60 'y': 210 z: 1 embeds: [] 3547c02e-5393-4b26-a9af-6f00dc2cbcdb: size: width: 60 height: 60 position: x: 180 'y': 210 z: 1 embeds: [] isassociatedwith: - 116a7f7b-14c5-489a-a3c8-faf276be7ab0 Parameters: InstanceType: Description: Server EC2 instance type Type: String Default: t2.micro AllowedValues: - t1.micro - t2.micro - t2.small - t2.medium - t3.micro - t3.small - t3.medium ConstraintDescription: must be a valid EC2 instance type. KeyName: Description: Name of an EC2 KeyPair to enable SSH access to the instance. Type: 'AWS::EC2::KeyPair::KeyName' ConstraintDescription: must be the name of an existing EC2 KeyPair. AdminUserName: Description: The admin account user name Default: 'admin' Type: String MinLength: 1 MaxLength: 16 AllowedPattern: '[a-zA-Z][a-zA-Z0-9]*' AdminEmail: Default: admin@gmail.com Description: The admin account user email Type: String AllowedPattern: '^[\x20-\x45]?[\w-\+]+(\.[\w]+)*@[\w-]+(\.[\w]+)*(\.[a-z]{2,})$' AdminPassword: Description: The admin account password Type: String NoEcho: true MinLength: 1 MaxLength: 16 AllowedPattern: '^[a-zA-Z0-9]*$' Debug: Default: 'False' AllowedValues: - 'False' - 'True' Description: Debug mode or not Type: String AllowedPattern: '^[a-zA-Z0-9]*$' SecretKey: Default: zICc59rlKXmlFRpG Description: Secret key for Django Type: String AllowedPattern: '^[a-zA-Z0-9]*$' EMailUseTSL: Default: 'False' AllowedValues: - 'False' - 'True' Description: SMTP will use TSL Type: String AllowedPattern: '^[a-zA-Z0-9]*$' EMailHost: Description: SMTP Host Type: String AllowedPattern: '^[\w-]+(\.[\w-]+)*(\.[a-z]{2,})$' EMailHostUser: Description: SMTP Host User Type: String MinLength: 1 MaxLength: 25 AllowedPattern: '^[a-zA-Z0-9][a-zA-Z0-9]{1,25}$' EMailHostPassword: Description: SMTP Host User password Type: String NoEcho: true MinLength: 0 MaxLength: 60 AllowedPattern: '^\p{Graph}+$' EMailHostPort: Description: SMTP Port Type: String MinLength: 1 MaxLength: 5 AllowedPattern: '^\d+$' WorkersCount: Description: Workers Count Type: String MinLength: 1 MaxLength: 3 AllowedPattern: '^\d+$' FromEmail: Default: webmaster@localhost Description: The email used to send from singup messages Type: String AllowedPattern: '^[\x20-\x45]?[\w-\+]+(\.[\w]+)*@[\w-]+(\.[\w]+)*(\.[a-z]{2,})?$' DockerImageName: Default: doccano/doccano:latest Description: The Docker image name Type: String AllowedPattern: '^[\w_-]+/[\w_-]+:[\w_-]+$' Outputs: PublicDNS: Value: !GetAtt - App - PublicDnsName Description: Newly created server DNS address