📜 ⬆️ ⬇️

Depla: Nginx, Puma and Mina

In this small article I would like to show the configuration of Rails - an application running on Nginx with Puma and how this is all deployed using Mina.

We will assume that you have already installed the whole environment on your server, except for the above-mentioned things (I prefer to put ruby ​​through rbenv, therefore the above configs for Mina will be intended for him.)

Mina
Putting Mina is very simple - we put gems and that's it (there is no need to place the installation in the Gemfile):
gem install mina

Then enter the command:
mina init
')
This command will generate a config / deploy.rb file that will contain the minimum required configuration.
Remember that git you need to be configured or (in extreme cases) login and password from the repository can be written directly in the config file Mina, as shown in the example. You must have all the settings that relate to databases. I also want to note that if you have not created any folders / files listed in the config, you need to create them.
Full configuration example:
deploy.rb
require 'mina/bundler' require 'mina/rails' require 'mina/git' require 'mina/rbenv' lock '3.2.1' set :user, 'admin' set :domain, '100.100.100.100' set :identity_file, "#{ENV['HOME']}/.ssh/google" set :deploy_to, '/var/www/admin_app' set :app_path, lambda { "#{deploy_to}/#{current_path}" } set :repository, 'https://admin:admin@github.com/Admin_app.git' set :branch, 'master' set :forward_agent, true set :rbenv_path, '/home/admin/.rbenv/' set :shared_paths, ['config/database.yml', 'log'] task :environment do invoke :'rbenv:load' end task :setup => :environment do queue! %[mkdir -p "#{deploy_to}/#{shared_path}/log"] queue! %[chmod g+rx,u+rwx "#{deploy_to}/#{shared_path}/log"] queue! %[mkdir -p "#{deploy_to}/#{shared_path}/config"] queue! %[chmod g+rx,u+rwx "#{deploy_to}/#{shared_path}/config"] queue! %[touch "#{deploy_to}/#{shared_path}/config/database.yml"] queue %[echo "-----> Be sure to edit '#{deploy_to}/#{shared_path}/config/database.yml'."] end desc "Deploys the current version to the server." task :deploy => :environment do to :before_hook do # Put things to run locally before ssh end deploy do invoke :'git:clone' invoke :'server:stop_server' invoke :'deploy:link_shared_paths' invoke :'bundle:install' invoke :'rails:db_migrate' invoke :'rails:assets_precompile' invoke :'deploy:cleanup' to :launch do queue "mkdir -p #{deploy_to}/#{current_path}/tmp/" queue "touch #{deploy_to}/#{current_path}/tmp/restart.txt" invoke :'server:start_server' end end end namespace :server do desc 'Stop server' task :stop_server do queue 'echo "-----> Stop Server"' queue 'kill -9 $(lsof -i :3000 -t) || true' queue '[ -f /var/www/admin/admin_app.pid ] && rm /var/www/admin/admin_app.pid || echo "File admin_app.pid not exist"' end desc 'Start server' task :start_server do queue 'echo "-----> Start Server"' queue! 'rails s -b 0.0.0.0 -e production -P /var/www/admin/admin_app.pid -d &' end end 


After you have verified that your deploy.rb file looks like the truth and seems to work, you need to enter the command:
mina setup

This command will create the necessary infrastructure of folders inside the root folder for your application (in the config it is / var / www / admin_app).
Make sure the database.yml file contains the information and it is correct. The file is in / var / www / myapp / shared / config.
Next, enter:
mina deploy

If this operation was successful, your application will wait for you along the path: / var / www / admin_app.

You can easily expand your deployment by writing tasks to deploy.rb and calling them inside: deploy =>: environment.
For example, we will write two tasks for starting and stopping resque - workers.
Task'i for resque
 desc 'Start resque-workers' task :start_workers do queue 'echo "-----> Start resque-workers"' queue "cd #{app_path} && RAILS_ENV=#{stage} && touch resque.pid" queue "cd #{app_path} && bundle exec rake resque:work QUEUE=contacts_adder BACKGROUND=yes TERM_CHILD=1" queue "cd #{app_path} && bundle exec rake resque:work QUEUE=photo_downloader BACKGROUND=yes TERM_CHILD=1" #      queue 'echo "-----> Start resque-scheduler"' queue "cd #{app_path} && rake resque:scheduler BACKGROUND=yes VERBOSE=yes RAILS_ENV=production " end desc 'Stop resque-workers' task :stop_workers do queue 'echo "-----> Stop resque-workers"' queue 'kill -9 `ps aux | grep [r]esque | grep -v grep | cut -c 10-16` || true' end 


You can view the list of available tasks using the command:
mina tasks

Puma
To configure Puma, you will need two files: the configuration file puma.rb and the shell - a script intended for starting / stopping / restarting Puma.

Create a file puma.rb in config /. And fill it with the following information:
puma.rb
 #!/usr/bin/env puma environment ENV['RAILS_ENV'] || 'production' pidfile "/var/www/admin/current/shared/tmp/pids/puma.pid" stdout_redirect "/var/www/admin/current/shared/tmp/log/stdout", "/var/www/admin/current/shared/tmp/log/stderr" threads 2, 16 workers 2 bind "unix:///var/www/admin/current/shared/tmp/sockets/puma.sock" daemonize true 


Carefully check the path when filling configs!

Create a file bin / puma.sh. Fill it in:
puma.sh
 #! /bin/sh PUMA_CONFIG_FILE=/var/www/admin/current/config/puma.rb PUMA_PID_FILE=/var/www/admin/current/shared/tmp/pids/puma.pid PUMA_SOCKET=/var/www/admin/current/shared/tmp/sockets/puma.sock # check if puma process is running puma_is_running() { if [ -e $PUMA_SOCKET ] ; then if [ -r $PUMA_PID_FILE ] ; then if ps -p `cat $PUMA_PID_FILE` > /dev/null; then return 0 else echo "No puma process found" fi else echo "No puma pid file found" fi else echo "No puma socket found" fi return 1 } case "$1" in start) echo "Starting puma..." if [ -e $PUMA_SOCKET ] ; then # if socket exists rm -f $PUMA_SOCKET echo "removed $PUMA_SOCKET" fi if [ -e $PUMA_CONFIG_FILE ] ; then echo "config" bundle exec puma -C $PUMA_CONFIG_FILE else echo "socket" bundle exec puma --daemon --bind unix://$PUMA_SOCKET --pidfile $PUMA_PID_FILE fi echo "done" ;; stop) echo "Stopping puma..." kill -s SIGTERM `cat $PUMA_PID_FILE` rm -f $PUMA_PID_FILE rm -f $PUMA_SOCKET echo "done" ;; restart) if puma_is_running ; then echo "Hot-restarting puma..." kill -s SIGUSR2 `cat $PUMA_PID_FILE` echo "Doublechecking the process restart..." sleep 5 if puma_is_running ; then echo "done" exit 0 else echo "Puma restart failed :/" exit 1 fi fi echo "Trying cold reboot" bin/puma.sh start ;; *) echo "Usage: script/puma.sh {start|stop|restart}" >&2 ;; esac 


Now we add the Puma settings to the deploy.rb file:
Task for puma
 namespace :puma do desc 'Start the application' task :start do queue 'echo "-----> Start Puma"' queue "cd #{app_path} && RAILS_ENV=#{stage} && bin/puma.sh start" , :pty => false end desc 'Stop the application' task :stop do queue 'echo "-----> Stop Puma"' queue "cd #{app_path} && RAILS_ENV=#{stage} && bin/puma.sh stop" end desc 'Restart the application' task :restart do queue 'echo "-----> Restart Puma"' queue "cd #{app_path} && RAILS_ENV=#{stage} && bin/puma.sh restart" end end 


Inside the block “to: launch do” (before starting the server) we write:
 invoke :'puma:restart' 

Remember to make the puma.sh file executable:
chmod + x bin / puma.sh

And re-produce warmly:
mina deploy

Nginx
Nginx can be installed directly from the package manager:
sudo apt-get install nginx

After nginx is installed, you need to remove the default site.
sudo rm /etc/nginx/conf.d/sites-enabled/default

Create the /etc/nginx/sites-available/my_app.conf file:
Nginx config
 upstream my_app { server unix:///var/www/admin/current/shared/tmp/sockets/puma.sock; } server { listen 80; server_name 100.100.100.100; # change to match your URL root /var/www/admin/current/public; location / { root /var/www/admin/current/public; try_files $uri @app; gzip_static on; expires max; proxy_read_timeout 150; add_header Cache-Control public; } location @app { proxy_pass http://my_app; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto http; proxy_set_header Host $http_host; proxy_redirect off; proxy_next_upstream error timeout invalid_header http_502; } 


If you suddenly have any problems, you can try to register these lines directly in the /etc/nginx/nginx.conf file. Server information (server {}) must be located inside the http (http {}) block.

Then create a link:
sudo ln -sf /etc/nginx/sites-available/my_app.conf /etc/nginx/sites-enabled/my_app.conf

And we will restart nginx'a:
sudo service nginx restart

That's all. Enjoyable :)

Source: https://habr.com/ru/post/265459/


All Articles