آموزش نصب FreshRSS روی سرور مجازی Ubuntu
راهنمای کامل نصب FreshRSS روی Ubuntu 24.04 با Apache و MariaDB. یاد بگیرید چگونه دیتابیس را تنظیم کنید، cron job برای بهروزرسانی بسازید و خطاهای API موبایل را رفع کنید.
آنچه در حال ساخت آن هستید
یک RSS reader خود-میزبان (self-hosted)، نرمافزاری برای خواندن فیدها است که روی سرور شخصی شما اجرا میشود؛ بنابراین هیچکس نمیتواند آن را متوقف کند یا محتوایی که به شما نمایش داده میشود را تغییر دهد. این راهنما FreshRSS را روی یک VPS با سیستمعامل Ubuntu 24.04 نصب میکند: Apache در لایه جلو، PHP در پسزمینه، MariaDB برای ذخیرهسازی، و یک cron job که مقالات جدید را دریافت میکند. RSS (مخفف Really Simple Syndication) فرمت فایلی است که یک وبسایت منتشر میکند تا نرمافزارها بتوانند مقالات آن را بخوانند. FreshRSS یک برنامه PHP است که این فایلها را جمعآوری کرده، مقالات را نگهداری میکند و یک رابط کاربری وب به همراه یک API (رابط برنامهنویسی اپلیکیشن) که اپلیکیشنهای موبایل با آن ارتباط برقرار میکنند، در اختیار شما قرار میدهد.
فرآیند نصب بسیار ساده است: استخراج یک release، ایجاد یک دیتابیس، نوشتن یک virtual host و اجرای یک نصبکننده خط فرمان. بخش عمدهای از کارهایی که در ادامه میآید، مربوط به مواردی است که کاربران معمولاً پس از نصب دچار اشتباه میشوند؛ یعنی تنظیم وظیفه بهروزرسانی (refresh job)، مدیریت اسلشهای کدگذاریشده برای API موبایل و تعیین مالکیت فایلها.
نسخه FreshRSS 1.29.1 نسخه فعلی تا جولای 2026 است و به PHP 8.1 یا جدیدتر نیاز دارد. سیستمعامل Ubuntu 24.04 به همراه PHP 8.3 عرضه میشود، بنابراین بستههای موجود در مخازن توزیع کافی هستند و نیازی به استفاده از مخازن PHP شخص ثالث ندارید.
شروع از یک LAMP stack فعال
برنامه FreshRSS یک اپلیکیشن PHP معمولی است، بنابراین به همان زیرساختی نیاز دارد که سایر برنامهها به آن وابسته هستند. اگر هنوز این زیرساخت را آماده نکردهاید، ابتدا راهنمای راهاندازی LAMP stack برای Ubuntu 24.04 را دنبال کنید و سپس به اینجا بازگردید. خلاصه مراحل:
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 اجرا نمیشود، دلیل معمول آن است که پردازش دیگری پورت 80 را اشغال کرده است؛ دستور sudo ss -ltnp | grep :80 نام آن پردازش را مشخص میکند.
افزونههای PHP مورد نیاز برای FreshRSS
برنامه 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 را به آن ارجاع دهید. جدا نگه داشتن دایرکتوری برنامه از document root باعث میشود که تنها پوشه 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 نیازی به پیکربندی ندارد و برای استفاده یک نفر با چند صد فید مناسب است. اگر چندین نفر از یک نمونه (instance) استفاده میکنند، MariaDB انتخاب بهتری است؛ زیرا در این حالت، نوشتن همزمان توسط فرآیند بهروزرسانی (refresh job) و رابط کاربری وب، دیگر باعث ایجاد تداخل در قفل فایل (file lock) نمیشود.
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/ است، نه بالاترین سطح درخت فایلها. سایر موارد، از جمله فایل پیکربندی که رمز عبور پایگاه داده شما در آن قرار دارد، در سطحی بالاتر از document root قرار میگیرند تا 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 apache2configtest باید Syntax OK را چاپ کند. AllowEncodedSlashes On اختیاری به نظر میرسد اما چنین نیست: Google Reader API شناسههای فیدی ارسال میکند که حاوی %2F هستند و بدون این دستور، Apache آنها را رد میکند؛ در نتیجه، برنامههای موبایل همگامسازی نمیشوند، در حالی که رابط وب به درستی کار میکند.
پیش از ورود به سیستم، HTTPS را فعال کنید
شما قصد دارید رمز عبور خود را در این سایت وارد کنید، بنابراین ابتدا یک گواهی دریافت کنید. یک رکورد A به سمت سرور تنظیم کنید، سپس راهنمای راهاندازی Certbot برای Apache روی Ubuntu را دنبال کرده و دستور sudo certbot --apache -d rss.example.com را اجرا کنید. Certbot فایل virtual host مربوط به پورت 443 را بازنویسی کرده و تغییر مسیر (redirect) را اضافه میکند. با استفاده از 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 نیز حائز اهمیت است، زیرا حالت development باعث میشود اعلانهای PHP در صفحه نمایش داده شوند.
فایل https://rss.example.com/ را بارگذاری کرده و با نام کاربری admin وارد شوید.
چرا فیدها بهطور خودکار بهروزرسانی نمیشوند
تا زمانی که به سیستم دستور ندهید، هیچکس فیدهای شما را بررسی (poll) نمیکند. FreshRSS تنها زمانی فیدها را بهروز میکند که مرورگر روی آن باز باشد؛ این یعنی اگر روزی دو بار به این سرویس سر بزنید، مقالاتی را میبینید که 12 ساعت قدیمی هستند. راهحل، استفاده از اسکریپتی است که پروژه برای این منظور ارائه کرده است، یعنی 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 دقیقه، حداقلِ منطقی برای این کار است، زیرا اسکریپت اجازه نمیدهد هیچ فیدی بیش از یکبار در هر 20 دقیقه بهروزرسانی شود؛ بنابراین زمانبندی فشردهتر فقط باعث هدر رفتن 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 (زبان نشانهگذاری پردازشگر طرحواره) فرمت استاندارد لیست فید است و هر خبرخوان قابلقبولی از آن پشتیبانی میکند. وارد کردن تعداد زیادی فید در اولین بهروزرسانی کند است، زیرا هر فید یکبار فراخوانی میشود؛ بنابراین پیش از قضاوت درباره سرعت، به اولین اجرای cron زمان کافی بدهید.
مطالعه روی تلفن همراه
نرمافزار FreshRSS از API سرویس Google Reader پشتیبانی میکند که تقریباً تمامی اپلیکیشنهای 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 را به عنوان رمز عبور وارد کنید.
جایگزین Docker
اگر ترجیح میدهید PHP و Apache را بهصورت دستی مدیریت نکنید، این پروژه یک image رسمی freshrss/freshrss منتشر میکند و یک فایل compose، برنامه و دیتابیس آن را در کنار هم در اختیار شما قرار میدهد. این روش معاملهای معمول است: قطعات متحرک کمتر روی سیستم میزبان، اما یک لایه اضافه برای عیبیابی در صورت بروز مشکل؛ همچنین همچنان برای TLS (امنیت لایه انتقال) به یک reverse proxy نیاز خواهید داشت. اگر این روش برای شما مناسبتر است، اصول Docker Compose برای VPS فرمت فایل را توضیح داده است و خط cron به docker exec --user www-data freshrss php ./app/actualize_script.php تغییر میکند.
پشتیبانگیری و ارتقا
وضعیت شما توسط دو بخش حفظ میشود: پایگاه داده و /srv/freshrss/data/. از اولی با استفاده از sudo mysqldump freshrss > freshrss.sql یک خروجی (Dump) تهیه کنید، دومی را کپی کنید و هر دو را در مکانی خارج از این سرور نگهداری کنید. تهیه خروجی OPML از لیست اشتراکها نیز بهصورت دورهای توصیه میشود، زیرا این فایل میتواند تنظیمات مطالعه شما را در هر نرمافزار RSS دیگری بازسازی کند.
ارتقا شامل استخراج نسخه جدیدتر روی همان دایرکتوری و اجرای مجدد دستورات تعیین مالکیت (ownership) است. FreshRSS در اولین بارگذاری صفحه پس از ارتقا، مهاجرتهای پایگاه داده (database migrations) را بهصورت خودکار اعمال میکند. پیش از ارتقا حتماً پشتیبان تهیه کنید، زیرا شکست در فرآیند مهاجرت روی پایگاه دادهای که قادر به بازیابی آن نیستید، وضعیتی غیرقابلبازگشت ایجاد میکند. یک سرویس RSS Reader ریسک اجرایی پایینی دارد و اگر در حال بررسی لیستی از سرویسهای مناسب برای self-hosting هستید، گزینه بسیار مناسبی برای شروع است.
FAQ
چرا فیدهای من فقط زمانی که FreshRSS را باز میکنم بهروزرسانی میشوند؟
زیرا تا زمانی که زمانبندی (scheduler) ایجاد نکنید، وجود ندارد. FreshRSS فیدها را فقط در حالی که نشست مرورگر باز است تازه میکند و با بستن تب، هیچ کاری انجام نمیدهد. خط cron را که app/actualize_script.php را فراخوانی میکند به عنوان کاربر www-data اضافه کنید، سپس اسکریپت را یک بار بهصورت دستی اجرا کرده و خروجی آن را بخوانید. سکوت معمولاً به این معنی است که cron آن را با کاربر اشتباه اجرا میکند، بنابراین PHP نمیتواند در data/ بنویسد.
اپلیکیشن موبایل من نمیتواند متصل شود، اما وبسایت کار میکند. چرا؟
Google Reader API اسلشهای کدگذاریشده (%2F) را در مسیرهای درخواست قرار میدهد و Apache بهطور پیشفرض آنها را رد میکند. عبارت AllowEncodedSlashes On را در virtual host اضافه کرده و Apache را reload کنید. با باز کردن https://rss.example.com/api/ و اجرای "Check full server configuration" که باید PASS را گزارش دهد، اصلاح را تأیید کنید. همچنین بررسی کنید که رمز عبور API در پروفایل شما تنظیم شده باشد، زیرا این رمز از رمز عبور ورود شما جدا است.
آیا باید از SQLite استفاده کنم یا MariaDB؟
برای یک کاربر، SQLite مناسب است زیرا نیازی به نصب ندارد و رمز عبوری برای مدیریت وجود ندارد. اگر بیش از یک نفر از instance استفاده میکند یا تعداد فیدها از چند صد مورد فراتر رفته است، از MariaDB استفاده کنید؛ زیرا کار تازه کردن فیدها و رابط وب همزمان مینویسند و قفل شدن یک فایل واحد به گلوگاه تبدیل میشود. جابهجایی بین آنها در آینده از طریق دستورات export و import ممکن است، بنابراین این یک تصمیم دائمی نیست.
نصبکننده هنگام نوشتن پیکربندی با خطا مواجه میشود. مشکل چیست؟
PHP تحت Apache با کاربر www-data اجرا میشود و آن کاربر نمیتواند در دایرکتوری که مالک آن root است بنویسد. دستورات sudo chown -R www-data:www-data /srv/freshrss و sudo chmod -R g+w /srv/freshrss/data را دوباره اجرا کنید، سپس نصبکننده را مجدداً شروع کنید. اگر قبلاً نصبکننده خط فرمان را به عنوان root اجرا کردهاید، فایلهای ایجاد شده در data/ را پیش از تلاش مجدد حذف کنید، زیرا مالکیت آنها مشکل اصلی است.
یک RSS reader خودمیزبان (self-hosted) به چه میزان منابع سرور نیاز دارد؟
بسیار کم. چند صد فید روی یک پلن کوچک بهراحتی اجرا میشود، زیرا بار کاری شامل انفجارهای کوتاه دریافت HTTP در هر بیست دقیقه است و با پاکسازی مقالات قدیمی، حجم دیتابیس کوچک باقی میماند. فضای دیسک با نگهداری مقالات افزایش مییابد، بنابراین به جای نگهداری همیشگی همه چیز، یک سیاست پاکسازی مقالات در تنظیمات آرشیو تعیین کنید.