zkt26/sk1
2026-05-20 08:53:09 +00:00
..
app.py Upload files to "sk1" 2026-05-20 07:31:24 +00:00
backup.sh Upload files to "sk1" 2026-05-20 08:53:09 +00:00
create-vm.sh Upload files to "sk1" 2026-05-20 08:53:09 +00:00
deploy.sh Upload files to "sk1" 2026-05-20 08:53:09 +00:00
destroy.sh Upload files to "sk1" 2026-05-20 08:53:09 +00:00
Dockerfile Upload files to "sk1" 2026-05-20 07:31:24 +00:00
index.html Upload files to "sk1" 2026-05-20 07:31:24 +00:00
init.sql Upload files to "sk1" 2026-05-20 07:31:24 +00:00
nginx.conf Upload files to "sk1" 2026-05-20 07:31:24 +00:00
prepare-app.sh Upload files to "sk1" 2026-05-20 07:31:24 +00:00
README.md Upload files to "sk1" 2026-05-20 07:31:24 +00:00
remove-app.sh Upload files to "sk1" 2026-05-20 07:31:24 +00:00
requirements.txt Upload files to "sk1" 2026-05-20 07:31:24 +00:00

Notes App — AWS Cloud Deployment

What the application does

A Notes web application where users can create, view, and delete short text notes via a web browser. Notes are stored persistently in a PostgreSQL database. The app is publicly accessible over HTTPS at the configured domain.


Cloud services and architecture

Cloud provider: Amazon Web Services (AWS), region eu-central-1 (Frankfurt)

Service Purpose
Amazon ECS Fargate Runs the frontend and backend containers serverlessly. Automatically restarts containers on failure.
Amazon RDS (PostgreSQL 16) Managed relational database. Provides persistent storage, automated backups (7-day retention).
Application Load Balancer (ALB) Receives all internet traffic. Routes /api/* to the backend, everything else to the frontend. Redirects HTTP → HTTPS.
AWS Certificate Manager (ACM) Issues and renews a free TLS/HTTPS certificate for the domain.
Amazon ECR Private Docker image registry. Stores the backend and frontend images.
AWS Secrets Manager Stores the database password securely. Never stored in code or Git.
Amazon CloudWatch Logs Collects access logs and application logs from both containers.
Amazon VPC + Security Groups Network isolation. ALB SG allows 80/443 from internet. ECS SG allows traffic only from ALB. RDS SG allows 5432 only from ECS.

Architecture

Browser (HTTPS)
      │
      ▼
Application Load Balancer  (port 443, ACM certificate, HTTP→HTTPS redirect)
      │
      ├── /api/*  ──▶  ECS Fargate: Backend (Flask, port 5000)
      │                        │
      │                        ▼
      │               RDS PostgreSQL (port 5432, private subnet)
      │
      └── /*      ──▶  ECS Fargate: Frontend (Nginx, port 80)

The browser loads the static frontend from the ALB. All API calls (/api/*) are made by the browser directly to the ALB, which forwards them to the backend. The frontend container serves only static files — it does not proxy to the backend. The backend connects to RDS using the DATABASE_URL environment variable.


Cost analysis — 1,000 users/day, 50 GB database

Estimated for eu-central-1 (Frankfurt), 1 year of operation.

Resource Specification Unit price Monthly Annual
ECS Fargate — Backend 0.25 vCPU, 0.5 GB RAM, 730 h/mo $0.04048/vCPU-h + $0.004445/GB-h ~$8.30 ~$99.60
ECS Fargate — Frontend 0.25 vCPU, 0.5 GB RAM, 730 h/mo same ~$8.30 ~$99.60
RDS db.t3.micro PostgreSQL, 1 vCPU, 1 GB RAM, 730 h/mo ~$0.022/h ~$16.10 ~$193.20
RDS Storage 50 GB gp2 $0.138/GB-mo ~$6.90 ~$82.80
RDS Automated Backups 50 GB (free up to DB size) $0.00 $0.00 $0.00
ALB 1 ALB + ~1,000 req/day (~30k/mo) $0.0252/h + LCU ~$18.50 ~$222.00
ECR ~500 MB images stored $0.10/GB-mo ~$0.05 ~$0.60
CloudWatch Logs ~5 GB/mo ingestion $0.57/GB ~$2.85 ~$34.20
Data Transfer Out ~10 GB/mo (1,000 users × ~330 KB) $0.09/GB ~$0.90 ~$10.80
Secrets Manager 1 secret $0.40/secret/mo $0.40 $4.80
Total ~$62.30 ~$747.60

Prices are estimates based on AWS public pricing (2025). Actual costs depend on traffic patterns. Use the AWS Pricing Calculator for exact quotes.


Files and their content

sk1/
├── prepare-app.sh        # Creates all AWS resources and deploys the app
├── remove-app.sh         # Tears down all AWS resources
├── backup.sh             # Creates a manual RDS snapshot
├── .env.example          # Template for required environment variables
├── .gitignore            # Excludes .env from Git
├── backend/
│   ├── app.py            # Flask REST API: GET/POST/DELETE /api/notes, /health
│   ├── requirements.txt  # Python dependencies: flask, psycopg2-binary
│   └── Dockerfile        # python:3.12-slim, runs app.py on port 5000
├── frontend/
│   ├── index.html        # Single-page app: dark UI, fetch() calls to /api/
│   ├── nginx.conf        # Nginx: serves index.html for all paths
│   └── Dockerfile        # nginx:1.27-alpine, serves static files
└── db/
    └── init.sql          # Creates notes table, inserts sample rows

Configuration description

All secrets and environment-specific values are passed via environment variables, never hardcoded in source files:

  • DATABASE_URL — injected into the backend ECS task definition at deploy time. Constructed from DB_USERNAME, DB_PASSWORD, DB_HOST, DB_NAME.
  • DB_PASSWORD — stored in AWS Secrets Manager under notes-app/db-password. Set via .env before running the script.
  • DOMAIN_NAME — the public domain for the app (e.g. notes.example.com). Used to request the ACM certificate and configure the ALB.
  • AWS_REGION / AWS_ACCOUNT_ID — target AWS account and region.

The .env file is listed in .gitignore and must never be committed to Git.


How to run and use the application

Prerequisites

  • AWS CLI installed and configured (aws configure) with permissions for: ECS, ECR, RDS, ELB, ACM, IAM, EC2, Secrets Manager, CloudWatch Logs
  • Docker installed and running
  • A domain name you control (to add DNS CNAME records)

Deploy

cd sk1
cp .env.example .env
# Edit .env — fill in AWS_REGION, AWS_ACCOUNT_ID, DOMAIN_NAME, DB_PASSWORD
source .env
chmod +x prepare-app.sh remove-app.sh
./prepare-app.sh

During deployment the script will print two DNS records to add:

  1. A CNAME for ACM certificate validation
  2. A CNAME pointing your domain to the ALB

Once DNS propagates and the certificate is validated, open https://your-domain.com in a browser.

Use the app

  • Type a note in the text box and click + Add Note
  • Notes appear below, newest first
  • Click ✕ Delete to remove a note

Remove everything

source .env
./remove-app.sh

The ACM certificate is not deleted automatically. Delete it manually if no longer needed: aws acm delete-certificate --certificate-arn <ARN> --region $AWS_REGION


How to perform a data backup

RDS automated backups are enabled with a 7-day retention period and run automatically every day.

Manual snapshot using the provided script:

source .env
./backup.sh

This creates a timestamped RDS snapshot (e.g. notes-app-manual-20260520-120000) and waits for it to complete.

Restore from snapshot:

aws rds restore-db-instance-from-db-snapshot \
  --db-instance-identifier notes-app-db-restored \
  --db-snapshot-identifier <snapshot-id> \
  --region $AWS_REGION

Export data as SQL dump (requires psql and RDS publicly accessible or VPN):

PGPASSWORD=$DB_PASSWORD pg_dump \
  -h <RDS_ENDPOINT> -U $DB_USERNAME -d $DB_NAME \
  > backup_$(date +%Y%m%d).sql

How to view access logs from the internet

Container logs (including Nginx access logs) are streamed to Amazon CloudWatch Logs.

Live tail — frontend (Nginx access log):

aws logs tail /ecs/notes-app/frontend --follow --region $AWS_REGION

Live tail — backend:

aws logs tail /ecs/notes-app/backend --follow --region $AWS_REGION

Query last 100 log events:

aws logs get-log-events \
  --log-group-name /ecs/notes-app/frontend \
  --log-stream-name $(aws logs describe-log-streams \
    --log-group-name /ecs/notes-app/frontend \
    --order-by LastEventTime --descending \
    --query "logStreams[0].logStreamName" --output text --region $AWS_REGION) \
  --limit 100 \
  --region $AWS_REGION

Conditions for running prepare-app.sh and remove-app.sh

prepare-app.sh:

  • AWS CLI must be installed and configured with credentials that have permissions for: ECS, ECR, RDS, ELB, ACM, IAM, EC2, Secrets Manager, CloudWatch Logs
  • Docker must be running locally
  • .env must exist with all required variables set (AWS_REGION, AWS_ACCOUNT_ID, DOMAIN_NAME, DB_PASSWORD)
  • The domain in DOMAIN_NAME must be one you can add DNS CNAME records to
  • Run from the sk1/ directory: source .env && ./prepare-app.sh
  • The script is idempotent — safe to run multiple times

remove-app.sh:

  • Same AWS CLI and .env requirements as above
  • All deletions are idempotent — safe to run multiple times
  • Run from the sk1/ directory: source .env && ./remove-app.sh

backup.sh:

  • Same AWS CLI and .env requirements as above (AWS_REGION is sufficient)
  • RDS instance notes-app-db must be running
  • Run from the sk1/ directory: source .env && ./backup.sh

Use of artificial intelligence

This project was developed with the assistance of Kiro AI (kiro-cli chat agent, Claude Sonnet model).

What How AI was used
prepare-app.sh, remove-app.sh, backup.sh Generated by AI, reviewed and verified by the author against AWS documentation
README.md Generated by AI based on assignment requirements, reviewed and corrected by the author
backend/app.py, frontend/index.html Originally written for a previous assignment, adapted with AI assistance
nginx.conf, Dockerfiles, init.sql Generated by AI, reviewed by the author

The AI was used as a coding assistant. All generated content was reviewed, understood, and verified by the author before submission.