Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save ARozputnii/ed4709786db2d62c04ea1d00bba65f39 to your computer and use it in GitHub Desktop.
Save ARozputnii/ed4709786db2d62c04ea1d00bba65f39 to your computer and use it in GitHub Desktop.
Setup Rails app on Ubuntu 20.04 LTS (DigitalOcean or AWS EC2)
// Basic server setup
1) Connect to your server
your_machine$ ssh root@server_host
2) Update/Upgrade your system packages
root# apt-get update && apt-get upgrade
3) Add swap space
https://www.digitalocean.com/community/tutorials/how-to-add-swap-space-on-ubuntu-20-04-ru
root# fallocate -l 4G /swapfile
root# chmod 600 /swapfile
root# mkswap /swapfile
root# swapon /swapfile
root# swapon --show
root# free -h
root# cp /etc/fstab /etc/fstab.bak
root# echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
4) Install dependencies for Ruby
root# apt install curl
root# curl -sL https://deb.nodesource.com/setup_14.x | sudo -E bash -
root# apt-get install -y nodejs
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# apt-get update && apt-get install yarn
root# apt-get install git-core 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 unzip
5) Postgresql
root# apt update
root# apt install postgresql postgresql-contrib libpq-dev
6) 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
7) Mainline nginx with stable ngx_pagespeed
root# bash <(curl -f -L -sS https://ngxpagespeed.com/install) -y --nginx-version latest -a ' \
--prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib/nginx/modules --conf-path=/etc/nginx/nginx.conf \
--error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid \
--lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp \
--http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp \
--http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx \
--group=nginx --with-compat --with-file-aio --with-threads --with-http_addition_module --with-http_auth_request_module \
--with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module \
--with-http_mp4_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module \
--with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module \
--with-http_v2_module --with-mail --with-mail_ssl_module --with-stream --with-stream_realip_module \
--with-stream_ssl_module --with-stream_ssl_preread_module'
root# adduser --system --no-create-home --shell /bin/false --group --disabled-login nginx
root# wget -O /etc/nginx/nginx.conf https://gist.githubusercontent.com/PavelBezpalov/6525017b7ab61c843264a0b544acfdd6/raw/nginx.conf
root# mkdir /etc/nginx/sites-enabled
root# mkdir /etc/nginx/sites-available
root# mkdir /var/cache/nginx
root# mkdir -p /var/ngx_pagespeed_cache
root# chown nginx:nginx /var/ngx_pagespeed_cache
root# wget -O /etc/init.d/nginx https://gist.githubusercontent.com/PavelBezpalov/6525017b7ab61c843264a0b544acfdd6/raw/nginx
root# chmod +x /etc/init.d/nginx
root# systemctl enable nginx.service
8) Nginx
root# apt update
root# apt install nginx
# choose everywhere -Y-
9) UFW
// https://www.digitalocean.com/community/tutorials/how-to-set-up-a-firewall-with-ufw-on-ubuntu-20-04
root# ufw status
root# ufw enable
root# ufw app list
root# ufw allow 'OpenSSH'
root# ufw allow 'Nginx Full'
root# ufw app list
10) Install Certbot
root# apt-get install software-properties-common
root# apt install certbot python3-certbot-nginx
root# apt-get update
root# apt-get install certbot
root$ nano /etc/letsencrypt/cli.ini
// ADD LINE
renew-hook = systemctl restart nginx
11) Add deployer user in sudo group
root# adduser deployer
root# gpasswd -a deployer sudo
12) Disable ssh root login, permit password login
root# nano /etc/ssh/sshd_config
EDIT:
PermitRootLogin no
PasswordAuthentication yes
SAVE CHANGES
root# service ssh restart
root# exit
13) Add authorized keys
your_machine$ cat ~/.ssh/id_rsa.pub | ssh deployer@IP_SERVER "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys"
your_machine$ ssh deployer@server_host
deployer$ mkdir apps & mkdir backup_files
14) RVM, Ruby 2.7.2, bundler
https://github.com/rvm/ubuntu_rvm
deployer$ sudo apt-get install libgdbm-dev libncurses5-dev automake libtool bison libffi-dev
deployer$ gpg --keyserver hkp://keys.gnupg.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 2.7.2 && rvm use 2.7.2 --default && ruby -v
deployer$ gem install bundler
15) 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
16) 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 nano /etc/postgresql/12/main/pg_hba.conf
host DB_NAME deployer all md5
deployer$ sudo nano /etc/postgresql/12/main/postgresql.conf
listen_addresses = '*'
// testing
deployer$ sudo service postgresql restart
your_machine$ psql -U deployer -h IP_SERVER -d DB_NAME
// Capistrano
17) Capistrano gems
Add to Gemfile:
_________________________
group :development do
gem "capistrano"
gem "capistrano-rvm"
gem "capistrano-rails"
gem "capistrano3-puma", github: "seuros/capistrano-puma"
gem "capistrano-nginx", "~> 1.0"
gem "capistrano-upload-config"
gem "sshkit-sudo"
end
_________________________
RUN:
your_app$ bundle
your_app$ cap install
18) Edit Capfile
_________________________
require 'capistrano/setup'
require 'capistrano/deploy'
require 'capistrano/scm/git'
install_plugin Capistrano::SCM::Git
require 'capistrano/rvm'
require 'capistrano/rails'
require 'capistrano/puma'
install_plugin Capistrano::Puma
install_plugin Capistrano::Puma::Nginx
install_plugin Capistrano::Puma::Jungle
require 'capistrano/nginx'
require 'capistrano/upload-config'
require 'sshkit/sudo'
Dir.glob('lib/capistrano/tasks/*.rake').each { |r| import r }
___________________________________________________________________________
19) Edit config/deploy.rb
EDIT config/deploy.rb AS ATTACHED deploy.rb AND CHANGE VARIABLES IN IT
______________________________________________________________________
lock "~> 3.15.0"
set :repo_url, ""
ask :branch, `git rev-parse --abbrev-ref HEAD`.chomp
set :user, "deployer"
set :rvm_ruby_version, "2.7.2"
set :pty, true
set :linked_files, fetch(:linked_files, []).push("config/database.yml", "config/secrets.yml", "config/master.key", "config/puma.rb")
set :linked_dirs, fetch(:linked_dirs, []).push("log", "tmp/pids", "tmp/cache", "tmp/sockets", "vendor/bundle", "public/system", "public/uploads", "public/images", "storage")
set :config_example_suffix, ".example"
set :config_files, ["config/database.yml", "config/secrets.yml"]
set :nginx_use_ssl, false
namespace :deploy do
before 'check:linked_files', 'set:master_key'
before 'check:linked_files', 'config:push'
before 'check:linked_files', 'puma:jungle:setup'
before 'check:linked_files', 'puma:nginx_config'
end
after "deploy:finished", "nginx:restart"
after "deploy:finished", "puma:start"
_______________________________________
20) Edit config/deploy/production.rb
_________________________________________________
server "server IP", user: "#{fetch(:user)}", roles: %w{app db web}, primary: true
set :application, "app-name"
set :deploy_to, "/home/#{fetch(:user)}/apps/#{fetch(:application)}"
set :environment, "production"
set :rails_env, "production"
set :nginx_server_name, "server IP"
set :puma_conf, "#{shared_path}/config/puma.rb"
__________________________________________________
21) Create rake tasks
loading master_key
your_app$ cd lib/capistrano/tasks
add file set_master_key.rake
____________________________
namespace :set do
task :master_key do
on roles(:app), in: :sequence, wait: 10 do
unless test("[ -f #{shared_path}/config/master.key ]")
upload! 'config/master.key', "#{shared_path}/config/master.key"
end
end
end
end
_________________________________
your_app$ cd lib/capistrano/tasks
add file puma_restart.rake
_________________________________
namespace :puma do
bundle_wrapper_path = "/home/deployer/.rvm/gems/ruby-2.7.2/wrappers/bundle"
desc "Start puma"
task :start do
on roles(:app) do
execute "cd #{release_path} && #{bundle_wrapper_path} exec pumactl -P #{shared_path}/tmp/pids/puma.pid start"
end
end
desc "Stop puma"
task :stop do
on roles(:app) do
execute "cd #{release_path} && #{bundle_wrapper_path} exec pumactl -P #{shared_path}/tmp/pids/puma.pid stop"
end
end
desc "Restart puma"
task :restart do
on roles(:app) do
execute "cd #{release_path} && #{bundle_wrapper_path} exec pumactl -P #{shared_path}/tmp/pids/puma.pid stop"
sudo "service puma restart"
end
end
end
_________________________________
22) Add config files
RUN:
your_app$ cp config/database.yml config/database.yml.example
your_app$ echo 'secret_key_base: <%= Rails.application.credentials.secret_key_base %>' >> config/secrets.yml
your_app$ cp config/secrets.yml config/secrets.yml.example
your_app$ cap production config:init
your_app$ echo '/config/database.yml' >> .gitignore
your_app$ echo '/config/database.production.yml' >> .gitignore
your_app$ echo '/config/secrets.yml' >> .gitignore
your_app$ echo '/config/secrets.production.yml' >> .gitignore
Edit with your parameters
/config/database.production.yml
/config/secrets.production.yml
23) Generate Nginx/puma config:
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
24) Add Ruby-Version file for Puma Jungle
your_app$ echo 'ruby-VERSION' > .ruby-version
25) GIT commit and push changes
26) Deploy
your_app$ cap production deploy
27) Edit deploy.rb
change - after "deploy:finished", "puma:start"
on - after "deploy:finished", "puma:restart"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment