Skip to content

EnamulRahman/memos-aws-infra

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

94 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Memos on AWS ECS Fargate

A self-hosted deployment of Memos on AWS ECS Fargate, provisioned with Terraform and deployed via GitHub Actions CI/CD.

🌐 Live URL: https://tm.myegh.com


Architecture

graph TD
    User["πŸ‘€ User"] -->|HTTPS| Route53["Route 53\ntm.myegh.com"]
    Route53 --> ALB["Application Load Balancer\nPort 80 β†’ 443 redirect\nACM TLS Certificate"]
    ALB -->|Port 8081| ECS["ECS Fargate\nmemos-cluster\nmemos-service"]
    ECS --> ECR["ECR\nDocker Image"]
    ECS --> CW["CloudWatch Logs\n/ecs/memos"]
    
    GHA["GitHub Actions\nbuild.yml + deploy.yml"] -->|Push image| ECR
    GHA -->|terraform apply| Infra["Terraform\nS3 Backend + DynamoDB Lock"]
    
    subgraph VPC ["VPC 10.0.0.0/16"]
        subgraph Public ["Public Subnets (eu-west-1a/1b)"]
            ALB
        end
        subgraph Private ["Private Subnets (eu-west-1a/1b)"]
            ECS
        end
    end
Loading

Infrastructure Overview

Component Details
Cloud AWS eu-west-1
Compute ECS Fargate (256 CPU, 512MB RAM)
Container Registry Amazon ECR
Load Balancer Application Load Balancer
TLS AWS Certificate Manager
DNS Route 53
State Backend S3 + DynamoDB locking
IaC Terraform (modular)
CI/CD GitHub Actions with OIDC

Terraform Modules

infra/
β”œβ”€β”€ main.tf
β”œβ”€β”€ variables.tf
β”œβ”€β”€ outputs.tf
β”œβ”€β”€ provider.tf
β”œβ”€β”€ terraform.tfvars
└── modules/
    β”œβ”€β”€ vpc/        # VPC, subnets, IGW, NAT, route tables
    β”œβ”€β”€ ecs/        # Cluster, task definition, service
    β”œβ”€β”€ alb/        # ALB, target group, listeners
    β”œβ”€β”€ ecr/        # Container registry
    β”œβ”€β”€ acm/        # TLS certificate
    β”œβ”€β”€ iam/        # Execution and task roles
    └── security/   # Security groups

CI/CD Pipeline

Two separate GitHub Actions workflows:

build.yml β€” Build and Push

  • Triggers on push to main or manual workflow_dispatch
  • Authenticates to AWS via OIDC (no static keys)
  • Builds Docker image and tags with Git SHA
  • Pushes to ECR

deploy.yml β€” Deploy and Verify

  • Triggers automatically when build.yml completes
  • Runs terraform fmt, validate, plan, apply
  • Waits 60s then hits /healthz β€” fails pipeline if unhealthy

Required GitHub Secret

Name Description
AWS_ROLE_ARN ARN of the IAM role with OIDC trust policy

Screenshots

VPC

VPC

Public Subnets

Subnets

Security Groups

Security Groups

Certificate Issued

ACM Certificate

DNS Resolution

DNS

Pushed to ECR

ECR

Load Balancer Working

ALB

Docker Image Running

Docker

Service Healthy in Cluster

ECS

Website Live with HTTPS

Live


How to Reproduce

Prerequisites

  • AWS CLI configured
  • Terraform >= 1.6.0
  • Docker
  • A registered domain in Route 53

1. Clone the repo

git clone https://github.com/EnamulRahman/ECS-Project.git
cd ECS-Project

2. Create S3 backend

aws s3api create-bucket \
  --bucket your-terraform-state-bucket \
  --region eu-west-1 \
  --create-bucket-configuration LocationConstraint=eu-west-1

aws s3api put-bucket-versioning \
  --bucket your-terraform-state-bucket \
  --versioning-configuration Status=Enabled

aws dynamodb create-table \
  --table-name terraform-locks \
  --attribute-definitions AttributeName=LockID,AttributeType=S \
  --key-schema AttributeName=LockID,KeyType=HASH \
  --billing-mode PAY_PER_REQUEST

3. Update variables

Edit infra/terraform.tfvars with your domain, region, and bucket name.

4. Deploy infrastructure

cd infra
terraform init
terraform apply

5. Set up OIDC for GitHub Actions

aws iam create-open-id-connect-provider \
  --url https://token.actions.githubusercontent.com \
  --client-id-list sts.amazonaws.com \
  --thumbprint-list ffffffffffffffffffffffffffffffffffffffff

aws iam create-role \
  --role-name github-actions-role \
  --assume-role-policy-document file://oidc-trust-policy.json

aws iam attach-role-policy \
  --role-name github-actions-role \
  --policy-arn arn:aws:iam::aws:policy/AdministratorAccess

Add AWS_ROLE_ARN to GitHub repository secrets.

6. Push to main

Any push to main will trigger the full build and deploy pipeline.

7. Tear down

cd infra
terraform destroy

Key Design Decisions

  • Fargate over EC2 β€” no server management, scales to zero
  • Private subnets for ECS β€” containers not directly internet accessible, traffic only via ALB
  • OIDC over static keys β€” no long-lived AWS credentials stored in GitHub
  • Modular Terraform β€” each layer isolated and independently manageable
  • Multi-stage Dockerfile β€” separate frontend (Node/pnpm) and backend (Go) build stages for smaller final image

About

My ECS Project

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors