SSD Nodes Learn メモリ 8GB — 年額 $66
ガイド Matt Connor著者 Matt Connor ・更新日 2026-08-01

Ubuntu VPSにFreshRSSをインストールする方法

Ubuntu 24.04 VPSにFreshRSS 1.29.1を導入します。Apache、PHP 8.3、MariaDBの設定からrelease展開、virtual host、cron更新、モバイルAPI対応まで解説します。

構築するもの

セルフホスト型RSSリーダーは、自分が所有するサーバー上で動作するフィードリーダーです。そのため、他者が停止したり、表示内容を変更したりすることはできません。このガイドでは、Ubuntu 24.04 VPSにFreshRSSを構築します。前段にApache、アプリケーション側にPHP、データ保存にMariaDBを使用し、新しい記事を取得するcronジョブを1つ設定します。RSS(really simple syndication)は、ソフトウェアが記事を読み取れるように、サイトが公開するファイル形式です。FreshRSSは、これらのファイルを収集して記事を保存し、Webインターフェースと、スマートフォンアプリが通信するAPI(application programming interface)を提供するPHPアプリケーションです。

インストール自体は簡単です。releaseを展開し、データベースを作成し、virtual hostを1つ記述して、コマンドラインインストーラーを1つ実行します。以下で説明する作業の大半は、その後に誤りやすい部分です。具体的には、更新ジョブ、モバイルAPI用のエンコード済みスラッシュ、ファイルの所有権です。

FreshRSS 1.29.1は2026年7月時点のcurrent releaseで、PHP 8.1以降が必要です。Ubuntu 24.04にはPHP 8.3が付属するため、distribution packageだけで十分です。third-party PHP repositoryは必要ありません。

動作するLAMPスタックから始める

FreshRSSは通常のPHPアプリケーションです。そのため、他の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 プロセス内で実行するため、新しくインストールした拡張機能は、Apache を再起動するまで Web サーバーから認識されません。

リリースをダウンロードする

FreshRSSをデフォルトのWebルートの外部にインストールし、Apacheがそこを参照するように設定します。アプリケーションディレクトリをドキュメントルートから分離すると、HTTP経由で到達できるのはpublicフォルダーだけになります。

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のドキュメントでは、この設定が厳密に指定されています。Webサーバーのユーザーがツリーを所有し、グループにはすべてのファイルの読み取り権限を付与し、グループは./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 はセットアップが不要で、数百件のフィードを1人で使用する場合に適しています。複数人でインスタンスを共有する場合は、MariaDB が適しています。更新ジョブと Web インターフェースによる同時書き込みで、1つのファイルロックを奪い合わなくなるためです。

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

utf8 ではなく utf8mb4 を使用します。フィードには絵文字や非ラテン文字のスクリプトが含まれます。旧式の3バイト utf8 エンコーディングでは、4バイト文字が最初に現れた位置で記事タイトルが切り詰められます。

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は識別子を拒否するため、Webインターフェースは正常に動作してもモバイルアプリは同期に失敗します。

ログインする前に 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が所有する設定ファイルが作成されます。その後、Webインターフェースで設定を保存できなくなります。--environment productionも重要です。開発用設定を有効にすると、PHPのnoticeがページに表示されます。

https://rss.example.com/を読み込み、adminとしてログインします。

フィードが自動で更新されない理由

指示しない限り、フィードのポーリングは行われません。FreshRSSはブラウザーで開いている間に更新されます。そのため、1日に2回アクセスするインスタンスでは、12時間前の記事が表示されます。対処方法は、プロジェクトがこの用途向けに提供しているスクリプト app/actualize_script.php をcronから実行することです。

sudo crontab -u www-data -e

次の1行を追加します。

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

20分が現実的な下限です。このスクリプトは、各フィードを20分に1回より頻繁には更新しないためです。これより短い間隔にしてもCPUを消費するだけです。まず手動で1回実行します。

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)は標準のフィードリスト形式です。移行に対応しているリーダーはすべて、この形式をサポートしています。大量にインポートすると、最初の更新に時間がかかります。すべてのフィードを1回取得するためです。速度を判断する前に、最初の cron 実行が完了するまで待ってください。

スマートフォンで読む

FreshRSSはGoogle Reader APIに対応しており、ほとんどのRSSアプリで利用できます。2つの条件を満たす必要があります。認証設定で「APIアクセスを許可」が有効になっている必要があります。これは、上記の--api-enabledフラグです。プロフィールでAPIパスワードに値を設定する必要があります。スマートフォンは紛失しやすいため、APIパスワードはログインパスワードとは意図的に別になっています。

https://rss.example.com/api/にアクセスし、「サーバー設定全体を確認」を選択します。正常な設定ではPASSが返されます。ここで失敗する場合、そのほとんどはAllowEncodedSlashes On行がないことが原因です。アプリでは、サーバーアドレスにhttps://rss.example.com/api/greader.php、ユーザー名にFreshRSSのユーザー名、パスワードにAPIパスワードを指定します。

Dockerの代替

PHPとApacheを手動で保守したくない場合は、プロジェクトが公式のfreshrss/freshrssイメージを公開しています。composeファイルを1つ用意するだけで、アプリケーションとデータベースをまとめて構成できます。一般的なトレードオフもあります。ホスト上の構成要素は減りますが、問題が発生したときにデバッグする層は1つ増えます。また、TLS(トランスポート層セキュリティ)には引き続きリバースプロキシが必要です。この方法が適している場合は、VPS向けDocker Composeの基本でファイル形式を確認できます。cronの行はdocker exec --user www-data freshrss php ./app/actualize_script.phpになります。

バックアップとアップグレード

状態を保持するものは、データベースと /srv/freshrss/data/ の2つです。前者は sudo mysqldump freshrss > freshrss.sql でダンプし、後者をコピーして、両方をこのサーバー以外の場所に保管してください。購読リストも、ときどき OPML としてエクスポートする価値があります。このファイルがあれば、どの RSS ソフトウェアでも読書環境を再構築できます。

アップグレードでは、同じディレクトリに新しいリリースを展開し、所有権のコマンドを再実行します。FreshRSS は、次回のページ読み込み時に独自のデータベースマイグレーションを適用します。復元できないデータベースでマイグレーションに失敗すると復旧できないため、先にバックアップしてください。リーダーは低リスクで運用できるサービスであり、セルフホスティングする価値があるものの一覧を検討している場合の最初の候補に適しています。

FAQ

FreshRSSを開いたときだけフィードが更新されるのはなぜですか?

スケジューラは作成するまで存在しないためです。FreshRSSはブラウザーセッションが開いている間にフィードを更新し、タブを閉じると何もしません。www-data ユーザーとして app/actualize_script.php を呼び出す cron の行を追加し、その後、スクリプトを手動で1回実行して出力を確認してください。何も出力されない場合は、通常、cronが誤ったユーザーとして実行されているため、PHPが data/ に書き込めません。

モバイルアプリから接続できませんが、Webサイトは動作します。なぜですか?

Google Reader APIはリクエストパス内にエンコードされたスラッシュ(%2F)を含めます。Apacheはデフォルトでこれを拒否します。仮想ホスト内に AllowEncodedSlashes On を追加し、Apacheをreloadしてください。https://rss.example.com/api/ を開いて「Check full server configuration」を実行し、PASS と報告されることを確認してください。APIパスワードはログインパスワードとは別なので、プロフィールで設定されていることも確認してください。

SQLiteとMariaDBのどちらを使用すべきですか?

単一ユーザーの場合はSQLiteを使用してください。インストールするものがなく、管理するパスワードもないためです。インスタンスを複数人で使用する場合、またはフィード数が数百を超える場合はMariaDBを使用してください。更新ジョブとWebインターフェースが同時に書き込みを行い、単一ファイルのロックが制限になるためです。後からexportコマンドとimportコマンドで移行できるため、永続的な選択ではありません。

インストーラーが設定を書き込むときに失敗します。何が問題ですか?

ApacheではPHPが 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