AI & AUTOMATIONSELF HOSTING

Hướng dẫn triển khai Forem trên macOS với OrbStack

Đợt Back to School của Apple vừa rồi mình thấy con Mac Mini M4 giá tốt quá nên mua trải nghiệm, dùng chán rồi nên giờ mang ra làm cái homelab để cài mấy ứng dụng nhỏ nhỏ. Tiện cài thử Forem làm cái cộng đồng chia sẻ về AI và Automation, nên làm lại bài hướng dẫn cho anh em nào cũng có cùng nhu cầu.

Triển khai Forem (mã nguồn của DEV.to) trên macOS sử dụng chip Apple Silicon (M1/M2/M3/M4) thường gặp rất nhiều vấn đề về hiệu năng và tương thích (lỗi nokogiri, lỗi kiến trúc amd64 vs arm64, lỗi quyền ghi file…).

Giải pháp tối ưu nhất không phải là chạy Docker trực tiếp trên Mac, mà là chạy một máy ảo Linux (Ubuntu) nhẹ thông qua OrbStack, sau đó triển khai Forem bên trong đó. Bài viết này sẽ hướng dẫn bạn từng bước, bao gồm cả cách “vá” những lỗi kinh điển mà tài liệu chính thức chưa cập nhật.

Chuẩn bị môi trường (OrbStack & Ubuntu VM)

Thay vì dùng Docker Desktop, chúng ta dùng OrbStack vì nó nhẹ, nhanh và hỗ trợ quản lý máy ảo Linux cực tốt. Nếu chưa cài OrbStack thì bạn xem bài hướng dẫn này: OrbStack – Lựa chọn thay thế lý tưởng cho Docker Desktop trên macOS

1. Tạo máy ảo Ubuntu

Mở Terminal trên Mac và chạy lệnh sau để tạo một máy ảo Ubuntu 24.04 (Noble):

orb create ubuntu:noble forem-server

2. Truy cập vào máy ảo

Từ giờ trở đi, mọi lệnh chúng ta sẽ gõ bên trong máy ảo này:

orb -m forem-server

3. Cài đặt Docker & Docker Compose bên trong VM

Dù OrbStack có Docker, nhưng để môi trường khép kín chuẩn Production, ta nên cài Docker Engine cho Ubuntu:

# Cập nhật hệ thống
sudo apt-get update && sudo apt-get upgrade -y

# Cài đặt Docker
sudo apt-get install -y docker.io docker-compose-v2

# Thêm user hiện tại vào nhóm docker (để không cần gõ sudo)
sudo usermod -aG docker $USER
newgrp docker

Tải mã nguồn & cấu hình

1. Clone Code (Lưu ý quan trọng)

Tuyệt đối không clone code ở ngoài Mac rồi mount vào. Hãy clone trực tiếp vào ổ cứng của máy ảo để đạt tốc độ tối đa và tránh lỗi Permission denied.

cd ~
git clone https://github.com/forem/forem.git
cd forem

2. “Vá” lỗi Containerfile

Image gốc của Forem đang dính 2 lỗi lớn: Repo Node.js bị chết (gây lỗi 404 khi build) và thiếu đường dẫn Bash. Chạy 2 lệnh sau để tự động sửa file Containerfile:

# Fix 1: Xóa repo NodeSource cũ gây lỗi build 404
sed -i 's/apt update/rm -f \/etc\/apt\/sources.list.d\/nodesource.list \&\& apt update/g' Containerfile

# Fix 2: Tạo symlink cho bash (Sửa lỗi: exec: "/usr/bin/bash": not found)
sed -i '/apt-get install -yq --no-install-recommends \\/a \      ln -s /bin/bash /usr/bin/bash && \\' Containerfile

3. Cấu hình file .env (Production)

Tạo file .env:

nano .env

Và dán nội dung tối ưu sau:

# APP IDENTITY
APP_DOMAIN="vnrom.net" 
APP_PROTOCOL="https://"
COMMUNITY_NAME="vnROM Community"
DEFAULT_EMAIL="[email protected]" # Phải trùng với SMTP User bên dưới
TZ=Asia/Ho_Chi_Minh

# SECRETS (Bạn có thể tạo chuỗi tại đây: https://tools.vnrom.net/token-generator)
FOREM_OWNER_SECRET="chuoi_bi_mat_dai_ngoang_1"
SECRET_KEY_BASE="chuoi_bi_mat_dai_ngoang_2"

# DATABASE & REDIS (Trỏ về service name, KHÔNG dùng localhost)
DATABASE_URL="postgresql://forem:forem@postgres:5432/forem_production"
DATABASE_NAME="forem_production"
DATABASE_POOL_SIZE=5
REDIS_URL="redis://redis:6379"
REDIS_SESSIONS_URL="redis://redis:6379"
REDIS_SIDEKIQ_URL="redis://redis:6379"

# --- ENVIRONMENT ---
RAILS_ENV="production"
NODE_ENV="production"
RAILS_SERVE_STATIC_FILES="true"
RAILS_LOG_TO_STDOUT="true"

# --- SMTP (Ví dụ dùng Larksuite/Gmail) ---
SMTP_ADDRESS="smtp.larksuite.com"
SMTP_PORT="465"
SMTP_DOMAIN="vnrom.net"
SMTP_USER_NAME="[email protected]"
SMTP_PASSWORD="mat_khau_ung_dung"
SMTP_AUTHENTICATION="login"
SMTP_TLS=true
SMTP_ENABLE_STARTTLS_AUTO=false
SMTP_OPENSSL_VERIFY_MODE="peer"

# --- SECURITY ---
FORCE_SSL_IN_RAILS="true"

4. Tạo file docker-compose.yml (Production)

Xóa file cũ và thay bằng nội dung này. Lưu ý dòng target: production là chìa khóa để fix lỗi thiếu Gemfile.

nano docker-compose.yml

Copy và paste nội dung sau:

services:
  postgres:
    image: postgres:13
    container_name: forem_postgres
    restart: always
    env_file:
      - .env
    environment:
      POSTGRES_USER: forem
      POSTGRES_PASSWORD: forem
      POSTGRES_DB: forem_production
    volumes:
      - db_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD", "pg_isready", "-U", "forem"]
      interval: 10s
      timeout: 5s
      retries: 5

  redis:
    image: redis:6.2-alpine
    container_name: forem_redis
    restart: always
    env_file:
      - .env
    volumes:
      - redis_data:/data
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 5s
      retries: 5

  web:
    build:
      context: .
      dockerfile: Containerfile
      target: production  # BẮT BUỘC CÓ để copy code vào image
    container_name: forem_web
    restart: always
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy
    env_file:
      - .env
    ports:
      - "3000:3000"
    command: bundle exec rails s -b 0.0.0.0
    volumes:
      - uploads_data:/opt/apps/forem/public/uploads
      - assets_data:/opt/apps/forem/public/assets

  sidekiq:
    build:
      context: .
      dockerfile: Containerfile
      target: production
    container_name: forem_sidekiq
    restart: always
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy
    env_file:
      - .env
    command: bundle exec sidekiq

volumes:
  db_data:
  redis_data:
  uploads_data:
  assets_data:

Build và chạy (The Magic Moment)

Chạy lần lượt các lệnh sau:

1. Build Image:

docker compose build

2. Khởi tạo Database:

Lưu ý dùng bundle exec thay vì bin/rails để tránh lỗi đường dẫn.

docker compose run --rm web bundle exec rails db:setup

3. Fix quyền thư mục Upload (Bắt buộc):

Nếu không làm bước này, bạn sẽ không thể upload avatar (Lỗi Errno::EACCES).

docker compose run --rm -u root web mkdir -p /opt/apps/forem/public/uploads/tmp
docker compose run --rm -u root web chown -R 1000:1000 /opt/apps/forem/public
docker compose run --rm -u root web chmod -R 777 /opt/apps/forem/public

4. Biên dịch giao diện:

docker compose run --rm web bundle exec rails assets:precompile

5. Khởi động hệ thống:

docker compose up -d

Tạo tài khoản Admin

Rất nhiều trường hợp bạn đăng ký trên Web sẽ bị lỗi do SMTP chưa thông, hoặc lỗi ghi file. Cách chắc chắn nhất là tạo Admin qua dòng lệnh:

  1. Truy cập Console:
docker compose exec web bundle exec rails c
  1. Gõ các lệnh sau để tạo Super Admin:
# Tạo user
u = User.new(
  name: "Super Admin", 
  username: "admin", 
  email: "[email protected]", 
  password: "MatKhauSieuManh123", 
  password_confirmation: "MatKhauSieuManh123"
)
u.save!

# Kích hoạt & Cấp quyền
u.confirm
u.add_role(:admin)
u.add_role(:super_admin)
u.save!
exit

Bây giờ bạn có thể đăng nhập ngay tại https://ten-mien-cua-ban.com (hoặc localhost:3000) mà không cần chờ email.

Sau khi đăng nhập thành công thì vào Dashboard Admin, sau đó cập nhật lại SMTP và restart lại container với 2 lệnh sau:

docker compose down
docker compose up -d

Tổng hợp các lỗi thường gặp & cách fix

Trong quá trình cài đặt, nếu bạn gặp lỗi, hãy tra cứu bảng bên dưới:

Lỗi (Error Log)Nguyên nhânCách khắc phục
nodesource ... does not have a Release fileRepo Node cũ trong Image bị die.Dùng lệnh sedPhần 2, Mục 2 để xóa file list bị lỗi trong Containerfile.
exec: "/usr/bin/bash": not foundScript gọi sai đường dẫn Bash (Do khác biệt OS).Dùng lệnh sed tạo symlink ln -s /bin/bash /usr/bin/bash trong Containerfile.
Could not locate GemfileDocker build thiếu code nguồn.Thêm dòng target: production vào docker-compose.yml.
ActiveRecord::ConnectionNotEstablished ... 127.0.0.1Rails tìm DB ở localhost thay vì container postgres.Sửa .env: DATABASE_URL=postgresql://...@postgres:5432....
Errno::EACCES (Permission denied @ dir_s_mkdir)Container không có quyền ghi vào thư mục uploads.Chạy bộ lệnh chownchmodPhần 3, Bước 3.
Net::ReadTimeout (khi gửi mail)Sai cổng SMTP hoặc chế độ SSL/TLS.Thử đổi cổng 587 (StartTLS) hoặc 465 (TLS=true). Kiểm tra DEFAULT_EMAIL phải trùng SMTP_USER.
PG::UniqueViolation: duplicate keyTài khoản đã được tạo nhưng UI báo lỗi ảo.Vào Rails Console, tìm user đó (User.find_by_email), và chạy lệnh confirm + add_role.
exec: "nc": executable file not foundImage production không có lệnh nc.Dùng lệnh Ruby hoặc Curl để test mạng (Xem lại chat history).

Bảo trì hệ thống (Update, Backup & Restore)

Vận hành một hệ thống Production không chỉ là cài đặt xong rồi để đó. Bạn cần biết cách cập nhật code mới từ Forem để vá lỗi bảo mật và quan trọng hơn là sao lưu dữ liệu đề phòng sự cố.

Vì đang chạy trên máy ảo Ubuntu (OrbStack) với Docker Compose, quy trình này sẽ thực hiện hoàn toàn trong Terminal của Ubuntu (orb -m forem-server).

Quy trình update Forem

Mã nguồn Forem thay đổi liên tục. Để cập nhật phiên bản mới nhất từ Github mà không làm hỏng hệ thống hiện tại, hãy làm theo các bước sau:

Bước 1: Chuẩn bị

Truy cập vào thư mục code:

cd ~/forem

Bước 2: Tải code mới nhất về

LƯU Ý:
Vì chúng ta đã sửa file Containerfile bằng lệnh sed trước đó, khi git pull có thể sẽ báo lỗi xung đột hoặc ghi đè. Tốt nhất là reset lại file này, kéo code mới, rồi vá lỗi lại.
# Hủy các thay đổi local để nhận code mới sạch sẽ
git checkout Containerfile

# Kéo code mới nhất từ nhánh main
git pull origin main

Bước 3: Vá lại lỗi Containerfile (Bắt buộc)

Code mới tải về vẫn sẽ dính lỗi cũ (NodeSource & Bash path), bạn phải chạy lại 2 lệnh thần thánh này:

# Fix lỗi NodeSource & Bash Path
sed -i 's/apt update/rm -f \/etc\/apt\/sources.list.d\/nodesource.list \&\& apt update/g' Containerfile
sed -i '/apt-get install -yq --no-install-recommends \\/a \      ln -s /bin/bash /usr/bin/bash && \\' Containerfile

Bước 4: Build và cập nhật Database

Quá trình này sẽ đóng gói code mới vào Image và cập nhật cấu trúc bảng dữ liệu (nếu có thay đổi).

# 1. Build lại Image Production (Mất vài phút)
docker compose build

# 2. Chạy Migration (Cập nhật cấu trúc DB)
# Lưu ý: KHÔNG chạy db:setup hay db:reset ở bước này (sẽ mất dữ liệu)
docker compose run --rm web bundle exec rails db:migrate

# 3. Biên dịch lại giao diện (Assets)
docker compose run --rm web bundle exec rails assets:precompile

Bước 5: Khởi động lại

# Khởi động lại container với image mới
docker compose up -d

# Xóa bớt image cũ cho nhẹ máy
docker image prune -f

Quy trình sao lưu (Backup)

Dữ liệu quan trọng nhất của Forem nằm ở 3 nơi:

  • Database (PostgreSQL): Chứa bài viết, user, comment…
  • Uploads: Chứa ảnh avatar, ảnh bài viết (nằm trong thư mục public/uploads).
  • File cấu hình: File .env.

Bạn nên tạo một thư mục backup riêng trong máy ảo:

mkdir -p ~/backups

1. Sao lưu Database (PostgreSQL)

Chúng ta dùng lệnh pg_dump từ bên trong container để xuất dữ liệu ra file SQL.

# Tạo file backup có tên kèm ngày tháng (ví dụ: forem_db_2023-10-27.sql)
docker compose exec -t postgres pg_dump -U forem forem_production > ~/backups/forem_db_$(date +%F).sql

2. Sao lưu file Uploads (Ảnh)

Copy toàn bộ thư mục uploads từ trong container ra ngoài máy ảo.

# Nén thư mục uploads lại thành file .tar.gz
docker compose exec -t web tar -czf /tmp/uploads.tar.gz -C /opt/apps/forem/public/uploads .

# Copy file nén ra ngoài
docker cp forem_web:/tmp/uploads.tar.gz ~/backups/uploads_$(date +%F).tar.gz

3. Sao lưu file .env

cp ~/forem/.env ~/backups/.env_backup
MẸO:
Bạn có thể copy thư mục ~/backups này từ máy ảo Ubuntu ra máy Mac để lưu trữ an toàn bằng cách mở Finder -> OrbStack -> Chọn máy ảo -> Copy thư mục.

Quy trình khôi phục (Restore)

Chỉ thực hiện khi bạn chuyển server, hoặc lỡ tay xóa nhầm dữ liệu. Cảnh báo: Dữ liệu hiện tại sẽ bị ghi đè.

Giả sử bạn đã có 2 file backup: forem_db.sqluploads.tar.gz.

Bước 1: Dừng hệ thống (Tránh xung đột)

docker compose stop web sidekiq

Bước 2: Khôi phục Database

Lệnh này sẽ xóa DB hiện tại và nạp lại từ file backup.

# 1. Xóa database cũ và tạo lại database trắng
docker compose exec postgres dropdb -U forem forem_production
docker compose exec postgres createdb -U forem forem_production

# 2. Nạp dữ liệu từ file SQL
# (Lưu ý dấu < để truyền file vào)
cat ~/backups/forem_db.sql | docker compose exec -T postgres psql -U forem forem_production

Bước 3: Khôi phục File Uploads

# 1. Copy file nén vào trong container
docker cp ~/backups/uploads.tar.gz forem_web:/tmp/uploads.tar.gz

# 2. Giải nén vào đúng vị trí
docker compose exec web tar -xzf /tmp/uploads.tar.gz -C /opt/apps/forem/public/uploads/

# 3. QUAN TRỌNG: Fix lại quyền (Permission) sau khi restore
# Nếu không làm bước này, ảnh sẽ không hiện hoặc không up mới được
docker compose exec -u root web chown -R 1000:1000 /opt/apps/forem/public/uploads
docker compose exec -u root web chmod -R 777 /opt/apps/forem/public/uploads

Bước 4: Khởi động lại

docker compose start

Tóm tắt các lệnh hay dùng hàng ngày

Tác vụLệnh
Khởi động serverdocker compose up -d
Dừng serverdocker compose stop
Xem logs (Web)docker compose logs -f web
Xem logs (Email/Job)docker compose logs -f sidekiq
Vào Console Railsdocker compose exec web bundle exec rails c
Check kết nối mạngdocker compose exec web curl -I https://google.com

Vậy là bạn đã có trong tay trọn bộ bí kíp để vận hành Forem an toàn và bền vững!

Hy vọng hướng dẫn này giúp bạn triển khai thành công Forem trên máy Mac của bạn.

Duy Nghiện
Hãy làm khán giả, đừng làm nhân vật chính :)

You may also like

Nhận thông báo qua email
Nhận thông báo cho
guest

0 Bình luận
Mới nhất
Cũ nhất Nhiều like nhất
Phản hồi nội tuyến
Xem tất cả bình luận