This Terraform configuration sets up the basic infrastructure for a Ruby on Rails application running on AWS, providing also a basic configuration to the server using cloud-init.
Use this as a foundation to jumpstart your development/staging environment and iterate as your project evolves. While this configuration provides essential building blocks, it's not production-ready and should be customized to meet your specific application needs, security requirements, and budget constraints.
Provider | Status | Resources | Link |
---|---|---|---|
AWS | ✅ | 1x Web + 1x Accessories | Repo |
AWS | 🚧 WIP | 1x Web + 1x Accessories + AWS RDS | Repo |
AWS | 🚧 WIP | Multiple Web and Accessories + Load Balancer | Repo |
This Terraform configuration creates (i) a public server ("web") designed to host the application and process background jobs, and (ii) a private server ("accessories") intended to run Redis for caching and job queuing, as well as a database.
- Terraform CLI installed. Terraform Installation guide
- AWS CLI configured with appropriate credentials. AWS CLI Installation Guide
- An AWS Keypair for SSH access to the servers.
Clone this repository and initialize terraform.
git clone github.com
cd kamal-terraform-recipes
touch terraform.tfvars
terraform init
terraform plan
terraform apply
- A Virtual Private Cloud (VPC)
- Two EC2 instances:
web
andaccessories
- Internet Gateway
- Public Subnets
- Route Tables
- Security Groups
- CIDR block and DNS settings are configurable via variables
- Web Instance:
- AMI: Configurable via variable
- Instance Type: Configurable via variable
- Located in the first public subnet
- Assigned Elastic IP
- Accessories Instance:
- AMI: Configurable via variable
- Instance Type: Configurable via variable
- Located in the second public subnet
- Internet Gateway
- Public Subnets in multiple Availability Zones
- Route Tables for public subnets
- Public Security Group: Allows inbound traffic on ports
80
,443
, and22
. - Private Security Group: Allows inbound traffic from the public security group.
Note: The private security group serves as a barrier to isolate the private instance from direct internet access. Instead of using a NAT Gateway or NAT Instance, which would incur significant costs, we've choose to combines AWS security group policies with UFW rules on the instance itself. This dual-layer strategy blocks inbound traffic from the internet while still allowing necessary outbound connections.
Both instances use cloud-init for initial setup configuration, including:
- Linux package updates
- Root user creation and SSH key setup
- Docker installation and private network configuration
- Uncomplicated Firewall (UFW) rules;
- Fail2ban installation.
Fail2ban instalation step has been removed from cloud-init config due to issues with Ubuntu 24.04. If deploying with another Linux version, you can add the following to your cloud-init configuration:
# 1. In cloudinit/base.yml
packages:
- docker.io
- curl
- git
- snapd
- ufw
- fail2ban
# ...
runcmd:
# ... add before reboot:
- systemctl start fail2ban
- systemctl enable fail2ban
- service fail2ban start
- fail2ban-client status
Key variables include:
variable_name | type | default | _ |
---|---|---|---|
web_instance_type | string | t4g.micro | 2vCPU, 1 GB RAM (free tier) |
db_instance_type | string | t4g.micro | 2vCPU, 1 GB RAM (free tier) |
ec2_ami | string | ami-0a4d44f3837d54a8a | Ubuntu Server 24.04 LTS (Arm64) |
key_name | string | app_staging | AWS key_name to be used on the servers |
environment | string | staging | |
app_tag | string | application | |
availability_zones | list(string) | ["sa-east-1a", "sa-east-1c"] |
Modify these in your variables.tf
file or when prompted during terraform apply
.
After running terraform apply
, you'll see the instance IP addresses as output:
Output | Description |
---|---|
web_instance_eip | Public IP for SSH access to the public instance |
accessories_instance_ip | Private IP for SSH access to the private instance |
To use a cloud back-end like HCP Terraform, provide credentials to access HCP Terraform by using the terraform login
command.
Add a cloud block to the directory's Terraform configuration, to specify which organization and workspace to use, then run terraform init
terraform {
cloud {
organization = "YOUR-ORG-NAME"
workspaces {
name = "your-project-workspace"
}
}
}
Add AWS_ACCESS_KEY_ID
and AWS_SECRET_ACCESS_KEY
as sensitive environment variables in your workspace at HCP Terraform.
To remove all created resources:
terraform destroy
If you have ideas for improvements or encounter any issues, please open an issue or submit a pull request on our GitHub repository.