Skip to content

Latest commit

 

History

History
128 lines (92 loc) · 7.1 KB

File metadata and controls

128 lines (92 loc) · 7.1 KB

deploy-stack-nuxt-example - Cloud Infrastructure

This infrastructure and CI/CD pipeline was auto-generated by deploy-stack.

It contains a production-ready AWS ECS Fargate architecture and a zero-secret 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 the official deploy-stack GitHub Action and 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 run your infrastructure changes, build your container, 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.

Run the automated teardown command from the root of your project:

npx deploy-stack destroy

Type yes when prompted. This will execute a safe Terraform teardown of your Load Balancer, ECS cluster, and networking components, followed by automatically emptying and deleting your remote S3 state bucket.

⚠️ 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.
  • Ruby on Rails: Rails 7.1+ includes a default /up health check. Ensure Rails.application.config.force_ssl = true isn't blocking HTTP health checks from the ALB.
  • Django: Add a simple view in urls.py that returns HttpResponse("OK", status=200) at your configured path.
  • Go: Add a handler to your mux: http.HandleFunc("/api/health", func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(200) })
  • Nuxt 3: Create a server route at server/routes/health.ts returning 200.

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)
  • Ruby on Rails: Bound automatically by the CLI's Puma command (-b tcp://0.0.0.0:3000).
  • Django: Bound automatically by the CLI's Gunicorn command (--bind 0.0.0.0:3000).
  • Go: Ensure your ListenAndServe string looks like this: http.ListenAndServe(":8080", nil) or http.ListenAndServe("0.0.0.0:8080", nil).
  • Nuxt 3: Bound automatically via the NITRO_HOST=0.0.0.0 environment variable injected by the CLI Dockerfile.

4. Static Sites (Vite, Astro, React, Vue, SvelteKit)

If you are deploying a static site, your application is served via a highly optimized, unprivileged Nginx container.

  • Zero-Config Build: The CLI automatically detected your framework's output folder (dist, build, etc.) and pre-configured your Dockerfile.
  • Health Checks: You do not need to configure a custom /health route. Nginx will automatically return a 200 OK when AWS pings the root / index page.

5. Database Connections (Backend Frameworks Only)

If you opted to include a managed AWS RDS PostgreSQL database, the infrastructure automatically creates the database in isolated private subnets and injects the credentials into your container's environment variables.

Ensure your backend framework (Rails, Django, Go, etc.) is configured to consume these variables at runtime:

  • DB_HOST: The AWS RDS endpoint URL
  • DB_PORT: 5432
  • DB_NAME: The auto-formatted database name
  • DB_USER: The auto-generated master username
  • DB_PASSWORD: The securely injected master password (sourced from AWS Secrets Manager)

🛡️ Security Scanning

This pipeline includes automated DevSecOps guardrails using Trivy. Every time you push code, the pipeline will scan both your Docker container and your Terraform configurations for vulnerabilities and misconfigurations.

To view the security reports:

  1. Navigate to the Actions tab in GitHub.
  2. Click on the latest deployment run.
  3. Scroll down the Summary page to view the generated vulnerability tables.