Eric Guo's blog.cloud-mes.com

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

Deploy Rails 7.1 and AnyCable 1.4 With RPC Services in Rocky Linux 9

Permalink

I’m using an brand new Rocky Linux 9 server, to deploy the pgac_demo project.

Install htop and atop

dnf -y install epel-release
dnf makecache
dnf -y install htop

If htop not found

dnf repolist
vi /etc/yum.repos.d/epel.repo # In the [epel] section, change enabled=0 to enabled=1
dnf -y install htop atop

Install nginx and certbot

dnf install nginx
dnf install certbot python3-certbot-nginx

Setup pgac user account

adduser pgac
gpasswd -a pgac wheel
cd /etc/sudoers.d
# you can later change more limit like "pgac ALL=(ALL) NOPASSWD:/usr/bin/systemctl"
echo "pgac ALL=(ALL) NOPASSWD:ALL" > 97-pgac-user
sudo su - pgac
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
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 pgac
git clone https://github.com/rbenv/rbenv .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://github.com/rbenv/ruby-build.git "$(rbenv root)"/plugins/ruby-build
git clone https://github.com/andorchen/rbenv-china-mirror.git "$(rbenv root)"/plugins/rbenv-china-mirror

Install Ruby 3.2.3

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

create deploy folder

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

The extra file for capistrano

The puma file which will lauch puma via system service.

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

The systemd service file.

/etc/systemd/system/puma_pgac.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_pgac
# - systemctl {start,stop,restart} puma_pgac
#
#
# Use `journalctl -u puma_pgac -rn 100` to view the last 100 lines of log output.
#
[Unit]
Description=Puma HTTP Server for pgac (production)
After=syslog.target network.target
[Service]
Type=simple
WatchdogSec=10
User=pgac
Environment=CABLE_URL=wss://pgac.redwoodjs.cn:3334/cable
WorkingDirectory=/var/www/pgac/current
ExecStart=/home/pgac/.rbenv/bin/rbenv exec bundle exec --keep-file-descriptors puma -C /var/www/pgac/shared/puma.rb
ExecReload=/bin/kill -USR1 $MAINPID
# if we crash, restart
RestartSec=10
Restart=on-failure
StandardOutput=append:/var/www/pgac/shared/log/puma.log
StandardError=append:/var/www/pgac/shared/log/puma.log
SyslogIdentifier=puma_pgac
[Install]
WantedBy=multi-user.target

The nginx conf files.

/etc/nginx/conf.d/pgac.conf
upstream puma_pgac_production {
server unix:/var/www/pgac/shared/tmp/sockets/puma.sock fail_timeout=0;
}
server {
if ($host = pgac.redwoodjs.cn) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
server_name pgac.redwoodjs.cn;
return 301 https://$host$1$request_uri;
}
server {
listen 443 ssl http2; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/pgac.redwoodjs.cn/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/pgac.redwoodjs.cn/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
server_name pgac.redwoodjs.cn;
root /var/www/pgac/current/public;
try_files $uri/index.html $uri @puma_pgac_production;
client_max_body_size 4G;
keepalive_timeout 10;
error_page 500 502 504 /500.html;
error_page 503 @503;
location @puma_pgac_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_pgac_production;
# limit_req zone=one;
access_log /var/www/pgac/shared/log/nginx.access.log;
error_log /var/www/pgac/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;
}
}

The systemd files for AnyCable Go/RPC service

Large following the AnyCable deployment document

Using redis as broadcast_adapter

/etc/systemd/system/pgac-anycable-rpc.service
[Unit]
Description=AnyCable gRPC Server for pgac
After=syslog.target network.target
[Service]
Type=simple
Environment=RAILS_ENV=production
Environment=ANYCABLE_REDIS_URL=redis://localhost:6379/5
Environment=ANYCABLE_REDIS_CHANNEL=__anycable__
WorkingDirectory=/var/www/pgac/current
ExecStart=/home/pgac/.rbenv/bin/rbenv exec bundle exec anycable
ExecStop=/bin/kill -TERM $MAINPID
User=pgac
RestartSec=9
Restart=on-failure
[Install]
WantedBy=multi-user.target

The anycable-go can download from release page

/etc/systemd/system/pgac-anycable-go.service
[Unit]
Description=anycable-go for pgac
After=syslog.target network.target
[Service]
Type=simple
Environment=ANYCABLE_HOST=pgac.redwoodjs.cn
Environment=ANYCABLE_PORT=3334
Environment=ANYCABLE_PATH=/cable
Environment=ANYCABLE_REDIS_URL=redis://localhost:6379/5
Environment=ANYCABLE_REDIS_CHANNEL=__anycable__
Environment=ANYCABLE_METRICS_HTTP=/metrics
WorkingDirectory=/var/www/pgac/current
ExecStart=/usr/local/bin/anycable-go --ssl_cert=/etc/letsencrypt/live/pgac.redwoodjs.cn/cert.pem --ssl_key=/etc/letsencrypt/live/pgac.redwoodjs.cn/privkey.pem
ExecStop=/bin/kill -TERM $MAINPID
User=pgac
LimitNOFILE=16384 # increase open files limit (see OS Tuning guide)
Restart=on-failure
[Install]
WantedBy=multi-user.target

You may need to fix access control for user pgac for letsencrypt key files.

Using http as broadcast_adapter

/etc/systemd/system/pgac-anycable-rpc.service
[Unit]
Description=AnyCable gRPC Server for pgac
After=syslog.target network.target
[Service]
Type=simple
Environment=RAILS_ENV=production
WorkingDirectory=/var/www/pgac/current
ExecStart=/home/pgac/.rbenv/bin/rbenv exec bundle exec anycable
ExecStop=/bin/kill -TERM $MAINPID
User=pgac
RestartSec=9
Restart=on-failure
[Install]
WantedBy=multi-user.target
/etc/systemd/system/pgac-anycable-go.service
[Unit]
Description=anycable-go for pgac
After=syslog.target network.target
[Service]
Type=simple
Environment=ANYCABLE_HOST=pgac.redwoodjs.cn
Environment=ANYCABLE_PORT=3334
Environment=ANYCABLE_PATH=/cable
Environment=ANYCABLE_METRICS_HTTP=/metrics
WorkingDirectory=/var/www/pgac/current
ExecStart=/usr/local/bin/anycable-go --ssl_cert=/etc/letsencrypt/live/pgac.redwoodjs.cn/cert.pem --ssl_key=/etc/letsencrypt/live/pgac.redwoodjs.cn/privkey.pem --broadcast_adapter=http --rpc_impl=grpc
ExecStop=/bin/kill -TERM $MAINPID
User=pgac
LimitNOFILE=16384 # increase open files limit (see OS Tuning guide)
Restart=on-failure
[Install]
WantedBy=multi-user.target

Comments