The purpose of this article is to describe in detail the organization of the server for Rails applications in the currently most popular bundle: rvm + Rails + Nginx + Unicorn. The writing of the article was prompted by the absence of complete step-by-step documentation on this bundle, which is understandable not only to the vigorous professionals in this field. Next, I will try in detail, step by step, to describe the ideologically correct process of organizing a server for servicing several Rails applications (using one example) - if you have absolute confidence that more than one application will never work on a test machine - the setting may Much shorter and simpler. I want to warn you that the subtleties concerning the work of the application under high load are not described in the article, since the goal was different - to make the application work in a bundle and reduce the number of conflicts with other applications to a minimum.ssh-copy-id vasya@rails-production.example.com where vasya is the name of the user on the server, on behalf of which the rights will be implemented by the deploy, and rails-production.example.com is the address or name of the server you just raised. After entering, it will be necessary to agree to add a host to the list of known hosts on your machine - that's okay - this is normal. And enter Vasin password. This will be the last time you will enter Vasily's password. Now access to the server is possible using the ssh key and nothing needs to be entered. sudo apt-get install mysql-server mysql-client libmysqld-dev # MySQL sudo apt-get install postgresql postgresql-client postgresql-server-dev #Postgresql Setting up a database on a server is the topic of a separate article, so suppose that you can handle it yourself. Therefore - tadaaam! DBMS is up and running. sudo apt-get install git-core curl # , Rvm. curl -L https://get.rvm.io | bash -s stable --ruby type rvm | head -1 The last command should issue "rvm is a function" or equivalent in Russian. If this does not happen, it is worthwhile to start studying from here until the moment - “until it works”. sudo apt-get install build-essential bison openssl libreadline6 libreadline6-dev curl git-core zlib1g zlib1g-dev libssl-dev libyaml-dev libsqlite3-0 libsqlite3-dev sqlite3 libxml2-dev libxslt-dev autoconf libc6-dev ncurses-dev rvm install ree-1.8.7-2011.03 # ree rvm ree # , Ruby . - : rvm ree@myapp --create. Bundler . gem install bundler # gem, . sudo mkdir -p /srv/myapp # , . sudo chown -R vasya:vasya /srv/myapp # ( , -R ). #! /bin/sh EXEC_PATH="/usr/local/nginx/sbin/nginx" case "$1" in start) echo "Starting NginX" start-stop-daemon --start --exec $EXEC_PATH ;; stop) echo "Stopping NginX" start-stop-daemon --stop --exec $EXEC_PATH ;; restart) echo "Stopping NginX" start-stop-daemon --stop --exec $EXEC_PATH sleep 1 echo "Starting NginX" start-stop-daemon --start --exec $EXEC_PATH ;; *) echo "Usage: {start|stop|restart}" exit 1 ;; esac exit 0 worker_processes 1; # . user vasya vasya; # worker - , . pid /tmp/nginx.pid; # - Nginx. error_log /tmp/nginx.error.log; events { worker_connections 1024; # . accept_mutex off; # - . } http { # - - - : include mime.types; default_type application/octet-stream; access_log /tmp/nginx.access.log combined; sendfile on; tcp_nopush on; tcp_nodelay off; gzip on; # . upstream . , . upstream myapp_server { server unix:/srv/myapp/shared/unicorn.sock fail_timeout=0; # config/unicorn.rb . } server { listen 80 default deferred; # , ip , - myapp.mydomain.ru:80 client_max_body_size 1G; # ( - ). server_name myapp.mydomain.ru; # keepalive_timeout 5; root /srv/myapp/current/public; # public Rails . current Capistrano try_files $uri/index.html $uri.html $uri @myapp; # - , location location @myapp { proxy_pass http://myapp_server; # http:// upstream . proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_redirect off; } error_page 500 502 503 504 /500.html; location = /500.html { root /srv/myapp/current/public; } } } server { ... } blocks should be placed in separate files in the /usr/local/nginx/conf/vhosts and in nginx.conf write include /usr/local/nginx/conf/vhosts/* - in the example of this is not done for clarity. gem 'unicorn' and run Unicorn with the bundle exec command. By the way, the recommendation applies not only to Unicorn, but also to any executable files that come with gems. Installing Unicorn within a specific application will allow you to have as many applications as you need on one machine. deploy_to = "/srv/myapp" rails_root = "#{deploy_to}/current" pid_file = "#{deploy_to}/shared/pids/unicorn.pid" socket_file= "#{deploy_to}/shared/unicorn.sock" log_file = "#{rails_root}/log/unicorn.log" err_log = "#{rails_root}/log/unicorn_error.log" old_pid = pid_file + '.oldbin' timeout 30 worker_processes 4 # , listen socket_file, :backlog => 1024 pid pid_file stderr_path err_log stdout_path log_file preload_app true # , , . GC.copy_on_write_friendly = true if GC.respond_to?(:copy_on_write_friendly=) # , , . before_exec do |server| ENV["BUNDLE_GEMFILE"] = "#{rails_root}/Gemfile" end before_fork do |server, worker| # , , . defined?(ActiveRecord::Base) and ActiveRecord::Base.connection.disconnect! # , 0 downtime deploy. if File.exists?(old_pid) && server.pid != old_pid begin Process.kill("QUIT", 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?(ActiveRecord::Base) and ActiveRecord::Base.establish_connection end group :development do gem "capistrano" gem "rvm-capistrano" end After installing the gem, execute the command: bundle exec capify . and we get an almost empty config / deploy.rb file. I will give an example of a file for our needs: require 'rvm/capistrano' # rvm require 'bundler/capistrano' # bundler. bundler , . set :application, "myapp" set :rails_env, "production" set :domain, "vasya@rails-production.example.com" # ssh. , . set :deploy_to, "/srv/#{application}" set :use_sudo, false set :unicorn_conf, "#{deploy_to}/current/config/unicorn.rb" set :unicorn_pid, "#{deploy_to}/shared/pids/unicorn.pid" set :rvm_ruby_string, 'ree' # , Ruby . set :scm, :git # git. , , - - svn, , git - git. set :repository, "git@github.com:myprojects/myapp.git" # . , , , rsa deployment keys . set :branch, "master" # . set :deploy_via, :remote_cache # , . . role :web, domain role :app, domain role :db, domain, :primary => true before 'deploy:setup', 'rvm:install_rvm', 'rvm:install_ruby' # rvm capistrano , cap deploy:setup rvm_ruby_string . after 'deploy:update_code', :roles => :app do # - database.yml. /srv/myapp/shared/config . . run "rm -f #{current_release}/config/database.yml" run "ln -s #{deploy_to}/shared/config/database.yml #{current_release}/config/database.yml" end # unicorn. - . # Rails 3 bundle exec unicorn_rails bundle exec unicorn namespace :deploy do task :restart do run "if [ -f #{unicorn_pid} ] && [ -e /proc/$(cat #{unicorn_pid}) ]; then kill -USR2 `cat #{unicorn_pid}`; else cd #{deploy_to}/current && bundle exec unicorn_rails -c #{unicorn_conf} -E #{rails_env} -D; fi" end task :start do run "bundle exec unicorn_rails -c #{unicorn_conf} -E #{rails_env} -D" end task :stop do run "if [ -f #{unicorn_pid} ] && [ -e /proc/$(cat #{unicorn_pid}) ]; then kill -QUIT `cat #{unicorn_pid}`; fi" end end Source: https://habr.com/ru/post/120368/
All Articles