Last active
May 3, 2023 16:40
-
-
Save rameerez/a3f88dff54737345c69c21be0ab31425 to your computer and use it in GitHub Desktop.
Configure an AWS EC2 instance running Amazon Linux 2023 (AL2023) to run a Rails 7 app using Capistrano for deployment
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# This scrips takes a clean AWS Amazon Linux 2023 AMI and installs and configures | |
# everything needed to deploy a Rails app to it. The resulting state is a clean | |
# instance that can be used to build a base AMI for an EC2 ASG. | |
# --- AESTHETICS --- | |
# Define the color code for green for echo messages | |
GREEN='\033[0;32m' | |
# Define the escape sequence for the alien emoji (U+1F47D) | |
ALIEN='\xF0\x9F\x91\xBD' | |
# Define the variable for resetting the color back to the default | |
NC='\033[0m' | |
# --- CONFIG SCRIPT STARTS --- | |
# Create rails user and add sudo privileges | |
# rails is the user we'll use for deploying and running the app | |
echo -e "${GREEN}${ALIEN} Creating rails user for Capistrano to use...${NC}" | |
sudo adduser rails | |
sudo chmod 755 /home/rails | |
echo 'rails ALL=(ALL) NOPASSWD: ALL' | sudo tee /etc/sudoers.d/rails | |
sudo chmod 0440 /etc/sudoers.d/rails | |
echo -e "${GREEN}${ALIEN} User rails created with appropriate permissions.${NC}" | |
# Switch to the new rails user from now on | |
su -l rails <<EOF | |
# Update package list and install essential packages | |
# --allowerasing allows us to remove gnupg2-minimal, because we're using gnupg2 instead | |
echo -e "${GREEN}${ALIEN} Installing required packages for a Rails production environment...${NC}" | |
sudo dnf update -y | |
sudo dnf install -y git zlib-devel openssl-devel readline-devel sqlite-devel libyaml-devel libxml2-devel libxslt-devel libcurl-devel libffi-devel gcc gcc-c++ patch make automake autoconf bison postgresql-devel gdbm-devel ncurses-devel ruby-devel jq gnupg2 postgresql15 htop ImageMagick --allowerasing | |
# crontab does not come installed by default in AL2023 (wtf?) | |
echo -e "${GREEN}${ALIEN} Installing crontab to run scheduled background jobs...${NC}" | |
sudo dnf install -y cronie | |
sudo systemctl enable crond.service | |
sudo systemctl start crond.service | |
# Install RVM and Ruby 3.1.2 | |
echo -e "${GREEN}${ALIEN} Installing RVM to manage Ruby versions...${NC}" | |
gpg2 --keyserver hkp://keyserver.ubuntu.com --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB | |
curl -sSL https://get.rvm.io | bash -s stable | |
source ~/.rvm/scripts/rvm | |
echo -e "${GREEN}${ALIEN} Installing Ruby v3.1.2...${NC}" | |
rvm install 3.1.2 | |
echo -e "${GREEN}${ALIEN} Setting Ruby v3.1.2 as system default...${NC}" | |
rvm use 3.1.2 --default | |
# Install Bundler 2.3.19 | |
echo -e "${GREEN}${ALIEN} Installing Bundler...${NC}" | |
gem install bundler -v 2.3.19 | |
# Install Node.js and yarn | |
echo -e "${GREEN}${ALIEN} Installing Node and yarn...${NC}" | |
sudo dnf install -y nodejs | |
curl --silent --location https://dl.yarnpkg.com/rpm/yarn.repo | sudo tee /etc/yum.repos.d/yarn.repo | |
sudo dnf install -y yarn | |
# Install and configure Nginx | |
echo -e "${GREEN}${ALIEN} Installing Nginx...${NC}" | |
sudo dnf install -y nginx | |
sudo systemctl enable nginx | |
sudo systemctl start nginx | |
sudo mkdir -p /etc/nginx/sites-available/ | |
sudo mkdir -p /etc/nginx/sites-enabled/ | |
sudo sed -i '/http {/a \ include \/etc\/nginx\/sites-enabled\/*;' /etc/nginx/nginx.conf | |
# Add nginx www-data following Ubuntu conventions (AL2023 has nginx user by default) | |
# This creates the www-data user with the www-data group as its primary group, sets its shell to /sbin/nologin (which prevents login), and omits creating a home directory with the -M flag | |
echo -e "${GREEN}${ALIEN} Adding group www-data to follow Ubuntu naming conventions (instead of using group nginx)...${NC}" | |
sudo groupadd www-data | |
sudo useradd -g www-data -s /sbin/nologin -M www-data | |
sudo chown -R www-data:www-data /var/log/nginx | |
sudo usermod -a -G www-data rails | |
sudo systemctl restart nginx | |
# Now that the www-data user is created for nginx, let's write the proper nginx configuration | |
echo -e "${GREEN}${ALIEN} Setting up global Nginx configuration...${NC}" | |
sudo sh -c 'cat > /etc/nginx/nginx.conf <<NGINX_CONF | |
user www-data; | |
worker_processes auto; | |
pid /run/nginx.pid; | |
include /etc/nginx/modules-enabled/*.conf; | |
events { | |
worker_connections 768; | |
# multi_accept on; | |
} | |
http { | |
## | |
# Basic Settings | |
## | |
sendfile on; | |
tcp_nopush on; | |
tcp_nodelay on; | |
keepalive_timeout 65; | |
types_hash_max_size 2048; | |
# server_tokens off; | |
# server_names_hash_bucket_size 64; | |
# server_name_in_redirect off; | |
include /etc/nginx/mime.types; | |
default_type application/octet-stream; | |
## | |
# SSL Settings | |
## | |
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE | |
ssl_prefer_server_ciphers on; | |
## | |
# Logging Settings | |
## | |
access_log /var/log/nginx/access.log; | |
error_log /var/log/nginx/error.log; | |
## | |
# Gzip Settings | |
## | |
gzip on; | |
# gzip_vary on; | |
# gzip_proxied any; | |
# gzip_comp_level 6; | |
# gzip_buffers 16 8k; | |
# gzip_http_version 1.1; | |
# gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript; | |
## | |
# Virtual Host Configs | |
## | |
include /etc/nginx/conf.d/*.conf; | |
include /etc/nginx/sites-enabled/*; | |
# Set Real IPs for Cloudflare. | |
# The following are Cloudflare IP ranges from here (https://www.cloudflare.com/ips/) | |
set_real_ip_from 103.21.244.0/22; | |
set_real_ip_from 173.245.48.0/20; | |
set_real_ip_from 103.21.244.0/22; | |
set_real_ip_from 103.22.200.0/22; | |
set_real_ip_from 103.31.4.0/22; | |
set_real_ip_from 141.101.64.0/18; | |
set_real_ip_from 108.162.192.0/18; | |
set_real_ip_from 190.93.240.0/20; | |
set_real_ip_from 188.114.96.0/20; | |
set_real_ip_from 197.234.240.0/22; | |
set_real_ip_from 198.41.128.0/17; | |
set_real_ip_from 162.158.0.0/15; | |
set_real_ip_from 104.16.0.0/13; | |
set_real_ip_from 104.24.0.0/14; | |
set_real_ip_from 172.64.0.0/13; | |
set_real_ip_from 131.0.72.0/22; | |
set_real_ip_from 2400:cb00::/32; | |
set_real_ip_from 2606:4700::/32; | |
set_real_ip_from 2803:f800::/32; | |
set_real_ip_from 2405:b500::/32; | |
set_real_ip_from 2405:8100::/32; | |
set_real_ip_from 2a06:98c0::/29; | |
set_real_ip_from 2c0f:f248::/32; | |
real_ip_header X-Forwarded-For; | |
real_ip_recursive on; | |
} | |
NGINX_CONF' | |
# Install Redis server | |
echo -e "${GREEN}${ALIEN} Installing Redis...${NC}" | |
sudo dnf install -y redis6 | |
sudo systemctl enable redis6 | |
sudo systemctl start redis6 | |
# Install Certbot | |
# Certbot cannot be installed with dnf, must be installed using Python3 env | |
# Source: https://certbot.eff.org/instructions?ws=nginx&os=pip via https://repost.aws/questions/QUKV7YqM2HR_a1p_pSlCkk3g/installing-let-s-encrypt-on-amazon-linux2023 | |
echo -e "${GREEN}${ALIEN} Installing Certbot...${NC}" | |
sudo dnf install -y python3 augeas-libs | |
sudo python3 -m venv /opt/certbot/ | |
sudo /opt/certbot/bin/pip install --upgrade pip | |
sudo /opt/certbot/bin/pip install certbot certbot-nginx | |
sudo ln -s /opt/certbot/bin/certbot /usr/bin/certbot | |
EOF | |
# Configure SSH key for the rails user (same as ec2-user, AWS configured key) | |
echo -e "${GREEN}${ALIEN} Adding ec2-user ssh key to user rails...${NC}" | |
sudo mkdir /home/rails/.ssh | |
sudo cp ~/.ssh/authorized_keys /home/rails/.ssh | |
sudo chown -R rails:rails /home/rails/.ssh | |
sudo chmod 700 /home/rails/.ssh | |
sudo chmod 600 /home/rails/.ssh/authorized_keys | |
echo -e "${GREEN}${ALIEN} You can now ssh as user rails using the same keypair as ec2-user.${NC}" | |
# Delete previous command history so we leave the AMI in a clean state | |
history -c | |
echo -e "${GREEN}${ALIEN} Amazon Linux 2023 machine initial setup for Rails 7 + Capistrano completed successfully.${NC}" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment