تثبيت FreshRSS على VPS يعمل بنظام Ubuntu
ثبّت FreshRSS 1.29.1 على VPS بنظام Ubuntu 24.04 باستخدام Apache وPHP 8.3 وMariaDB، مع إعداد cron للتحديث وAPI لتطبيق الهاتف.
ما الذي ستبنيه
قارئ RSS مستضاف ذاتيًا هو قارئ خلاصات يعمل على خادم تملكه، لذلك لا يستطيع أحد إيقافه أو تغيير المحتوى الذي يعرضه لك. يثبت هذا الدليل FreshRSS على VPS يعمل بنظام Ubuntu 24.04: يتولى Apache الواجهة الأمامية، ويعمل PHP في الخلفية، وتستخدم MariaDB لتخزين البيانات، وتنفذ مهمة cron واحدة لجلب المقالات الجديدة. إن RSS، أي التلقيم البسيط جدًا، هو تنسيق الملفات الذي ينشر به الموقع مقالاته لكي تتمكن البرامج من قراءتها. أما FreshRSS فهو تطبيق PHP الذي يجمع هذه الملفات، ويحفظ المقالات، ويوفر لك واجهة ويب بالإضافة إلى API، أي واجهة برمجة التطبيقات، التي تتصل بها تطبيقات الهاتف.
عملية التثبيت نفسها بسيطة: فك حزمة إصدار، وإنشاء قاعدة بيانات، وكتابة مضيف افتراضي واحد، وتشغيل مثبت واحد من سطر الأوامر. معظم الأخطاء تحدث لاحقًا، وتحديدًا في مهمة التحديث، والشرطات المائلة المرمّزة في API الخاص بتطبيق الهاتف، وملكية الملفات.
الإصدار الحالي من FreshRSS هو 1.29.1 اعتبارًا من July 2026، ويتطلب PHP 8.1 أو إصدارًا أحدث. يتضمن Ubuntu 24.04 إصدار PHP 8.3، لذلك تكفي حزم التوزيعة ولا تحتاج إلى مستودع PHP تابع لجهة خارجية.
ابدأ بحزمة LAMP تعمل
FreshRSS تطبيق PHP عادي، لذلك يحتاج إلى الأساس نفسه الذي يحتاج إليه أي تطبيق آخر. إذا لم تكن قد أعددت هذا الأساس بعد، فاتبع إعداد حزمة LAMP على 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، وإلى GMP على نظام 32 بت. تتوفر هذه الملحقات على Ubuntu في صورة حزم للتوزيعة:
sudo apt install -y php-curl php-mbstring php-xml php-zip php-mysql php-intl php-gmp
sudo systemctl restart apache2تحقق من الملحقات التي حمّلها PHP فعليًا باستخدام php -m. لا يمنع غياب أحد الملحقات أداة التثبيت من البدء. لكنه يوقفها عند شاشة المتطلبات، حيث يظهر سطر أحمر يذكر اسم الملحق. اكتشاف المشكلة في هذه المرحلة مربك، لذا تحقق منها الآن. إعادة تشغيل Apache مهمة لأن libapache2-mod-php يُبقي PHP داخل عملية Apache. لذلك لا يرى خادم الويب الملحق المثبت حديثًا حتى يُعاد تشغيله.
تنزيل الإصدار
ثبّت FreshRSS خارج جذر الويب الافتراضي، ووجّه Apache إليه. يؤدي إبقاء دليل التطبيق منفصلًا عن جذر المستندات إلى جعل المجلد العام فقط متاحًا عبر 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. قد تحتوي الخلاصات على رموز emoji ونصوص بكتابات غير لاتينية، بينما يؤدي ترميز 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 OK. يبدو AllowEncodedSlashes On اختياريًا، لكنه ليس كذلك: ترسل Google Reader API معرّفات موجزات تحتوي على %2F، ومن دون هذا التوجيه يرفض Apache هذه المعرّفات، فتفشل مزامنة تطبيقات الأجهزة المحمولة بينما تعمل واجهة الويب بشكل كامل.
أضف HTTPS قبل تسجيل الدخول
أنت على وشك إدخال كلمة مرور في هذا الموقع، لذلك احصل على شهادة أولًا. وجّه سجل A إلى الخادم، ثم اتبع إعداد Certbot لـ Apache على Ubuntu وشغّل 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عشرون دقيقة هي الحد الأدنى المناسب، لأن البرنامج النصي يرفض تحديث أي خلاصة منفردة أكثر من مرة كل عشرين دقيقة. لذلك لا يؤدي ضبط جدول أقصر إلا إلى استهلاك وحدة المعالجة المركزية. شغّله يدويًا مرة واحدة أولًا:
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 واجهة Google Reader API، التي تدعمها تقريبًا جميع تطبيقات RSS. يجب تحقق أمرين. في إعدادات المصادقة، يجب تفعيل الخيار "Allow API access"، وقد فعّلته العلامة --api-enabled أعلاه. في ملفك الشخصي، يجب أن يحتوي حقل كلمة مرور API على قيمة. وتختلف كلمة المرور هذه عمدًا عن كلمة مرور تسجيل الدخول، لأن فقدان الهاتف أسهل.
انتقل إلى https://rss.example.com/api/ واختر "Check full server configuration". يعرض الإعداد العامل النتيجة PASS. يحدث الفشل هنا غالبًا بسبب غياب السطر AllowEncodedSlashes On. في التطبيق، أدخل عنوان الخادم https://rss.example.com/api/greader.php، واسم المستخدم باعتباره مستخدم FreshRSS، وكلمة مرور API باعتبارها كلمة المرور.
البديل باستخدام Docker
إذا كنت تفضّل عدم إدارة PHP وApache يدويًا، ينشر المشروع صورة freshrss/freshrss رسمية. ويوفّر لك ملف compose واحد التطبيق وقاعدة بياناته معًا. المقابل هو المعتاد: مكوّنات أقل على المضيف، وطبقة إضافية تحتاج إلى تصحيح أخطائها عند حدوث مشكلة. وستظل بحاجة إلى وكيل عكسي من أجل TLS (أمان طبقة النقل). إذا كان هذا الخيار أنسب لك، يشرح دليل أساسيات Docker Compose لخادم VPS تنسيق الملف، ويصبح سطر cron هو docker exec --user www-data freshrss php ./app/actualize_script.php.
النسخ الاحتياطية والترقيات
هناك شيئان يحفظان حالتك: قاعدة البيانات و/srv/freshrss/data/. صدّر قاعدة البيانات باستخدام sudo mysqldump freshrss > freshrss.sql، وانسخ العنصر الثاني، واحتفظ بكليهما في مكان آخر غير هذا الخادم. كما تستحق قائمة الاشتراكات تصديرًا دوريًا بتنسيق OPML، لأن هذا الملف يعيد إعداد القراءة لديك على أي برنامج RSS تقريبًا.
تتم الترقية بفك إصدار أحدث فوق الدليل نفسه، ثم إعادة تشغيل أوامر الملكية. يطبّق FreshRSS عمليات ترحيل قاعدة البيانات الخاصة به عند تحميل الصفحة التالية. أنشئ نسخة احتياطية أولًا، لأن فشل عملية الترحيل في قاعدة بيانات لا يمكنك استعادتها يضعك في حالة يتعذر إصلاحها. تشغيل قارئ الخلاصات خدمة منخفضة المخاطر، وهو مرشح جيد للبدء إذا كنت تعمل على قائمة بما يستحق الاستضافة الذاتية.
FAQ
لماذا لا تُحدَّث خلاصاتي إلا عند فتح FreshRSS؟
لأنه لا يوجد مجدول حتى تُنشئ واحدًا. تُحدِّث FreshRSS الخلاصات أثناء فتح جلسة المتصفح، ولا تفعل شيئًا عند إغلاق علامة التبويب. أضف سطر cron الذي يستدعي app/actualize_script.php باسم المستخدم www-data، ثم شغّل البرنامج النصي يدويًا مرة واحدة واقرأ ناتجه. يعني عدم ظهور أي مخرجات غالبًا أن 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 باسم www-data تحت Apache، ولا يستطيع ذلك المستخدم الكتابة في دليل يملكه root. أعد تشغيل sudo chown -R www-data:www-data /srv/freshrss وsudo chmod -R g+w /srv/freshrss/data، ثم ابدأ المثبّت مجددًا. إذا شغّلت مثبّت سطر الأوامر باسم root من قبل، فاحذف الملفات التي أنشأها ضمن data/ قبل إعادة المحاولة، لأن ملكية هذه الملفات هي المشكلة الفعلية.
ما مقدار موارد الخادم التي يحتاج إليها قارئ RSS مستضاف ذاتيًا؟
يحتاج إلى موارد قليلة جدًا. يكون تشغيل بضع مئات من الخلاصات على خطة صغيرة مريحًا، لأن الحمل يأتي على شكل دفعات قصيرة من جلب HTTP كل عشرين دقيقة، وتظل قاعدة البيانات صغيرة بعد حذف المقالات القديمة. يزداد استهلاك القرص مع مدة الاحتفاظ، لذلك اضبط سياسة لحذف المقالات من إعدادات الأرشفة بدلًا من الاحتفاظ بكل شيء إلى الأبد.