Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save Epictetus/837869cf3d7cbc17e5fee12afdfe968c to your computer and use it in GitHub Desktop.
Save Epictetus/837869cf3d7cbc17e5fee12afdfe968c to your computer and use it in GitHub Desktop.
Deploy Rails to VPS(Ubuntu 20.04LTS). Nginx mainline + pagespeed, Puma with Jungle, Capistrano3, PostgreSQL, RVM, Certbot
//------ ROOT --------
root# apt-get update
root# apt-get upgrade
// Dependencies
apt-get install -y git-core curl zlib1g-dev build-essential libssl-dev libreadline-dev libyaml-dev \
libsqlite3-dev sqlite3 libxml2-dev libxslt1-dev libcurl4-openssl-dev software-properties-common libffi-dev \
libpcre3-dev unzip htop zip
// Node.js v14
root# curl -sL https://deb.nodesource.com/setup_14.x | sudo -E bash -
root# apt-get install -y nodejs
// Yarn
root# curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
root# echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
root# sudo apt-get update && sudo apt-get install yarn
// Redis
https://www.digitalocean.com/community/tutorials/how-to-install-and-secure-redis-on-ubuntu-20-04
// DB: Postgresql latest version
https://www.digitalocean.com/community/tutorials/how-to-install-and-use-postgresql-on-ubuntu-20-04
// DB: Postgresql 9.6
root# echo 'deb http://apt.postgresql.org/pub/repos/apt/ xenial-pgdg main' > /etc/apt/sources.list.d/pgdg.list
root# wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add -
root# apt-get update && apt-get install -y postgresql-9.6 libpq-dev
// Mongo
// 3.0
// https://docs.mongodb.com/v3.0/tutorial/install-mongodb-on-ubuntu/
$ sudo vim /etc/systemd/system/mongodb.service // insert seting
Create
$ sudo systemctl start mongodb.service
$ sudo systemctl status mongodb.service
# if all ok
$ sudo systemctl enable mongodb.service
$ sudo reboot
$ sudo systemctl status mongodb.service
# 3.6
https://www.digitalocean.com/community/tutorials/how-to-install-mongodb-on-ubuntu-18-04
// Fix perl: warning: Setting locale failed.
root# echo -e 'LANG="en_US.UTF-8"\nLC_ALL="en_US.UTF-8"\nLANGUAGE="en_US:en"' > /etc/default/locale
// Nginx
root# apt update
root# apt install nginx
// UFW
// https://www.digitalocean.com/community/tutorials/how-to-set-up-a-firewall-with-ufw-on-ubuntu-18-04
root# ufw status
root# ufw enable
root# ufw app list
root# ufw allow 'OpenSSH'
root# ufw allow 'Nginx Full'
root# ufw app list
root# ufw deny 3000
root# ufw status numbered
root# ufw delete NUMBER
// Certbot (install from sites)
-> https://certbot.eff.org
root$ vim /etc/letsencrypt/cli.ini
// ADD LINE
renew-hook = systemctl restart nginx
// Deployer user in sudo group
-> https://www.digitalocean.com/community/tutorials/initial-server-setup-with-ubuntu-20-04
root# adduser deployer
root# gpasswd -aG deployer sudo
// Editor
sudo update-alternatives --config editor
// Сhoose Vim: 3
// Disable ssh root login, permit password login
root# vim /etc/ssh/sshd_config
EDIT:
PermitRootLogin no
PasswordAuthentication yes
SAVE CHANGES
root# service ssh restart
root# exit
# Установка Java с apt в Ubuntu 20.04
https://www.digitalocean.com/community/tutorials/how-to-install-java-with-apt-on-ubuntu-20-04-ru
# Initial Server Setup with Ubuntu 20.04
https://www.digitalocean.com/community/tutorials/initial-server-setup-with-ubuntu-20-04#step-4-%E2%80%94-setting-up-a-basic-firewall
# Установка Jenkins в Ubuntu 20.04
https://www.digitalocean.com/community/tutorials/how-to-install-jenkins-on-ubuntu-20-04-ru
//------ DEPLOYER --------
$ ssh deployer@server
deployer$ mkdir apps & mkdir backup_files
// SSH Generate
deployer$ ssh-keygen -t rsa -b 4096 -C "[email protected]"
deployer$ exit
local$ cat ~/.ssh/id_rsa.pub | ssh deployer@IP_SERVER "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys"
Add Swap Space on Ubuntu
https://www.digitalocean.com/community/tutorials/how-to-add-swap-space-on-ubuntu-20-04
// RVM, Ruby 3.0.1, bundler
deployer$ sudo apt-get install libgdbm-dev libncurses5-dev automake libtool bison libffi-dev libpq-dev build-essential
deployer$ gpg2 --keyserver hkp://pool.sks-keyservers.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB
deployer$ curl -sSL https://get.rvm.io | bash -s stable
deployer$ echo "gem: --no-document" > ~/.gemrc
deployer$ source ~/.rvm/scripts/rvm
deployer$ rvm install 3.0.1 && rvm use 3.0.1 --default
deployer$ gem install bundler
// DotNet
https://dotnet.microsoft.com/download/linux-package-manager/ubuntu18-04/sdk-current
https://docs.microsoft.com/ru-ru/dotnet/core/install/linux-ubuntu
// PM2
// Certbot (Let's Encrypt)
deployer$ sudo certbot --nginx
// For postgresql deployer user, project db
deployer$ sudo su - postgres
postgres$ createuser --pwprompt deployer
postgres$ createdb -O deployer <<APP_DB_NAME>>
postgres$ psql -U postgres -W
postgres$ \list
postgres$ \q
postgres$ exit
// PostgreSQL Remote Connections
https://www.digitalocean.com/community/tutorials/how-to-secure-postgresql-against-automated-attacks
deployer$ sudo ufw allow 5432
deployer$ sudo ufw status
deployer$ sudo vim /etc/postgresql/10/main/pg_hba.conf
host DB_NAME deployer all md5
deployer$ sudo vim /etc/postgresql/10/main/postgresql.conf
listen_addresses = '*'
// testing
psql -U deployer -h IP_SERVER -d DB_NAME
// Install and Configure VNC on Ubuntu 18.04
https://www.digitalocean.com/community/tutorials/how-to-install-and-configure-vnc-on-ubuntu-18-04
deployer$ sudo ufw allow 5901
// Capistrano
#---------------
#---------------
// ADD TO Gemfile:
group :development do
# Gem for deploy
gem 'capistrano', '~> 3.16', require: false
gem 'capistrano-rvm', require: false
gem 'capistrano-nginx', require: false
gem 'capistrano3-puma', require: false
gem 'capistrano-rails', require: false
gem 'capistrano-rails-db', require: false
gem 'capistrano-rails-console', require: false
gem 'capistrano-upload-config', require: false
gem 'sshkit-sudo', require: false
# gem 'capistrano-figaro-yml' require: false
# gem 'capistrano-sidekiq' require: false # For gem sidekiq
end
#---------------
#---------------
// RUN:
your_app$ bundle install
your_app$ cap install
#---------------
#---------------
// EDIT Capfile AS ATTACHED Capfile
require 'capistrano/setup'
require 'capistrano/deploy'
require 'capistrano/scm/git'
install_plugin Capistrano::SCM::Git
require 'capistrano/rails'
require 'capistrano/rails/migrations'
require 'capistrano/rails/db'
require 'capistrano/rails/console'
require 'capistrano/bundler'
require 'capistrano/nginx'
require 'capistrano/rvm'
require 'capistrano/upload-config'
require 'capistrano/puma'
install_plugin Capistrano::Puma
install_plugin Capistrano::Puma::Nginx
install_plugin Capistrano::Puma::Systemd # cap production puma:systemd:config puma:systemd:enable
require 'capistrano/rails/assets'
require 'sshkit/sudo'
# Load custom tasks from `lib/capistrano/tasks` if you have any defined
Dir.glob('lib/capistrano/tasks/*.rake').each { |r| import r }
#---------------
#---------------
#---------------
#---------------
// EDIT config/deploy.rb AS ATTACHED deploy.rb AND CHANGE VARIABLES IN IT
# config valid for current version and patch releases of Capistrano
lock '~> 3.16.0'
set :rvm_ruby_version, '3.0.1'
set :repo_url, '[email protected]:slastion/bbt.git'
set :user, 'deployer'
set :application, 'bbt'
set :environment, 'production'
set :rails_env, 'production'
set :deploy_to, "/home/#{fetch(:user)}/apps/#{fetch(:application)}"
set :pty, false
set :linked_files,
fetch(:linked_files, []).push('config/database.yml', 'config/puma.rb', 'config/master.key',
'config/credentials.yml.enc')
set :linked_dirs,
fetch(:linked_dirs, []).push('log', 'tmp/cache', 'tmp/pids', 'tmp/sockets', 'vendor/bundle', 'public/system',
'public/uploads', 'public/images', 'storage')
set :config_example_suffix, '.example'
set :config_files, %w[config/database.yml]
set :puma_conf, "#{shared_path}/config/puma.rb"
set :puma_systemctl_bin, '/bin/systemctl'
set :puma_service_unit_name, "puma-#{fetch(:application)}"
set :keep_releases, 5
# set :nginx_use_ssl, false
# set :puma_restart_command, 'sudo systemctl restart puma-kozjin.service'
# set :nginx_ssl_certificate, 'my-domain.crt'
# set :nginx_ssl_certificate_path, "#{shared_path}/ssl/certs"
# set :nginx_ssl_certificate_key, 'my-domain.key'
# set :nginx_ssl_certificate_key_path, "#{shared_path}/ssl/private"
# namespace :sidekiq do
# task :quiet do
# on roles(:app) do
# puts capture("pgrep -f 'sidekiq' | xargs kill -TSTP")
# end
# end
# task :restart do
# on roles(:app) do
# execute :sudo, :systemctl, :restart, :sidekiq
# end
# end
# task :status do
# on roles(:app) do
# execute :sudo, :systemctl, :status, :sidekiq
# end
# end
# end
namespace :setup do
desc "setup: copy config/master.key to shared/config"
task :copy_linked_master_key do
on roles(:app) do
sudo :mkdir, "-pv", shared_path
upload! "config/master.key", "#{shared_path}/config/master.key"
sudo :chmod, "600", "#{shared_path}/config/master.key"
upload! "config/credentials.yml.enc", "#{shared_path}/config/credentials.yml.enc"
sudo :chmod, "600", "#{shared_path}/config/credentials.yml.enc "
end
end
end
namespace :deploy do
before 'check:linked_files', 'config:push'
before 'check:linked_files', 'puma:config'
# before 'check:linked_files', 'setup:copy_linked_master_key'
# before 'check:linked_files', 'puma:nginx_config'
after 'puma:restart', 'nginx:restart'
# after 'deploy:starting', 'sidekiq:quiet'
# after 'deploy:reverted', 'sidekiq:restart'
# after 'deploy:published', 'sidekiq:restart'
# after 'deploy:published', 'sidekiq:status'
end
#---------------
#---------------
your_app$ cap production config:init
// EDIT WITH YOUR PARAMETERS:
/config/database.production.yml
/config/secrets.production.yml
// RUN:
your_app$ rails g capistrano:nginx_puma:config
// EDIT OR LEAVE AS IS:
config/deploy/templates/nginx_conf.erb
config/deploy/templates/puma.rb.erb
// update file config/deploy/production.rb
server 'IP', user: fetch(:user).to_s, roles: %w(app db web), primary: true
set :nginx_server_name, 'DOMEN'
set :environment, 'production'
set :rails_env, 'production'
// ADD RUBY-VERSION FILE FOR PUMA JUNGLE:
your_app$ echo 'ruby-3.0.1' > .ruby-version
// GIT COMMIT AND PUSH CHANGES
// RUN:
your_app$ cap production deploy
// RUN:
https://github.com/seuros/capistrano-puma
your_app$ cap production puma:systemd:config puma:systemd:enable
$ vim /etc/systemd/system/puma-NAME-APP
ExecStart=/home/deployer/.rvm/bin/rvm 3.0.1 do bundle exec puma -C /home/deployer/apps/bbt
deployer$ sudo sudo visudo
ALL=NOPASSWD:/bin/systemctl
ALL=NOPASSWD:/usr/sbin/service
CONGRATULATION! ALL DONE!
CHECK YOUR RUNNIG SERVER!
[Unit]
Description=Puma HTTP Server NameProject
After=network.target
[Service]
# Foreground process (do not use --daemon in ExecStart or config.rb)
Type=simple
# Preferably configure a non-privileged user
User=deployer
Group=deployer
# Specify the path to your puma application root
WorkingDirectory=/home/deployer/apps/NameProject/current
# Helpful for debugging socket activation, etc.
Environment=PUMA_DEBUG=1
# The command to start Puma
ExecStart=/home/deployer/.rvm/wrappers/ruby-2.6.3/bundle exec puma -C /home/deployer/apps/NameProject/current/config/puma.rb
ExecStop=/home/deployer/.rvm/wrappers/ruby-2.6.3/bundle exec bundle exec pumactl -F /home/deployer/apps/NameProject/current/config/puma.rb stop
ExecReload=/home/deployer/.rvm/wrappers/ruby-2.6.3/bundle exec bundle exec pumactl -F /home/deployer/apps/NameProject/current/config/puma.rb phased-restart
PIDFile=/home/deployer/apps/NameProject/current/tmp/pids/puma.pid
ExecStop=/bin/kill -s QUIT $MAINPID
Restart=always
[Install]
WantedBy=multi-user.target
sudo systemctl status puma.service
sudo systemctl start puma.service
sudo systemctl status puma.service
sudo systemctl enable puma.service
sudo reboot
sudo systemctl status puma.service
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment