This guide provides detailed instructions for deploying Fider on AWS ECS with the tasks running inside the private subnet and the application load balancer(ALB) as front-facing.
“Simply put, things always had to be in a production-ready state: if you wrote it, you darn well had to be there to get it running!”
AWS services used
- Elastic container registry(ECR)
- Elastic container service(ECS Fargate launch type)
- Application Load Balancer(ALB)
- Elastic File System(EFS)
- Amazon Certificate Manager (ACM)
What is Fider ?
Pre-flight checks:
Before starting, ensure that you have an AWS account with access to the free tier or a valid payment method on file.
Install AWS CLI:
Step 1:
You need the awscli package installed for pushing the images built locally to Elastic Container Registry(ECR).
Step 2:
If you use ubuntu distro, Check the snap version by using the following command.
snap version
Run the following snap install command for the AWS CLI.
sudo snap install aws-cli --classic
After the installation is complete, verify the installation by using the command,
aws --version
Step 4: Configure AWS CLI
Use this command to configure the AWS CLI.
aws configure
Once configured, verify your AWS CLI credentials using the following command.
aws configure list
Step 5: Pull official docker images from DockerHub
Pull the official docker image for Fider from the DockerHub registry at:
Now pull the official docker image of Postgres from the DockerHub registry at:
Check if the docker images are available in your instance.
docker images
Name the repo getfider/fider and repeat the same process for postgres.
Step 2: View the push commands
View the push commands by clicking on the respective repository.
tag your pulled image so you can push the image to this repository.
Repeat the same steps for tagging and pushing the postgres image to the repository and view the pushed images in the ECR.
Create a VPC
Step 1: Create a standalone VPC for deploying Fider application
Login to the management console then navigate to the VPC service console and click on Create VPC.
A route table will also get created with route to local traffic.
By clicking on Add route attach the the IGW to the route table.
Step 3: Create Public Subnets
Create at least two public subnets, so that the Application Load Balancer can reside in it.
Navigate to the VPC Console, under the subnets section create two public subnets.
Decide the subnet CIDR range and provision it accordingly.
Step 4: Create Private Subnets
Create at least two private subnets, so that your ECS tasks and EFS can reside in it.
Navigate to the VPC Console, under the subnets section create at least two private subnets.
Step 5: Create a Private route table
Create a private route table in the VPC console under the route tables section to route traffic locally.
Associate the private subnets to the private route table, like how you did with the public route table, and follow the same steps.
Step 6: Create NAT gateway
Create a NAT gateway to allow tasks in the private subnet to connect to the internet.
Navigate to NAT gateway section under the VPC console and create a NAT gateway.
The private route table now has a route to the NAT gateway.
Create an EFS volume
Step 1:
Navigate to the EFS console and click on create file system prompt.
Step 2: Create an access point
Navigate into the file system and create an access point.
Set the default path to the root directory for now and click on Create access point.
Change the default security group setting to EFS-sg settings as EFS listens on port 2049, so create security group for that.
Create Task Definition
Step 1:
Navigate to the task definition section under the ECS console and create a task definition named fider-app-task.
Set the configuration type to configure at task definition creation.
Refer to the following JSON task definition for creating the task definition via JSON.
{
"taskDefinitionArn": "arn:aws:ecs:us-east-2:545009831165:task-definition/fider-app-task:7",
"containerDefinitions": [
{
"name": "Fider-app",
"image": "545009831165.dkr.ecr.us-east-2.amazonaws.com/getfider/fider:main",
"cpu": 2048,
"memory": 6144,
"memoryReservation": 5120,
"portMappings": [
{
"name": "fider-app-3000-tcp",
"containerPort": 3000,
"hostPort": 3000,
"protocol": "tcp",
"appProtocol": "http"
}
],
"essential": true,
"environment": [
{
"name": "EMAIL_SMTP_PORT",
"value": "587"
},
{
"name": "DATABASE_URL",
"value": "postgres://<username>:<password>@localhost:5432/<database>?sslmode=disable"
},
{
"name": "EMAIL_SMTP_PASSWORD",
"value": "Your-SMTP-Password"
},
{
"name": "JWT_SECRET",
"value": "Generate a secure secret, for example using https://jwtsecret.com"
},
{
"name": "EMAIL_SMTP_ENABLE_STARTTLS",
"value": "'true'"
},
{
"name": "EMAIL_SMTP_USERNAME",
"value": "Use-SMTP-Username-here"
},
{
"name": "BASE_URL",
"value": "Provide your URL"
},
{
"name": "EMAIL_SMTP_HOST",
"value": "Provide your SMTP host"
},
{
"name": "EMAIL_NOREPLY",
"value": "Provide your noreply mail"
}
],
"environmentFiles": [],
"mountPoints": [],
"volumesFrom": [],
"dependsOn": [
{
"containerName": "postgres-db",
"condition": "HEALTHY"
}
],
"ulimits": [],
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/ecs/fider-app-task",
"mode": "non-blocking",
"awslogs-create-group": "true",
"max-buffer-size": "25m",
"awslogs-region": "us-east-2",
"awslogs-stream-prefix": "ecs"
},
"secretOptions": []
},
"systemControls": []
},
{
"name": "postgres-db",
"image": "545009831165.dkr.ecr.us-east-2.amazonaws.com/postgres:13.16",
"cpu": 2048,
"memory": 6144,
"memoryReservation": 5120,
"portMappings": [
{
"name": "postgres-db-5432-port",
"containerPort": 5432,
"hostPort": 5432,
"protocol": "tcp",
"appProtocol": "http"
}
],
"essential": true,
"environment": [
{
"name": "POSTGRES_USER",
"value": "fider"
},
{
"name": "POSTGRES_PASSWORD",
"value": "s0m3g00dp4ssw0rd"
},
{
"name": "POSTGRES_DB",
"value": "fider"
},
{
"name": "PGDATA",
"value": "/var/lib/postgresql/data"
}
],
"environmentFiles": [],
"mountPoints": [],
"volumesFrom": [],
"healthCheck": {
"command": [
"CMD-SHELL",
"pg_isready -U fider"
],
"interval": 10,
"timeout": 5,
"retries": 5
},
"systemControls": []
}
],
"family": "fider-app-task",
"executionRoleArn": "arn:aws:iam::545009831165:role/ecsTaskExecutionRole",
"networkMode": "awsvpc",
"revision": 7,
"volumes": [
{
"name": "pg_data_volume",
"efsVolumeConfiguration": {
"fileSystemId": "fs-08874b6ca635e5349",
"rootDirectory": "/",
"transitEncryption": "ENABLED",
"transitEncryptionPort": 2049,
"authorizationConfig": {
"accessPointId": "fsap-0bc6e6c2dd68da7b8",
"iam": "DISABLED"
}
}
}
],
"status": "ACTIVE",
"requiresAttributes": [
{
"name": "ecs.capability.execution-role-awslogs"
},
{
"name": "com.amazonaws.ecs.capability.ecr-auth"
},
{
"name": "com.amazonaws.ecs.capability.docker-remote-api.1.28"
},
{
"name": "com.amazonaws.ecs.capability.docker-remote-api.1.21"
},
{
"name": "ecs.capability.container-health-check"
},
{
"name": "ecs.capability.execution-role-ecr-pull"
},
{
"name": "com.amazonaws.ecs.capability.docker-remote-api.1.18"
},
{
"name": "ecs.capability.task-eni"
},
{
"name": "com.amazonaws.ecs.capability.docker-remote-api.1.29"
},
{
"name": "com.amazonaws.ecs.capability.logging-driver.awslogs"
},
{
"name": "com.amazonaws.ecs.capability.docker-remote-api.1.24"
},
{
"name": "ecs.capability.efsAuth"
},
{
"name": "com.amazonaws.ecs.capability.docker-remote-api.1.19"
},
{
"name": "ecs.capability.efs"
},
{
"name": "ecs.capability.container-ordering"
},
{
"name": "com.amazonaws.ecs.capability.docker-remote-api.1.25"
}
],
"placementConstraints": [],
"compatibilities": [
"EC2",
"FARGATE"
],
"requiresCompatibilities": [
"FARGATE"
],
"cpu": "4096",
"memory": "24576",
"runtimePlatform": {
"cpuArchitecture": "X86_64",
"operatingSystemFamily": "LINUX"
},
"registeredAt": "2024-10-27T11:10:15.921Z",
"registeredBy": "arn:aws:sts::your-account-id:assumed-role/AWSReservedSSO_AdministratorAccess_06c094dca8d9665c/your-account-name",
"enableFaultInjection": false,
"tags": []
}
Configuring mail server for Fider
Fider requires a mail server so administrators can set up SMTP (Simple Mail Transfer Protocol) details in Fider's environment settings. This usually involves specifying the mail server’s hostname, port, and authentication credentials (if needed) or via API, ensuring Fider can send emails reliably and securely.
The application requires email verification as part of the signup process to prevent spam and ensure only valid users access the platform.
Step 1: Setup a Mailgun account
Sign up with Sinch Mailgun and create an account at:
Step 2: Navigate to Domains paths under send
Once the sign up process is completed, Log in with your account and navigate to the
Domain path under the sending navigation panel.
I'll be using the SMTP credentials in my app's settings (environment variables).
Use these SMTP credentials inside the task definition of the Elastic container service.
Create an ECS service
Step 1:
Navigate to the ECS cluster you created and click on it, once inside the cluster click on service.
Choose service as the application type in the deployment configuration and Replica as the service type.
Turn off the public IP address as the tasks will use NAT gateway.
Configure the Application load balancer and place it inside the public subnet as front-facing for your application.
Click on create in the end and navigate to Cloudformation to view the status.
Navigate to the ACM console and click on request a certificate.
Provide your domain name and choose the DNS validation method.
Your SSL certificate is ready to be used with the application load balancer.
Choose ACM as a certificate source in Secure listener settings.
In routing actions select the Redirect to URL option and click on save changes.
Navigate to your DNS registrar's DNS settings and map it to your subdomain.
Viola! There you have it. Fider's up and about with the tasks running securely inside a private subnet of their own and the ALB routing requests to them.
SOCIAL SHARE CARD GENERATOR