Skip to content

Instantly share code, notes, and snippets.

@jtatum
Last active June 11, 2022 12:10
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jtatum/15994aabd469cd9120ceb2a45b509b8c to your computer and use it in GitHub Desktop.
Save jtatum/15994aabd469cd9120ceb2a45b509b8c to your computer and use it in GitHub Desktop.
Running Sendy on AWS ECS + Fargate

Sendy on ECS + Fargate

It's possible to run Sendy on ECS + Fargate. My infrastructure is as follows:

  • RDS MySQL
  • EFS
  • ALB
  • ACM certificate
  • ECS Service
  • ALB target group
  • ALB listener rule

The task security group has permissions to access MySQL via the security group in RDS. Likewise, the task security group is granted permission on the EFS security group. Finally, the load balancer security group is added to the task security group.

Note: at present, it seems like Sendy can't use the task role to get permissions in SES. For now, you'll need to continue to use an AWS access key + secret for Sendy to access SES.

{
"Statement": [
{
"Action": [
"ssm:GetParameters"
],
"Effect": "Allow",
"Resource": "arn:aws:ssm:<@@@region>:<@@@account-id>:parameter/sendy/prod/*",
"Sid": ""
}
],
"Version": "2012-10-17"
}
{
"ipcMode": null,
"executionRoleArn": "<@@@ARN for execution role, must have cloudwatch logs permissions (e.g. AmazonECSTaskExecutionRolePolicy) and permissions to read ssm secrets in /sendy/prod (see sendy_secrets_policy.json). documentation at https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_execution_IAM_role.html>",
"containerDefinitions": [
{
"dnsSearchDomains": null,
"environmentFiles": null,
"logConfiguration": {
"logDriver": "awslogs",
"secretOptions": null,
"options": {
"awslogs-group": "/ecs/sendy",
"awslogs-region": "<@@@shoud be the region you're deploying into>",
"awslogs-stream-prefix": "ecs"
}
},
"entryPoint": null,
"portMappings": [
{
"hostPort": 80,
"protocol": "tcp",
"containerPort": 80
}
],
"command": null,
"linuxParameters": null,
"cpu": 0,
"environment": [
{
"name": "MYSQL_DATABASE",
"value": "sendy <@@@ this database / user must already exist>"
},
{
"name": "MYSQL_HOST",
"value": "<@@@rds endpoint address>"
},
{
"name": "MYSQL_USER",
"value": "sendy"
},
{
"name": "SENDY_FQDN",
"value": "<your fqdn here>"
},
{
"name": "SENDY_PROTOCOL",
"value": "<@@@if you're terminating traffic on an ALB with SSL, set this to https. otherwise http>"
}
],
"resourceRequirements": null,
"ulimits": null,
"dnsServers": null,
"mountPoints": [
{
"readOnly": null,
"containerPath": "/var/www/html/uploads",
"sourceVolume": "uploads"
}
],
"workingDirectory": null,
"secrets": [
{
"valueFrom": "/sendy/prod/db/password <note: this is a securestring in AWS SSM, the database password for the user above>",
"name": "MYSQL_PASSWORD"
}
],
"dockerSecurityOptions": null,
"memory": null,
"memoryReservation": null,
"volumesFrom": [],
"stopTimeout": null,
"image": "bubbajames/sendy:5.2.3",
"startTimeout": null,
"firelensConfiguration": null,
"dependsOn": null,
"disableNetworking": null,
"interactive": null,
"healthCheck": null,
"essential": true,
"links": null,
"hostname": null,
"extraHosts": null,
"pseudoTerminal": null,
"user": null,
"readonlyRootFilesystem": null,
"dockerLabels": null,
"systemControls": null,
"privileged": null,
"name": "sendy"
}
],
"placementConstraints": [],
"memory": "512",
"taskRoleArn": "<sendy doesn't use any aws permissions so this task role can contain no policies. if you want to use ecs exec, you will need to add some policies - see https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-exec.html#ecs-exec-enabling-and-using>",
"compatibilities": [
"EC2",
"FARGATE"
],
"family": "sendy",
"requiresAttributes": [
{
"targetId": null,
"targetType": null,
"value": null,
"name": "com.amazonaws.ecs.capability.logging-driver.awslogs"
},
{
"targetId": null,
"targetType": null,
"value": null,
"name": "ecs.capability.execution-role-awslogs"
},
{
"targetId": null,
"targetType": null,
"value": null,
"name": "ecs.capability.efsAuth"
},
{
"targetId": null,
"targetType": null,
"value": null,
"name": "com.amazonaws.ecs.capability.docker-remote-api.1.19"
},
{
"targetId": null,
"targetType": null,
"value": null,
"name": "ecs.capability.efs"
},
{
"targetId": null,
"targetType": null,
"value": null,
"name": "com.amazonaws.ecs.capability.task-iam-role"
},
{
"targetId": null,
"targetType": null,
"value": null,
"name": "com.amazonaws.ecs.capability.docker-remote-api.1.25"
},
{
"targetId": null,
"targetType": null,
"value": null,
"name": "ecs.capability.secrets.ssm.environment-variables"
},
{
"targetId": null,
"targetType": null,
"value": null,
"name": "com.amazonaws.ecs.capability.docker-remote-api.1.18"
},
{
"targetId": null,
"targetType": null,
"value": null,
"name": "ecs.capability.task-eni"
}
],
"pidMode": null,
"requiresCompatibilities": [
"FARGATE"
],
"networkMode": "awsvpc",
"cpu": "256",
"revision": 8,
"status": "ACTIVE",
"inferenceAccelerators": null,
"proxyConfiguration": null,
"volumes": [
{
"fsxWindowsFileServerVolumeConfiguration": null,
"efsVolumeConfiguration": {
"transitEncryptionPort": null,
"fileSystemId": "<@@@id of efs volume>",
"authorizationConfig": null,
"transitEncryption": null,
"rootDirectory": "/uploads <@@@note: this directory must exist in the efs volume prior to task start!>"
},
"name": "uploads",
"host": null,
"dockerVolumeConfiguration": null
}
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment