Lessons

PHP and Application Deployment

Level: Advanced Module: Web Services 9 min read Lesson 25 of 66

Overview

  • What you’ll learn: How to install PHP and PHP-FPM on Ubuntu, integrate PHP processing with Apache and Nginx, configure PHP settings, connect to MySQL/MariaDB databases, and deploy a complete PHP application.
  • Prerequisites: Lesson 22 — Apache2 Web Server, Lesson 23 — Nginx Web Server, Lesson 24 — TLS Certificates and HTTPS
  • Estimated reading time: 20 minutes

Introduction

PHP is the most widely used server-side scripting language on the web, powering platforms such as WordPress, Laravel, Drupal, and Magento. While web servers like Apache and Nginx handle static files directly, they need a PHP processor to execute PHP scripts and generate dynamic content.

On modern Ubuntu systems, PHP-FPM (FastCGI Process Manager) is the standard way to run PHP. PHP-FPM manages a pool of PHP worker processes that receive requests from the web server via the FastCGI protocol, execute the PHP code, and return the output. This architecture provides better performance, resource management, and isolation compared to the older mod_php approach.

In this lesson, you will install PHP and PHP-FPM, configure integration with both Apache and Nginx, tune PHP settings for production use, set up database connectivity, and deploy a real PHP application step by step.

Installing PHP and PHP-FPM

# Install PHP-FPM and common extensions
$ sudo apt update
$ sudo apt install php-fpm php-cli php-common php-mysql php-xml 
    php-mbstring php-curl php-zip php-gd php-intl php-bcmath

# Check PHP version
$ php -v
PHP 8.1.2-1ubuntu2 (cli)

# Check PHP-FPM service status
$ sudo systemctl status php8.1-fpm
● php8.1-fpm.service - The PHP 8.1 FastCGI Process Manager
     Active: active (running)

# List installed PHP modules
$ php -m

The PHP-FPM service name includes the version number (e.g., php8.1-fpm). Adjust commands according to your installed version.

PHP-FPM Pool Configuration

PHP-FPM manages worker processes through pool configurations. The default pool is defined in /etc/php/8.1/fpm/pool.d/www.conf:

# /etc/php/8.1/fpm/pool.d/www.conf — key settings
[www]
user = www-data
group = www-data

; Listen on a Unix socket (faster than TCP)
listen = /run/php/php8.1-fpm.sock
listen.owner = www-data
listen.group = www-data

; Process manager: static, dynamic, or ondemand
pm = dynamic
pm.max_children = 50
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 35
pm.max_requests = 500

Process manager modes:

  • static: A fixed number of worker processes. Best for dedicated servers with predictable load.
  • dynamic: Workers are spawned and killed based on demand, within configured limits. Good default for most servers.
  • ondemand: Workers are spawned only when requests arrive and killed after idle timeout. Best for low-traffic sites sharing resources.
# Create a separate pool for a specific application
$ sudo cp /etc/php/8.1/fpm/pool.d/www.conf /etc/php/8.1/fpm/pool.d/myapp.conf
# /etc/php/8.1/fpm/pool.d/myapp.conf
[myapp]
user = myapp
group = myapp
listen = /run/php/myapp.sock
listen.owner = www-data
listen.group = www-data
pm = dynamic
pm.max_children = 20
pm.start_servers = 3
pm.min_spare_servers = 2
pm.max_spare_servers = 10

; Per-pool PHP settings
php_admin_value[error_log] = /var/log/php/myapp-error.log
php_admin_flag[log_errors] = on
php_value[memory_limit] = 256M
php_value[upload_max_filesize] = 50M
php_value[post_max_size] = 50M
# Restart PHP-FPM to apply changes
$ sudo systemctl restart php8.1-fpm

Integrating PHP-FPM with Apache

Apache connects to PHP-FPM using the proxy_fcgi module:

# Enable required modules
$ sudo a2enmod proxy_fcgi setenvif
$ sudo a2enconf php8.1-fpm

# Or configure manually in a virtual host:
<VirtualHost *:80>
    ServerName myapp.example.com
    DocumentRoot /var/www/myapp/public

    <Directory /var/www/myapp/public>
        Options -Indexes +FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>

    <FilesMatch .php$>
        SetHandler "proxy:unix:/run/php/php8.1-fpm.sock|fcgi://localhost"
    </FilesMatch>

    ErrorLog ${APACHE_LOG_DIR}/myapp-error.log
    CustomLog ${APACHE_LOG_DIR}/myapp-access.log combined
</VirtualHost>
$ sudo apache2ctl configtest
$ sudo systemctl reload apache2

Integrating PHP-FPM with Nginx

Nginx passes PHP requests to PHP-FPM using the fastcgi_pass directive:

# /etc/nginx/sites-available/myapp
server {
    listen 80;
    server_name myapp.example.com;
    root /var/www/myapp/public;
    index index.php index.html;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ .php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php8.1-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }

    # Deny access to hidden files
    location ~ /.ht {
        deny all;
    }

    # Deny access to sensitive files
    location ~ /.(env|git) {
        deny all;
    }
}
$ sudo ln -s /etc/nginx/sites-available/myapp /etc/nginx/sites-enabled/
$ sudo nginx -t
$ sudo systemctl reload nginx

PHP Configuration Tuning

PHP’s main configuration file is php.ini. There are separate files for CLI and FPM:

# FPM php.ini location
$ php --ini   # CLI config
$ php-fpm8.1 -i | grep "Loaded Configuration"   # FPM config
# Typically: /etc/php/8.1/fpm/php.ini

# Key production settings
$ sudo nano /etc/php/8.1/fpm/php.ini
; Production-recommended settings
memory_limit = 256M
max_execution_time = 30
max_input_time = 60
upload_max_filesize = 50M
post_max_size = 50M

; Error handling — never display errors in production
display_errors = Off
display_startup_errors = Off
log_errors = On
error_log = /var/log/php/error.log
error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT

; Session configuration
session.save_handler = files
session.save_path = "/var/lib/php/sessions"
session.gc_maxlifetime = 1440

; OPcache — critical for production performance
opcache.enable = 1
opcache.memory_consumption = 128
opcache.interned_strings_buffer = 8
opcache.max_accelerated_files = 10000
opcache.validate_timestamps = 0
opcache.revalidate_freq = 0
# Create log directory
$ sudo mkdir -p /var/log/php
$ sudo chown www-data:www-data /var/log/php

# Restart PHP-FPM after configuration changes
$ sudo systemctl restart php8.1-fpm

Database Connectivity

Most PHP applications require a database. Here is how to set up MySQL/MariaDB connectivity:

# Install MariaDB server
$ sudo apt install mariadb-server
$ sudo mysql_secure_installation

# Create a database and user for the application
$ sudo mysql -u root
MariaDB> CREATE DATABASE myapp_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
MariaDB> CREATE USER 'myapp_user'@'localhost' IDENTIFIED BY 'StrongPassword123!';
MariaDB> GRANT ALL PRIVILEGES ON myapp_db.* TO 'myapp_user'@'localhost';
MariaDB> FLUSH PRIVILEGES;
MariaDB> EXIT;
# Test PHP database connectivity
$ cat > /tmp/dbtest.php <<'EOF'
<?php
$pdo = new PDO('mysql:host=localhost;dbname=myapp_db', 'myapp_user', 'StrongPassword123!');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
echo "Database connection successful!n";
EOF
$ php /tmp/dbtest.php
Database connection successful!
$ rm /tmp/dbtest.php

Deploying a PHP Application

Here is a step-by-step example deploying a Laravel application:

# Install Composer (PHP dependency manager)
$ curl -sS https://getcomposer.org/installer | php
$ sudo mv composer.phar /usr/local/bin/composer

# Clone the application
$ cd /var/www
$ sudo git clone https://github.com/example/myapp.git
$ cd myapp

# Install dependencies
$ sudo composer install --no-dev --optimize-autoloader

# Set permissions
$ sudo chown -R www-data:www-data /var/www/myapp
$ sudo chmod -R 755 /var/www/myapp
$ sudo chmod -R 775 /var/www/myapp/storage
$ sudo chmod -R 775 /var/www/myapp/bootstrap/cache

# Configure environment
$ sudo cp .env.example .env
$ sudo nano .env   # Set DB credentials, APP_URL, etc.
$ php artisan key:generate
$ php artisan migrate --force

# Optimize for production
$ php artisan config:cache
$ php artisan route:cache
$ php artisan view:cache

Key Takeaways

  • PHP-FPM is the standard way to run PHP on modern Ubuntu servers, providing better performance and isolation than mod_php.
  • PHP-FPM pools allow separate worker configurations per application with different users, memory limits, and log files.
  • Apache uses proxy_fcgi to connect to PHP-FPM; Nginx uses fastcgi_pass.
  • Always disable display_errors in production and enable OPcache for significant performance improvements.
  • Use Composer for dependency management and follow the application’s deployment documentation for environment setup.
  • Set proper file ownership (www-data) and permissions, especially for writable directories like storage and cache.

What’s Next

In Lesson 26, you will learn how to configure Nginx and Apache as reverse proxies and load balancers, distributing traffic across multiple backend application servers for high availability and scalability.

繁體中文

概述

  • 您將學到: 如何在 Ubuntu 上安裝 PHP 和 PHP-FPM、將 PHP 處理整合到 Apache 和 Nginx、設定 PHP 參數、連接 MySQL/MariaDB 資料庫,以及部署完整的 PHP 應用程式。
  • 先決條件: 第 22 課 — Apache2 網頁伺服器、第 23 課 — Nginx 網頁伺服器、第 24 課 — TLS 憑證和 HTTPS
  • 預估閱讀時間: 20 分鐘

簡介

PHP 是網頁上使用最廣泛的伺服器端腳本語言,驅動著 WordPress、Laravel、Drupal 和 Magento 等平台。在現代 Ubuntu 系統上,PHP-FPM(FastCGI 程序管理器)是執行 PHP 的標準方式。

PHP-FPM 管理一個 PHP 工作程序池,透過 FastCGI 協定從網頁伺服器接收請求、執行 PHP 程式碼並返回輸出。這種架構比舊式 mod_php 方法提供更好的效能和資源管理。

安裝 PHP 和 PHP-FPM

$ sudo apt update
$ sudo apt install php-fpm php-cli php-common php-mysql php-xml 
    php-mbstring php-curl php-zip php-gd php-intl

$ php -v
$ sudo systemctl status php8.1-fpm

PHP-FPM 池設定

PHP-FPM 透過池設定管理工作程序。預設池定義在 /etc/php/8.1/fpm/pool.d/www.conf

  • static: 固定數量的工作程序,適合專用伺服器。
  • dynamic: 根據需求動態產生和終止工作程序。
  • ondemand: 僅在請求到達時產生工作程序,適合低流量網站。

將 PHP-FPM 整合到 Apache

$ sudo a2enmod proxy_fcgi setenvif
$ sudo a2enconf php8.1-fpm
$ sudo systemctl reload apache2

將 PHP-FPM 整合到 Nginx

location ~ .php$ {
    include snippets/fastcgi-php.conf;
    fastcgi_pass unix:/run/php/php8.1-fpm.sock;
}

PHP 設定調整

; 生產環境建議設定
memory_limit = 256M
display_errors = Off
log_errors = On
opcache.enable = 1
opcache.memory_consumption = 128

資料庫連接

$ sudo apt install mariadb-server
$ sudo mysql_secure_installation

$ sudo mysql -u root
CREATE DATABASE myapp_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'myapp_user'@'localhost' IDENTIFIED BY 'StrongPassword123!';
GRANT ALL PRIVILEGES ON myapp_db.* TO 'myapp_user'@'localhost';
FLUSH PRIVILEGES;

部署 PHP 應用程式

# 安裝 Composer
$ curl -sS https://getcomposer.org/installer | php
$ sudo mv composer.phar /usr/local/bin/composer

# 安裝相依套件
$ composer install --no-dev --optimize-autoloader

# 設定權限
$ sudo chown -R www-data:www-data /var/www/myapp
$ sudo chmod -R 775 /var/www/myapp/storage

重點整理

  • PHP-FPM 是在現代 Ubuntu 伺服器上執行 PHP 的標準方式。
  • PHP-FPM 池允許為每個應用程式單獨設定工作程序。
  • Apache 使用 proxy_fcgi 連接 PHP-FPM;Nginx 使用 fastcgi_pass
  • 在生產環境中始終停用 display_errors 並啟用 OPcache。
  • 設定正確的檔案所有權和權限,特別是可寫目錄。

下一步

在第 26 課中,您將學習如何設定 Nginx 和 Apache 作為反向代理和負載均衡器。

日本語

概要

  • 学習内容: Ubuntu での PHP と PHP-FPM のインストール、Apache/Nginx との PHP 処理の統合、PHP 設定、MySQL/MariaDB データベース接続、完全な PHP アプリケーションのデプロイ。
  • 前提条件: レッスン 22 — Apache2 ウェブサーバー、レッスン 23 — Nginx ウェブサーバー、レッスン 24 — TLS 証明書と HTTPS
  • 推定読了時間: 20 分

はじめに

PHP はウェブで最も広く使用されているサーバーサイドスクリプト言語で、WordPress、Laravel、Drupal、Magento などのプラットフォームを駆動しています。現代の Ubuntu システムでは、PHP-FPM(FastCGI Process Manager)が PHP を実行する標準的な方法です。

PHP-FPM は PHP ワーカープロセスのプールを管理し、FastCGI プロトコルを介してウェブサーバーからリクエストを受信し、PHP コードを実行して出力を返します。

PHP と PHP-FPM のインストール

$ sudo apt update
$ sudo apt install php-fpm php-cli php-common php-mysql php-xml 
    php-mbstring php-curl php-zip php-gd php-intl

$ php -v
$ sudo systemctl status php8.1-fpm

PHP-FPM プール設定

PHP-FPM はプール設定でワーカープロセスを管理します:

  • static: 固定数のワーカープロセス。専用サーバーに最適。
  • dynamic: 需要に応じてワーカーを生成・終了。大半のサーバーに適切なデフォルト。
  • ondemand: リクエスト到着時のみワーカーを生成。低トラフィックサイトに最適。

Apache との PHP-FPM 統合

$ sudo a2enmod proxy_fcgi setenvif
$ sudo a2enconf php8.1-fpm
$ sudo systemctl reload apache2

Nginx との PHP-FPM 統合

location ~ .php$ {
    include snippets/fastcgi-php.conf;
    fastcgi_pass unix:/run/php/php8.1-fpm.sock;
}

PHP 設定チューニング

; 本番環境推奨設定
memory_limit = 256M
display_errors = Off
log_errors = On
opcache.enable = 1
opcache.memory_consumption = 128

データベース接続

$ sudo apt install mariadb-server
$ sudo mysql_secure_installation

$ sudo mysql -u root
CREATE DATABASE myapp_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'myapp_user'@'localhost' IDENTIFIED BY 'StrongPassword123!';
GRANT ALL PRIVILEGES ON myapp_db.* TO 'myapp_user'@'localhost';
FLUSH PRIVILEGES;

PHP アプリケーションのデプロイ

# Composer をインストール
$ curl -sS https://getcomposer.org/installer | php
$ sudo mv composer.phar /usr/local/bin/composer

# 依存パッケージをインストール
$ composer install --no-dev --optimize-autoloader

# パーミッションを設定
$ sudo chown -R www-data:www-data /var/www/myapp
$ sudo chmod -R 775 /var/www/myapp/storage

重要ポイント

  • PHP-FPM は現代の Ubuntu サーバーで PHP を実行する標準的な方法。
  • PHP-FPM プールによりアプリケーションごとに個別のワーカー設定が可能。
  • Apache は proxy_fcgi で PHP-FPM に接続、Nginx は fastcgi_pass を使用。
  • 本番環境では常に display_errors を無効にし、OPcache を有効にする。
  • 適切なファイル所有権とパーミッションを設定する(特に書き込み可能なディレクトリ)。

次のステップ

レッスン 26 では、Nginx と Apache をリバースプロキシおよびロードバランサーとして設定する方法を学びます。

You Missed