Install PHP
- 🐧 Linux Command Line
Ansible Playbook
Core
Install PHP
install-php.sh
#!/bin/sh
# Interactive input for PHP version
read -p "Please enter the PHP version you want to install (e.g., 8.3.15): " php_version
# Install required dependencies
dnf install -y gcc gcc-c++ make libxml2-devel bzip2-devel curl-devel libpng-devel libjpeg-devel libXpm-devel freetype-devel gmp-devel libmcrypt-devel oniguruma-devel libxslt-devel libzip-devel libwebp-devel zip cronie sqlite sqlite-devel systemd-devel
# Download and compile PHP
cd /usr/local/src
wget https://www.php.net/distributions/php-${php_version}.tar.gz
tar -xzf php-${php_version}.tar.gz
cd php-${php_version}
make clean
./configure \
--prefix=/usr/local/php \
--enable-gd \
--enable-soap \
--enable-intl \
--enable-bcmath \
--enable-sockets \
--enable-opcache \
--enable-mbstring \
--enable-pcntl \
--enable-fpm \
--with-config-file-path=/usr/local/php \
--with-fpm-user=www \
--with-fpm-group=www \
--with-fpm-systemd \
--with-mysqli \
--with-pdo-mysql \
--with-openssl \
--with-curl \
--with-zip \
--with-zlib \
--with-bz2 \
--with-external-pcre \
--with-jpeg \
--with-freetype \
--with-xsl \
--with-pear
make -j$(nproc)
make install
cp php.ini-production /usr/local/php/php.ini
cp /usr/local/php/etc/php-fpm.conf.default /usr/local/php/etc/php-fpm.conf
Configure PHP
/usr/local/php/php.ini
include_path = ".:/usr/local/php/lib/php"
expose_php = Off
error_log = "/var/log/php-error.log"
max_execution_time = 30
memory_limit = 128M
post_max_size = 8M
display_errors = Off
disable_functions = exec,passthru,shell_exec,system,proc_open,popen,show_source
mysqli.default_socket = /run/mysqld.sock
pdo_mysql.default_socket = /run/mysqld.sock
Configure PHP-FPM
/usr/local/php/etc/php-fpm.conf
pid = /run/php-fpm.pid
error_log = /var/log/php-fpm.log
log_level = notice
Directory and Permissions
# Directory and permissions for log files
mkdir -p /var/log
touch /var/log/php-fpm.log
touch /var/log/php-error.log
chown www:www /var/log/php-fpm.log
chown www:www /var/log/php-error.log
chmod 640 /var/log/php-fpm.log
chmod 640 /var/log/php-error.log
# The 'www' user needs read access to the PHP installation directory to load core files, but should not have root-level write access.
chown -R root:www /usr/local/php
chmod -R 750 /usr/local/php
# PHP-FPM requires access to extension modules (e.g., redis.so).
chown -R root:www /usr/local/php/lib/php/extensions
chmod -R 750 /usr/local/php/lib/php/extensions
# The PHP-FPM master process needs to read global and pool configuration files.
chown -R www:www /usr/local/php/etc
chmod -R 750 /usr/local/php/etc
# Write permissions are needed for PHP-FPM error and access logs.
mkdir -p /var/log/php-fpm
chown -R www:www /var/log/php-fpm
chmod -R 750 /var/log/php-fpm
Create PHP-FPM Service
vi /etc/systemd/system/php-fpm.service
[Unit]
Description=PHP FastCGI Process Manager
After=network.target
[Service]
Type=simple
RuntimeDirectory=php-fpm
RuntimeDirectoryMode=0750
RuntimeDirectoryOwner=www
RuntimeDirectoryGroup=www
PIDFile=/run/php-fpm.pid
ExecStart=/usr/local/php/sbin/php-fpm --nodaemonize --fpm-config /usr/local/php/etc/php-fpm.conf
ExecReload=/bin/kill -USR2 $MAINPID
ExecStop=/bin/kill -SIGQUIT $MAINPID
PrivateTmp=true
[Install]
WantedBy=multi-user.target
Start PHP-FPM Service
systemctl daemon-reload
systemctl enable --now php-fpm
systemctl status php-fpm
install-php.yml
- name: Compile and install PHP
hosts: all
remote_user: root
vars:
php_version: "8.3.15"
php_prefix: "/usr/local/php"
php_user: "www"
php_group: "www"
tasks:
- name: Install required dependencies
dnf:
name:
- gcc
- gcc-c++
- make
- libxml2-devel
- bzip2-devel
- curl-devel
- libpng-devel
- libjpeg-devel
- libXpm-devel
- freetype-devel
- gmp-devel
- libmcrypt-devel
- oniguruma-devel
- libxslt-devel
- libzip-devel
- libwebp-devel
- zip
- cronie
- sqlite
- sqlite-devel
- systemd-devel
state: present
- name: Download PHP source code
get_url:
url: "https://www.php.net/distributions/php-{{ php_version }}.tar.gz"
dest: "/usr/local/src/php-{{ php_version }}.tar.gz"
- name: Extract PHP source code
unarchive:
src: "/usr/local/src/php-{{ php_version }}.tar.gz"
dest: "/usr/local/src/"
remote_src: true
- name: Check if Makefile exists
stat:
path: "/usr/local/src/php-{{ php_version }}/Makefile"
register: makefile_stat
- name: Clean previous PHP build
command: make clean
args:
chdir: "/usr/local/src/php-{{ php_version }}"
when: makefile_stat.stat.exists
- name: Configure PHP
command: >
./configure
--prefix={{ php_prefix }}
--enable-gd
--enable-soap
--enable-intl
--enable-bcmath
--enable-sockets
--enable-opcache
--enable-mbstring
--enable-pcntl
--enable-fpm
--with-config-file-path={{ php_prefix }}
--with-fpm-user={{ php_user }}
--with-fpm-group={{ php_group }}
--with-mysqli
--with-pdo-mysql
--with-openssl
--with-curl
--with-zip
--with-zlib
--with-bz2
--with-external-pcre
--with-jpeg
--with-freetype
--with-xsl
--with-pear
args:
chdir: "/usr/local/src/php-{{ php_version }}"
register: configure_output
changed_when: configure_output.rc != 0
- name: Compile and install PHP (/tmp/php_build_output.log)
shell: |
set -o pipefail
make -j"{{ ansible_processor_vcpus }}" | tee /tmp/php_build_output.log
make install
args:
chdir: "/usr/local/src/php-{{ php_version }}"
register: php_build_output
changed_when: php_build_output.rc != 0
- name: Copy php.ini production configuration
copy:
src: "/usr/local/src/php-{{ php_version }}/php.ini-production"
dest: "{{ php_prefix }}/php.ini"
remote_src: true
mode: "0644"
- name: Configure php.ini
vars:
php_settings:
- {key: "include_path", value: '".:/usr/local/php/lib/php"'}
- {key: "expose_php", value: "Off"}
- {key: "error_log", value: '"/var/log/php-error.log"'}
- {key: "max_execution_time", value: "30"}
- {key: "memory_limit", value: "128M"}
- {key: "post_max_size", value: "8M"}
- {key: "display_errors", value: "Off"}
- {key: "disable_functions", value: "exec,passthru,shell_exec,system,proc_open,popen,show_source"}
- {key: "mysqli.default_socket", value: "/run/mysqld.sock"}
- {key: "pdo_mysql.default_socket", value: "/run/mysqld.sock"}
lineinfile:
path: /usr/local/php/php.ini
regexp: "^{{ item.key }} ="
line: "{{ item.key }} = {{ item.value }}"
create: true
mode: "0644"
loop: "{{ php_settings }}"
- name: Copy default PHP-FPM configuration
copy:
src: "{{ php_prefix }}/etc/php-fpm.conf.default"
dest: "{{ php_prefix }}/etc/php-fpm.conf"
remote_src: false
mode: "0644"
- name: Update php-fpm.conf configuration
lineinfile:
path: "{{ php_prefix }}/etc/php-fpm.conf"
regexp: "{{ item.regexp }}"
line: "{{ item.line }}"
loop:
- {regexp: "^;?pid =", line: "pid = /run/php-fpm.pid"}
- {regexp: "^;?error_log =", line: "error_log = /var/log/php-fpm.log"}
- {regexp: "^;?log_level =", line: "log_level = notice"}
- name: Create log files
file:
path: "{{ item }}"
state: touch
owner: "{{ php_user }}"
group: "{{ php_group }}"
mode: "0640"
with_items:
- /var/log/php-fpm.log
- /var/log/php-error.log
- name: Set permissions for PHP directories
file:
path: "{{ php_prefix }}"
owner: "root"
group: "{{ php_group }}"
mode: "0750"
recurse: true
- name: Ensure PHP extensions directory is accessible
file:
path: "{{ php_prefix }}/lib/php/extensions"
owner: "root"
group: "{{ php_group }}"
mode: "0750"
recurse: true
- name: Set ownership and permissions for PHP-FPM configuration
file:
path: "{{ php_prefix }}/etc"
owner: "{{ php_user }}"
group: "{{ php_group }}"
mode: "0750"
recurse: true
- name: Ensure PHP-FPM log directory exists
file:
path: /var/log/php-fpm
state: directory
owner: "{{ php_user }}"
group: "{{ php_group }}"
mode: "0750"
- name: Create php-fpm systemd service file
copy:
dest: /etc/systemd/system/php-fpm.service
mode: "0644"
content: |
[Unit]
Description=PHP FastCGI Process Manager
After=network.target
[Service]
Type=simple
RuntimeDirectory=php-fpm
RuntimeDirectoryMode=0750
RuntimeDirectoryOwner=www
RuntimeDirectoryGroup=www
PIDFile=/run/php-fpm.pid
ExecStart=/usr/local/php/sbin/php-fpm --nodaemonize --fpm-config /usr/local/php/etc/php-fpm.conf
ExecReload=/bin/kill -USR2 $MAINPID
ExecStop=/bin/kill -SIGQUIT $MAINPID
PrivateTmp=true
[Install]
WantedBy=multi-user.target
- name: Reload systemd
systemd:
daemon_reload: true
- name: Enable and start PHP-FPM
systemd:
name: php-fpm
enabled: true
state: started