Skip to content

Instantly share code, notes, and snippets.

@VasylShevchenko
Last active September 22, 2023 19:31
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save VasylShevchenko/78137b2dc5f7175fabc2c0c2e4fdb1d7 to your computer and use it in GitHub Desktop.
Save VasylShevchenko/78137b2dc5f7175fabc2c0c2e4fdb1d7 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 "your_email@example.com"
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, 'git@github.com: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
@ARozputnii
Copy link

in // Mainline nginx with stable ngx_pagespeed
if present error

./configure: error: SSL modules require the OpenSSL library.
You can either do not enable the modules, or install the OpenSSL library
into the system, or build the OpenSSL library statically from the source
with nginx by using --with-openssl=<path> option.

need to do
apt install libssl-dev

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment