התקנת LAMP stack על Ubuntu 24.04 עם PHP-FPM
מדריך מעשי להקמת LAMP על Ubuntu 24.04 הכולל Apache, MariaDB ו-PHP 8.3. למדו כיצד להגדיר PHP-FPM, לפתור שגיאות נפוצות ב-unix_socket ולהטמיע תעודת HTTPS חינמית עם Certbot.
מה אתם בונים
מחסנית LAMP מורכבת מארבעה רכיבים הפועלים על שרת Ubuntu 24.04 יחיד: Linux בתשתית, Apache המשיב לבקשות HTTP, MariaDB המאחסן את הנתונים, ו־PHP 8.3 המריץ את הקוד. בסיום התהליך יהיה ברשותכם virtual host מבוסס שם המגיש תוכן מספריית יישום אמיתית, מסד נתונים עם משתמש ייעודי בעל הרשאות מינימליות, PHP המחובר ל־Apache באמצעות PHP-FPM, ותעודת Let's Encrypt חינמית המאבטחת את התעבורה.
ההתקנה עצמה מורכבת מארבע פקודות apt. רוב המדריך הזה עוסק בחיבור בין הרכיבים ובטעויות הנפוצות שגורמות למחסנית חדשה להציג דף ריק, להציע את קוד המקור להורדה בדפדפן, או למנוע גישה למסד הנתונים שהרגע התקנתם. לכל אחת מהתקלות הללו יש סימנים מזהים, וכל אחת מהן מפורטת להלן עם הטקסט המדויק שיופיע במערכת.
דרישות קדם ומלכודות נפוצות
הניחו כי ברשותכם שרת VPS מסוג KVM עם Ubuntu 24.04, משתמש בעל הרשאות sudo או גישת root, וכתובת IPv4 ציבורית. מחסנית (stack) מינימלית תרוץ על 1 GB של RAM; הקצו 2 GB לפני הרצת יישום מבוסס מסד נתונים, שכן מאגרי הזיכרון (buffers) של MariaDB יחד עם מספר תהליכי PHP-FPM יצרכו את הגיגה-בייט הראשון במהירות.
שני תנאים חייבים להתקיים כדי ש־Certbot יעבוד בסוף התהליך, לכן יש להסדיר אותם כעת. עליכם להחזיק בשם מתחם (domain name) עם רשומת A המצביעה על כתובת ה־IP הציבורית של ה־VPS; Let's Encrypt מבצעת אימות באמצעות HTTP מול שם זה, וכתובת IP חשופה לעולם לא תוכל לקבל תעודה. בנוסף, פורטים 80 ו־443 חייבים להיות נגישים מהאינטרנט. אצל ספקיות רבות משמעות הדבר היא פתיחת הפורטים ב־firewall של לוח הבקרה, וגם בתוך ufw בשרת עצמו. עדכון רשומות DNS עשוי להימשך עד שעה, לכן הגדירו את רשומת ה־A תחילה כדי שתהיה פעילה ברגע שתזדקקו לה.
שלב 1 - התקנת Apache ואימות דף ברירת המחדל
sudo apt update
sudo apt install -y apache2apt מפעיל את השירות ומגדיר אותו לעלייה אוטומטית. בדקו את מצבו:
systemctl status apache2עליכם לראות שורה המציינת active (running). כעת פתחו את http://YOUR_SERVER_IP/ בדפדפן. הופעת הדף Apache2 Ubuntu Default Page עם הכותרת הגדולה "It works!" היא התוצאה התקינה; היא מהווה הוכחה לכך ש-Apache מגיש תוכן ואינה מעידה על תקלה. דף זה נמצא ב-/var/www/html/index.html ומוגש על ידי ה-virtual host המובנה 000-default.conf. בהמשך תנטרלו את שניהם; לעת עתה, נוכחותם היא בדיוק מה שצריך לראות.
אם הדף אינו נטען כלל אך systemctl מדווח שהתהליך רץ, ייתכן שחומת אש חוסמת את הגישה. זהו הצעד הבא.
שלב 2 - פתיחת ה-firewall עבור HTTP ו-HTTPS
חבילת ה-apache2 רושמת שלושה פרופילי יישום מסוג ufw. הצג אותם ברשימה:
sudo ufw app listתראה את Apache, Apache Full, ו-Apache Secure. הפרופיל Apache הוא עבור פורט 80 בלבד, Apache Secure הוא עבור 443 בלבד, ו-Apache Full כולל את שניהם; זהו הפרופיל שאתה צריך, מכיוון שאתה מוסיף TLS בסוף התהליך.
sudo ufw allow OpenSSH
sudo ufw allow "Apache Full"
sudo ufw enableאפשר את OpenSSH לפני שתריץ את ufw enable. ברירת המחדל של ufw היא חסימת כל תעבורה נכנסת, והפעלה שלו ללא חוק עבור SSH תנתק אותך ברגע שה-firewall יופעל; הסשן הנוכחי יישמר, אך לא תוכל להתחבר מחדש. אשר את ההגדרות באמצעות sudo ufw status; עליך לוודא ש-OpenSSH, Apache Full, והגרסאות שלהם ל-v6 מוגדרות כ-ALLOW.
שלב 3 - התקנת MariaDB ואבטחתה
sudo apt install -y mariadb-server
systemctl status mariadbהגרסה Ubuntu 24.04 כוללת את MariaDB 10.11, מהדורת תמיכה לטווח ארוך (LTS), לכן אין צורך במאגר חיצוני. לאחר שהשירות פועל, יש להקשיח אותו:
sudo mysql_secure_installationמומלץ לקרוא את ההנחיות במקום ללחוץ על Enter באופן אוטומטי. כאשר המערכת מבקשת את ה-current root password, לחצו על Enter, שכן טרם הוגדרה סיסמה. כאשר המערכת שואלת "Switch to unix_socket authentication?", התשובה אינה משנה דבר כיוון שהאפשרות כבר מופעלת בחבילה זו, לכן לחצו על n. ענו n לבקשה "Change the root password?" מהסיבה המפורטת בפסקה הבאה, ולאחר מכן ענו Y ליתר השאלות: הסרת משתמשים אנונימיים, מניעת התחברות מרחוק של root, מחיקת מסד הנתונים test, וטעינה מחדש של טבלאות ההרשאות.
זהו החלק שגורם לבלבול רב. בגרסת MariaDB של Ubuntu, חשבון מסד הנתונים root משתמש באימות unix_socket ולא בסיסמה. המשמעות היא שמסד הנתונים סומך על משתמש ה-operating-system שכבר עבר אימות. לכן, הפקודה הבאה תעבוד מתוך shell של root:
sudo mysql...והיא תעביר אתכם ל-prompt של MariaDB [(none)]> ללא בקשת סיסמה. אותה פקודה שתורץ כמשתמש ללא הרשאות תידחה, וזו בדיוק המטרה: הגישה ל-root של מסד הנתונים קשורה ל-sudo במכונה, ואין סיסמה שניתן לגנוב, להשיג בפישינג או לפצח ב-brute-force. שיטה זו מאובטחת יותר מסיסמה, לכן אל תשנו אותה. הכלל הנובע מכך הוא: לעולם אל תגדירו יישום להשתמש בחשבון root. צרו משתמש ייעודי לכל יישום (שלב 7), כיוון שיישום המתחבר דרך TCP עם שם משתמש וסיסמה אינו יכול להשתמש באימות socket בכל מקרה, וחשוב להגביל כל יישום למסד הנתונים שלו בלבד.
שלב 4 - התקנת PHP 8.3 עם PHP-FPM
גרסת ה-PHP המוגדרת כברירת מחדל ב-Ubuntu 24.04 היא 8.3. התקינו את מנהל התהליכים FPM ואת התוספים שיישום טיפוסי זקוק להם:
sudo apt install -y php8.3-fpm php8.3-mysql php8.3-cli \
php8.3-curl php8.3-xml php8.3-mbstring php8.3-zipשימו לב למה שאינו מופיע ברשימה: libapache2-mod-php. חבילה ישנה זו מטמיעה מפרש PHP בתוך כל תהליך של Apache. היא פשוטה לשימוש, אך כל worker נושא עותק של PHP בין אם הוא מגיש סקריפט ובין אם הוא מגיש תמונה סטטית, השניים חולקים מחזור חיים אחד, והיא עובדת רק עם ה-MPM מסוג prefork של Apache, שהוא הפחות יעיל מביניהם. לעומת זאת, PHP-FPM מריץ את PHP כמאגר תהליכים עצמאי ש-Apache מתקשר איתו דרך socket. כך Apache יכול להשתמש ב-MPM מסוג event מרובה-תהליכונים (threaded) עבור קבצים סטטיים ולהעביר רק את בקשות ה-PHP הלאה; המאגר מכוונן בנפרד משרת האינטרנט, ואותה תצורת FPM תעבוד בהמשך גם אם תציבו nginx בחזית. זוהי ברירת המחדל הנוכחית מסיבות טובות.
Apache ניגש ל-FPM דרך המודול proxy_fcgi. הפעילו אותו, הפעילו את קובץ התצורה שהותקן על ידי חבילת ה-FPM, ובצעו הפעלה מחדש:
sudo a2enmod proxy_fcgi setenvif
sudo a2enconf php8.3-fpm
sudo systemctl restart apache2a2enconf php8.3-fpm מפעיל את /etc/apache2/conf-available/php8.3-fpm.conf, המכיל את הכלל שמנתב קבצי PHP ל-socket של ה-FPM. ליבת התצורה מתאימה כל קובץ .php ומעבירה אותו ל-socket בנתיב /run/php/php8.3-fpm.sock:
<FilesMatch ".+\.ph(ar|p|tml)$">
SetHandler "proxy:unix:/run/php/php8.3-fpm.sock|fcgi://localhost"
</FilesMatch>אין צורך לערוך את הקובץ הזה; הוא מגיע בתצורה תקינה. עם זאת, הכרת נתיב ה-socket היא מה שמאפשר לכם לאבחן תקלות מסוג "PHP downloads instead of running" ו-"Primary script unknown" בהמשך; שתיהן נובעות מחוסר התאמה בין Apache ל-FPM בנוגע ל-socket זה או לקובץ שמאחוריו.
שלב 5 - הגדרת Virtual Host מבוסס שם עבור היישום שלך
אירוח וירטואלי מבוסס שם מאפשר לכתובת IP אחת לשרת אתרים רבים; Apache בוחר את האתר לפי ה-header מסוג Host: בבקשה. צור ספרייה עבור היישום, הרחק מתיקיית ברירת המחדל /var/www/html:
sudo mkdir -p /var/www/testapp
sudo chown -R www-data:www-data /var/www/testapp
sudo chmod -R 755 /var/www/testappלבעלות על קבצים יש חשיבות. Apache ו-PHP-FPM רצים שניהם תחת המשתמש www-data ב-Ubuntu, לכן קבצים ששרת האינטרנט צריך לקרוא, וספריות שהיישום צריך לכתוב אליהן (כמו תיקיית העלאות), צריכים להיות בבעלות www-data. אם בכוונתך לערוך קבצים גם כמשתמש המערכת שלך, דפוס נפוץ הוא להגדיר את הקבצים בבעלותך ולהוסיף את המשתמש שלך לקבוצה www-data; עבור פריסה פשוטה, www-data:www-data הוא הפתרון הפחות מפתיע.
צור את ה-Virtual Host בנתיב /etc/apache2/sites-available/testapp.conf:
<VirtualHost *:80>
ServerName app.example.com
DocumentRoot /var/www/testapp
<Directory /var/www/testapp>
Options -Indexes +FollowSymLinks
AllowOverride All
Require all granted
</Directory>
ErrorLog ${APACHE_LOG_DIR}/testapp-error.log
CustomLog ${APACHE_LOG_DIR}/testapp-access.log combined
</VirtualHost>הגדר את ServerName לדומיין האמיתי שלך. Options -Indexes מונע מ-Apache להציג את רשימת הקבצים בספרייה כאשר אין קובץ index, אחרת מבקרים יוכלו לעיין בעץ המקור שלך. AllowOverride All מאפשר לקובץ .htaccess לעבוד, דבר שרוב יישומי ה-PHP מצפים לו עבור כתובות URL נקיות; ניתן להסיר זאת ל-None עבור שיפור קל במהירות אם היישום שלך אינו זקוק לכך. הפעל את האתר הזה, נטרל את ברירת המחדל, בדוק את התצורה, וטען מחדש:
sudo a2ensite testapp
sudo a2dissite 000-default
sudo apache2ctl configtest
sudo systemctl reload apache2הפקודה apache2ctl configtest אמורה להדפיס Syntax OK. השורה a2dissite 000-default היא זו שאנשים נוטים לשכוח, וזו הסיבה שדף ברירת המחדל נראה תקוע מאוחר יותר, כפי שמתואר בסעיף הכשלים.
שלב 6 - אימות הרצת PHP ומחיקת קובץ הבדיקה
צרו קובץ PHP בעל שורה אחת בתיקיית השורש של היישום:
echo "<?php phpinfo();" | sudo tee /var/www/testapp/info.phpבקרו ב-http://app.example.com/info.php. תוצאה תקינה היא טבלת PHP Version 8.3.x ארוכה בצבעי סגול ואפור המפרטת את המודולים הטעונים, כאשר השורה Server API מציגה FPM/FastCGI. שורה אחרונה זו מאשרת כי הבקשות עוברות דרך PHP-FPM ולא דרך mod_php.
כעת מחקו את הקובץ מיד:
sudo rm /var/www/testapp/info.phpphpinfo() חושף את גרסת ה-PHP המדויקת שלכם, את כל התוספים הטעונים, נתיבי קבצים ופרטי סביבה; זהו מידע יקר ערך לכל מי שסורק את השרת בחיפוש אחר גרסה עם פרצת אבטחה ידועה. זהו כלי בדיקה, לא תכונה. מחקו אותו ברגע שראיתם את הדף. אם במקום הטבלה הדפדפן הציע לכם להוריד את info.php, סימן ש-PHP אינו מוגדר כראוי מול Apache; עברו לסעיף התקלות לפני שתבצעו פעולה נוספת.
שלב 7 - יצירת מסד הנתונים של היישום ומשתמש בעל הרשאות מינימליות
פתחו את מסד הנתונים באמצעות משתמש ה-root המאומת דרך ה-socket:
sudo mysqlלאחר מכן, צרו מסד נתונים אחד ומשתמש אחד המוגבל למסד נתונים זה בלבד:
CREATE DATABASE appdb CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'appuser'@'localhost' IDENTIFIED BY 'a-long-random-password';
GRANT ALL PRIVILEGES ON appdb.* TO 'appuser'@'localhost';
FLUSH PRIVILEGES;
EXIT;ביצענו כאן שלוש בחירות מכוונות. utf8mb4 הוא UTF-8 מלא של ארבעה בתים; הכינוי הישן utf8 קוטע בשקט אימוג'ים ותווים מסוימים של CJK, לכן השתמשו תמיד ב-utf8mb4. ההרשאה ניתנת על appdb.*, ולא על *.*: משתמש זה יכול לגשת למסד הנתונים שלו בלבד, כך שפרצת SQL-injection ביישום לא תאפשר קריאת טבלאות של אתרים אחרים. בנוסף, 'appuser'@'localhost' מגביל את החשבון לחיבורים שמקורם בשרת עצמו.
בצעו בדיקה כמשתמש זה:
mysql -u appuser -p appdbהמערכת תבקש סיסמה ותעביר אתכם להנחיית MariaDB [appdb]>. שימו לב שאין דגל -h; השאירו אותו מחוץ לפקודה כדי שהלקוח יתחבר דרך ה-Unix socket המקומי, וזה בדיוק מה ש-MariaDB מחשיבה כ-localhost. נקודה אחת שחשוב להכיר: עבור MySQL ו-MariaDB, localhost משמעו ה-Unix socket ו-127.0.0.1 משמעו חיבור TCP. בגרסת MariaDB סטנדרטית ב-Ubuntu 24.04, השרת עדיין מתרגם חיבור TCP מ-127.0.0.1 חזרה ל-localhost, כך ששניהם תואמים לחשבון. עם זאת, בשרתים שבהם מופעל skip-name-resolve (שיפור ביצועים נפוץ, וסטנדרט בהרבה אימג'ים של מכולות), השניים מזוהים כמארחים שונים, ויישום שמתחבר ל-127.0.0.1 יידחה עם ERROR 1045 (28000): Access denied for user 'appuser'@'127.0.0.1' (using password: YES) גם אם הסיסמה נכונה.
לכן, הגדירו ביישום שלכם את המארח כ-localhost, את המשתמש כ-appuser ואת מסד הנתונים כ-appdb, ולעולם לא כ-root. הספריות mysqli ו-PDO ב-PHP עוברות לשימוש ב-Unix socket כאשר המארח הוא המחרוזת המילולית localhost, מה שמתאים לחשבון שיצרתם זה עתה. אם framework מסוים מתעקש על מארח TCP מספרי, צרו את המשתמש כך שיתאים לאופן שבו הוא מתחבר בפועל, 'appuser'@'127.0.0.1', או @'%' (בצירוף חוק firewall) רק אם עליו להגיע למסד הנתונים ממכונה אחרת.
שלב 8 - הוספת HTTPS באמצעות Certbot
הגשת טופס התחברות על גבי HTTP גלוי שולחת סיסמאות בטקסט פשוט, וכל דפדפן מודרני מסמן את הדף כ"לא מאובטח". Certbot פותר זאת בפקודה אחת. התקינו אותו עם התוסף עבור Apache:
sudo apt install -y certbot python3-certbot-apache
sudo certbot --apacheCertbot משתמש כאן בשני תוספים. ה-apache authenticator מוכיח שאתם שולטים בדומיין על ידי הגשה זמנית של קובץ אתגר דרך ה-Apache הפעיל שלכם, וה-apache installer משכתב לאחר מכן את ה-virtual host שלכם כדי להוסיף את בלוק ה-443, מצביע על התעודה החדשה, ומפנה את כל תעבורת ה-HTTP ל-HTTPS כברירת מחדל. מאז Certbot 2.0 אין שאלה לגבי הפניה; העבירו את הדגל --no-redirect אם אתם צריכים להמשיך להגיש HTTP פשוט. מכיוון שהגדרתם ServerName אמיתי בשלב 5, Certbot מזהה את הדומיין באופן אוטומטי. תעודות תקפות ל-90 יום והחבילה מתקינה טיימר של systemd שמחדש אותן; ודאו את הטיימר בעזרת sudo certbot renew --dry-run, שאמור להסתיים ב-Congratulations, all simulated renewals succeeded.
למדריך המלא על תהליך האתגר, טיימר החידוש, ודרישות ה-DNS וה-firewall, עיינו במדריך הנלווה בנושא הנפקת תעודות TLS חינמיות של Let's Encrypt עם Certbot על Apache.
גיבויים, שדרוגים והקשחת אבטחה
בצעו גיבוי לשני הרכיבים ששומרים את המצב שלכם: מסדי הנתונים וספריית ה-web root. יצירת dump לוגי לילי היא הגישה הפשוטה והאמינה ביותר, sudo sh -c 'mysqldump --all-databases --single-transaction | gzip > /root/db-$(date +%F).sql.gz', ולאחר מכן העתקתו אל מחוץ לשרת. עטיפת כל התהליך ב-sudo sh -c היא קריטית: בלעדיה, ה-shell יריץ את ה-redirect של > /root/... תחת המשתמש שלכם וייכשל עם Permission denied, כיוון שרק mysqldump ירש את ה-sudo. הפקודה --single-transaction מספקת תמונת מצב עקבית של טבלאות InnoDB ללא נעילתן. שלבו זאת עם tar של /var/www ו-/etc/apache2/sites-available, ותוכלו לשחזר את כל ה-stack על שרת VPS חדש מתוך הקבצים הללו.
שדרוגים הם תהליך sudo apt update && sudo apt upgrade רגיל. מה שעלול להפתיע הוא עדכון גרסת PHP, כאשר גרסה עתידית של Ubuntu מעבירה את ברירת המחדל ל-PHP 8.4; במקרה כזה, apt עשוי להתקין את php8.4-fpm לצד 8.3, ה-socket יהפוך ל-/run/php/php8.4-fpm.sock, בעוד הגדרות ה-Apache שלכם עדיין יצביעו על ה-socket של 8.3. הפעילו את ה-conf החדש (sudo a2enconf php8.4-fpm) ובטלו את הישן, אחרת האתר יתחיל להחזיר Primary script unknown לאחר שדרוג שגרתי לכאורה. כיוון שגרסאות PHP מתעדכנות מהר יותר מהפצות LTS, בדקו את הערות השחרור העדכניות של PHP במקום לקבע גרסת patch ספציפית.
כדאי לבצע שני צעדי הקשחה כבר ביום הראשון. ראשית, הגדירו Fail2Ban לניטור SSH על השרת; שרת VPS חשוף לאינטרנט סופג ניסיונות התחברות אוטומטיים תוך דקות, ו-jail קטן יצמצם אלפי ניסיונות למספר בודד לפני חסימה. שנית, אם אתם מעדיפים לנהל את ה-virtual hosts של Apache, את מסדי הנתונים של MariaDB ואת המשתמשים דרך דפדפן במקום לערוך קבצים ידנית, לוח הבקרה מבוסס האינטרנט Webmin יושב על גבי אותו ה-stack ומנהל את אותם קובצי הגדרה שכתבתם זה עתה. אף אחד מהכלים הללו אינו מחליף את הצורך להבין את הרכיבים, אך שניהם מפחיתים את החיכוך בניהול השוטף.
מצבי כשל והודעות שגיאה נפוצות
דף ברירת המחדל אינו נעלם. ערכת את ה-virtual host, ביצעת טעינה מחדש, אך הדפדפן עדיין מציג את "Apache2 Ubuntu Default Page" ואת הכותרת "It works!". Apache מגיש את ה-virtual host הראשון שתואם לבקשה. כאשר אף ServerName אינו תואם, הקובץ שמופיע ראשון בסדר אלפביתי הוא זה שקובע, ו-000-default.conf קודם ל-testapp.conf. ייתכן ששם המתחם בבקשה אינו תואם ל-ServerName שלך, או שלא הרצת את sudo a2dissite 000-default. בטל את הגדרת ברירת המחדל באמצעות sudo systemctl reload apache2, ואמת זאת עם apache2ctl -S, שמציג את מפת ה-vhost ומראה איזו הגדרה אחראית על דף ברירת המחדל. נקה גם את ה-cache של הדפדפן; דף ישן ששמור ב-cache עלול להמשיך להופיע כ-200 OK.
קובץ .php יורד במקום להריץ. אתה פותח את info.php והדפדפן מוריד קובץ המכיל את קוד ה-<?php הגולמי, או מציג אותו כטקסט פשוט במקום להריץ אותו. Apache מגיש את הקובץ כנכס סטטי כיוון ש-PHP handler לא מחובר, דילגת על sudo a2enmod proxy_fcgi, או על sudo a2enconf php8.3-fpm, או שלא ביצעת restart ל-Apache לאחר מכן. הרץ את שלושתם (שלב 4) וטען מחדש. ודא שהמודול טעון באמצעות apache2ctl -M | grep fcgi, שאמור להציג את proxy_fcgi_module. זוהי דליפת קוד מקור, לא בעיה קוסמטית, לכן יש לתקן זאת לפני העלאת תוכן אמיתי לשרת.
ERROR 1698 (28000): Access denied for user 'root'@'localhost'. הרצת את mysql -u root או mariadb -u root ללא sudo. חשבון ה-root משתמש באימות unix_socket, לכן הוא מקבל גישה רק כאשר משתמש ה-OS שלך הוא אכן root. הפתרון הוא sudo mysql, ללא -u root וללא סיסמה. הודעה זו היא התנהגות תקינה של אימות socket, ולא התקנה שבורה.
ERROR 1045 (28000): Access denied for user 'appuser'@'127.0.0.1' מהיישום, עם הסיסמה הנכונה. החשבון קיים כ-'appuser'@'localhost', אך היישום שלך מתחבר ב-TCP ל-127.0.0.1 בשרת שבו רזולוציית שמות מארח מבוטלת (skip-name-resolve). לכן MariaDB מתייחסת לשניים כאל מארחים שונים: localhost הוא ה-Unix socket, ו-127.0.0.1 הוא ה-TCP. כוון את היישום למארח localhost כדי שישתמש ב-socket ויתאים לחשבון, או צור חשבון שני 'appuser'@'127.0.0.1' אם ה-framework תומך רק ב-TCP.
AH01071: Got error 'Primary script unknown' ב-/var/log/apache2/testapp-error.log, כשהדפדפן מציג File not found.. Apache העביר את הבקשה ל-PHP-FPM, אך FPM לא מצא את הסקריפט בנתיב ש-Apache סיפק. שתי סיבות נפוצות: ה-socket של FPM בהגדרות מצביע על גרסת PHP שאינה מותקנת (למשל socket של php8.4 לאחר שדרוג כשמותקנת רק גרסה 8.3), או שהקובץ אינו קיים בנתיב בגלל חוסר התאמה בין DocumentRoot לבין הספרייה בפועל. בדוק שה-socket קיים עם ls -l /run/php/, ודא ש-DocumentRoot תואם למיקום הקובץ, ובצע restart ל-php8.3-fpm ול-apache2.
AH00558: apache2: Could not reliably determine the server's fully qualified domain name בכל restart. זוהי אזהרה בלבד, לא שגיאה. Apache מודיע שלא הוגדר ServerName גלובלי. ניתן להשתיק זאת על ידי כתיבת ServerName your.domain לתוך /etc/apache2/conf-available/servername.conf והרצת sudo a2enconf servername.
(98)Address already in use: AH00072: make_sock: could not bind to address 0.0.0.0:80 בעת הפעלת Apache. שרת אינטרנט אחר כבר תופס את פורט 80, לרוב מדובר ב-nginx שנשאר מניסוי קודם. מצא אותו בעזרת sudo ss -ltnp | grep :80, ולאחר מכן עצור ובטל את השירות האחר לפני הפעלת Apache.
FAQ
mod_php או PHP-FPM - במה כדאי להשתמש?
השתמשו ב-PHP-FPM. ה-mod_php מטמיע מפרש בתוך כל תהליך של Apache ומחייב שימוש ב-MPM מסוג prefork האיטי, כך ש-Apache נושא בעומס של PHP גם בעת הגשת קובץ סטטי. PHP-FPM מריץ את PHP כמאגר (pool) נפרד ומכוונן באופן עצמאי, ש-Apache ניגש אליו דרך socket; הוא עובד עם ה-MPM המהיר יותר מסוג event, ומאפשר מעבר קל ל-nginx בעתיד. זוהי ברירת המחדל המודרנית; ה-mod_php הגיוני רק עבור יישומים ישנים התלויים בהתנהגות ספציפית של תהליך פנימי.
מדוע הדפדפן שלי מוריד את קובץ ה-PHP במקום להריץ אותו?
Apache מתייחס לקובץ ה-.php כאל הורדה סטטית מכיוון שלא מוגדר לו handler של PHP. ב-Ubuntu 24.04 עם FPM, המשמעות היא שדילגתם על אחד מהשלבים: sudo a2enmod proxy_fcgi, sudo a2enconf php8.3-fpm, או ביצוע restart ל-Apache לאחר מכן. הריצו את שלושתם וטענו מחדש את השירות, ולאחר מכן ודאו בעזרת apache2ctl -M | grep fcgi ש-proxy_fcgi_module מופיע ברשימה. עד לתיקון הבעיה, השרת חושף את קוד המקור, לכן יש לטפל בכך בדחיפות.
מדוע הגישה כ-root נדחית ב-MariaDB גם עם הסיסמה הנכונה?
מכיוון שאין סיסמה, MariaDB ב-Ubuntu מאמתת את חשבון ה-root באמצעות unix_socket, מה שקושר אותו למשתמש ה-root של מערכת ההפעלה. הרצת mysql -u root מתוך shell רגיל תחזיר ERROR 1698 (28000): Access denied for user 'root'@'localhost' כחלק מהתכנון המקורי. התחברו במקום זאת עם sudo mysql, וצרו משתמש נפרד המאומת באמצעות סיסמה עבור כל יישום, במקום לעשות שימוש חוזר ב-root.
כיצד אוסיף HTTPS לאתר ה-LAMP שלי?
התקינו את certbot ואת python3-certbot-apache, הצביעו עם רשומת A של הדומיין אל השרת, ולאחר מכן הריצו את sudo certbot --apache. רכיב האימות של Apache מוכיח שליטה בדומיין דרך ה-Apache הפעיל שלכם, והמתקין משכתב את ה-virtual host עבור פורט 443 ומגדיר חידוש אוטומטי. ה-מדריך המלא ל-Certbot ו-Apache מכסה את תהליך האימות, את טיימר החידוש ואת כשלי התצורה הנפוצים.