Eric Guo's blog.cloud-mes.com

Hoping writing JS, Ruby & Rails and Go article, but fallback to DevOps note

Deploy High-Five Rails App on Rocky Linux 9 Using Capistrano

Permalink

Setup high_five user account

adduser high_five
gpasswd -a high_five wheel
cd /etc/sudoers.d
# you can later change more limit like "high_five ALL=(ALL) NOPASSWD:/usr/bin/systemctl"
echo "high_five ALL=(ALL) NOPASSWD:ALL" > 95-high_five-user
sudo su - high_five
mkdir .ssh
chmod 700 .ssh
vi .ssh/authorized_keys
chmod 600 .ssh/authorized_keys

Install ruby dep

sudo dnf -y install git make gcc curl openssl-devel zlib-devel libffi-devel readline-devel sqlite-devel postgresql-devel
sudo dnf --enablerepo=crb -y install libyaml-devel gdbm-devel
sudo yum -y install gcc-c++ # required by grpc
sudo yum -y install rust # if need YJIT
sudo yum -y install git-lfs # if any repository using LFS to store picture

Install rbenv and ruby-build

cd # as a high_five
git clone https://git.thape.com.cn/rails/rbenv.git .rbenv
echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile
~/.rbenv/bin/rbenv init # also edit ~/.bash_profile
# As an rbenv plugin
mkdir -p "$(rbenv root)"/plugins
git clone https://git.thape.com.cn/rails/ruby-build.git "$(rbenv root)"/plugins/ruby-build
git clone https://git.thape.com.cn/rails/rbenv-china-mirror.git "$(rbenv root)"/plugins/rbenv-china-mirror

Install Ruby 3.3.5

rbenv install -l
rbenv install 3.3.5
rbenv global 3.3.5
rbenv shell 3.3.5
echo "gem: --no-document" > ~/.gemrc
gem update --system

Create deploy folder

cd /var/www
sudo mkdir high_five
sudo chown high_five:high_five high_five/

Create DB user and DB

sudo su - postgres
createuser high_five
psql
ALTER ROLE high_five LOGIN;
ALTER USER high_five PASSWORD '';
CREATE DATABASE high_five_prod WITH ENCODING='UTF8' OWNER=high_five;
logout
vi /var/lib/pgsql/16/data/pg_hba.conf
# TYPE DATABASE USER ADDRESS METHOD
host high_five_prod high_five 0.0.0.0/0 scram-sha-256

Reload conf without restart DB

sudo su - postgres
/usr/pgsql-16/bin/pg_ctl reload

The extra file for capistrano

puma

The puma file which will lauch puma via system service.

/var/www/high_five/shared/puma.rb
#!/usr/bin/env puma
directory '/var/www/high_five/current'
rackup "/var/www/high_five/current/config.ru"
environment 'production'
tag ''
pidfile "/var/www/high_five/shared/tmp/pids/puma.pid"
state_path "/var/www/high_five/shared/tmp/pids/puma.state"
stdout_redirect '/var/www/high_five/shared/log/puma_access.log', '/var/www/high_five/shared/log/puma_error.log', true
threads 0,16
bind 'unix:///var/www/high_five/shared/tmp/sockets/puma.sock'
workers 0
restart_command 'bundle exec puma'
prune_bundler
on_restart do
puts 'Refreshing Gemfile'
ENV["BUNDLE_GEMFILE"] = ""
end

systemd service file

/etc/systemd/system/puma_high_five.service
# This file tells systemd how to run Puma as a 24/7 long-running daemon.
#
# Customize this file based on your bundler location, app directory, etc.
# Customize and copy this into /usr/lib/systemd/system (CentOS) or /lib/systemd/system (Ubuntu).
# Then run:
# - systemctl enable puma_high_five
# - systemctl {start,stop,restart} puma_high_five
#
#
# Use `journalctl -u puma_high_five -rn 100` to view the last 100 lines of log output.
#
[Unit]
Description=Puma HTTP Server for high_five (production)
After=syslog.target network.target
[Service]
Type=simple
WatchdogSec=10
User=high_five
WorkingDirectory=/var/www/high_five/current
ExecStart=/home/high_five/.rbenv/bin/rbenv exec bundle exec --keep-file-descriptors puma -C /var/www/high_five/shared/puma.rb
ExecReload=/bin/kill -USR1 $MAINPID
# if we crash, restart
RestartSec=1
Restart=on-failure
StandardOutput=append:/var/www/high_five/shared/log/puma.log
StandardError=append:/var/www/high_five/shared/log/puma.log
SyslogIdentifier=puma_high_five
[Install]
WantedBy=multi-user.target

nginx conf files

/etc/nginx/conf.d/high_five.conf
upstream puma_high_five_production {
server unix:/var/www/high_five/shared/tmp/sockets/puma.sock fail_timeout=0;
}
server {
if ($host = high-five.thape.com.cn) {
return 301 https://$host$request_uri;
}
listen 80;
server_name high-five.thape.com.cn;
return 301 https://$host$1$request_uri;
}
server {
listen 443 ssl http2;
ssl_certificate /etc/ssl/cert/STAR_thape_com_cn_integrated.crt;
ssl_certificate_key /etc/ssl/private/STAR_thape_com_cn.key;
server_name high-five.thape.com.cn;
root /var/www/high_five/current/public;
try_files $uri/index.html $uri @puma_high_five_production;
client_max_body_size 4G;
keepalive_timeout 10;
error_page 500 502 504 /500.html;
error_page 503 @503;
location @puma_high_five_production {
proxy_http_version 1.1;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $host;
proxy_redirect off;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header X-Forwarded-Proto https;
proxy_pass http://puma_high_five_production;
# limit_req zone=one;
access_log /var/www/high_five/shared/log/nginx.access.log;
error_log /var/www/high_five/shared/log/nginx.error.log;
}
location ~ (/manifest.json|/favicon.ico|/*.txt|/*.png) {
access_log off;
expires 3d;
gzip_static on;
add_header Cache-Control public;
}
location ^~ /assets/ {
gzip_static on;
expires max;
add_header Cache-Control public;
}
location = /50x.html {
root html;
}
location = /404.html {
root html;
}
location @503 {
error_page 405 = /system/maintenance.html;
if (-f $document_root/system/maintenance.html) {
rewrite ^(.*)$ /system/maintenance.html break;
}
rewrite ^(.*)$ /503.html break;
}
if ($request_method !~ ^(GET|HEAD|PUT|PATCH|POST|DELETE|OPTIONS)$ ){
return 405;
}
if (-f $document_root/system/maintenance.html) {
return 503;
}
}

Comments