Skip to content

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

deploy-stack-express-example - Cloud Infrastructure

This project was provisioned by deploy-stack. It contains a production-ready AWS ECS Fargate architecture and a GitHub Actions deployment pipeline.

💰 Cost Estimate & Disclaimer

This infrastructure provisions a highly available Application Load Balancer (ALB) and an ECS Fargate container (Size: Micro (0.25 vCPU, 512MB RAM)).

  • Estimated Monthly Cost: ~$25.00 / month
  • Note: AWS bills by the hour. If you destroy this stack after a few hours of testing, it will cost less than $0.20.

⚠️ DISCLAIMER: This cost is a rough estimate. AWS pricing changes and varies by region. You are solely responsible for all AWS charges incurred by deploying this infrastructure. The creators of deploy-stack are not liable for unexpected cloud costs, compromised credentials, or runaway billing. Always monitor your AWS Billing Dashboard and set up budget alerts.

🚀 Deployment Guide

  1. Initial Provisioning:

    cd terraform
    terraform init
    terraform apply
  2. Push Secrets (Optional): If your application requires environment variables, create a local .env file and sync it directly to AWS Secrets Manager:

    npx deploy-stack secrets push .env
  3. Automated CI/CD (Keyless via OIDC): Push this repository to GitHub. Your deployment pipeline uses AWS IAM OpenID Connect (OIDC) to authenticate securely with temporary credentials—no long-lived AWS secret keys are required in GitHub Secrets. Every push to main will automatically build, package, and deploy your application.

⚠️ Troubleshooting: OIDC Provider Already Exists

AWS only permits one GitHub Actions OIDC provider per AWS account. If terraform apply fails with an EntityAlreadyExists error regarding the OIDC provider, it indicates GitHub Actions was previously configured in this account.

The Fix: Open terraform/oidc.tf and update the default value of create_oidc_provider to false:

variable "create_oidc_provider" {
  type    = bool
  default = false # <--- Change this from true to false
}

Re-run terraform apply to link directly to your existing provider.

🛑 Safe Teardown (Destroying the Stack)

If you are done testing and want to stop all AWS billing, you must destroy the infrastructure.

Because our Terraform configuration is set to force-delete the ECR image repository (even if images are present), teardown is a single, clean command:

cd terraform
terraform destroy

Type yes when prompted. This will permanently delete the Load Balancer, ECS cluster, log groups, and associated networking components.

⚠️ Critical Application Prerequisites

Before you push your code to GitHub, ensure your application is configured to run inside a Docker container and respond to AWS Load Balancer health checks.

1. The Health Check Route (All Frameworks)

AWS constantly pings your container to ensure it is alive. If you configured a custom health check path (e.g., /api/health) during the CLI setup, you must create that route in your application. If AWS receives a 404 Not Found, it will assume your app is broken and terminate the container.

Make sure your app returns a 200 OK at your configured path:

  • Next.js (App Router): Create app/api/health/route.ts returning a 200 response.
  • Express.js: Add app.get('/api/health', (req, res) => res.sendStatus(200));
  • FastAPI/Python: Add @app.get("/api/health") returning a 200 status.

2. Enable Standalone Output (Next.js ONLY)

Next.js must be configured in "standalone" mode so it can bundle a minimal Node.js server. Without this, your GitHub Actions Docker build will crash.

Open next.config.js or next.config.ts in your root directory and add output: 'standalone':

import type { NextConfig } from 'next';

const nextConfig: NextConfig = {
  output: 'standalone', // <--- Add this exact line
};

export default nextConfig;

3. Container Network Binding (Node & Python)

When running inside a Docker container, your server must bind to all network interfaces (0.0.0.0), not just localhost or 127.0.0.1. If you bind to localhost, the AWS Load Balancer will not be able to route traffic to your application.

Make sure your app is configured correctly:

  • Express.js: app.listen(port, '0.0.0.0', () => ...)
  • FastAPI: uvicorn.run(app, host="0.0.0.0", port=8000)

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages