Chia sẻ kinh nghiệm deploy Ruby on Rails trên CentOS

Chào mọi người, việc deploy Ruby on Rails trên Ubuntu hẳn nhiên đã quá quen thuộc, tuần vừa qua mình có việc cần deploy trên CentOS, khi đó cả đống vấn đề nảy sinh. Có thể do kiến thức mình chưa nắm được nên gặp khó khăn, tuy nhiên mình vẫn muốn chia sẻ mọi người kinh nghiệm deploy với bọn CentOS này.

Tiện đang mượn được tài khoản AWS, mình hướng dẫn luôn việc tạo và deploy trên AWS. Đầu tiên là cần tạo một instance trong trang quản lý EC2 của AWS. Mình chỉ muốn lưa ý một số điều như sau :

  • Để có thể tạo instance CentOS, sau khi chọn Lauch Instance, bạn cần chọn tab AWS Marketplace, vì mặc định bạn sẽ chỉ tìm thấy Ubuntu và Windows. Tại đây bạn search theo từ khóa CentOS và chọn một bản mà bạn thích.

  • Trong khi tạo instance, tới bước thứ 6 : Step 6: Configure Security Group. Bạn hay thêm ít nhất là rule HTTP vào nhé, default chỉ có SSH

Vậy là xong, giờ bạn có một instance CentOS đủ để thí nghiệm.

Giờ đến phần chính, tạo môi trường để deploy.

Chuẩn bị môi trường

Mặc định bên EC2 sẽ tạo cho bạn account centos, bạn hãy thạo thêm một account khác là deploy cho nó chuyên nghiệp cũng như rõ ràng hơn cho việc quản lý sau này. 😄. Trước khi làm gì, update phát cho mới mẻ nhỉ, mình rất thích update 😃 sudo yum -y update Rồi, giờ tới tạo tài khoản deploy và set password cho nó : sudo adduser deploy sudo passwd deploy Mở file visudo bằng lệnh sudo visudo và thêm đoạn code này và vào deploy ALL=(ALL) ALL Vậy là tạm ổn rồi, hãy chuyển sang sử dụng account này để nghịch su - deploy

Việc cần làm tiếp theo là thêm công 80 vào IP table, mở file /etc/sysconfig/iptables bằng công cụ gì bạn thích, tìm dòng

-A INPUT -i lo -j ACCEPT

và đưa đoạn này vào ngay dưới nó :

-A INPUT -m state --state NEW -p tcp --dport 80 -j ACCEPT

Tóm lại bạn sẽ có nội dung tương tự như sau : ...

-A INPUT -i lo -j ACCEPT

-A INPUT -m state --state NEW -p tcp --dport 80 -j ACCEPT

-A INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT

...

Sau đó restart lại server iptables :

sudo service iptables restart

Cài đặt các phần mềm cần thiết

Nếu thích bạn có thể cài cả gói công cụ này vào, trong đó có sẵn Git, hoặc trong trường hợp này bạn cài mỗi Git không thôi cũng được. Mình thì mình cứ cài cả, không dùng trước thì dùng sau

sudo yum groupinstall -y "development tools"

Trước khi cài những gói tiếp theo, bạn sẽ cần phải enable EPEL repository lên, như bản thân bọn CentOS từ AWS này, base repo sẽ không có nginx, NodeJS ... :

sudo yum install epel-release (Dùng cho CentOS 6.x, bản 7 không biết dùng được không, nếu không bạn cứ search theo từ khóa EPEL repo là ra)

Xong, giờ ung dung cài lần lượt các gói sau:

sudo yum install -y nodejs

sudo yum install -y nginx

sudo yum install mysql-server

sudo yum install mysql-devel

Nếu bạn sử dụng server CentOS do khách hàng đã cấu hình từ trước, hoặc vấn đề nào đó các app bạn cài bên trên không start được hoặc không như mong muốn, thì khả năng cao bên đó đang để cài default app từ repo mà họ sắp đặt từ trước. Khi đó bạn có thể gỡ app ra, và cài lại app trực tiếp từ repo base. Mình đã thử và thành công khi cài xong mysql-servermysql-devel nhưng không thể nào cài nổi gem mysql2...

sudo yum --disablerepo="*" --enablerepo="base" install APP_U_WANT

Cài Ruby on Rails

Mình sẽ dùng rvm để cài Ruby.

gpg --keyserver hkp://keys.gnupg.net --recv-keys D39DC0E3

curl -L https://get.rvm.io | bash -s stable

source ~/.rvm/scripts/rvm

echo "source ~/.rvm/scripts/rvm" >> ~/.bashrc

rvm requirements

rvm install 2.3.1

rvm use 2.3.1 --default

echo "gem: --no-ri --no-rdoc" > ~/.gemrc

gem install bundler

gem install rails

Xong !

Cấu hình SSH

Đầu tiên là bạn cần add SSH pubic key của máy client bạn muốn deploy lên server. Nếu máy bạn chưa có SSH public key thì có thể tạo bằng lệnh :

ssh-keygen

Nếu trên server của bạn chưa có sẵn file /.ssh/authorized_keys (Nếu dùng tài khoản deploy mình vừa tạo thì chắc chắn sẽ không có). Dùng lệnh sau để tạo :

mkdir ~/.ssh

touch ~/.ssh/authorized_keys

chmod 700 ~/.ssh

chmod 600 ~/.ssh/authorized_keys

Rồi, giờ lấy SSH pubic key của máy bạn cat ~/.ssh/id_rsa.pub, rồi vất lên file authorized_keys ta vừa tại trên server.

Giờ đến lượt làm sao để server có thể lấy được code từ GitHub về. Tương tự trên, bạn lấy SSH public key của server, đưa vào danh sách Deploy keys trên trang cài đặt repo của bạn trên GitHub.

Khởi tạo database

Phải start service của mysql lên đã nhỉ?

sudo service mysqld start

Sau đó tạo một database bằng lệnh

mysql -u root -e "create database database_name_u_want"

Init project

Mình sẽ để project cần chạy theo đường dẫn /usr/local, còn bạn muốn đặt đâu thì tùy. Giả sử project của mình tên ZZZ

sudo mkdir /usr/local/ZZZ

sudo mkdir -p /usr/local/ZZZ/shared/config

sudo vi /usr/local/ZZZ/shared/config/database.yml (Điền thông tin database của bạn vào)

sudo vi /usr/local/ZZZ/shared/config/application.yml (Có thể sử dụng rake secret trên máy local để tạo đoạn mã, rồi đưa vào file). Ví dụ :

SECRET_KEY_BASE: "775864793bfac59b168ad8928d612fe0057a4f36351e146c97da37f412c0c482723bced521598c26cfc6ceefc49f9186c50db04f656fd410138e50f93b687a17"

Rồi, giờ thì đổi quyền để account deploy của ta có quyền đọc, ghi vào thư mục ta vừa tạo : sudo chown -R deploy:root /usr/local/ZZZ

Xử lý vụ SELinux

Khái niệm chi tiết mình kiếm được, đọc cũng dễ hiểu nên post lại nguyên văn chính chủ cho mọi người tham khảo :

SELinux - Security-Enhanced Linux, là một module bảo mật trong Linux kernel được phát triển đầu tiên bởi Cơ quan An ninh Quốc Gia Hoa Kỳ (NSA), nhằm cung cấp một cơ chế an ninh và kiểm soát truy cập bắt buộc đối với các dịch vụ hoạt động trong hệ thống theo tiêu chuẩn của Bộ Quốc Phòng Hoa Kỳ.

SELinux kiểm soát các sửa đổi kernel và các công cụ trong không gian người dùng được thêm vào trong các bản phân phối Linux khác nhau. Kiến trúc của nó cố gắng tách biệt việc thực thi các quyết định an ninh với việc phân loại các dịch vụ cần thi hành các chính sách an ninh.

SELinux khoanh vùng các tập tin và tài nguyên mà các chương trình người dùng và máy chủ hệ thống được phép truy cập, qua đó hạn chế thiệt hại do các ứng dụng độc hại hoặc những ứng dụng lỗi gây ra. Cơ chế khoanh vùng của SELinux hoạt động độc lập với cơ chế kiểm soát truy cập truyền thống của Linux, bỏ qua tất cả các khái niệm và ưu tiên của super-user, và vì thế không có các thiếu sót của hệ thống cũ.

SELinux cung cấp nhiều lựa chọn như kiểm soát truy cập bắt buộc, điều khiển toàn vẹn bắt buộc, kiểm soát truy cập dựa trên vai trò người dùng, an ninh đa cấp và kiểu kiến trúc thực thi.

Đấy, nghe thì rất là tuyệt vời, nhưng nó có thể gây rắc rối cho Nginx của chúng ta. Có thể bạn sẽ gặp lỗi Nginx không thể động vào được socket, mất khá nhiều thời gian mới biết nó là do SELinux (Kiến thức hạn hẹp nó khổ vậy đó). Cụ thể ta sẽ làm đích xác như trong trả lời của post sau : (13: Permission denied) while connecting to upstream:[nginx]

sudo cat /var/log/audit/audit.log | grep nginx | grep denied | audit2allow -M mynginx

sudo semodule -i mynginx.pp

Sau khi chạy 2 lệnh do Joseph Barbere hướng dẫn mà không có tác dụng, bạn chịu khó chạy lại 2 lệnh đó lần nữa. Hiện tại mình cũng chưa rõ tạo sao nhưng chạy 2 lần có tác dụng cho mình. Bác nào nghiên cứu ký hơn vụ này thì để lại comment bên dưới nhé.

Tổng kết

Bài viết trên là những kinh nghiệm mình gặp phải, cũng như cách thức xử lý mà mình tìm hiểu, lọ mọ tra cứu trên mạng. Còn những phần còn lại để deploy thì mình xin không đưa vào đây vì nó cũng không có vấn đề gì cần chia sẻ.

Bài viết được soạn bởi kiến thức còn non trẻ về Linux cũng như việc deploy, vậy nên sẽ không tránh khỏi sai sót, mong mọi người tích cực đóng góp ý kiến để mình hoàn thiện bài viết cũng như trau dồi thêm kiến thức.