איך מתקינים FreshRSS ב-VPS עם Ubuntu 24.04
מדריך להתקנת 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 היא הגרסה הנוכחית נכון ליולי 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 mariadbsystemctl 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. הזנות עשויות להכיל אמוג'י וכתבים שאינם לטיניים, והקידוד הישן בן שלושת הבתים 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 apache2configtest אמור להדפיס Syntax OK. AllowEncodedSlashes On נראה אופציונלי, אך אינו כזה: ה-API של Google Reader שולח מזהי הזנות שמכילים את %2F, וללא הנחיה זו Apache דוחה אותם. לכן יישומים ניידים אינם מצליחים להסתנכרן, אף שממשק האינטרנט פועל באופן תקין.
הוספת HTTPS לפני ההתחברות
אתם עומדים להקליד סיסמה באתר הזה, לכן השיגו תחילה אישור. הגדירו רשומת A שתפנה אל השרת, ולאחר מכן פעלו לפי הגדרת Certbot עבור Apache ב-Ubuntu והריצו את sudo certbot --apache -d rss.example.com. Certbot משנה את הגדרות ה־virtual host עבור פורט 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 (שפת סימון למעבדי מבנים) הוא הפורמט התקני לרשימות הזנות, וכל קורא שכדאי לעבור ממנו תומך בו. ייבוא גדול אטי ברענון הראשון, מכיוון שכל הזנה נמשכת פעם אחת. לכן יש להמתין להפעלה הראשונה של 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 באופן ידני, הפרויקט מפרסם image רשמי מסוג 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 מדי עשרים דקות, ומסד הנתונים נשאר קטן לאחר שמוחקים מאמרים ישנים. שטח הדיסק גדל בהתאם לתקופת השמירה, לכן הגדירו מדיניות למחיקת מאמרים בהגדרות הארכוב במקום לשמור הכול לצמיתות.