PHP 7.4.33
Preview: fargate.yaml Size: 12.03 KB
/home/godevadmin/public_html/upload_images/home/000~ROOT~000/retool/retool-onpremise/cloudformation/fargate.yaml

AWSTemplateFormatVersion: '2010-09-09'
Parameters:
  Environment:
    Type: String
    Description: Environment string sent back to plogger with the logs
  SubnetId:
    Type: List<AWS::EC2::Subnet::Id>
    Description: Select at two subnets in your selected VPC.
  Cluster:
    Type: String
    Description: Cluster to put service in.
  Image:
    Type: String
    Description: Image to use in the service.
  DesiredCount:
    Type: Number
    Description: Default number of tasks to run
  MaximumPercent:
    Type: Number
    Description: Maximum percentage of tasks to run during a deployment
    Default: 150
  MinimumHealthyPercent:
    Type: Number
    Default: 50
    Description: Maximum percentage of tasks to run during a deployment
  VpcId:
    Type: AWS::EC2::VPC::Id
    Description: Select a VPC that allows instances access to the Internet.
  Force:
    Type: String
    Description: "Used to force the deployment even when the image and parameters are otherwised unchanged."
    Default: "false"

Resources:
  ALBSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: !Join [" ", [!Ref 'AWS::StackName', 'load balancer security group']]
      VpcId: !Ref 'VpcId'

  GlobalHttpInbound:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      GroupId: !Ref 'ALBSecurityGroup'
      IpProtocol: tcp
      FromPort: '3000'
      ToPort: '3000'
      CidrIp: '0.0.0.0/0'

  CloudwatchLogsGroup:
    Type: AWS::Logs::LogGroup
    Properties:
      LogGroupName: !Join ['-', [ECSLogGroup, !Ref 'AWS::StackName']]
      RetentionInDays: 14

  RDSSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: !Join [" ", [!Ref 'AWS::StackName', 'database security group']]
      VpcId: !Ref 'VpcId'

  RetoolECSPostgresInbound:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      GroupId: !GetAtt [RDSSecurityGroup, GroupId]
      IpProtocol: tcp
      FromPort: '5432'
      ToPort: '5432'
      CidrIp: '0.0.0.0/0'

  RetoolTask:
    Type: AWS::ECS::TaskDefinition
    Properties:
      NetworkMode: awsvpc
      Cpu: '1024'
      Memory: '4096'
      Family: 'retool'
      TaskRoleArn: !Ref 'RetoolTaskRole'
      ExecutionRoleArn: !Ref 'RetoolExecutionRole'
      RequiresCompatibilities:
        - FARGATE
      ContainerDefinitions:
      - Name: 'retool'
        Essential: 'true'
        Image: !Ref 'Image'
        LogConfiguration:
          LogDriver: awslogs
          Options:
            awslogs-group: !Ref 'CloudwatchLogsGroup'
            awslogs-region: !Ref 'AWS::Region'
            awslogs-stream-prefix: "SERVICE_RETOOL"
        Environment:
          - Name: DEPLOYMENT_TEMPLATE_TYPE
            Value: "aws-ecs-fargate"
          - Name: NODE_ENV
            Value: production
          - Name: SERVICE_TYPE
            Value: MAIN_BACKEND,DB_CONNECTOR,DB_SSH_CONNECTOR
          - Name: "FORCE_DEPLOYMENT"
            Value: !Ref "Force"
          - Name: POSTGRES_DB
            Value: hammerhead_production
          - Name: POSTGRES_HOST
            Value: !GetAtt [RetoolRDSInstance, Endpoint.Address]
          - Name: POSTGRES_SSL_ENABLED
            Value: "true"
          - Name: POSTGRES_PORT
            Value: "5432"
          - Name: POSTGRES_USER
            Value: !Join ['', ['{{resolve:secretsmanager:', !Ref RetoolRDSSecret, ':SecretString:username}}' ]]
          - Name: POSTGRES_PASSWORD
            Value: !Join ['', ['{{resolve:secretsmanager:', !Ref RetoolRDSSecret, ':SecretString:password}}' ]]
          - Name: JWT_SECRET
            Value: !Join ['', ['{{resolve:secretsmanager:', !Ref RetoolJWTSecret, ':SecretString:password}}' ]]
          - Name: ENCRYPTION_KEY
            Value: !Join ['', ['{{resolve:secretsmanager:', !Ref RetoolEncryptionKeySecret, ':SecretString:password}}' ]]
          - Name: LICENSE_KEY
            Value: "EXPIRED-LICENSE-KEY-TRIAL"

          # Remove below when serving Retool over https
          - Name: COOKIE_INSECURE
            Value: "true"
        PortMappings:
        - ContainerPort: '3000'
          # HostPort: '80'
        Command: ["./docker_scripts/start_api.sh"]

  RetoolJobsRunnerTask:
    Type: AWS::ECS::TaskDefinition
    Properties:
      NetworkMode: awsvpc
      Cpu: '2048'
      Memory: '4096'
      Family: 'retool'
      TaskRoleArn: !Ref 'RetoolTaskRole'
      ExecutionRoleArn: !Ref 'RetoolExecutionRole'
      RequiresCompatibilities:
        - FARGATE
      ContainerDefinitions:
      - Name: 'retool-jobs-runner'
        Essential: 'true'
        Image: !Ref 'Image'
        LogConfiguration:
          LogDriver: awslogs
          Options:
            awslogs-group: !Ref 'CloudwatchLogsGroup'
            awslogs-region: !Ref 'AWS::Region'
            awslogs-stream-prefix: "SERVICE_RETOOL"
        Environment:
          - Name: DEPLOYMENT_TEMPLATE_TYPE
            Value: "aws-ecs-fargate"
          - Name: NODE_ENV
            Value: production
          - Name: SERVICE_TYPE
            Value: JOBS_RUNNER
          - Name: "FORCE_DEPLOYMENT"
            Value: !Ref "Force"
          - Name: POSTGRES_DB
            Value: hammerhead_production
          - Name: POSTGRES_HOST
            Value: !GetAtt [RetoolRDSInstance, Endpoint.Address]
          - Name: POSTGRES_SSL_ENABLED
            Value: "true"
          - Name: POSTGRES_PORT
            Value: "5432"
          - Name: POSTGRES_USER
            Value: !Join ['', ['{{resolve:secretsmanager:', !Ref RetoolRDSSecret, ':SecretString:username}}' ]]
          - Name: POSTGRES_PASSWORD
            Value: !Join ['', ['{{resolve:secretsmanager:', !Ref RetoolRDSSecret, ':SecretString:password}}' ]]
          - Name: JWT_SECRET
            Value: !Join ['', ['{{resolve:secretsmanager:', !Ref RetoolJWTSecret, ':SecretString:password}}' ]]
          - Name: ENCRYPTION_KEY
            Value: !Join ['', ['{{resolve:secretsmanager:', !Ref RetoolEncryptionKeySecret, ':SecretString:password}}' ]]
          - Name: LICENSE_KEY
            Value: "EXPIRED-LICENSE-KEY-TRIAL"
        Command: ["./docker_scripts/start_api.sh"]

  RetoolJWTSecret:
    Type: AWS::SecretsManager::Secret
    Properties:
      Description: 'This is the secret for Retool JWTs'
      GenerateSecretString:
        SecretStringTemplate: '{}'
        GenerateStringKey: 'password'
        PasswordLength: 16
        ExcludeCharacters: '"@/\'

  RetoolEncryptionKeySecret:
    Type: AWS::SecretsManager::Secret
    Properties:
      Description: 'This is the secret for encrypting credentials'
      GenerateSecretString:
        SecretStringTemplate: '{}'
        GenerateStringKey: 'password'
        PasswordLength: 16
        ExcludeCharacters: '"@/\'

  RetoolRDSSecret:
    Type: AWS::SecretsManager::Secret
    Properties:
      Description: 'This is the secret for the Retool RDS instance'
      GenerateSecretString:
        SecretStringTemplate: '{"username": "retool"}'
        GenerateStringKey: 'password'
        PasswordLength: 16
        ExcludeCharacters: '"@/\'


  RetoolRDSInstance:
    Type: AWS::RDS::DBInstance
    Properties:
      AllocatedStorage: "80"
      DBInstanceClass: "db.m5.large"
      Engine: postgres
      EngineVersion: "13.11"
      DBName: "hammerhead_production"
      MasterUsername: !Join ['', ['{{resolve:secretsmanager:', !Ref RetoolRDSSecret, ':SecretString:username}}' ]]
      MasterUserPassword: !Join ['', ['{{resolve:secretsmanager:', !Ref RetoolRDSSecret, ':SecretString:password}}' ]]
      Port: "5432"
      VPCSecurityGroups: [!GetAtt [RDSSecurityGroup, GroupId]]
      DBSubnetGroupName: !Ref 'RDSSubnetGroup'

  RDSSubnetGroup:
    Type: AWS::RDS::DBSubnetGroup
    Properties: 
      DBSubnetGroupDescription: !Join [" ", [!Ref 'AWS::StackName', 'rds subnet security group']]
      SubnetIds: !Ref 'SubnetId'

  ECSALB:
    Type: AWS::ElasticLoadBalancingV2::LoadBalancer
    Properties:
      Name: !Join ['-', [!Ref 'AWS::StackName', 'lb']]
      Scheme: "internet-facing"
      LoadBalancerAttributes:
      - Key: idle_timeout.timeout_seconds
        Value: '60'
      Subnets: !Ref 'SubnetId'
      SecurityGroups: [!Ref 'ALBSecurityGroup']

  ALBListener:
    Type: AWS::ElasticLoadBalancingV2::Listener
    DependsOn: RetoolServiceRole
    Properties:
      DefaultActions:
      - Type: forward
        TargetGroupArn: !Ref 'ECSTG'
      LoadBalancerArn: !Ref 'ECSALB'
      Port: '3000'
      Protocol: HTTP

  ECSALBListenerRule:
    Type: AWS::ElasticLoadBalancingV2::ListenerRule
    DependsOn: ALBListener
    Properties:
      Actions:
      - Type: forward
        TargetGroupArn: !Ref 'ECSTG'
      Conditions:
      - Field: path-pattern
        Values: [/]
      ListenerArn: !Ref 'ALBListener'
      Priority: 1

  ECSTG:
    Type: AWS::ElasticLoadBalancingV2::TargetGroup
    DependsOn: ECSALB
    Properties:
      TargetType: ip
      HealthCheckIntervalSeconds: 61
      HealthCheckPath: '/api/checkHealth'
      HealthCheckProtocol: HTTP
      HealthCheckTimeoutSeconds: 60
      HealthyThresholdCount: 4
      Name: !Join ['-', [!Ref 'AWS::StackName', 'tg']]
      Port: '3000'
      Protocol: HTTP
      UnhealthyThresholdCount: 10
      VpcId: !Ref 'VpcId'
      TargetGroupAttributes:
      - Key: deregistration_delay.timeout_seconds
        Value: '30'

  RetoolECSservice:
    Type: AWS::ECS::Service
    DependsOn: ALBListener
    Properties:
      NetworkConfiguration:
        AwsvpcConfiguration:
          AssignPublicIp: ENABLED
          SecurityGroups: [!Ref 'ALBSecurityGroup']
          Subnets: !Ref 'SubnetId'
      Cluster: !Ref 'Cluster'
      DesiredCount: !Ref 'DesiredCount'
      LaunchType: FARGATE
      DeploymentConfiguration:
        MaximumPercent: !Ref 'MaximumPercent'
        MinimumHealthyPercent: !Ref 'MinimumHealthyPercent'
      LoadBalancers:
      - ContainerName: 'retool'
        ContainerPort: '3000'
        TargetGroupArn: !Ref 'ECSTG'
      # Role: !Ref 'RetoolServiceRole'
      TaskDefinition: !Ref 'RetoolTask'

  RetoolJobsRunnerECSservice:
    Type: AWS::ECS::Service
    Properties:
      NetworkConfiguration:
        AwsvpcConfiguration:
          AssignPublicIp: ENABLED
          SecurityGroups: [!Ref 'ALBSecurityGroup']
          Subnets: !Ref 'SubnetId'
      Cluster: !Ref 'Cluster'
      DesiredCount: 1
      LaunchType: FARGATE
      TaskDefinition: !Ref 'RetoolJobsRunnerTask'

  RetoolServiceRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Statement:
        - Effect: Allow
          Principal:
            Service: [ecs.amazonaws.com]
          Action: ['sts:AssumeRole']
      Path: /
      Policies:
      - PolicyName: !Join ['-', ['Retool', !Ref 'Environment', 'service-policy']]
        PolicyDocument:
          Statement:
          - Effect: Allow
            Action: [
              'elasticloadbalancing:DeregisterInstancesFromLoadBalancer',
              'elasticloadbalancing:DeregisterTargets',
              'elasticloadbalancing:Describe*',
              'elasticloadbalancing:RegisterInstancesWithLoadBalancer',
              'elasticloadbalancing:RegisterTargets',
              'ec2:Describe*',
              'ec2:AuthorizeSecurityGroupIngress']
            Resource: '*'

  RetoolTaskRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Statement:
        - Effect: Allow
          Principal:
            Service: ['ecs-tasks.amazonaws.com']
          Action: ['sts:AssumeRole']
      Path: /
      Policies: []

  RetoolExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Statement:
        - Effect: Allow
          Principal:
            Service: ['ecs-tasks.amazonaws.com']
          Action: ['sts:AssumeRole']
      Path: /
      Policies:
      - PolicyName: !Join ['-', ['Retool', !Ref 'Environment', 'execution-policy']]
        PolicyDocument:
          Statement:
          - Effect: Allow
            Action: [
              "ecr:GetAuthorizationToken",
              "ecr:BatchCheckLayerAvailability",
              "ecr:GetDownloadUrlForLayer",
              "ecr:BatchGetImage",
              "logs:CreateLogStream",
              "logs:PutLogEvents"]
            Resource: '*'

Outputs:
  ECSALB:
    Description: Your ALB DNS URL
    Value: !GetAtt [ECSALB, DNSName]

Directory Contents

Dirs: 0 × Files: 7

Name Size Perms Modified Actions
12.19 KB lrw-r--r-- 2025-11-05 08:36:50
Edit Download
12.03 KB lrw-r--r-- 2025-11-05 08:36:50
Edit Download
2.63 KB lrw-r--r-- 2025-11-05 08:36:50
Edit Download
44.15 KB lrw-r--r-- 2025-11-05 08:36:50
Edit Download
37.54 KB lrw-r--r-- 2025-11-05 08:36:50
Edit Download
38.67 KB lrw-r--r-- 2025-11-05 08:36:50
Edit Download
10.65 KB lrw-r--r-- 2025-11-05 08:36:50
Edit Download

If ZipArchive is unavailable, a .tar will be created (no compression).