After deploying web applications for so long using Heroku or other services that automate deployment, I realized that I didn’t really know everything that happens behind the scenes from taking an application from development to production. So I spent a weekend trying to deploy a Rails app to a bare metal server provisioned on AWS. It was a fun experience and I learned a lot. Here’re my notes from the entire process.
Set up Amazon EC2 (link)
- Sign up for AWS
- Create a key pair
- Create a security group (info)
Set up an EC2 instance (Server) (link)
- EC2 Instance: A virtual machine hosted at an Availability Zone on the AWS infrastructure
- Availability Zone: An isolated data center
- Access to the EC2 instance is managed using a key pair and a security group
- Key pair: to prove your identity
- Security group: virtual firewall to control incoming and outgoing traffic
Connect to the Server (link) (prereqs)
-
ssh -i /private-key.cer [email protected]
Follow the Server Setup instructions. (link)
- Except for firewall, as it’s already set up
- Don’t create new user (see next step)
Create a new user on the server (link)
- Use this user for your application.
- Add user to the sudo group
sudo nano /etc/sudoers
user_name ALL=(ALL) ALL
Ruby on Rails
- Set the environment to Production
export RAILS_ENV=production. # ~/.zshrc
- Install rbenv (link)
sudo apt install rbenv
- Install / Update ruby-build (link)
$ mkdir -p "$(rbenv root)"/plugins
$ git clone https://github.com/rbenv/ruby-build.git "$(rbenv root)"/plugins/ruby-build
- Skip gem documentation
echo "gem: --no-document" > ~/.gemrc
- Install bundler
gem install bundler
- Install rails and foreman
gem install rails
gem install foreman
rbenv rehash
- Install nodejs and npm using nvm (link)
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | zsh
nvm install 16.13.2
- Install yarn
npm install --global yarn
- Set up the credentials (copy from development)
nano config/master.key. # (copy from development)
- Ensure Tailwind is setup properly in production
bundle lock --add-platform x86_64-linux
bundle install
- Precompile the Assets
rails assets:precompile
Database
- Install MySQL and MyCLI
sudo apt-get install libmysqlclient-dev
gem install mysql2
sudo apt install mysql-server
sudo apt-get install mycli
- Check MySQL is running
systemctl status mysql.service # OR
sudo service mysql status
- Access MySQL
sudo mysql # uses 'root' user OR
sudo mycli # password is the login password
- Setup user for your application
create user 'writer'@'localhost' identified by '37signals';
- Grant Privileges to the user
sudo mycli
> grant all privileges on writer_production.* to 'writer'@'localhost';
- Prepare the database
bin/rails db:prepare
Nginx
These steps follow this guide. If you are using AWS EC2 instance that uses a security group, you don’t need the enable ufw.
- Install Nginx
sudo apt update
sudo apt install nginx
- Check if Nginx is running
systemctl status nginx
- If it’s not, run the executable file to start.
nginx -s signal (stop quit reload reopen) OR
sudo systemctl start nginx
- Go to the server IP address or domain to see the Welcome to nginx! page
- Set up a test page
sudo mkdir -p /var/www/your_domain/html
sudo chown -R $USER:$USER /var/www/your_domain/html
sudo chmod -R 755 /var/www/your_domain
nano /var/www/your_domain/html/index.html
sudo chown -R $USER:$USER /var/log/nginx
- Set up a server directive
sudo nano /etc/nginx/sites-available/your_domain
server {
listen 80;
listen [::]:80;
root /var/www/your_domain/html;
index index.html index.htm index.nginx-debian.html;
server_name your_domain www.your_domain;
location / {
try_files $uri $uri/ =404;
}
}
sudo ln -s /etc/nginx/sites-available/your_domain /etc/nginx/sites-enabled/
sudo rm /etc/nginx/sites-enabled/default # remove the default
- Restart Nginx
sudo nginx -s reload
- Serve Rails app from Nginx
server {
server_name writesoftwarewell www.writesoftwarewell.com;
root /var/www/writer/public;
location / {
proxy_pass http://localhost:3000/;
}
location /assets/ {
}
}
Notes
/etc/nginx
: The Nginx configuration directory. All of the Nginx configuration files reside here./etc/nginx/nginx.conf
: The main Nginx configuration file. This can be modified to make changes to the Nginx global configuration./etc/nginx/sites-available/
: The directory where per-site server blocks can be stored. Nginx will not use the configuration files found in this directory unless they are linked to the sites-enabled directory. Typically, all server block configuration is done in this directory, and then enabled by linking to the other directory./etc/nginx/sites-enabled/
: The directory where enabled per-site server blocks are stored. Typically, these are created by linking to configuration files found in the sites-available directory.