Ứng dụng Ruby và Rails
Cài Ruby, deploy Rails, Sinatra hay ứng dụng Rack khác từ Git với Bundler và Puma, precompile asset, kết nối database và đặt biến môi trường.
Ứng dụng Ruby chạy trên ZoPanel như ứng dụng server: ZoPanel cài gem bằng Bundler, build bản release, chạy ứng dụng như một dịch vụ của tài khoản hosting phía sau nginx và chuyển sang bản mới không gián đoạn. Trang này dành cho Ruby on Rails, ứng dụng Rack (Sinatra, Hanami…) và server Ruby thuần; cổng, phát hành blue/green và log hoạt động như mô tả trong Ứng dụng Node.js và Python.
Cài Ruby lên máy chủ
Quản trị viên cài Ruby một lần:
- Mở Runtime.
- Trong thẻ Ruby ("Ruby kèm Bundler, cho Rails và Sinatra."), bấm Cài đặt.
ZoPanel cài Ruby của hệ điều hành kèm Bundler và các thư viện mà gem native cần:
ruby-full ruby-bundler build-essential libyaml-dev zlib1g-dev libssl-dev
libpq-dev libsqlite3-dev default-libmysqlclient-dev pkg-config
Nhờ vậy các gem như pg, mysql2, sqlite3, psych, nokogiri biên dịch được mà không cần thêm bước nào. Sau khi cài, thẻ hiển thị phiên bản Ruby.
Mỗi máy chủ có một bản Ruby, chính là bản hệ điều hành cung cấp:
| Hệ điều hành | Ruby | Rails mới nhất chạy được |
|---|---|---|
| Ubuntu 22.04 | 3.0 | Rails 7.1 |
| Debian 12 | 3.1 | Rails 7.2 |
| Ubuntu 24.04 | 3.2 | Rails 8 |
| Debian 13 | 3.3 | Rails 8 |
Rails 8.0 cần Ruby 3.2 trở lên, Rails 7.2 cần Ruby 3.1 trở lên (hướng dẫn nâng cấp Rails). Dòng ruby "x.y" trong Gemfile phải khớp Ruby của máy chủ, nếu không Bundler sẽ dừng. Ô Phiên bản và Gemfile không chọn được Ruby khác. Mọi log build đều bắt đầu bằng Ruby đang dùng, ví dụ "Using the system Ruby 3.2.3", và thêm cảnh báo khi Gemfile yêu cầu phiên bản khác. Nếu ứng dụng cần phiên bản Ruby khác, hãy deploy bằng Dockerfile (xem Deploy bằng Docker).
Deploy
- Ở Website → Thêm website, chọn Git deploy, nhập Địa chỉ repository, Nhánh (và Thư mục gốc với monorepo) rồi bấm Tạo website. Với website có sẵn, dùng tab Deploy.
- ZoPanel nhận diện Ruby qua
Gemfilevà đề xuất các lệnh bên dưới. - Khai báo cấu hình trong Biến môi trường rồi bấm Lưu & deploy lại.
Lệnh được nhận diện
Mọi ứng dụng Ruby dùng chung lệnh cài đặt. Gem được cài vào bản release (vendor/bundle), không cài cho toàn hệ thống, và bỏ qua nhóm development, test:
bundle config set --local path vendor/bundle && bundle config set --local without 'development test' && bundle install --jobs 4
| Nhận diện là | Khi nào | Lệnh build | Lệnh chạy |
|---|---|---|---|
| Ruby on Rails | Có config/application.rb hoặc Gemfile có rails |
RAILS_ENV=production SECRET_KEY_BASE=precompile bundle exec rails assets:precompile, chỉ khi có app/assets/config/manifest.js hoặc app/javascript |
RAILS_ENV=production bundle exec rails server -b 127.0.0.1 -p $PORT |
| Rack (Sinatra, Hanami…) | Có config.ru |
– | bundle exec rackup -o 127.0.0.1 -p $PORT -E production |
| Ruby | Các trường hợp khác | – | bundle exec ruby app.rb -o 127.0.0.1 -p $PORT (cần kiểm tra lại) |
Với Rails, Đường dẫn lưu trữ cố định được đặt là storage và log, log deploy ghi chú "Set SECRET_KEY_BASE and DATABASE_URL in the environment variables". Dòng web: trong Procfile luôn được ưu tiên làm lệnh chạy.
Muốn đổi lệnh, tắt Tự nhận diện trong thẻ Build & chạy, sửa rồi bấm Lưu & deploy.
Puma
rails server khởi động Puma, server mặc định của ứng dụng Rails mới (gem "puma" trong Gemfile). Tuỳ chọn -b và -p gắn Puma vào 127.0.0.1:$PORT. Số thread lấy từ config/puma.rb (RAILS_MAX_THREADS, mặc định 3 ở Rails 8). Muốn chạy Puma trực tiếp, có thể dùng:
bundle exec puma -C config/puma.rb -b tcp://127.0.0.1:$PORT -e production
Với ứng dụng Rack dùng Rack 3 (Sinatra 4 trở lên), lệnh rackup nằm trong gem riêng: thêm gem "rackup" và gem "puma" vào Gemfile (README của Sinatra).
Biến môi trường
Đặt các biến sau trong Biến môi trường ở tab Deploy. Chúng dùng được khi build và khi chạy; PORT được đặt tự động.
| Biến | Giá trị |
|---|---|
SECRET_KEY_BASE |
Chuỗi bí mật ngẫu nhiên dài, ví dụ kết quả của bin/rails secret hoặc openssl rand -hex 64. Rails dùng giá trị này thay cho giá trị trong credentials đã mã hoá. |
RAILS_MASTER_KEY |
Chỉ cần khi ứng dụng đọc giá trị khác từ config/credentials.yml.enc. |
DATABASE_URL |
Chuỗi kết nối (xem bên dưới). |
RAILS_LOG_TO_STDOUT |
1 với ứng dụng cũ hơn Rails 7.1, để log hiện trong Log ứng dụng. Từ Rails 7.1, log mặc định ghi ra stdout. |
SOLID_QUEUE_IN_PUMA |
1 để chạy job Solid Queue ngay trong Puma (theo config/puma.rb mặc định của Rails 8). |
Lệnh build chỉ đặt SECRET_KEY_BASE giả cho bước assets:precompile, nên bước precompile không cần khoá thật.
Database
SQLite (mặc định của Rails 8). Ứng dụng Rails 8 mới lưu database production trong storage/ (storage/production.sqlite3 cùng các database cache, queue, cable). storage là đường dẫn lưu trữ cố định nên dữ liệu được giữ qua mọi lần deploy. Ngoài migration, không cần làm gì thêm.
MariaDB hoặc PostgreSQL. Tạo database ở Cơ sở dữ liệu rồi đặt DATABASE_URL; host là 127.0.0.1 (cấu hình database của Rails):
# MariaDB với gem mysql2
DATABASE_URL=mysql2://alice_app:mat-khau@127.0.0.1:3306/alice_app
# MariaDB với gem trilogy (Rails 7.1+)
DATABASE_URL=trilogy://alice_app:mat-khau@127.0.0.1:3306/alice_app
# PostgreSQL với gem pg
DATABASE_URL=postgresql://alice_app:mat-khau@127.0.0.1:5432/alice_app
Mã hoá URL các ký tự đặc biệt trong mật khẩu (ví dụ @ thành %40).
Migration
Migration không tự chạy. Tắt Tự nhận diện rồi thêm vào cuối lệnh build:
RAILS_ENV=production SECRET_KEY_BASE=precompile bundle exec rails assets:precompile && RAILS_ENV=production bundle exec rails db:prepare
db:prepare tạo database còn thiếu và chạy các migration đang chờ. Bước build chạy trước khi bản mới được đưa lên, trong lúc bản cũ vẫn phục vụ khách, nên hãy viết migration sao cho bản đang chạy vẫn hoạt động được.
SSL, file tĩnh và file tải lên
- nginx xử lý SSL và gửi header
X-Forwarded-Proto. Rails 8 bậtconfig.assume_sslvàconfig.force_sslở production, Rails 7.1 bậtconfig.force_ssl: hãy giữ SSL miễn phí (Let's Encrypt), nếu không cookie bảo mật và chuyển hướng sẽ làm hỏng đăng nhập qua HTTP thường. - nginx chuyển mọi request tới ứng dụng, kể cả file trong
public/. Từ Rails 7.1, Rails tự phục vụ các file này; với Rails 7.0 hãy đặtRAILS_SERVE_STATIC_FILES=1. - Active Storage dùng disk local sẽ ghi vào
storage/, vốn là đường dẫn lưu trữ cố định. Thư mục khác cần giữ lại giữa các bản, ví dụpublic/uploads, hãy thêm vào Đường dẫn lưu trữ cố định.
Release, log và khởi động lại
- Bản mới khởi động ở slot đang rảnh và phải trả lời Đường dẫn health check (mặc định
/) với mã dưới 500 trong vòng 90 giây; chuyển hướng vẫn tính là đạt. Từ Rails 7.1 có sẵn route/upđể dùng làm health check. Chỉ khi đó nginx mới chuyển sang và tiến trình cũ mới dừng. - Các bản release giữ 5 bản build gần nhất để Rollback (database không được rollback).
- Log ứng dụng hiển thị 400 dòng cuối ứng dụng ghi ra; bật Trực tiếp để theo dõi. Thư mục
log/cũng được lưu trữ cố định. - Dịch vụ tự khởi động lại khi Puma thoát. RAM và CPU được tính vào gói của tài khoản.
Xử lý sự cố
| Thông báo hoặc hiện tượng | Cách xử lý |
|---|---|
bundle: command not found ở bước cài đặt |
Nhờ quản trị viên cài Ruby ở Runtime. |
| "Your Ruby version is …, but your Gemfile specified …" | Gemfile yêu cầu Ruby khác bản của máy chủ (log build cảnh báo điều này trước bước cài đặt). Nới dòng ruby (ví dụ ruby "~> 3.2", hoặc xóa dòng đó), hoặc deploy bằng Dockerfile. |
| Một gem không biên dịch được | Đọc log build trong Tác vụ; các header thông dụng đã được cài cùng Ruby. Thư viện native khác cần quản trị viên cài thêm. |
| "the app did not respond on port … within 90s (it must listen on $PORT)" | Gắn vào 127.0.0.1:$PORT (-b 127.0.0.1 -p $PORT). |
| "the app exited during startup" | Đọc Log ứng dụng: thường do thiếu SECRET_KEY_BASE, DATABASE_URL, hoặc chưa chạy migration. |
ActiveRecord::PendingMigrationError |
Thêm bundle exec rails db:prepare vào lệnh build (xem phần Migration). |
| Đăng nhập lặp vòng hoặc mất cookie | Website chạy không có SSL trong khi Rails ép SSL. Hãy cấp chứng chỉ (xem Chứng chỉ SSL). |
| Repository bị nhận diện là Node.js | File package.json ở thư mục gốc (jsbundling, cssbundling) được ưu tiên hơn Gemfile. Tắt Tự nhận diện, chọn Runtime là ruby, Loại là Ứng dụng server (tiến trình) và nhập các lệnh Rails ở trên; thêm npm ci && vào đầu lệnh build nếu asset cần Node.js. |