SSD Nodes Learn Hosting plans →
指南 Matt Connor作者: Matt Connor

Ubuntu 24.04 自架 FreshRSS 教學:安裝與設定指南

在 Ubuntu 24.04 VPS 上部署 FreshRSS。本指南涵蓋 Apache 設定、MariaDB 資料庫建立、PHP 擴充功能安裝、cron 自動更新排程以及行動版 API 的正確配置方式。

您要建置的內容

自架 RSS 閱讀器是在您擁有的伺服器上執行的 feed reader,因此不會有人能將其關閉,或變更它顯示給您的內容。本指南會在 Ubuntu 24.04 VPS 上部署 FreshRSS:前端使用 Apache、後端使用 PHP、以 MariaDB 儲存資料,並設定一個會抓取新文章的 cron 工作。RSS(really simple syndication)是網站發布的檔案格式,讓軟體能讀取網站文章。FreshRSS 是以 PHP 撰寫的應用程式,負責收集這些檔案、保存文章,並提供網頁介面與 API(application programming interface),讓手機應用程式能與其通訊。

安裝本身並不複雜:解開 release、建立資料庫、撰寫一個 virtual host、執行 command line installer,然後使用 cli/create-user.php 建立帳戶。以下大部分內容都在處理安裝後最容易出錯的部分,包括更新工作、行動 API 使用的 encoded slashes,以及檔案擁有權。

FreshRSS 1.30.4 於 October 21, 2026 發布,截至 October 29, 2026 為目前的 release,且需要 PHP 8.1 或更新版本。Ubuntu 24.04 隨附 PHP 8.3,因此使用 distribution packages 即可,不需要第三方 PHP repository。

從運作中的 LAMP 環境開始

FreshRSS 是一般的 PHP 應用程式,因此它需要與其他應用程式相同的基礎環境。若您尚未建立該基礎,請先依照 Ubuntu 24.04 的 LAMP 環境建置指南 進行設定,完成後再回到此處。簡要說明如下:

sudo apt update
sudo apt install -y apache2 mariadb-server php libapache2-mod-php
sudo systemctl enable --now apache2 mariadb

systemctl status apache2 應顯示 active (running)。若 Apache 無法啟動,通常是因為其他處理程序已佔用 port 80,此時可透過 sudo ss -ltnp | grep :80 找出該程序。

FreshRSS 所需的 PHP 擴充功能

FreshRSS 將 libxml、cURL、JSON、PDO_MySQL、PCRE 與 ctype 視為必要項目。此外,它也需要 mbstring、iconv、Zlib 與 ZipArchive,若在 32 位元系統上則還需要 GMP。在 Ubuntu 上,這些項目可透過發行版套件安裝:

sudo apt install -y php-curl php-mbstring php-xml php-zip php-mysql php-intl php-gmp
sudo systemctl restart apache2

請使用 php -m 檢查 PHP 實際載入的項目。若缺少擴充功能,安裝程式仍會啟動,但會停在需求檢查畫面並以紅字標示缺少的擴充功能名稱。在該處發現問題會造成困擾,因此請務必先行確認。重新啟動 Apache 至關重要,因為 libapache2-mod-php 會將 PHP 保留在 Apache 進程中,導致新安裝的擴充功能在重啟網頁伺服器前無法被偵測到。

下載發行版本

將 FreshRSS 安裝在預設網站根目錄之外,並讓 Apache 指向該位置。將應用程式目錄與文件根目錄分開,可確保透過 HTTP 存取的只有公開目錄。

cd /tmp
curl -fsSLO https://github.com/FreshRSS/FreshRSS/archive/refs/tags/1.30.4.tar.gz
tar xzf 1.30.4.tar.gz
sudo mv FreshRSS-1.30.4 /srv/freshrss

接著設定權限。FreshRSS 文件對此有嚴格要求:網站伺服器使用者擁有整個目錄樹,群組可讀取所有檔案,且群組可寫入 ./data/。

sudo chown -R www-data:www-data /srv/freshrss
sudo chmod -R g+r /srv/freshrss
sudo chmod -R g+w /srv/freshrss/data

若略過此步驟,安裝程式會在寫入設定時失敗,因為 PHP 以 www-data 執行,而 www-data 無法寫入由 root 擁有的目錄。

建立資料庫

FreshRSS 支援 SQLite、MariaDB、MySQL 與 PostgreSQL。SQLite 需要 php-sqlite3 擴充功能,但不需要設定資料庫伺服器,並會將每位使用者的資料儲存在獨立的 data/users/_user_/db.sqlite 檔案中。新增使用者不會將其寫入內容放入同一個共用的 SQLite 檔案;本指南會使用 LAMP stack 中的 MariaDB。

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;"

請使用 utf8mb4,不要使用 utf8。Feed 可能包含 emoji 與非拉丁文字,而舊的 3-byte utf8 編碼無法儲存 4-byte 字元。在 MariaDB 預設的 strict mode 下,無法支援的字元會造成錯誤;是否截斷則取決於 SQL mode,以及 IGNORE 等 statement 選項。

Apache 虛擬主機

公開目錄為 p/,而非目錄樹的頂層。其餘所有檔案(包含存放資料庫密碼的設定檔)皆位於文件根目錄之外,Apache 永遠不會對外提供這些檔案。

<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>

將其儲存為 /etc/apache2/sites-available/freshrss.conf 並啟用:

sudo a2enmod rewrite
sudo a2ensite freshrss
sudo a2dissite 000-default
sudo apache2ctl configtest
sudo systemctl reload apache2

configtest 應顯示 Syntax OK。AllowEncodedSlashes On 看似可選,實則不然:Google Reader API 會發送包含 %2F 的訂閱識別碼,若無此指令,Apache 將會拒絕請求,導致網頁介面運作正常,但行動應用程式無法同步。

在登入前新增 HTTPS

您即將在此網站輸入密碼,請先取得憑證。將 A 記錄指向伺服器,接著依照 Ubuntu 上 Apache 的 Certbot 設定 操作並執行 sudo certbot --apache -d rss.example.com。Certbot 會重寫連接埠 443 的虛擬主機並新增重新導向。請使用 curl -I https://rss.example.com/ 確認,該指令應回傳 200 或重新導向至登入頁面。

從命令列執行安裝程式

FreshRSS 提供瀏覽器安裝程式,但命令列版本可重複執行,並能精確記錄您的選擇。

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'

請以 www-data 身分執行這兩項指令。若以 root 身分執行,會導致產生的設定檔由 root 擁有,進而造成網頁介面後續無法儲存任何設定。--environment production 也同樣重要,因為開發模式設定會將 PHP 通知訊息輸出至頁面中。

載入 https://rss.example.com/ 並以 admin 身分登入。

為什麼動態消息不會自行更新

在你設定之前,沒有任何程序會輪詢動態消息。開啟 FreshRSS 不會排程擷取動態消息;如果沒有排程器,請使用導覽選單中的更新連結,手動擷取文章。解決方式是使用專案隨附的專用指令碼 app/actualize_script.php,並從 cron 執行。

sudo crontab -u www-data -e

新增一行:

*/20 * * * * php /srv/freshrss/app/actualize_script.php > /tmp/FreshRSS.log 2>&1

每 20 分鐘執行一次是合理的排程,但每個動態消息仍會套用自己的更新間隔:預設為 1 小時,個別動態消息則支援最低 15 分鐘的間隔。先手動執行一次:

sudo -u www-data php /srv/freshrss/app/actualize_script.php

正常輸出會回報更新作業,並在結尾沒有 PHP 錯誤;加入或更新文章時,輸出中會顯示動態消息名稱。如果完全沒有輸出,請檢查 PHP 的錯誤輸出與 FreshRSS 日誌;單憑沒有輸出,無法判定原因是 cron 使用者。若 data/ 發生權限錯誤,請檢查其擁有者與寫入權限。

新增您的第一個訂閱源

使用介面左上角的加號按鈕,貼上網站網址,FreshRSS 會自動為您偵測訂閱連結。大多數網站即使未明確標示,通常也會在 /feed、/rss 或 /atom.xml 提供訂閱源。分類即為資料夾,您可以透過拖曳方式在分類間移動訂閱源。

若您是從其他閱讀器遷移過來,請先在該處匯出 OPML 檔案,並在訂閱管理頁面進行匯入。OPML (Outline Processor Markup Language) 是訂閱列表的標準格式,所有值得使用的閱讀器皆支援此格式。若匯入數量龐大,首次重新整理時速度會較慢,因為系統需要逐一擷取每個訂閱源,請在評估效能前,先給予 cron 執行一次的時間。

在手機上閱讀

FreshRSS 支援許多 RSS 應用程式使用的 Google Reader API。以下兩項條件都必須成立。在驗證設定中,必須啟用「Allow API access」;上方的 --api-enabled 旗標已完成此設定。在個人檔案中,API password 欄位必須有值。這個密碼刻意與登入密碼分開,因為手機較容易遺失。

前往 https://rss.example.com/api/,自動執行伺服器設定檢查。設定正常時會回傳 PASS。如果檢查失敗,請檢查虛擬主機的 AllowEncodedSlashes On 設定和顯示的錯誤。在應用程式中,將伺服器位址設為 https://rss.example.com/api/greader.php,使用你的 FreshRSS 使用者名稱,並將 API password 設為密碼。

Docker 的替代方案

如果您不想手動維護 PHP 和 Apache,該專案有發布官方的 freshrss/freshrss 映像檔,且只需一個 compose 檔案即可同時部署應用程式及其資料庫。這涉及常見的取捨:主機上的組件較少,但若發生故障時會多出一層需要除錯,且仍需反向代理伺服器來處理 TLS (傳輸層安全性)。若此方式更適合您,VPS 的 Docker Compose 基礎教學 涵蓋了檔案格式,而 cron 排程指令則變更為 docker exec --user www-data freshrss php ./app/actualize_script.php。

備份與升級

有兩項資料保存了您的狀態:資料庫與 /srv/freshrss/data/。使用 sudo mysqldump freshrss > freshrss.sql 傾印前者,複製後者,並將兩者儲存於這台伺服器以外的位置。訂閱清單也值得定期匯出為 OPML,因為該檔案可將您的 feed 清單移轉至其他支援 OPML 的閱讀器。但它不會保留 FreshRSS 專屬設定,例如更新頻率、認證資訊、user agent 或 XPath 網頁擷取規則;若要一併保留這些設定,請使用 SQLite 匯出。

升級方式是將較新的 release 解壓縮至相同目錄,然後重新執行擁有權設定指令。請依照專案逐版本的升級路徑操作,並在每個步驟後確認 FreshRSS 是否正常。FreshRSS 會在下一次載入頁面時執行自身的資料庫 migration。請先備份,因為若 migration 失敗,而您又無法還原資料庫,就無法復原。若您是從 1.29.1 等較舊的 tarball 安裝,請升級至 1.30.4:1.30.x 的安全性 release 包含在認證變更時輪替 session ID,以及限制 ZIP 匯入範圍;1.30.4 也更新了替代的 Alpine Docker images,以修補嚴重的 PHP 漏洞。閱讀器服務的執行風險低,若您正在整理值得自行託管的服務清單,它很適合作為第一個項目。

FAQ

為什麼只有開啟 FreshRSS 時,訂閱來源才會更新?

開啟頁面不會排程抓取訂閱來源。沒有排程器時,請使用更新連結手動重新整理。以 www-data 使用者身分加入呼叫 app/actualize_script.php 的 cron 設定列,然後手動執行一次該指令碼並查看輸出。如果沒有任何輸出,請檢查 PHP 的錯誤輸出與 FreshRSS 日誌,再確認 cron 使用者對 data/ 具備寫入權限。

為什麼行動應用程式無法連線,但網站可以正常使用?

Google Reader API 會在請求路徑中放入編碼斜線(%2F),而 Apache 預設會拒絕這類請求。在虛擬主機設定中加入 AllowEncodedSlashes On,然後重新載入 Apache。開啟 https://rss.example.com/api/,確認自動設定檢查是否回報 PASS,以驗證修正結果。另外也請確認個人檔案中已設定 API 密碼,因為它與登入密碼分開。

應該使用 SQLite 還是 MariaDB?

SQLite 需要 php-sqlite3 擴充功能,但不需要管理資料庫伺服器或資料庫密碼。每位使用者都會取得獨立的 SQLite 資料庫檔案,因此新增第二位使用者不會造成同一個共用檔案的競爭,也不需要 MariaDB。若希望使用 LAMP stack 中的資料庫伺服器,請選擇 MariaDB。之後仍可透過匯出與匯入指令在兩者之間移轉,因此這不是永久性的決定。

安裝程式寫入設定時失敗。問題在哪裡?

Apache 會以 www-data 身分執行 PHP,而該使用者無法寫入 root 擁有的目錄。重新執行 sudo chown -R www-data:www-data /srv/freshrss 和 sudo chmod -R g+w /srv/freshrss/data,然後再次啟動安裝程式。如果先前已以 root 執行命令列安裝程式,請先修正它在 data/ 下建立之檔案的擁有權,再重試。

自架 RSS 閱讀器需要多少伺服器資源?

需求很低。FreshRSS 設計為可在資源有限的硬體上執行,但資源使用量取決於訂閱來源數量、文章大小與保留設定。磁碟使用量會隨保留內容增加,因此請在封存設定中設定文章清理政策,不要永久保留所有文章。

這篇文章對您有幫助嗎?