SSD Nodes Learn 8GB 記憶體 — 每年 $66
指南 Matt Connor作者: Matt Connor · 已更新 2026-08-01

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

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

您將建置的內容

自架 RSS 閱讀器是運行於您自有伺服器上的訂閱閱讀器,確保無人能將其關閉或竄改顯示內容。本指南將在 Ubuntu 24.04 VPS 上部署 FreshRSS:前端使用 Apache,後端使用 PHP,資料庫使用 MariaDB,並透過一個 cron job 定期抓取新文章。RSS (Really Simple Syndication) 是網站發布內容的檔案格式,供軟體讀取文章。FreshRSS 是一款 PHP 應用程式,負責收集這些檔案、儲存文章,並提供網頁介面與手機應用程式使用的 API (Application Programming Interface)。

安裝過程相當精簡:解壓縮 release、建立資料庫、編寫一個虛擬主機設定檔,並執行一次命令列安裝程式。以下大部分工作在於後續容易出錯的環節,即重新整理任務、行動版 API 的編碼斜線處理,以及檔案擁有權設定。

截至 2026 年 7 月,FreshRSS 1.29.1 為當前版本,需搭配 PHP 8.1 或更新版本。Ubuntu 24.04 內建 PHP 8.3,因此使用發行版套件即可,無需額外安裝第三方 PHP 套件庫。

從運作中的 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 指向該目錄。將應用程式目錄與文件根目錄分開,可確保僅有 public 資料夾能透過 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/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 無需額外設定,適合單人使用且訂閱數在數百個以內的場景。若有多人共用此實例,建議選擇 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。訂閱內容包含表情符號與非拉丁語系文字,舊有的三位元組 utf8 編碼會導致文章標題在遇到第一個四位元組字元時被截斷。

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

建議設定為二十分鐘,因為該指令碼拒絕在二十分鐘內重複更新同一個訂閱來源,設定過於頻繁只會浪費 CPU 資源。請先手動執行一次:

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

正常的輸出會列出每個已擷取的訂閱來源,並在結束時不顯示任何 PHP 錯誤。若完全沒有輸出,代表 cron 使用者設定錯誤;若 data/ 出現權限錯誤,則表示跳過了 chmod -R g+w 的步驟。

新增您的第一個訂閱源

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

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

在手機上閱讀

FreshRSS 支援 Google Reader API,幾乎所有 RSS 應用程式皆可使用。必須滿足兩個條件。在驗證設定中,必須開啟「Allow API access」,上述 --api-enabled 旗標已完成此設定。在您的個人資料中,API password 欄位必須填入數值;此密碼與您的登入密碼分開,因為手機較容易遺失。

請前往 https://rss.example.com/api/ 並選擇「Check full server configuration」。設定正確時會回傳 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 匯出資料庫,並複製 /srv/freshrss/data/,將兩者儲存於本伺服器之外。訂閱清單亦建議定期匯出為 OPML 格式,此檔案可在任何 RSS 軟體上重建您的閱讀環境。

升級方式為將新版本解壓縮至相同目錄,並重新執行擁有權變更指令。FreshRSS 會在下次載入頁面時自動執行資料庫遷移。請務必先進行備份,因為若資料庫遷移失敗且無法還原,將導致系統無法復原。RSS 閱讀器屬於低風險服務,若您正在參考 值得自行架設的服務清單,它是極佳的入門選擇。

FAQ

為什麼我的訂閱源只有在開啟 FreshRSS 時才會更新?

因為在您建立排程器之前,系統不會自動執行更新。FreshRSS 僅在瀏覽器工作階段開啟時更新訂閱源,關閉分頁後即停止運作。請以 www-data 使用者身分新增呼叫 app/actualize_script.php 的 cron 項目,接著手動執行一次指令碼並檢查輸出。若無任何輸出,通常代表 cron 以錯誤的使用者身分執行,導致 PHP 無法寫入 data/

我的行動應用程式無法連線,但網站運作正常,為什麼?

Google Reader API 會在請求路徑中加入編碼斜線 (%2F),而 Apache 預設會拒絕此類請求。請在虛擬主機設定中加入 AllowEncodedSlashes On 並重新載入 Apache。您可以開啟 https://rss.example.com/api/ 並執行「檢查完整伺服器設定」(Check full server configuration) 來確認修復結果,系統應顯示 PASS。此外,請確認您已在個人檔案中設定 API 密碼,該密碼與您的登入密碼不同。

我應該使用 SQLite 還是 MariaDB?

若為單一使用者,請使用 SQLite,因為無需安裝任何軟體,也不需管理密碼。若有多人使用該實例,或訂閱源數量超過數百個,請使用 MariaDB;因為更新作業與網頁介面會同時寫入資料庫,單一檔案鎖定機制將成為效能瓶頸。日後可透過匯出與匯入指令在兩者間轉換,因此這並非永久性的決定。

安裝程式在寫入設定檔時失敗,出了什麼問題?

PHP 在 Apache 下以 www-data 身分執行,該使用者無法寫入由 root 擁有的目錄。請重新執行 sudo chown -R www-data:www-data /srv/freshrsssudo chmod -R g+w /srv/freshrss/data,然後再次啟動安裝程式。若您已使用 root 身分執行過命令列安裝程式,請先刪除 data/ 下建立的檔案再重試,因為檔案擁有權才是問題所在。

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

需求極低。在小型方案上處理數百個訂閱源非常輕鬆,因為負載僅限於每 20 分鐘一次的短暫 HTTP 抓取,且在清除舊文章後資料庫體積會保持精簡。磁碟空間需求隨保留策略增加,建議在封存設定中設定文章清除原則,而非永久保留所有內容。

#freshrss#rss#self-hosting#php#apache