13 July 2015

http://www.rubytreesoftware.com/resources/ruby-on-rails-41-ubuntu-1404-server-deployment
http://www.gotealeaf.com/blog/deploy-rails-apps-with-capistrano
http://blog.mohitkanwal.com/blog/2013/04/10/deploying-rails-on-nginx-and-thin/

Deployment to Nairobi

Fedora + nginx

  1. production.rb ⇒
    1. config.assets.compile = true,
    2. config.serve_static_files = ENV['RAILS_SERVE_STATIC_FILES'].present? || true
  2. Create new postrges user with password as configures in database.yml
  3. ftp (sin tmp ni log)
  4. cambio a root (si el usuario no es sudoer)
  5. cd <appdir> ⇒ crea gemset
  6. regreso a usuario
  7. bundle install –without development test (pide password (sudoer))
  8. env vars - see below
  9. rake db:create
  10. rake db:migrate
  11. rake db:seed

Extract from https://github.com/rails/spring

Deployment

You must not install Spring on your production environment. To prevent it from being installed, provide the –without development test argument to the bundle install command which is used to install gems on your production machines:

$ bundle install --without development test

Spring removal

  1. 'Unspring' your bin/ executables: bin/spring binstub –remove –all
  2. Remove spring from your Gemfile

Deployment: ShK

TO ALSER:

cap staging deploy

TO NAIROBI

cap production deploy
ssh nairobi.pres.in  --> enter password
su  --> enter root password
/etc/init.d/thin restart   OR  thin restart -C /etc/thin/shk.yml

Check if rails server can start

curl 0.0.0.0:3010

Thin instances restart - SHK

Every thin instance has its own configuration file:

thin restart -C /etc/thin/shk.yml

SAAP: First deploy in nairobi

cap production deploy:check_write_permissions
cap production deploy

Fails because database still doesn't exist.

Prepare database.yml and secrets.yml in development pc

cap production setup:upload_yml

In the production server, create the database in the release folder

rake db:create

Configure thin configuration file

/etc/thin/saap.rb
cap production deploy
cap production setup:seed_db
cap production deploy:start   -->> the first time o do it locally 'thin start -C /etc/thin/saap.yml'

The deployment process is asking for password to restart the server. Ctrl+C to stop it and do it locally:

thin start -C /etc/thin/saap.yml

In the production server, to update the crontab (tha cap task is not working because 'can not locate Gemfile'

bundle exec whenever --update-crontab saap_production --set environment=production --roles=web,app,db
bundle exec whenever --clear-crontab saap_production   --> clears the crontab, careful!

SAAP: next deployments

cap production deploy

Connect to production server, as su

thin restart -C /etc/thin/saap.yml

If necessary

bundle exec whenever --update-crontab saap_production --set environment=production --roles=web,app,db

Rollback

cap production deploy:rollback

Rails console

bundle exec rails console

Tutorials

Code

thin restart -e production --servers 3 --onebyone --wait 30

Matar proceso server

$ cat tmp/pids/server.pid
=> numero de proceso
$ kill -9 numero_de_proceso

Create new postgres user with password

$ sudo -u postgres psql postgres
postgres=# CREATE USER username WITH PASSWORD 'password';
postgres=# GRANT ALL PRIVILEGES ON DATABASE database TO username;
postgres=# ALTER ROLE username WITH SUPERUSER;

Production vars

$ RAILS_ENV=production rake secret > clave.txt

… add at the end opening the file clave.txt (in vi :r)

#!/bin/bash
export RAILS_ENV=production
export RAKE_ENV=production
export SECRET_KEY_BASE=clave
export VAM1_DATABASE_PASSWORD=password

In one of these files…

$ vi ~/.bash_profile
$ vi ~/.bash_login
$ vi ~/.profile
$ vi ~/.bashrc

bash file to start rails server

File name: start_activity_logger.sh

Execute with: ./start_activity_logger.sh

#!/bin/bash --login
cd ~/projects/activity_logger/
rvm gemset use activity_logger
rails s -p 3001

To execute on boot, put it in /etc/init.d and there execute:

sudo update-rc.d startactivitylogger.sh defaults

nginx & Thin

Install thin

http://www.gotealeaf.com/blog/deploy-rails-apps-with-capistrano
http://archive.railsforum.com/viewtopic.php?id=17284
http://stackoverflow.com/questions/3230404/rvm-and-thin-root-vs-local-user/3376785#3376785
http://articles.slicehost.com/2009/4/17/centos-thin-web-server-for-ruby

Check rvmsudo thin install

As root

rvm gemset use global -> maybe not necessary nor possible
gem install thin
thin install
Installing thin service at /etc/rc.d/thin ...
mkdir -p /etc/rc.d
writing /etc/rc.d/thin
chmod +x /etc/rc.d/thin
mkdir -p /etc/thin

If it fails with message mkmf.rb can't find header files for ruby at /usr/share/include/ruby.h

sudo yum install ruby-devel (redhat)
sudo apt-get install ruby-dev (debian)

After thin install, as the message after installation says, the script 'thin' is installed into /etc/rc.d. And if we want thin to be installed as a service, the script must be put into init.d. Maybe you can read the scripts under init.d for more information.

sudo mv /etc/rc.d/thin /etc/rc.d/init.d/thin
reboot or start service manually

To configure thin to start at system boot:

on RedHat like systems:

sudo /sbin/chkconfig --level 345 thin on

on Debian-like systems (Ubuntu):

sudo /usr/sbin/update-rc.d -f thin defaults

Start service manually

service thin start or /etc/init.d/thin start

Configuration file sample for app 'shk' deployed in ALSER as root:

#/etc/thin/shk.yml
---
chdir: "/root/rails_apps/shk/current"
environment: production
address: 0.0.0.0
port: 3000
timeout: 30
log: "/root/log/thin.log"
pid: tmp/pids/thin.pid
max_conns: 1024
max_persistent_conns: 100
rackup: config.ru
require: []
wait: 30
threadpool_size: 20
daemonize: true

In Nairobi (thin installed as root)

---
chdir: "/home/alfredo/rails_apps/shk/current"
environment: production
address: 0.0.0.0
port: 3010
timeout: 30
log: "/home/alfredo/rails_apps/log/thin.log"
pid: "tmp/pids/thin.pid"
rackup: config.ru
max_conns: 1024
max_persistent_conns: 100
require: []
wait: 30
threadpool_size: 20
daemonize: true

If using RVM

rvm wrapper ruby-2.2.0-p0 bootup thin

Edit /etc/init.d/thin

Change DAEMON line by

DAEMON=/usr/local/rvm/bin/bootup_thin

For thin config file in project (same config in all stages)
Create app/config/thin.yml with thin config
Create symlink (app sharingkitchn deployed with capistrano)

ln -s rails_apps/sharingkitchn/current/config/thin.yml /etc/thin/sharingkitchn.yml

Commands:

/etc/init.d/thin start

or

service thin start/stop/restart

How thin start rails app

thin config -C /etc/thin/my-app -c /var/www/my-app/current --servers 1 -e production

Thin commands by instances (applications)

1. Set the content of your /etc/init.d/thin file to use:

#!/bin/sh
### BEGIN INIT INFO
# Provides:          thin
# Required-Start:    $local_fs $remote_fs
# Required-Stop:     $local_fs $remote_fs
# Default-Start:     2 3 4 5
# Default-Stop:      S 0 1 6
# Short-Description: thin initscript
# Description:       thin
### END INIT INFO

# Original author: Forrest Robertson

# Do NOT "set -e"

DAEMON=/usr/local/bin/thin
SCRIPT_NAME=/etc/init.d/thin
CONFIG_PATH=/etc/thin

# Exit if the package is not installed
[ -x "$DAEMON" ] || exit 0

if [ "X$2" = X ] || [ "X$3" = X ]; then
    INSTANCES="--all $CONFIG_PATH"
else
    INSTANCES="-C $3"
fi

case "$1" in
  start)
  $DAEMON start $INSTANCES 
  ;;
  stop)
  $DAEMON stop $INSTANCES
  ;;
  restart)
  $DAEMON restart $INSTANCES
  ;;
  *)
  echo "Usage: $SCRIPT_NAME {start|stop|restart} (-C config_file.yml)" >&2
  exit 3
  ;;
esac

:

Use thin restart -C /etc/thin/my_website.yml.

Use thin restart (or start or stop, of course) for all instances.

nginx config

/etc/nginx/nginx.conf – main lines (see nairobi)

user webs;
...
    server {
        client_max_body_size 20M;
        client_body_temp_path /home/alfredo/rails_apps/uploads_temp;
        listen  80;
        server_name  beta.sharingkitchn.com *.beta.sharingkitchn.com;
        root         /home/alfredo/webs/sharingkitchn.com/;

        location / {
                proxy_pass_header Server;
                proxy_temp_path /tmp/nginx 1 2;

                proxy_set_header  X-Real-IP  $remote_addr;
                proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header Host $http_host;
                proxy_redirect off;
                proxy_pass http://localhost:3010;
                break;
                }
        }

nginx restart

service nginx restart

nginx start/stop

http://wiki.nginx.org/CommandLine

for starting nginx:

  /usr/bin/nginx

for stoping nginx:

  /usr/bin/nginx -s stop

nginx reload if changes nginx.conf

service nginx reload

Testing with SAAP project

Bash script: start_saap_server.sh
Run by: . /start_saap_server.sh

#!/bin/bash
. saap_production_vars.sh
cd ~/projects/saap
rvm gemset use saap
thin -C thin.yml start

Thin commands: restart stop start

thin -C thin.yml restart

Ruby script: thin.yml
Command line to create: thin config -R config.ru -e production -s 1 -O -d -C thin.yml
See doc for more options: https://github.com/macournoyer/thin/

---
chdir: "/home/alfredo/projects/saap"
environment: production
address: 0.0.0.0
port: 3000
timeout: 30
log: log/thin.log
pid: tmp/pids/thin.pid
max_conns: 1024
max_persistent_conns: 100
require: []
wait: 30
threadpool_size: 20
rackup: config.ru
servers: 1
onebyone: true
daemonize: true

Deploying Rails app using Nginx, Puma and Capistrano 3

Setting up Nginx with Rails

STAGING server

views in beta

You want to have a new view path in your application. You can create a “app/views/beta” directory, and put your views as if you were in “app/views”.

In your ApplicationController, in a before_filter, have your logic do a prepend_view_path “app/views/beta”. Something like:

before_filter :setup_beta
def setup_beta
  if request.subdomain == "beta"
    prepend_view_path "app/views/beta"
    # other beta setup
  end
end

This way, templates are resolved in “app/views/beta” first, and then, if not found, in “app/views”. Note that, you only have to put in “app/views/beta” the views that differ from those in “app/views”.