[Rails] Nginx, Puma environment deployment & server study [AWS EC2]

Introduction

Personally developed apps WEB server: Nginx Application server: Puma I deployed to AWS EC2 using.

Ruby 2.5.3 Rails 5.2.4.2 MacOS:Catalina 10.15.6

The AWS settings were OK while advancing the understanding according to the excellent article already mentioned, but since I just started, I felt that the Nginx settings (nginx.conf etc.) were particularly difficult, overcame many errors, and tried and errored. And cleared.

I think that many people choose Puma as an application server these days.

Since there was no article that listed the two settings of nginx.conf and yourapp.conf required for deployment, I thought it would be useful for someone.

I'm glad that I stumbled on the error and deepened my understanding of the server by investigating it, but probably everyone who challenges it will also stumbled at the same place, so ** I was able to deploy with such a setting ** I would like to write an article with my body.

1 Organize about Nginx and Puma

I will organize both of them with the meaning of review myself (please tell me if there are any differences!).

[** Nginx **] ... WEB server. Receives content requests from the browser and responds to the browser. In the case of a request for static content (image, etc.), the WEB server processes it. The application server is responsible for the dynamic content. Representatives of WEB servers are Apache, Nginx, etc.

[** Puma **] ... Application server. While Nginx handles static content on a web server, this handles dynamic content that Nginx cannot process. Request from WEB server → Receive application server → Return Rails application processing result to WEB server. Typical examples are Unicorn, Puma, etc. Rails is currently using Puma as its default application server.

There seems to be a difference between Puma and Unicorn, but the former is multithreaded and the latter is multiprocessed. Puma seems to have the advantage of handling more requests more efficiently, but some say it doesn't change much in normal use. I chose Puma, which is recommended by Rails.

2 Puma.rb settings

Next is the setting of puma.rb. Below are my settings.

puma.rb(local)


#Application directory
app_dir = File.expand_path("../../", __FILE__)
#Specify URI with bind for socket communication
bind "unix://#{app_dir}/tmp/sockets/puma.sock"
#PID file location(Process ID)
pidfile "#{app_dir}/tmp/pids/puma.pid"
#The state file operates the server with the pumactl command. Its whereabouts.
state_path "#{app_dir}/tmp/pids/puma.state"
#Standard output/The location of the file that outputs the standard error.
stdout_redirect "#{app_dir}/log/puma.stdout.log", "#{app_dir}/log/puma.stderr.log", true
threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 }
threads threads_count, threads_count
#port       ENV.fetch("PORT") { 3000 }
environment ENV.fetch("RAILS_ENV") { "development" }
plugin :tmp_restart

I commented it out because I don't use port.

Puma and Nginx are specified by bind on the second line for socket communication. In bind, specify the path by URI as shown below.

bind "unix://#{app_dir}/tmp/sockets/puma.sock"

3 nginx.conf settings

Nginx mainly modifies two files. 1 nginx.conf ... Nginx itself configuration file 2 yourapp.conf ... Nginx configuration file for each application

Below is my nginx.conf settings

(EC2)etc/nginx/nginx.conf


user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /var/run/nginx.pid;

include /usr/share/nginx/modules/*.conf;

events {
    worker_connections 1024;
}

http {
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile            on;
    tcp_nopush          on;
    tcp_nodelay         on;
    keepalive_timeout   65;
    types_hash_max_size 2048;

    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;

    include /etc/nginx/conf.d/*.conf;

    index   index.html index.htm;

    upstream puma {
        server unix:///var/www/rails/yourapp/shared/tmp/sockets/puma.sock;
    }
    server {
        listen       80 default_server;
        listen       [::]:80 default_server;
        server_name  Elastic IP(URL);
        root         /var/www/rails/yourapp/current/public;

        location / {
            try_files $uri $uri/index.html $uri.html @webapp;
        }

        location @webapp {
            proxy_read_timeout 300;
            proxy_connect_timeout 300;
            proxy_redirect off;
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_set_header Host $http_host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_pass http://puma;
        }

        error_page 404 /404.html;
            location = /40x.html {
        }

        error_page 500 502 503 504 /50x.html;
            location = /50x.html {
        }
    }
    server {
    	listen 443 ssl;
    	server_name Elastic IP(URL);
    	location @webapp {
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_pass http://puma;
      }
    }
}

4 Settings in yourapp.conf

Although it is called yourapp.conf, yourapp will contain the name of the application you are creating.

ruby:(EC2)/etc/nginx/conf.d/yourapp.conf


  # log directory
  error_log  /var/www/rails/yourapp/shared/log/nginx.error.log;
  access_log /var/www/rails/yourapp/shared/nginx.access.log;
  upstream app_server {
    # for UNIX domain socket setups
    server unix:/var/www/rails/yourapp/shared/tmp/sockets/yourapp-puma.sock fail_timeout=0;
  }
  server {
    listen 80;
    server_name ;
    # nginx so increasing this is generally safe...
    # path for static files
    root /var/www/rails/yourapp/current/public;
    # page cache loading
    try_files $uri/index.html $uri @app_server;
    location / {
      # HTTP headers
      proxy_pass http://app_server;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header Host $http_host;
      proxy_redirect off;
    }
    # Rails error pages
    error_page 500 502 503 504 /500.html;
    location = /500.html {
      root /var/www/rails/yourapp/current/public;
    }
    client_max_body_size 4G;
    keepalive_timeout 5;
  }

I will post an article that I referred to when deploying.

Deploy a Rails5 + Puma + Nginx environment to EC2 with Capistrano3 (Part 2)

Network construction by AWS of Rails5 application Nginx + Puma + Capistrano environment and AWS construction (VPC EC2 RDS CloudFlont Route53 etc)

Infrastructure beginners deploy Nginx + Puma Rails 5 application on Capistrano 3

Impressions

Since I was not accustomed to handling the server, I had more difficulty in setting Nginx and Puma above than setting AWS etc. when deploying to EC2. Finally, I was able to deploy to AWS EC2 using Capistrano and CircleCI. Regarding CDs, I think you can do it without difficulty if you follow the articles of the predecessors. I will come when there are many errors, but I can't stop because I am more than happy when I can implement new functions and resolve errors!

Recommended Posts

[Rails] Nginx, Puma environment deployment & server study [AWS EC2]
[Rails] AWS EC2 instance environment construction
Easy deployment with Capistrano + AWS (EC2) + Rails
[AWS] Publish rails app with nginx + puma
virtulbox + vagrant + Docker + nginx + puma + MySQL Rails environment construction
I tried automatic deployment with CircleCI + Capistrano + AWS (EC2) + Rails
Rails application development environment construction with Docker [Docker, Rails, Puma, Nginx, MySQL]
For beginners! Automatic deployment with Rails6 + CircleCI + Capistrano + AWS (EC2)
Rails (postgeresql. Ubuntu environment), heroku deployment
Launch Rails on EC2 (manual deployment)
rails AWS deployment is not reflected
[EC2 / Vue / Rails] EC2 deployment procedure for Vue + Rails
[Rails] AWS deployment error encounter summary
Build a development environment on AWS EC2 with CentOS7 + Nginx + pm2 + Nuxt.js
Deployed using Docker + Rails + AWS (EC2 + RDS)
Rails API server environment construction using docker-compose
[Rails] Image posting by CarrierWave [AWS EC2]
[Note] Update to production environment (AWS EC2)
When nginx conf is not reflected well in AWS Elastic Beanstalk + Rails environment
Rails5.1 + puma SSL connection in local production environment
500 Internal Server Error occurs in Rails production environment
Recipe for deploying Rails apps on AWS EC2