rails-template-deploy-stack

Public
A Rails application template that automatically scaffolds production-ready AWS ECS Fargate & RDS infrastructure via deploy-stack
Used 0 times
• Created by
A Anton

Usage
The official deploy-stack application template for Ruby on Rails.

This Rails template acts as an invisible bridge between your new Rails application and AWS. By simply appending a -m flag when generating a new Rails app, it automatically scaffolds a production-ready AWS architecture directly into your repository.

What it generates under the hood:

  • Compute & Networking: An AWS ECS Fargate cluster, Application Load Balancer, and an optional managed Amazon RDS PostgreSQL database.
  • DevSecOps CI/CD: A GitHub Actions workflow utilizing keyless IAM OIDC and automated Trivy container vulnerability scanning.
  • Container Hardening: Automatically patches the generated Rails Dockerfile to upgrade the Alpine OS and securely bump default Ruby standard library gems to guarantee a 0-CVE vulnerability scan.
  • Secrets Management: Securely extracts your Rails Master Key and syncs it with AWS Systems Manager (SSM) so your Fargate tasks can decrypt credentials seamlessly.
  • State Management: Native Terraform templates with an encrypted S3 remote state backend.

šŸ“¦ Usage (Zero Installation)
You do not need to clone this repository or install any gems. You can pass the raw template URL directly to the standard rails new command.

rails new my_app -m https://raw.githubusercontent.com/anton-codes-iac/rails-template-deploy-stack/main/template.rb
During generation, you will be prompted for:

  1. aws_region: Target AWS region for deployment (e.g., us-east-2).
  2. include_managed_rds: Select y to automatically inject the pg gem, update database.yml, and provision a secure Amazon RDS PostgreSQL instance.
  3. port: The port your Rails app listens on (default: 3000).
Once the standard Rails scaffolding completes, the template automatically runs deploy-stack in headless mode, patches the Dockerfile for DevSecOps compliance, and safely injects your RAILS_MASTER_KEY into the Terraform state.

šŸš€ Deployment (Day 1)
Navigate into your newly created application directory. Before pushing to GitHub, provision your AWS infrastructure and sync your secrets:

cd my_app

# 1. Provision the AWS ECR, VPC, ALB, and ECS Cluster
npx --yes deploy-stack apply

# 2. Encrypt and push your Rails Master Key into AWS SSM
npx --yes deploy-stack secrets push .env

šŸ”„ Automation (Day 2)
Push your code to GitHub. The generated GitHub Actions CI/CD pipeline will automatically build your Docker image, scan it for vulnerabilities using Trivy, and deploy the new task definition to AWS Fargate securely via IAM OIDC.

git branch -M main
git remote add origin https://github.com/your-username/my_app.git
git add .
git commit -m "ci: 0-CVE deployment with synchronized master keys"
git push -u origin main

šŸ—‘ļø Teardown (Stopping AWS Billing)
To remove all provisioned infrastructure, destroy the database, and stop billing, run:

npx --yes deploy-stack destroy

🧠 Powered by deploy-stack
This Rails template is a headless automation wrapper around the core deploy-stack engine. For custom architectures, full CLI flags, or supporting other web frameworks, visit the main deploy-stack repository.


šŸ’° AWS Costs & Disclaimer
This tool provisions real AWS resources which will incur charges on your AWS bill.
An ECS Fargate cluster with an Application Load Balancer running 24/7 typically costs around ~$25 - $35/month minimum, depending on your region. A managed RDS database will add additional monthly costs.

Disclaimer: The maintainers are not responsible for unexpected AWS charges. Always monitor your AWS Billing Dashboard.

Run this command in your Rails app directory in the terminal:

rails app:template LOCATION="https://railsbytes.com/script/Xo5svv"
Template Source

Review the code before running this template on your machine.

say "\nā˜ļø  [deploy-stack] Scaffolding AWS Fargate & RDS infrastructure for Rails...", :green

# --- 1. COLLECT ALL INPUTS ---
say "\nWhich AWS region do you want to deploy to?", :cyan
say "1) us-east-1 (N. Virginia)"
say "2) us-east-2 (Ohio)"
say "3) eu-west-1 (Ireland)"
say "4) eu-central-1 (Frankfurt)"
say "5) ap-southeast-2 (Sydney)"
region_choice = ask("Enter the number of your choice (1-5):", limited_to: ["1", "2", "3", "4", "5"], default: "1")
regions = { "1" => "us-east-1", "2" => "us-east-2", "3" => "eu-west-1", "4" => "eu-central-1", "5" => "ap-southeast-2" }
aws_region = regions[region_choice]

needs_db = yes?("\nDo you need a managed AWS RDS PostgreSQL database? (y/n)")
db_flag = needs_db ? "true" : "false"

port_input = ask("\nWhat port does your Rails application listen on? (default: 3000)")
port = port_input.strip.empty? ? "3000" : port_input.strip

# --- 2. PREPARE DEPENDENCIES & PATCH CVEs ---
if needs_db
  say "\n🐘 Injecting PostgreSQL dependencies...", :blue
  gem "pg"
  gsub_file "config/database.yml", /adapter: sqlite3/, "adapter: postgresql", verbose: false
end

say "šŸ›”ļø  Patching default Ruby library CVEs...", :blue
gem "erb", ">= 4.0.4"
gem "net-imap", ">= 0.4.24"
gem "resolv", ">= 0.3.2"
gem "rexml", ">= 3.3.9"
gem "uri", ">= 0.13.3"
gem "zlib", ">= 3.1.2"

# --- 3. EXECUTE AT THE VERY END ---
after_bundle do
  say "\nšŸ› ļø  Adding Alpine Linux (musl) platforms to Gemfile.lock...", :blue
  run "bundle lock --add-platform=x86_64-linux-musl > /dev/null 2>&1"
  run "bundle lock --add-platform=aarch64-linux-musl > /dev/null 2>&1"

  # Map the Rails Master Key to .env for the CLI tool
  if File.exist?("config/master.key")
    key = File.read("config/master.key").strip
    File.open(".env", "a") { |f| f.puts "\nRAILS_MASTER_KEY=#{key}" }
  end

  say "šŸ¤– Running deploy-stack in headless mode...\n", :blue
  run "npx --yes deploy-stack@latest --headless --framework=rails --region=#{aws_region} --needsDatabase=#{db_flag} --port=#{port}"

  # Inject the Master Key directly into Terraform so Fargate receives it on the first apply
  if Dir.exist?("terraform") && File.exist?("config/master.key")
    key = File.read("config/master.key").strip
    File.open("terraform/terraform.auto.tfvars", "a") do |f|
      f.puts %(\nrails_master_key = "#{key}")
    end
  end
end
Comments

Sign up or Login to leave a comment.