This guide is intended for operating a WordPress or similar PHP-MySQL-based application on a dedicated or cloud/VPS server with 12GB to 16 GB. You can use a server from any web host of your choice. We can suggest you use VPSDime OpenVZ instances for small to medium websites. 6GB RAM, 10Gbps connection instances will cost you $7.00/mo. If you need dedicated resources, then you can test their premium KVM VPS. If you can not follow this guide, you can request them to complete it for a small fee. The links we have provided you are affiliate links. Again, you can use a server from any web host of your choice such as Ionos, Linode, Digital Ocean, Hostgator, Namecheap, Vultr etc to name a few.
Before following this guide, you need to complete these two steps:
For this guide, we will use Ondřej Surý’s PHP repositories. You must not be the root user on SSH. If you run these commands as a root user, it will lead to a complex situation later for file management, apart from security risks.
---
In this guide, we have given an example with PHP 7.2 because we do not know whether your web app supports the latest version of PHP.
How To Install PHP and Apache2 on Ubuntu 22.04
1 2 3 4 5 6 | sudo apt-get install software-properties-common sudo add-apt-repository ppa:ondrej/php sudo apt update sudo add-apt-repository ppa:ondrej/apache2 sudo apt update sudo apt install apache2 apache2-doc apache2-utils |
In this guide, we have given an example with PHP 7.2 because we do not know whether your web app supports the latest version of PHP. You can always switch between different versions of PHP (for example, PHP 8.x to PHP 7.x or vice versa):
1 | sudo update-alternatives --config php |
Which version of PHP you’ll use is your matter. Many are forced to use PHP 7.2, 7.4 etc for compatibility issues.
This command will install all the required components to run PHP-FPM for version 7.2:
1 | apt-get -y install libapache2-mod-php php7.2 php7.2-common php7.2-gd php7.2-mysql php7.2-imap php7.2-cli php7.2-cgi libapache2-mod-fcgid apache2-suexec-pristine php-pear mcrypt imagemagick libruby libapache2-mod-python php7.2-curl php7.2-intl php7.2-pspell php7.2-recode php7.2-sqlite3 php7.2-tidy php7.2-xmlrpc php7.2-xsl php-imagick php7.2-gettext php7.2-zip php7.2-mbstring php-soap php7.2-soap php7.2-fpm |
Please change the version number of PHP from 7.2 to your required version (such as 8.2, 8.3). You can search the repository for modules for your version of PHP:
1 | apt search php8.3 |
Completing this step requires your attention since PHP is the main thing for PHP-MySQL-based web software. First, disable the mod_php:
1 | sudo a2dismod php7.2 |
Next, disable mod prefork:
1 | sudo a2dismod mpm_prefork |
Enable mpm_event:
1 | sudo a2enmod mpm_event |
Activate the required Apache2 modules:
1 2 3 4 5 | sudo apt install php7.2-fpm sudo apt install libapache2-mod-fcgid sudo a2enconf php7.2-fpm sudo a2enmod proxy sudo a2enmod proxy_fcgi |
Now check the below configuration file:
1 | cat /etc/apache2/conf-enabled/php7.2-fpm.conf |
This must not be empty. Run configuration test and restart Apache:
1 2 | sudo apachectl configtest sudo systemctl restart apache2 |
Now your site should be running on PHP-FPM.
1 | sudo apachectl -M | grep 'mpm' |
output will be as follows:
1 | mpm_event_module (shared) |
Check the proxy module and FastCGI:
1 2 3 4 | sudo apachectl -M | grep 'proxy' ## output # proxy_module (shared) # proxy_fcgi_module (shared) |
Create a PHP info webpage and check from the browser:
1 | sudo nano /var/www/html/info.php |
Paste this content:
Do not forget to delete this file after checking.
To prevent the server from HTTPOXY attacks, we will create the httpoxy.conf file:
1 | nano /etc/apache2/conf-available/httpoxy.conf |
Paste this configuration:
1 | RequestHeader unset Proxy early |
Save the file. Enable the HTTPOXY configuration file and restart Apache:
1 2 3 4 | a2enconf httpoxy # activate headers module to avoid apache2's error sudo a2enmod headers sudo systemctl restart apache2 |
Optimizing Apache2 mpm_event and PHP-FPM
Open the mpm_event configuration file:
1 | nano /etc/apache2/mods-enabled/mpm_event.conf |
Add/modify to reflect the below content:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | <IfModule mpm_event_module> KeepAlive On KeepAliveTimeout 5 MaxKeepAliveRequests 128 ServerLimit 10 StartServers 4 ThreadLimit 128 ThreadsPerChild 128 MinSpareThreads 256 MaxSpareThreads 512 MaxRequestWorkers 1280 MaxConnectionsPerChild 2048 </IfModule> |
Test it:
1 2 3 4 5 6 | sudo systemctl restart apache2 cd ~ apt install python wget https://raw.githubusercontent.com/pixelb/ps_mem/master/ps_mem.py chmod a+x ps_mem.py sudo python ps_mem.py |
On my test 16GB dedicated server, it was sucking 2GB RAM:
1 2 3 4 5 6 7 8 9 | Private + Shared = RAM used Program ... ... 113.3 MiB + 11.3 MiB = 124.6 MiB apache2 (5) 1.3 GiB + 652.9 MiB = 2.0 GiB php-fpm7.2 (31) 3.0 GiB + 390.5 KiB = 3.0 GiB mysqld --------------------------------- 5.3 GiB |

Open the PHP-FPM configuration file:
1 | nano /etc/php/7.2/fpm/pool.d/www.conf |
Adjust these parameters:
1 2 3 4 5 6 | pm = dynamic pm.max_children = 100 pm.start_servers = 20 pm.min_spare_servers = 10 pm.max_spare_servers = 30 pm.process_idle_timeout = 10s; |
You can adjust the values to higher later after reading various documentation and guides available all over the internet. We have tried to deliver a balanced setting.
Restart Apache and PHP-FPM:
1 2 | sudo systemctl restart php7.2-fpm sudo systemctl restart apache2 |
Normally, you’ll not need more optimization for running a single domain. To add multiple websites (separated from each other), you have to add a new Apache user, and add a new configuration file at /etc/php/7.2/fpm/pool.d.
Enable HTTP/2 from virtual host file and test it. You can list the modules Apache2 has loaded:
1 | apachectl -M |
This is our output:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | Loaded Modules: core_module (static) so_module (static) watchdog_module (static) http_module (static) log_config_module (static) logio_module (static) version_module (static) unixd_module (static) access_compat_module (shared) alias_module (shared) auth_basic_module (shared) authn_core_module (shared) authn_file_module (shared) authz_core_module (shared) authz_host_module (shared) authz_user_module (shared) autoindex_module (shared) brotli_module (shared) deflate_module (shared) dir_module (shared) env_module (shared) expires_module (shared) fcgid_module (shared) filter_module (shared) geoip_module (shared) headers_module (shared) http2_module (shared) mime_module (shared) mpm_event_module (shared) negotiation_module (shared) proxy_module (shared) proxy_fcgi_module (shared) python_module (shared) reqtimeout_module (shared) rewrite_module (shared) setenvif_module (shared) slotmem_shm_module (shared) socache_dbm_module (shared) socache_shmcb_module (shared) ssl_module (shared) status_module (shared) unique_id_module (shared) |
You can install and activate the modules in this way:
1 2 3 4 | sudo a2enmod expires sudo apachectl configtest # look for Syntax OK sudo systemctl restart apache2 |
It will take time to install all the modules. Apache on Ubuntu 22.04 has one server block enabled by default that is configured to serve documents from the /var/www/html directory. While this works well for a single site, it can become complex if you are hosting multiple sites. Your virtual host files are located here:
1 | /etc/apache2/sites-available/ |
You have to follow this guide to configure Let’s Encrypt.
Tagged With noisem45