Skip to content
Miguel Sancho Fernandez edited this page Nov 13, 2021 · 18 revisions

Deploy with Nginx and Unicorn

Installing Passenger + Nginx

suppouse the name parent folder is 'deploy':

deploy/
\_ /cenit

Add the new folders

deploy
\_ /cenit
\_ /shared
  \_ /pids
  \_ /sockets
  \_ /log

Inside cenit folder

deploy
\_ /cenit

Create a file for your environment variables on config/application.yml

MONGODB_URI: 'mongodb://#internal_ip:27017/production'
DB_PROD: production

UNICORN_CENIT_SERVER: true
BASE_MULTIPLIER_ACTIVE_TASKS: 50
UNICORN_CENIT_SERVER: true
SCHEDULER_LOOKUP_INTERVAL: 8
UNICORN_WORKERS: 8
MAXIMUM_UNICORN_CONSUMERS: 8
LOOKUP_SCHEDULER_OFF: false
LOAD_DELAYED_MESSAGES_ON_START: true

OAUTH_TOKEN_END_POINT: embedded

NOTIFIER_EMAIL: [email protected]
EXCEPTION_RECIPIENTS: [email protected], [email protected]
GMAIL_USERNAME: [email protected]
GMAIL_PASSWORD: *******

DEFAULT_FILE_STORE: Cenit::FileStore::AwsS3Default

AWS_S3_BUCKET_PREFIX: existing_bucket_name
AWS_ACCESS_KEY_ID: *******
AWS_SECRET_ACCESS_KEY: ********


# replace cenit.io for your domain
SING_OUT_URL: http://cenit.io
HOMEPAGE: https://cenit.io
HOST: cenit.io

UNICORN_WORKERS: 8
MAXIMUM_UNICORN_CONSUMERS: 6

# RabbitMQ
RABBIT_MQ_USER: *****
RABBIT_MQ_PASSWORD: *****

REDIS_HOST: redis_private_ip

'Setup::SystemNotification:attachment:uploader': EmbeddedUploader
'Setup::Execution:attachment:uploader': EmbeddedUploader
$ bundle install --deployment --without development test

To run redis use docker

docker run -d redis:5.0

Install rabbitmq including Management Plugin, to be able to see the dashboard UI.

https://www.rabbitmq.com/install-debian.html

the project has in Gemfile

gem 'unicorn'  

Open up a blank unicorn.rb document, which will be saved inside config/ directory in your project:

$ vim config/unicorn.rb

Place the below block of code, modifying it as necessary:

# Set your full path to application.
app_dir = File.expand_path('../../', __FILE__)
shared_dir = File.expand_path('../../../shared/', __FILE__)
app_name = "cenit"
 
# Set unicorn options
worker_processes 4
preload_app true
timeout 30
 
GC.respond_to?(:copy_on_write_friendly=) and GC.copy_on_write_friendly = true
 
# Fill path to your app
working_directory app_dir
 
# Set up socket location
listen "#{shared_dir}/sockets/unicorn.#{app_name}.sock", :backlog => 64
 
# Loging
stderr_path "#{shared_dir}/log/unicorn.#{app_name}.stderr.log"
stdout_path "#{shared_dir}/log/unicorn.#{app_name}.stdout.log"
 
# Set master PID location
pid "#{shared_dir}/pids/unicorn.#{app_name}.pid"
 
before_fork do |server, worker|
  defined?(ActiveRecord::Base) and ActiveRecord::Base.connection.disconnect!
  old_pid = "#{server.config[:pid]}.oldbin"
  if File.exists?(old_pid) && server.pid != old_pid
    begin
      sig = (worker.nr + 1) >= server.worker_processes ? :QUIT : :TTOU
      Process.kill(sig, File.read(old_pid).to_i)
    rescue Errno::ENOENT, Errno::ESRCH
      # someone else did our job for us
    end
  end
end
 
after_fork do |server, worker|
  defined?(Rails) and Rails.cache.respond_to?(:reconnect) and Rails.cache.reconnect
end
 
before_exec do |server|
  ENV['BUNDLE_GEMFILE'] = "#{app_dir}/Gemfile"
end
$ rake assets:precompile RAILS_ENV=production RACK_ENV=production

Create unicorn init script with app name (optional)

$ sudo vi /etc/init.d/cenit

note: field with BOLD need to be changed

#!/bin/sh

### BEGIN INIT INFO
# Provides:          unicorn
# Required-Start:    $all
# Required-Stop:     $all
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: starts the unicorn app server
# Description:       starts unicorn using start-stop-daemon
### END INIT INFO

set -e

USAGE="Usage: $0 "

# app settings
USER="deploy"
APP_NAME="appname"
APP_ROOT="/home/$USER/$APP_NAME"
ENV="production"

# environment settings
PATH="/home/$USER/.rbenv/shims:/home/$USER/.rbenv/bin:$PATH"
CMD="cd $APP_ROOT && bundle exec unicorn -c config/unicorn.rb -E $ENV -D"
PID="$APP_ROOT/shared/pids/unicorn.pid"
OLD_PID="$PID.oldbin"

# make sure the app exists
cd $APP_ROOT || exit 1

sig () {
  test -s "$PID" && kill -$1 `cat $PID`
}

oldsig () {
  test -s $OLD_PID && kill -$1 `cat $OLD_PID`
}

case $1 in
  start)
    sig 0 && echo >&2 "Already running" && exit 0
    echo "Starting $APP_NAME"
    su - $USER -c "$CMD"
    ;;
  stop)
    echo "Stopping $APP_NAME"
    sig QUIT && exit 0
    echo >&2 "Not running"
    ;;
  force-stop)
    echo "Force stopping $APP_NAME"
    sig TERM && exit 0
    echo >&2 "Not running"
    ;;
  restart|reload|upgrade)
    sig USR2 && echo "reloaded $APP_NAME" && exit 0
    echo >&2 "Couldn't reload, starting '$CMD' instead"
    $CMD
    ;;
  rotate)
    sig USR1 && echo rotated logs OK && exit 0
    echo >&2 "Couldn't rotate logs" && exit 1
    ;;
  *)
    echo >&2 $USAGE
    exit 1
    ;;
esac
$ sudo chmod 755 /etc/init.d/cenit
$ sudo update-rc.d cenit defaults

Test service

$ sudo service cenit start  
$ sudo service cenit stop

Configuring NGNIX

$ cd /etc/nginx/sites-available
$ vim default 

and the copy the next specification:

upstream cenit {
    # Path to Unicorn SOCK file
    server unix:/home/ubuntu/deploy/shared/sockets/unicorn.cenit.sock fail_timeout=0;
}

server {
    # Application root, as defined previously
    root /home/ubuntu/deploy/cenit/public;

    listen  80;
    server_name localhost;

    try_files $uri/index.html $uri @cenit;

    access_log /var/log/nginx/cenit_access.log combined;
    error_log /var/log/nginx/cenit_error.log;

    location @cenit {
        proxy_set_header X-Forwarded-For $remote_addr;
        proxy_set_header Host $http_host;
        proxy_redirect off;
        proxy_pass http://cenit;
    }

    error_page 500 502 503 504 /500.html;
    client_max_body_size 4G;
    keepalive_timeout 10;
}

with HTTPS should be something like this

server {
  listen 80;
  server_name cenit.io www.cenit.io;
  return 301 https://$server_name$request_uri;
}

upstream cenit {
    server unix:/home/ubuntu/deploy/shared/sockets/unicorn.cenit.sock fail_timeout=0;
}

server {
    root /home/ubuntu/deploy/cenit/public;

    listen 443;
    ssl on;
    ssl_certificate         /etc/nginx/ssl/cenit.io.crt;
    ssl_certificate_key     /etc/nginx/ssl/cenitio.key;

    ssl_protocols           TLSv1.2 TLSv1.1 TLSv1;
    ssl_ciphers             "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4";
    ssl_prefer_server_ciphers on;
    ssl_session_cache shared:SSL:10m;

    add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";

    server_name localhost www.cenit.io cenit.io;
    access_log /var/log/nginx/cenit_access.log combined;
    error_log /var/log/nginx/cenit_error.log;

    location ^~ /assets/ {
      gzip_static on;
      gzip_vary on;
      expires max;
      add_header Cache-Control public;
    }

    location / {
      try_files $uri/index.html $uri @cenit;
    }
    
    location @cenit {
        proxy_set_header X-Forwarded-For $remote_addr;
        proxy_set_header X-Forwarded-Proto https;
        proxy_set_header Host $http_host;
        proxy_redirect off;
        proxy_pass http://cenit;
    }

    try_files $uri @cenit @service;

    error_page 500 502 503 504 /500.html;
    client_max_body_size 4G;
    keepalive_timeout 10;
}

restart nginx server

$ sudo service nginx restart

if you did not use the optional step above you can run :

$ bundle exec unicorn_rails -c config/unicorn.rb -D

The first user that you create in the UI will be the super admin.