AWS Developer Blog

Introducing the ‘aws-rails-provisioner’ gem developer preview

AWS is happy to announce that the aws-rails-provisioner gem for Ruby is now in developer preview and available for you to try!

What is aws-rails-provisioner?

The new aws-rails-provisioner gem is a tool that helps you define and deploy your containerized Ruby on Rails applications on AWS. It currently only supports AWS Fargate.

aws-rails-provisioner is a command line tool using the configuration file aws-rails-provisioner.yml to generate AWS Cloud Development Kit (CDK) stacks on your behalf. It automates provisioning AWS resources to run your containerized Ruby on Rails applications on AWS Fargate with a few commands. It can also generate a CI/CD AWS CodePipeline pipeline for your applications when you enable its CI/CD option.

Why use aws-rails-provisioner?

Moving a local Ruby on Rails application to a well-configured web application running on the cloud is a complicated task. While aws-rails-provisioner doesn’t change this into a “one-click” task, it helps ease the most monotonous and detail-oriented aspects of the job.

The aws-rails-provisioner gem shifts your primary focus to component-oriented definitions inside a concise aws-rails-provisioner.yml file. This file defines the AWS resources your application needs, such as container image environment, a database cluster engine, or Auto Scaling strategies.

The new gem handles default details—like VPC configuration, subnet placement, inbound traffic rules between databases and applications—for you. With CI/CD opt-in, aws-rails-provisioner can also generate and provision a predefined CI/CD pipeline, including a database migration phase.

For containerized Ruby on Rails applications that you already maintain on AWS, aws-rails-provisioner helps to keep the AWS infrastructure for your application as code in a maintainable way. This ease allows you to focus more on application development.

Prerequisites

Before using the preview gem, you must have the following resources:
• A Ruby on Rails application with Dockerfile
• A Docker daemon set up locally
• The AWS CDK installed (requires `Node.js` >= 8.11.x) npm i -g aws-cdk

Using aws-rails-provisioner

Getting started with aws-rails-provisioner is fast and easy.

Step 1: Install aws-rails-provisioner

You can download the aws-rails-provisioner preview gem from RubyGems.

To install the gem, run the following command:


gem install 'aws-rails-provisioner' -v 0.0.0.rc1

Step 2: Define your aws-rails-provisioner.yml file

The aws-rails-provisioner.yml configuration file allows you to define how and what components you want aws-rails-provisioner to provision to run your application image on Fargate.

An aws-rails-provisioner.yml file looks like the following format:

version: '0'
vpc:
	max_azs: 2
services:
	rails_foo:
    source_path: ../sandbox/rails_foo
    fargate:
      desired_count: 3
      public: true
      envs:
        PORT: 80
        RAILS_LOG_TO_STDOUT: true
    db_cluster:
      engine: aurora-postgresql
      db_name: myrails_db
      instance: 2	
	  scaling:
		max_capacity: 2
		on_cpu:
			target_util_percent: 80
			scale_in_cool_down: 300
	rails_bar:
		...

aws-rails-provisioner.yml file overview

The aws-rails-provisioner.yml file contains two parts: vpc and services. VPC defines networking settings, such as Amazon VPC hosting your applications and databases. It can be as simple as:

vpc:
  max_az: 3
  cidr: '10.0.0.0/21'
	enable_dns: true

Left unmodified, aws-rails-provisioner defines a default VPC with three Availability Zones containing public, private, and isolated subnets with a CIDR range of 10.0.0.0/21 and DNS enabled. If these default settings don’t meet your needs, you can configure settings yourself, such as in the following example, which defines the subnets with details:

vpc:
	subnets:
		application: # a subnet name
 			cidr_mark: 24
			type: private
		...

You can review the full range of VPC configuration options to meet your exact needs.

The services portion of aws-rails-provisioner.yml allows you to define your Rails applications, Database cluster, and Auto Scaling policies.
For every application, you can add their entry with identifiers like:

services:
	my_awesome_rails_app:
	  source_path: ../path/to/awesome_app # relative path from `aws-rails-provisioner.yml`
		...
	my_another_awesome_rails_app:
	  source_path: ./path/to/another_awesome_app # relative path from `aws-rails-provisioner.yml`
		...

When you run aws-rails-provisioner commands later, it takes the configuration values of a service—under fargate:, db_cluster:, and scaling: to provision a Fargate service fronted by an Application Load Balancer (DBClusters resource and Auto Scaling policies are optional for a service).

Database cluster

The db_cluster portion of aws-rails-provisioner.yml defines database settings for your Rails application. It currently supports Aurora PostgreSQL, Aurora MySQL, and Aurora. You can specify the engine version by appending engine_version to the command. You can also choose to provide a user name for your databases; if not, aws-rails-provisioner automatically generates username and password and stores it in AWS Secrets Manager.

To enable storage encryption for the Amazon RDS database cluster, provide kms_key_arn with the AWS KMS key ARN you use for storage encryption:

 my_awesome_rails_app:
	  source_path: ../path/to/awesome_app
	  db_cluster:
		engine: aurora-postgresql
      db_name: awesome_db
		username: myadmin

You can review the full list of db_cluster: configuration options to meet your specific needs.

AWS Fargate
The fargate: portion of aws-rails-provisioner.yml defines which Fargate services and Tasks that running your application image, for example:

my_awesome_rails_app:
	source_path: ../path/to/awesome_app
	fargate:
		public: true
		memory: 512
		cpu: 256
		container_port: 80
		envs:
			RAILS_ENV: ...
			RAILSLOGTO_STDOUT: ...
  ...

For HTTPs applications, you can provide certificate with a certificate ARN from AWS Certificate Manager. This automatically associates with the Application Load Balancer and sets container_port to 443. You can also provide a domain name and domain zone for your application under domain_name and domain_zone. If you don’t provide these elements, the system provides a default DNS address from the Application Load Balancer.

When providing environment variables for your application image, you don’t have to define DATABASE_URL by yourself; aws-rails-provisioner computes the value based on your db_cluster configuration. Make sure to update the config/database.yml file for your Rails application to recognize the DATABASE_URL environment variable.

You can review the full list of fargate: configuration options to meet your specific needs.

Scaling
You can also configure the Auto Scaling setting for your service. In this prototype stage, you can configure scaling policies on_cpu, on_metric, on_custom_metric, on_memory, on_request, or on_schedule.

my_awesome_rails_app:
	source_path: ../path/to/awesome_app
	scaling:
	  max_capacity: 10
    on_memory:
      target_util_percent: 80
      scale_out_cool_down: 200
    on_request:
      requests_per_target: 100000
      disable_scale_in: true
    ...

You can review the full list of scaling: configuration options to meet your specific needs.

Step 3: Build and deploy

With aws-rails-provisioner.yml defined, you can run a build command. Doing so bootstraps AWS CDK stacks in code, defining all the necessary AWS resources and connections for you.

Run the following:


aws-rails-provisioner build

This command initializes and builds a CDK project with stacks—installing all required CDK packages—leaving a deploy-ready project. By default, it generates an InitStack that defines the VPC and Amazon ECS cluster, hosting Fargate services. It also generates a FargateStack that defines a database cluster and a load-balanced, scaling Fargate service for each service entry.

When you enable --with-cicd, the aws-rails-provisioner also provides a pipeline stack containing source, build, database migration, and deploy stages for each service defined for you. You can enable CI/CD with the following command:


aws-rails-provisioner build --with-cicd

After the build completes, run the following deploy command to deploy all defined AWS resources:


aws-rails-provisioner deploy

Instead of deploying everything all at the same time, you can deploy stack by stack or application by application:


# only deploys the stack that creates the VPC and ECS cluster
aws-rails-provisioner deploy --init

# deploys the fargate service and database cluster when defined
aws-rails-provisioner deploy --fargate

# deploy the CI/CD stack
aws-rails-provisioner deploy --cicd

# deploy only `my_awesome_rails_app` application
aws-rails-provisioner deploy --fargate --service my_awesome_rails_app

You can check on the status of your stacks by logging in to the AWS console and navigating to AWS CloudFormation. Deployment can take several minutes.

Completing deployment leaves your applications running on AWS Fargate, fronted with the Application Load Balancer.

Step 4: View AWS resources

To see your database cluster, log in to the Amazon RDS console.

To see an ECS cluster created, with Fargate Services and tasks running, you can also check the Amazon ECS console.

To view the application via DNS address or domain address, check the Application Load Balancing dashboard.

Any applications with databases need rails migration to work. The generated CI/CD stack contains a migration phase. The following CI/CD section contains additional details.
To view all the aws-rails-provisioner command line options, run:


aws-rails-provisioner -h

Step 5: Trigger the CI/CD pipeline

To trigger the pipeline that aws-rails-provisioner provisioned for you, you must commit your application source code and Dockerfile with AWS CodeBuild build specs into an AWS CodeCommit repository. The aws-rails-provisioner gem automatically creates this repository for you.

To experiment with application image build and database migration on your own, try these example build spec files from the aws-rails-provisioner GitHub repo.

Conclusion
Although aws-rails-provisioner for RubyGems is currently under developer preview, it provides you with a powerful, time-saving tool. I would love for you to try it out and return with feedback for how AWS can improve this asset before its final launch. As always, you can leave your thoughts and feedback on GitHub.