Hướng dẫn cài đặt FreshRSS trên Ubuntu VPS chi tiết
Cài đặt FreshRSS trên Ubuntu 24.04 với Apache, PHP 8.3 và MariaDB. Hướng dẫn cấu hình virtual host, thiết lập cron job tự động và khắc phục lỗi API cho ứng dụng di động.
Bạn đang xây dựng cái gì
Một trình đọc RSS tự lưu trữ là trình đọc feed chạy trên máy chủ do bạn sở hữu, vì vậy không ai có thể tắt nó hoặc thay đổi nội dung hiển thị cho bạn. Hướng dẫn này cài đặt FreshRSS trên một VPS Ubuntu 24.04: Apache ở phía trước, PHP ở phía sau, MariaDB để lưu trữ và một cron job để lấy bài viết mới. RSS (really simple syndication) là định dạng tệp mà một trang web xuất bản để phần mềm có thể đọc các bài viết của nó. FreshRSS là ứng dụng PHP thu thập các tệp đó, lưu giữ các bài viết và cung cấp cho bạn giao diện web cùng với một API (application programming interface) mà các ứng dụng điện thoại có thể giao tiếp.
Việc cài đặt rất nhỏ gọn: giải nén một bản release, tạo cơ sở dữ liệu, viết một virtual host, chạy một trình cài đặt dòng lệnh. Hầu hết công việc bên dưới là phần mà mọi người thường làm sai sau đó, đó là tác vụ làm mới, các dấu gạch chéo được mã hóa cho API di động và quyền sở hữu tệp.
FreshRSS 1.29.1 là bản release hiện tại tính đến tháng 7 năm 2026 và nó yêu cầu PHP 8.1 trở lên. Ubuntu 24.04 đi kèm với PHP 8.3, vì vậy các gói của bản phân phối là đủ và bạn không cần kho lưu trữ PHP của bên thứ ba.
Bắt đầu từ một LAMP stack đang hoạt động
FreshRSS là một ứng dụng PHP thông thường, vì vậy nó cần nền tảng giống như bất kỳ ứng dụng nào khác. Nếu bạn chưa xây dựng nền tảng đó, hãy làm theo hướng dẫn thiết lập LAMP stack trên Ubuntu 24.04 trước rồi quay lại đây. Tóm tắt ngắn gọn:
sudo apt update
sudo apt install -y apache2 mariadb-server php libapache2-mod-php
sudo systemctl enable --now apache2 mariadbsystemctl status apache2 sẽ báo active (running). Nếu Apache không khởi động được, nguyên nhân thường là do một tiến trình khác đang chiếm dụng port 80, và sudo ss -ltnp | grep :80 sẽ chỉ ra tiến trình đó.
Các PHP extension mà FreshRSS yêu cầu
FreshRSS coi libxml, cURL, JSON, PDO_MySQL, PCRE và ctype là bắt buộc. Nó cũng yêu cầu mbstring, iconv, Zlib, ZipArchive và GMP trên hệ thống 32 bit. Trên Ubuntu, các thành phần này được cung cấp dưới dạng các gói phân phối:
sudo apt install -y php-curl php-mbstring php-xml php-zip php-mysql php-intl php-gmp
sudo systemctl restart apache2Kiểm tra những gì PHP đã thực sự tải bằng php -m. Một extension bị thiếu sẽ không ngăn trình cài đặt khởi chạy. Nó sẽ dừng lại ở màn hình yêu cầu với một dòng màu đỏ nêu tên extension đó, đây là nơi gây khó hiểu để phát hiện vấn đề, vì vậy hãy xác nhận ngay bây giờ. Việc khởi động lại Apache rất quan trọng vì libapache2-mod-php giữ PHP bên trong tiến trình Apache, do đó một extension mới cài đặt sẽ không hiển thị với web server cho đến khi nó được khởi động lại.
Tải xuống bản phát hành
Cài đặt FreshRSS bên ngoài thư mục web root mặc định và trỏ Apache vào đó. Việc giữ thư mục ứng dụng tách biệt với document root giúp đảm bảo chỉ thư mục public mới có thể truy cập được qua HTTP.
cd /tmp
curl -fsSLO https://github.com/FreshRSS/FreshRSS/archive/refs/tags/1.29.1.tar.gz
tar xzf 1.29.1.tar.gz
sudo mv FreshRSS-1.29.1 /srv/freshrssBây giờ là phần phân quyền, nội dung mà tài liệu của FreshRSS yêu cầu rất nghiêm ngặt: người dùng web server phải sở hữu toàn bộ cây thư mục, group có quyền đọc mọi file và group có quyền ghi vào ./data/.
sudo chown -R www-data:www-data /srv/freshrss
sudo chmod -R g+r /srv/freshrss
sudo chmod -R g+w /srv/freshrss/dataBỏ qua bước này sẽ khiến trình cài đặt thất bại khi ghi cấu hình, vì PHP chạy dưới quyền www-data và www-data không thể ghi vào thư mục do root sở hữu.
Tạo cơ sở dữ liệu
FreshRSS hỗ trợ SQLite, MariaDB, MySQL và PostgreSQL. SQLite không cần thiết lập và phù hợp cho một người dùng với vài trăm feed. MariaDB là lựa chọn tốt hơn khi có nhiều người cùng chia sẻ instance, vì các thao tác ghi đồng thời từ tiến trình làm mới và giao diện web sẽ không còn tranh chấp khóa file đơn lẻ.
sudo mariadb -e "CREATE DATABASE freshrss CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
sudo mariadb -e "CREATE USER 'freshrss'@'localhost' IDENTIFIED BY 'ReplaceThisPassword';"
sudo mariadb -e "GRANT ALL PRIVILEGES ON freshrss.* TO 'freshrss'@'localhost';"
sudo mariadb -e "FLUSH PRIVILEGES;"Sử dụng utf8mb4 thay vì utf8. Các feed chứa emoji và các bộ ký tự không phải Latin, và mã hóa utf8 ba byte cũ sẽ cắt cụt tiêu đề bài viết tại ký tự bốn byte đầu tiên.
Apache virtual host
Thư mục public là p/, không phải là thư mục gốc của cây thư mục. Mọi thứ khác, bao gồm cả tệp cấu hình chứa mật khẩu cơ sở dữ liệu của bạn, đều nằm phía trên document root nơi Apache sẽ không bao giờ phục vụ nội dung.
<VirtualHost *:80>
ServerName rss.example.com
DocumentRoot /srv/freshrss/p/
<Directory /srv/freshrss/p>
AllowOverride AuthConfig FileInfo Indexes Limit
Require all granted
</Directory>
ErrorLog ${APACHE_LOG_DIR}/freshrss_error.log
CustomLog ${APACHE_LOG_DIR}/freshrss_access.log combined
AllowEncodedSlashes On
</VirtualHost>Lưu tệp đó dưới tên /etc/apache2/sites-available/freshrss.conf và kích hoạt nó:
sudo a2enmod rewrite
sudo a2ensite freshrss
sudo a2dissite 000-default
sudo apache2ctl configtest
sudo systemctl reload apache2configtest sẽ in ra Syntax OK. AllowEncodedSlashes On trông có vẻ tùy chọn nhưng thực tế không phải vậy: Google Reader API gửi các định danh feed chứa %2F, và nếu không có chỉ thị này, Apache sẽ từ chối chúng, khiến các ứng dụng di động không thể đồng bộ trong khi giao diện web vẫn hoạt động bình thường.
Thêm HTTPS trước khi đăng nhập
Bạn sắp nhập mật khẩu vào trang web này, vì vậy hãy lấy chứng chỉ trước. Trỏ một bản ghi A về server, sau đó làm theo hướng dẫn thiết lập Certbot cho Apache trên Ubuntu và chạy sudo certbot --apache -d rss.example.com. Certbot sẽ viết lại virtual host cho cổng 443 và thêm lệnh chuyển hướng. Xác nhận bằng curl -I https://rss.example.com/, lệnh này sẽ trả về 200 hoặc chuyển hướng đến trang đăng nhập.
Chạy trình cài đặt từ dòng lệnh
FreshRSS có trình cài đặt trên trình duyệt, nhưng phiên bản dòng lệnh có thể lặp lại và lưu lại hồ sơ chính xác về những gì bạn đã chọn.
sudo -u www-data php /srv/freshrss/cli/do-install.php \
--default-user admin --auth-type form --environment production \
--base-url https://rss.example.com --language en --api-enabled \
--db-type mysql --db-host localhost --db-user freshrss \
--db-password 'ReplaceThisPassword' --db-base freshrss
sudo -u www-data php /srv/freshrss/cli/create-user.php \
--user admin --password 'a-long-passphrase' --api-password 'a-different-passphrase'Chạy cả hai lệnh dưới quyền www-data. Chạy chúng dưới quyền root sẽ tạo ra các tệp cấu hình thuộc sở hữu của root, khiến giao diện web không thể lưu bất kỳ cài đặt nào sau đó. --environment production cũng rất quan trọng, vì cài đặt development sẽ in các thông báo PHP lên trang web.
Tải https://rss.example.com/ và đăng nhập với tư cách admin.
Tại sao các feed không tự động làm mới
Không có tiến trình nào tự động truy vấn feed của bạn trừ khi bạn thiết lập. FreshRSS chỉ làm mới khi bạn mở trình duyệt truy cập vào nó, nghĩa là nếu bạn chỉ ghé thăm mỗi ngày hai lần, các bài viết sẽ bị cũ mất mười hai tiếng. Giải pháp là sử dụng script mà dự án cung cấp cho việc này, app/actualize_script.php, được thực thi thông qua cron.
sudo crontab -u www-data -eThêm một dòng sau:
*/20 * * * * php /srv/freshrss/app/actualize_script.php > /tmp/FreshRSS.log 2>&1Hai mươi phút là khoảng thời gian tối thiểu hợp lý, vì script sẽ từ chối làm mới bất kỳ feed nào với tần suất dày hơn hai mươi phút một lần, nên việc đặt lịch dày hơn chỉ gây lãng phí CPU. Hãy chạy thử thủ công một lần trước:
sudo -u www-data php /srv/freshrss/app/actualize_script.phpKết quả trả về bình thường sẽ liệt kê tên từng feed đã được lấy dữ liệu và kết thúc mà không có lỗi PHP. Nếu không có bất kỳ thông tin nào được in ra, có thể người dùng chạy cron không đúng, và lỗi phân quyền trên data/ nghĩa là bạn đã bỏ qua bước chmod -R g+w.
Thêm các feed đầu tiên của bạn
Sử dụng nút dấu cộng ở phía trên bên trái giao diện, dán địa chỉ trang web vào, và FreshRSS sẽ tự động tìm liên kết feed cho bạn. Hầu hết các trang web vẫn xuất bản feed ngay cả khi họ không quảng bá nó, thường là tại /feed, /rss hoặc /atom.xml. Các danh mục đóng vai trò như thư mục, và việc di chuyển một feed giữa các danh mục này chỉ cần thao tác kéo thả.
Nếu bạn chuyển từ một trình đọc khác, hãy xuất tệp OPML từ đó và nhập vào trang quản lý đăng ký. OPML (outline processor markup language) là định dạng danh sách feed tiêu chuẩn, và mọi trình đọc đáng dùng đều hỗ trợ nó. Một lần nhập dữ liệu lớn sẽ chạy chậm trong lần làm mới đầu tiên vì mỗi feed đều được tải về một lần, vì vậy hãy để cron chạy xong trước khi bạn đánh giá tốc độ.
Đọc trên điện thoại của bạn
FreshRSS hỗ trợ Google Reader API, giao thức mà hầu hết các ứng dụng RSS đều tương thích. Bạn cần đảm bảo hai điều kiện. Trong phần cài đặt xác thực, tùy chọn "Allow API access" phải được bật, điều này đã được thực hiện bởi flag --api-enabled ở trên. Trong hồ sơ của bạn, trường API password phải có giá trị; nó được tách biệt với mật khẩu đăng nhập vì điện thoại là thiết bị dễ bị thất lạc.
Truy cập https://rss.example.com/api/ và chọn "Check full server configuration". Một cấu hình hoạt động bình thường sẽ trả về PASS. Lỗi ở bước này hầu như luôn do thiếu dòng AllowEncodedSlashes On. Trong ứng dụng, hãy nhập địa chỉ máy chủ là https://rss.example.com/api/greader.php, tên người dùng là tài khoản FreshRSS của bạn và mật khẩu API là mật khẩu đã thiết lập.
Giải pháp thay thế Docker
Nếu bạn không muốn tự tay bảo trì PHP và Apache, dự án có phát hành một image freshrss/freshrss chính thức, và một file compose sẽ cung cấp cho bạn ứng dụng cùng cơ sở dữ liệu đi kèm. Sự đánh đổi ở đây là điều thường thấy: ít thành phần chạy trực tiếp trên host hơn, nhưng thêm một lớp cần debug khi có sự cố, và bạn vẫn cần một reverse proxy để xử lý TLS (transport layer security). Nếu cách này phù hợp với bạn hơn, các kiến thức cơ bản về Docker Compose cho VPS sẽ bao gồm định dạng file, và dòng cron sẽ trở thành docker exec --user www-data freshrss php ./app/actualize_script.php.
Sao lưu và nâng cấp
Có hai thành phần lưu giữ trạng thái của bạn: cơ sở dữ liệu và /srv/freshrss/data/. Hãy dump thành phần thứ nhất bằng sudo mysqldump freshrss > freshrss.sql, sao chép thành phần thứ hai, và lưu trữ cả hai ở một nơi khác ngoài server này. Danh sách đăng ký của bạn cũng nên được xuất ra định dạng OPML định kỳ, vì tệp đó giúp khôi phục thiết lập đọc tin trên bất kỳ phần mềm RSS nào.
Việc nâng cấp chỉ đơn giản là giải nén bản release mới hơn đè lên cùng thư mục đó và chạy lại các lệnh phân quyền sở hữu. FreshRSS sẽ tự động áp dụng các migration cơ sở dữ liệu trong lần tải trang tiếp theo. Hãy sao lưu trước, vì một quá trình migration thất bại trên cơ sở dữ liệu mà bạn không thể khôi phục sẽ dẫn đến tình trạng không thể cứu vãn. Trình đọc tin là một dịch vụ có rủi ro thấp và là ứng viên phù hợp để bắt đầu nếu bạn đang xem qua danh sách các dịch vụ đáng để tự host.
FAQ
Tại sao các feed của tôi chỉ cập nhật khi tôi mở FreshRSS?
Vì không có trình lập lịch nào tồn tại cho đến khi bạn tạo ra nó. FreshRSS làm mới các feed khi phiên trình duyệt đang mở và không làm gì cả khi tab bị đóng. Hãy thêm dòng cron gọi app/actualize_script.php với tư cách là người dùng www-data, sau đó chạy thủ công script này một lần và đọc kết quả đầu ra. Sự im lặng thường có nghĩa là cron đang chạy nó với sai người dùng, khiến PHP không thể ghi vào data/.
Ứng dụng di động của tôi không thể kết nối, nhưng trang web vẫn hoạt động. Tại sao?
Google Reader API đặt các dấu gạch chéo được mã hóa (%2F) bên trong các đường dẫn yêu cầu, và Apache mặc định từ chối các yêu cầu đó. Hãy thêm AllowEncodedSlashes On vào bên trong virtual host và tải lại Apache. Xác nhận sửa lỗi bằng cách mở https://rss.example.com/api/ và chạy "Check full server configuration", kết quả sẽ báo PASS. Ngoài ra, hãy kiểm tra xem mật khẩu API đã được thiết lập trong hồ sơ của bạn chưa, vì nó tách biệt với mật khẩu đăng nhập của bạn.
Tôi nên sử dụng SQLite hay MariaDB?
Sử dụng SQLite cho một người dùng, vì không có gì cần cài đặt và không cần quản lý mật khẩu. Sử dụng MariaDB khi có nhiều hơn một người đọc trên instance, hoặc khi bạn vượt quá vài trăm feed, vì tác vụ làm mới và giao diện web ghi dữ liệu cùng lúc và khóa file đơn lẻ sẽ trở thành giới hạn. Việc chuyển đổi giữa chúng sau này là có thể thông qua các lệnh export và import, vì vậy đây không phải là quyết định vĩnh viễn.
Trình cài đặt bị lỗi khi ghi cấu hình. Có vấn đề gì vậy?
PHP chạy dưới quyền www-data trên Apache, và người dùng đó không thể ghi vào thư mục thuộc sở hữu của root. Hãy chạy lại sudo chown -R www-data:www-data /srv/freshrss và sudo chmod -R g+w /srv/freshrss/data, sau đó bắt đầu lại trình cài đặt. Nếu bạn đã chạy trình cài đặt dòng lệnh với quyền root, hãy xóa các file mà nó đã tạo trong data/ trước khi thử lại, vì quyền sở hữu của chúng chính là vấn đề thực sự.
Một trình đọc RSS tự lưu trữ cần bao nhiêu tài nguyên máy chủ?
Rất ít. Vài trăm feed trên một gói nhỏ là thoải mái, vì tải trọng chỉ là các đợt truy xuất HTTP ngắn sau mỗi hai mươi phút và cơ sở dữ liệu vẫn nhỏ gọn sau khi các bài viết cũ bị xóa. Dung lượng đĩa tăng theo thời gian lưu trữ, vì vậy hãy thiết lập chính sách xóa bài viết trong cài đặt lưu trữ thay vì giữ lại mọi thứ mãi mãi.