Eric Guo's blog.cloud-mes.com

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

How to Start Learning Ruby on Rails Chinese 2024 Edition

Permalink

作者背景

任何一门劝人入坑的文章大家都要注意背景,比如有些 Google 的雇员,因为要推广 Flutter,会把 Flutter 的能力写的花好稻好,然后最近直接团队被裁员,只留下误导新人的一篇篇文章,当然,我也得承认我写的这篇肯定也存在误导,但是我可以发自内心的表示,我至少绝对不是有意为之,我书写本文的目的因为我本身比较喜欢 Ruby 的自由,还有 Rails 的高开发效率。另外从 2012 年全面转向使用 Ruby on Rails 编程以来,它也给了我一份相对不错的工作。

TLDR

  • 若您认为计算机语言书写的代码必须带有类型标记,那么本文不适合您,如果您不知道前面一句话啥意思,可以继续阅读;
  • 若您认为前后端使用同一种语言可以少学一门语言,并且团队内更容易协作或者相互替换,那么本文不适合您,我推荐 Next.js,请注意,它背后的母公司 Vercel 以卖 deploy/host 为主业,所以以后的应用发布要达到完美状态,您需要在 Deploy 上付出比学习 Rails 更多的努力,另外您需要书写的代码量也会稍微偏多至少 2~3 倍。
  • 若您现在急需转码,找工作,那么我推荐 Python,Python 在数据处理/AI 上的工作岗位比 Ruby 要多很多,是您更好的选择,另外友情提示不要学 Java,这个赛道人数已经卷爆了。
  • 若您比较注重程序写好后的运行效率(Web 服务需要单机 200 request/s 以上,约等于一个细分赛道的 SaaS 软件提供商所需的正常 Web 请求处理能力的 10 倍左右),那么我推荐 Go,Go 配合 Next.js 是很好的前后端选择。

正文开始

环境准备

有钱上 Mac,直接 brew install ruby,然后安装 rails,没钱用 Ubuntu 的 omakub,当然我也知道用 Linux 的用户绝对不会按照我推荐的 omakub,尽量不要在 windows 上搞 Rails,不是不行,坑太多,实在要搞,用 WSL 和直接用 ubuntu 类似。

快速入门

此快速入门不会导致后期的练功反噬,请放心学习。

请直接阅读官方的guide 最新版本开始,中文的手册版本到 Rails 5.1,还是推荐英语。

官方手册是最快速最正统的导览,后端的功能基本上都提到了,原先可能还需要阅读一下《The Rails Way》,目前是第七版,不过这个是可选。

快速入门阶段最好不要过于扣细节,比如belongs_tohas_many是从哪里来的,是方法的话,在哪里定义的之类的框架细节,尽量将 Rails 作为一种 web 应用的定义语言(只是它恰好可以让计算机运行和发布成 web 应用)使用。

官方 Guide 没有提及任何的自动测试内容,这是对的,但是若您接下来就要接手或者开始维护,开发一个真实的 Rails 应用,《Rails Tutorial 6th 6.1.3.p1 中文版本》推荐一读,因为真实的应用多多少少都有一些 TDD 的内容,不过这只是可选。

另外的一个选择是《Agile Web Development with Rails 7.2》,也是半官方的教材,内容更加深入一些,已经不单单是一个入门教材了。

深入 Ruby

当没有完成 Guide 的整个流程前,请不要深入 Ruby 学习,因为这样会不必要的减少您学习 Rails 的时间。

当您开始对诸如1.day.ago之类的 Rails 调用感到惊奇时,您可以考虑学习一点 Ruby 语言的知识,注意 Ruby 语言语法比 JavaScript 还要复杂,所以不要过于钻牛角尖,《Ruby 基础教程》第四版就是很好的入门。

权威性的 Ruby 教材是《Programming Ruby 3.3 5th》,只有英语版本。

入门后的前端选择

不必深入 Ruby 也可以进行以下任意方向的学习

Rails 主要是一门后端框架,核心是 Active Record,还有一些 MVC 架构的约定,入门的定义是对这些已经掌握了,但是 Rails 毕竟是一种全栈的 Web 开发框架,相比后端,在前端的选择是非常非常多的。

抛去目前被废弃的 rails-ujs,Rails 出场自带的前端框架是 turbo / stimulus,若您没有任何的前端经验,推荐学习这套。

Rails 也同时支持Webpack 集成(顺带也支持了 React/Selte/Angular),Rails 也有Vite/Vue.js的支持。

若您有传统的 JSP/ASP.net MVC 程序员背景,更喜欢比较成熟的框架,Bootstrap 的支持也有现成模版,注意这个模版是笔者维护,并且使用了 coreui.io 的扩展,若您喜欢纯官方的,也可以自行封装。

《Modern Front End Development for Rails 2nd》也有助于对整个 Rails 前端生态有更多了解,但是这已经不是入门内容了。

入门后的 API 支持

Rails 支持 Restful 类型的 API,OpenAPI 3.0 规范 或者 GraphQL。

入门后若要进行 API 书写,推荐直接使用官方的 jbuilder 即可,OpenAPI 3.0 需要学习 grape,GraphQL 需要学习 gem graphql。

入门后的部署选择

传统的 VPS 笔者还是推荐 capistrano,若您对 docker 有偏好,可以使用 kamal 2

进阶

Active Cable 基于实时双向的交互值得学习,想更深入也可以看一下 AnyCable,Bug 较多,但是性能更好。《Advanced CableReady》一书可以阅读

一些高阶的 Postgresql 数据库的特性也值得学习,Active Record 虽然非常强了,但是直接裸写 SQL 有时候更加方便。《High performance Postgresql for Rails》推荐。《Pganalyze Efficient Search in Rails with Postgres》也可以阅读。

代码风格

《Ruby Science》by thoughtbot 可以阅读,不过我还是劝您不要花时间在这里,ruby 是很自由的语言,搞一下 standard 的代码风格检查已经做的有点过了。

Review the Book: Improving Performance: How to Manage the White Space on the Organization Chart

Permalink

今年的公司读书会的第二本书,我是从头翻到尾的读了一遍了,读完才发现被骗了,这书的中文标题就是错的:“流程圣经:让流程自动管理绩效”,我是读到最后一页才意识到被骗了,因为最后一个章节是“译后记”,译者总算在最后良心发现,提了一嘴我一直没主要到的细节,这书的英语名字是“Improving Performance: How to manage the white space on the organization chart”,这书出版于 2014 年,那时候还没 AI 和 GPT,不过我似乎已经找到了 2024 年的 AI/GPT 弱智根源,看着这英语书名,能翻译成“流程圣经:让流程自动管理绩效”,怎么说呢,完全突破了我的想象力,让我大受震撼!

本来我打算看完一遍就开始写书评了,但是看到最后一页这个英语书名和中文书名,让我有了很大的去读原文的冲动,毕竟,如果全书的翻译水准和书名的翻译一样水准的话,我就算再看一遍这本中文版的流程圣经,又有何意义呢?等等,圣经!译者想暗示这英语版就是骗人的吗?我不禁又一次陷入了沉思…

但我手头也没有英文版,但是我只能小心翼翼的,仔细读了译后记,果然发现了更多的问题,这书号称从 250 个成功实施的项目中总结而来,历经惠普,3M,壳牌石油和花旗银行等一众 500 强企业,具有实操性,所以,这就是这 10 年来,惠普蟑螂门,3M 沦落到 PDD 卖胶水,花旗银行,我一个好友供职的公司对华银行业务全关的真相?译后记还提到了“最系统,最科学,最完整”的流程方法论,嗯,可能 2014 年新的广告法还没有实施?译者知道这样写最,最,最,现在连拼多多的垃圾货也不会用这样的广告词啊!

吐槽结束,让我们在仔细看看这本书,第一章作者提出了一个很好的问题,就是直接画出类似苹果的组织图的企业是危险的,因为没有显示企业为客户提供价值的流程,从研发到生产到销售的过程。

嗯,我们姑且不论苹果是不是近年来最成功的公司,先看一下作者提到的几个核心主流程(第 50 页,流程层绩效):

  1. 业务开发
  2. 生产服务开发与推广
  3. 生产制造
  4. 分销
  5. 收帐
  6. 订单执行客服
  7. 保修管理

坦白说,我认为,无论你如何设计流程,前面 5 个主流程都是困难的,而且是各个企业不同的,甚至这根本不是流程的问题。

我疑惑了,我又一次读了“译者导读”:“这套方法论能切切实实的为为数众多的中国企业带来绩效回报,尤其在劳动力缺乏,劳动力成本升高的今天,对企业压缩成本,提升效率,改进绩效的实践活动有着立竿见影的帮助”,我悟了,这书的前提有问题,错把结果当原因,绩效只是一个系统运行后的评价结果指标,流程是不可能自动管理绩效的,最多最多就是节省点思考时间,节省点人力,节省人力是有用的,节省思考时间是危险的,不可能把业务开发这样的高难度高灵活性高优先级的活动流程化,还是要靠人,最多最多,企业的这样的流程不造成阻碍作用,能帮助业务开发人员节省点时间就上上大吉了。

我其实重点是想做绩效,这个的确是流程的衍生,因为绩效总是想做的更客观一些,尽量排除主观的因素,读了第12章,绩效测评与管理体系设计,第250页,写到:“展示了绩效管理的3大构件,以岗位层为例:步骤1,为每个岗位设定产出和绩效期望值(目标设定)。”,是的直接跳到了步骤二,我不知道其他读者看了啥心情,我又仔细翻了前后,这本书最大的问题是在不该省略的地方惜字如金,在可以省略的地方给你大段的表格和流程图。本质上,我觉得这个书可能更接近于一本随着作者给美国企业培训流程设计,发给学员的教科书,还是2000年教改以后减负的版本。

我又稍微看了一下这本书的续篇,《流程圣经》的续篇:流程绩效实战,英语title是:“Serious Performance Consulting: According to Rummler”(Rummler是这两本书作者),我觉得这本就写的比较好,因为它提出了绩效设计的垂直职位的绩效矛盾和水平协作问题,而且表格也终于少下来了。图还是一样多。

总的来看,流程和绩效系统想设计的好,绩效的指标,期望值,或者说目标设定,还有指标之间的比例真的是艺术,缺了哪点都不行,而且似乎永远你能看到矛盾点,比如强调成单率比如影响回款率,因为销售倾向于无论啥单子都做,最后往往回不了款。

无论如何有书总比没书好,设计系统的时候有个checklist也好,不过我觉得我们设计现在的绩效系统,或者其他的,往往都是陷入于细节中,总体设计的时间,已经不能说是偏少的,简直就是没有…

Deploy Rails 7.0 in a New Aliyun Ubuntu 22.04 Server

Permalink

Another brand new Ubuntu 22.04 server and another installation log.

Install as root

Install htop and atop

apt-get install htop atop

Install nginx

apt-get install nginx
nginx -v # here is nginx 1.18.0

Install node.js v20

Using nodesource distribution

apt-get install -y curl
curl -fsSL https://deb.nodesource.com/setup_20.x -o nodesource_setup.sh
apt-get install -y nodejs
nodejs --version # here is nodejs v20.16.0

Install Rust

apt install rustc
rustc --version # here is rustc 1.75.0

Install Yarn

curl -sL https://dl.yarnpkg.com/debian/pubkey.gpg | gpg --dearmor | sudo tee /usr/share/keyrings/yarnkey.gpg >/dev/null
echo "deb [signed-by=/usr/share/keyrings/yarnkey.gpg] https://dl.yarnpkg.com/debian stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
apt-get update && apt-get install yarn
yarn --version # here is yarn 1.22.22

Install PostgreSQL 16

Reference

Add PostgreSQL Repository

apt install gnupg2 wget
sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list'
curl -fsSL https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo gpg --dearmor -o /etc/apt/trusted.gpg.d/postgresql.gpg
sudo apt update

Install PostgreSQL 16

sudo apt install postgresql-16 postgresql-contrib-16 libpq-dev

Make sure PG16 works

sudo systemctl start postgresql
sudo systemctl enable postgresql
sudo -u postgres psql # here is 16.3 (Ubuntu 16.3-1.pgdg22.04+1)

Create user and DB

sudo su - postgres
createuser sdassi_user
psql
ALTER ROLE sdassi_user LOGIN;
CREATE DATABASE sdassi_wefocusin_db WITH ENCODING='UTF8' OWNER=sdassi_user;
logout

Install Redis 7

Reference

curl -fsSL https://packages.redis.io/gpg | sudo gpg --dearmor -o /usr/share/keyrings/redis-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/redis-archive-keyring.gpg] https://packages.redis.io/deb $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/redis.list
sudo apt-get update
sudo apt-get install redis

Install as user

Create new user

adduser sdassi_user
sudo su - sdassi_user
mkdir .ssh
chmod 700 .ssh
vi .ssh/authorized_keys # and paste your public key
chmod 600 .ssh/authorized_keys

Enable new user as sudo

sudo su -
cd /etc/sudoers.d/
echo "sdassi_user ALL=(ALL) NOPASSWD:ALL" > 85-sdassi-user

Install rbenv and Ruby 3.3.4

sudo apt-get install libyaml-dev
sudo apt install rbenv
sudo su - sdassi_user
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
rbenv install 3.3.4
rbenv global 3.3.4
echo "gem: --no-document" > ~/.gemrc
eval "$(rbenv init -)" >> ~/.bash_profile # or past the `rbenv init -`
rbenv shell 3.3.4
ruby --version --yjit # here is ruby 3.3.4 (2024-07-09 revision be1089c8ec) +YJIT [x86_64-linux]

create deploy folder

cd /var/www
sudo mkdir sdassi_oa
sudo chown sdassi_user:sdassi_user sdassi_oa/

The extra file for capistrano

The puma file which will lauch puma via system service.

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

My 2024 Monthly Subscription Review List

Permalink

Like the before 2022 / 2023 year, here is my current subscription, the first number is RMB per month.

  1. (68) iCloud 2T
  2. (17) Apple Music family plan
  3. (26) Dragonruby Pro (annual 42 USD)
  4. (32) bandwagon host (month 33 USD, shared)
  5. (6) Adblock Pro (annual 70 RMB)
  6. (32) Rubymine (annual 53 USD)
  7. (6) blog domain (annual 10 USD)
  8. (1.5) 香哈菜谱 (annual 18 RMB)
  9. (49) AWS hosting (3 Year 206 USD, month 1.35 USD)
  10. (16.8) Meituan biking
  11. (43) Google Workspace Business Starter (month 6 USD)
  12. (115) Cursor.sh AI editor. (yearly 192 USD)
  13. (8.2) Ivory for Mastondon. (yearly 98 RMB)
  14. (8) IndieWeb.Social Backer. (monthly 1.5 SGD)
  15. (31) Sublime Text and Merge (3 yearly, 152 AUD)
  16. (0) Margin Note Max (free for 6 month)
  17. (21) Surge (Est 2 years, 513 RMB)

So totally 480 RMB per month have to pay, in previous year is 419 RMB, so 14% higher compare with year 2023.

Review of the Management Transformation of HuaWei

Permalink

其实这本书可以吐槽的地方非常多,看了几页后,我就有了两个槽点:为啥书名是《华为管理变革》,而不是《华为变革》呢?看书的目录,国际化,研发,供应链,财经,组织,人力各个方面都说到了,为啥要单单强调管理变革呢?还有全书真正和华为密切相关的内容实在不多,绝大多数的内容,将华为改成小米也一样成立,那么这本书的独特性在哪里呢?抱着这两个疑问,又因为这本是直属领导要求的读书会交流书目,我开始了精读。

关于作者

年轻的时候,觉得一本书最重要的是内容,常常跳过序,现在年纪大了,觉得序和作者是最重要的,序代表的写作的出发点,作者的背景决定了书的方向和内容,《华为管理变革》的第一作者是吴晓波,第二作者是Johann Peter Murmann,成书于 2017 年,是一个国际化合作和充满希望的年代。

关于序

本书有两个序,序 2 更值得一读,提到了中澳合作,最优秀的中国企业融入全球化,还有根本的原因,恐惧。序 2 也回答了本文一开始的疑问,因为是管理学院的人书写的,所以必须加上管理两个字。

第一章,概述

概述的作者是老外,所以更精读一下,也不知道这 36 页到底给了老外多少钱,华为以客户为第一,通用电器为股东利益为第一次,西南航空以员工满意为第一优先目标,从 2024 年的角度看,这三者显然都不太成功。文中还提到了华为基本法,但是华为基本法从 1998 年后就没有发布过更新版本。任也从曾经的削足适履学习 IBM 到不再遵循基本法,可见华为管理变革的目标就是变革,华为本身是没有目标的,如果活下去不能算作目标的话。

这一章最大的看点还是2007年到2005年任的地位的空前提高,这显然离不开 IPD,让我想起了任的学习毛泽东思想的标兵身份,可见一个组织内的权利收拢必须有外部威胁,也需要内部流程变革,如果是收拢权利的话,这个案例真的值得学习,可惜只能从字里行间读,实在是不直白。

第七章,研发管理变革

华为主要分三个阶段:

  1. 第一个阶段是生产直接研发,体系崩溃的原因是想做的产品太多,做不过来,质量无法保证,救火不断,甚至损害了企业声誉
  2. 第二个阶段是成立的中央测试部,并且将测试的重要性放到非常高,实际上为了确保测试的重要性,甚至为了中央测试而成立了中央研究部,这样具体研发的级别就低于测试,体系奔溃的原因还是想做的产品太多,以至于中央研究部和测试部成了瓶颈,而且估计是中央研究部的待遇高,进入又必须有成功的项目经验,导致想做的产品更多了,所以崩溃没商量。
  3. 第三个阶段就是 IPD,学 IBM 阶段,其实本质上就是把中央研究部打散,所有的人都围着项目做,而且由于拉上了市场部,第一线销售,可以有效防止承诺功能过多而做不出来,再加上项目的人数总体总是小于华为的总人数,所以不太容易奔溃。缺点也不是没有,就是研发人员的大大增加,直接拉到了70000人,研发效率在我看来是存疑的。

总结

时间关系,就看了两章,总的结论就是华为是一个挺典型的国内企业案例,啥都想做,也没啥目标,后面的国际化全球化其实还是卖货,估计西班牙用了华为很多产品,所以必须建立一个研究中心,总之这些套路也是微软玩下来的,大家都差不多。

一句话总结全文就是,既要还要也要,唯一不变的就是变化,能赚到钱就能请管理学院的人写书,实打实的表示羡慕。

Install dify.ai at Rocky Linux 9.3 From Source Code

Permalink

Setup dify user account

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

Install local python 3.10 for dify

sudo dnf install tar curl gcc openssl-devel bzip2-devel libffi-devel zlib-devel wget make -y
wget https://www.python.org/ftp/python/3.10.13/Python-3.10.13.tar.xz
tar -xf Python-3.10.13.tar.xz
cd Python-3.10.13
./configure --enable-optimizations
make -j 2
sudo make altinstall

Create a Virtual Environment in Python

Copy from guide

python3.10 -m venv dify_env
source dify_env/bin/activate # also add in .bash_profile

Install basic environment

following guide

cd dify/api
cp .env.example .env
openssl rand -base64 42
sed -i 's/SECRET_KEY=.*/SECRET_KEY=<your_value>/' .env
pip install -r requirements.txt
# if meet https://github.com/langgenius/dify/pull/707
pip install -r requirements.txt --upgrade --force-reinstall

Create postgresql db user

sudo su - postgres
createuser dify
psql
ALTER ROLE dify LOGIN;
CREATE DATABASE dify_prod WITH ENCODING='UTF8' OWNER=dify;
logout
flask db upgrade

Install ffmpeg as dify require it

following guide

sudo dnf install epel-release
sudo dnf config-manager --set-enabled crb
sudo dnf install --nogpgcheck https://mirrors.rpmfusion.org/free/el/rpmfusion-free-release-$(rpm -E %rhel).noarch.rpm -y
sudo dnf install --nogpgcheck https://mirrors.rpmfusion.org/nonfree/el/rpmfusion-nonfree-release-$(rpm -E %rhel).noarch.rpm -y
sudo dnf install ffmpeg ffmpeg-devel

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