Back-end Engineering Articles

I write and talk about backend stuff like Ruby, Ruby On Rails, Databases, Testing, Architecture / Infrastructure / System Design, Cloud, DevOps, Backgroud Jobs, and more...



Create Production and Staging Environment with Capistrano and AWS EC2

First, I have an EC2 instance on a public IP, under an Elastic IP: Im strating from here to the whole process, even obtaining a DNS

Github with commits:

Step #1 - Create a new branch and change all from that

$ git branch staging
$ git checkout staging

EDITOR="code --wait" bin/rails credentials:edit

Change the envs

secret_key_base: asdasdasd

  host: xxx
  port: xx
  database: xx
  username: xx
  password: xx

  host: yyy
  port: yyy
  database: yyy
  username: yyy
  password: yyy

# config/database.yml

  adapter: sqlserver
  host: <%= Rails.application.credentials.staging[:host] %>
  port: <%= Rails.application.credentials.staging[:port] %>
  database: <%= Rails.application.credentials.staging[:database] %>
  username: <%= Rails.application.credentials.staging[:username] %>
  password: <%= Rails.application.credentials.staging[:password] %>
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  timeout: 5000

# config/deploy.rb
# comment branch
# set :branch, "main"

# config/deploy/production.rb
set :repo_url, "[email protected]:danielmoralesp/repo_name.git"
set :branch, "main"
set :deploy_to, '/var/www/app_name'
set :stage, :production

# config/deploy/staging.rb
role :app, %w{[email protected]}
role :web, %w{[email protected]}
role :db,  %w{[email protected]}

set :branch, "staging"
set :deploy_to, '/var/www/staging'
set :stage, :staging

# set :ssh_options, {
#     keys: ['~/.ssh/APP_NAME_keypair.pem'],
#     forward_agent: false,
#     auth_methods: ["publickey", "password"]
# }

set :ssh_options, {
    keys: %w(~/.ssh/APP_NAME_keypair.pem),
    forward_agent: true,
    auth_methods: %w(publickey password)

# to check the environments
<% if Rails.env.production? %>
  - In production
<% elsif Rails.env.staging?  %>
  - In Staging
<% elsif Rails.env.development? %>
  - In Development
<% end %>

Step #2 - Setup in AWS Instance

$ ssh -p 22 -i ~/.ssh/xxx.pem [email protected]

# permisson if domain name servers are long like

[email protected]:/etc/nginx$ sudo vim nginx.conf

uncomment or add server_names_hash_bucket_size 128;

[email protected]:~$ cd /var/www/
[email protected]:/var/www$ sudo mkdir staging

[email protected]:~$ cd /etc/nginx/sites-enabled$ 
[email protected]:/etc/nginx/sites-enabled$ sudo vim hello_world.conf

server {
    listen 80;
    server_name IPADDRESS;
    rails_env    production;
    root /var/www/APP_NAME/current/public;

    passenger_enabled on;
    passenger_ruby /usr/local/rvm/gems/ruby-2.6.8/wrappers/ruby;

[email protected]:/etc/nginx/sites-enabled$ sudo touch staging.conf
[email protected]:/etc/nginx/sites-enabled$ sudo vim staging.conf

server {
    listen 80;

    root /var/www/staging/current/public;
    passenger_enabled on;
    passenger_app_env staging;

    passenger_ruby /usr/local/rvm/gems/ruby-2.6.8/wrappers/ruby;

$ sudo service nginx reload

- Loguearme como sudo user
    - Ssh -i …..
    - sudo chown deploy_user: /var/www/staging

$ Make deploy via Capistrano to create the staging/shared folder

- Loguearme como sudo user
		- cd /var/www/staging/shared/config/
    - sudo touch master.key
    - sudo touch application.yml
    - EDITOR="code --wait" bin/rails credentials:edit
        - Esto abre el archivo de credenciales con VisualStudio Code, copia en algun lugar seguro la credencial de secret_master_key y cierra el archivo
        - Abre el archivo master-key del proyecto local de rails y copia en algun lugar seguro la credencial
    - sudo vim application.yml (copia y pega aqui los valores dentro de las llaves dadas)
        - RAILS_MASTER_KEY=ohai
        - SECRET_KEY_BASE=1234567890
    - sudo vim master.key
        - Copia aqui el master.key también
    - Cd
    - sudo service nginx reload

Step 3 - Deploy

$ git add .
$ git commit -m ...
$ git push origin staging
$ cap staging deploy
$ git checkout main
$ git merge staging
$ git push origin main
$ cap production deploy