SSD Nodes Learn Hosting plans →
الأدلة Matt Connorبقلم Matt Connor · آخر تحديث في 2026-08-07

ثبّت FreshRSS على VPS مع Ubuntu وApache

ثبّت FreshRSS 1.29.1 على VPS يعمل بـ Ubuntu 24.04 باستخدام Apache وPHP وMariaDB، واضبط cron للتحديث وAPI لتطبيق الهاتف وتجنّب أخطاء المسارات.

ما الذي ستبنيه

قارئ RSS مستضاف ذاتياً هو قارئ خلاصات يعمل على خادم تملكه، لذلك لا يستطيع أحد إيقافه أو تغيير ما يعرضه لك. يثبّت هذا الدليل FreshRSS على VPS يعمل بنظام Ubuntu 24.04: يكون Apache أمام التطبيق، وPHP خلفه، وتُستخدم MariaDB لتخزين البيانات، مع مهمة cron واحدة لجلب المقالات الجديدة. RSS، أي Really Simple Syndication، هو تنسيق ملف ينشره الموقع لكي تتمكن البرامج من قراءة مقالاته. أما FreshRSS فهو تطبيق PHP الذي يجمع هذه الملفات ويحفظ المقالات، ويوفّر لك واجهة ويب وواجهة API، أي Application Programming Interface، تتصل بها تطبيقات الهاتف.

عملية التثبيت نفسها صغيرة: فك ضغط إصدار، وإنشاء قاعدة بيانات، وكتابة virtual host واحد، وتشغيل مثبّت واحد من سطر الأوامر. معظم العمل أدناه يتعلق بالأمور التي يخطئ الناس فيها بعد ذلك، وهي مهمة التحديث، والشرطات المائلة المرمّزة في واجهة 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 bit. في 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

تُعد مدة عشرين دقيقة الحد الأدنى المناسب، لأن البرنامج النصي يرفض تحديث أي خلاصة منفردة أكثر من مرة كل عشرين دقيقة. لذلك لا يفعل الجدول الأقصر من ذلك سوى استهلاك 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 على قيمة. وهذه الكلمة منفصلة عمداً عن كلمة مرور تسجيل الدخول لأن الهاتف جهاز أسهل فقدانه.

انتقل إلى 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 واحد التطبيق وقاعدة بياناته معاً. المقابل المعتاد هو عدد أقل من المكوّنات التي تديرها على الخادم، وطبقة إضافية واحدة لتشخيصها عند حدوث عطل، مع استمرار الحاجة إلى Reverse Proxy لتوفير 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 كل عشرين دقيقة، وتبقى قاعدة البيانات صغيرة بعد حذف المقالات القديمة. يزداد استخدام القرص مع مدة الاحتفاظ، لذلك اضبط سياسة لحذف المقالات في إعدادات الأرشفة بدلاً من الاحتفاظ بكل شيء إلى الأبد.