Ubuntu Apache step by step configuration with php + Nginx

Started by Ghazala, Aug 12, 2022, 12:29 AM

Previous topic - Next topic

GhazalaTopic starter

Ubuntu Apache step by step configuration with php + Nginx version selection as reverse proxy

Succeeding tasks will be solved and described in the post:

1. Installing Apache + PHP
2. Ability to choose PHP versions
3. The ability to work websites from different clients, with a restriction on reading directories of other sites.
4. Install Nginx with pagespeed module from google
5. Setting up Nginx as a reverse proxy

All stages will contain explanations. Installed Ubuntu 16.0.4 as server with SSH only.

STAGE 1 (Install Apache + PHP)

Start a shell with root rights:

sudo -i

Install apache:

apt install -y apache2



needed in order to automatically answer all questions positively through the installation process. For instance, if you execute:

 apt install apache2

then during the installation process we will be asked if we really want to install.

Install php (as mod_php)

 apt install -y php libapache2-mod-php

At this stage, we have php version 7 installed as an apache module.

STAGE 2 (Option to select PHP versions)

At the initial stage, we installed the Apache + PHP server, and PHP works for us as an Apache module. There are some modes of PHP operation. Detailed information can be found at the link "Briefly about CGI, FastCGI, PHP-FPM and mod_php".

If you are too lazy to read, then I will explain more simply:

1. mod_php - Apache itself executes the php script.

Pros: works quickly, requires a minimum of settings and knowledge
Cons: scripts run as apache client (usually www-data)

2. CGI/FastCGI - The Apache server runs the php-cgi interpreter application script, which in turn executes the php script

Pros: scripts are executed from an arbitrary user, can be used in conjunction with other applications (Nginx + PHP), PHP configuration can be made individual
Cons: speed, additional configuration

3.PHP-FPM is a modernized fast-cgi server that constantly keeps pool processes ready for work.

Pros: speed of work, scripts are executed from an arbitrary client, can be used in conjunction with other applications (Nginx + PHP-FPM is the most common implementation)
Cons: additional configuration, occupies a port, a separate port is opened for each user.

We will focus on CGI/FastCGI. In fact, many may be scared that it is the slowest, but on most shared hosting providers, this is the mode of operation (ispmanager uses this particular mode of operation). We will need to build the php versions that we need from the sources.

2.1 Building php from source

Update the repository:

apt update

Install the required packages for assembly:

apt install -y make \
git autoconf\
unzip \

The \ character is used as a line break for readability.

Create folders for php:

mkdir -p /opt/source/php
mkdir -p /opt/php/

Go to the directory where the php sources will be stored

cd /opt/source/php

Download the required version of php and unpack it:

wget -c http://php.net/get/php-5.6.18.tar.bz2/from/this/mirror -O php-5.6.18.tar.bz2
tar xvjf php-5.6.18.tar.bz2

In the last command, we downloaded php-5.6.18 from the link and saved it as php-5.6.18.tar.bz2
Then the archive was unpacked.

Go to the directory of downloaded and unpacked php

cd /opt/source/php/php-5.6.18

Configuring php

./configure --enable-cli\
 --prefix=/opt/php/php-5.6.18 \
 --disable-rpath \
 --enable-calendar \
 --enable-discard-path \
 --enable-force-cgi-redirect \
 --enable-ftp \
 --enable-inline-optimization \
 --enable-mbregex \
 --enable-mbstring \
 --enable-pcntl \
 --enable-soap \
 --enable-sockets \
 --enable-sysvsem \
 --enable-sysvshm \
 --enable-zip \
 --with-bz2 \
 --with-curl \
 --with-curl \
 --with-freetype-dir \
 --with-gd \
 --with-gd \
 --with-jpeg-dir \
 --with-jpeg-dir=/usr/lib/ \
 --with-libdir=/lib/x86_64-linux-gnu \
 --with-libxml-dir=/usr \
 --with-mcrypt \
 --with-mhash \
 --with-mysql \
 --with-mysql \
 --with-mysqli \
 --with-mysqli \
 --with-openssl \
 --with-pcre-regex \
 --with-pdo-mysql \
 --with-png-dir=/usr \

It is worth paying attention to the --prefix=/opt/php/php-5.6.18 line. That is the directory where the project will be built. You can also add or remove the necessary php module and components yourself. But when configuring, there must be --enable-fastcgi and --enable-force-cgi-redirect. After the configuration, we collect php

make install

The assembly process is unusually long, so do not worry about it. Upon completion of the assembly, you can check with the command:

/opt/php/php-5.6.18/bin/php -v

The result will be something like:

PHP 5.6.18 (cli) (built: Jun 8 2017 15:59:20)
Copyright © 1997-2016 The PHP Group
Zend Engine v2.6.0, Copyright © 1998-2016 Zend Technologies

2.2 Setting up Apache

Next, we need Apache to call the php script through fastcgi mode. Install and activate mod_fcgi

apt install libapache2-mod-fcgid
a2enmod cgi fcgid actions

restart Apache service

service apache2 restart

2.3 Creating a CGI script

Create a wrapper to run PHP-FastCGI

mkdir -p /opt/php/php-5.6.18/fcgi-bin

In this folder, create a script named php with the succeeding content
#!/opt/php/php-5.6.18/bin/php-cgi. Personally, I use the nano editor.

nano /opt/php/php-5.6.18/fcgi-bin/php

Paste the code, exit CTRL + X and confirm the changes.

Making the file executable:

chmod +x /opt/php/php-5.6.18/fcgi-bin/php

In the same directory we create a php.ini file () you can copy /opt/source/php/php-5.6.18/php.ini-production.

2.4 Apache host setup

The instance will show the default virtual host setup:

<VirtualHost *:80>
         ServerAdmin webmaster@localhost
         DocumentRoot /var/www/html
         <IfModule mod_fcgid.c>
             IPCCommTimeout 7200
             FcgidConnectTimeout 320
             MaxRequestLen 25728640
             FcgidMaxRequestsPerProcess 0
             FcgidBusyTimeout 3600
             FcgidOutputBufferSize 0

         <FilesMatch "\.ph(p[3-5]?|tml)$">
                 SetHandler fcgid-script
                 FCGIWrapper /opt/php/php-5.6.18/fcgi-bin/php
         ErrorLog /var/www/html/error.log
         CustomLog /var/www/html/access.log combined
<Directory /var/www/html>
         Options +Includes +ExecCGI

Restart Apache settings:

service apache2 reload

STAGE 3 (The ability to work sites from different users, with a restriction on reading directories of other sites.)

To differentiate rights by user, Apache has 2 different modules suEXEC and ITK.

Let's see how each of them works:

ITK - When a request is received, apache creates a handler process that inherits the rights of the root process, but after checking the context, changes its rights to the specified client.

suEXEC - When requested, apache runs CGI and similar native or third party scripts/programs inside the domain's web folder on behalf of the specified user.

suEXEC in our version is recommended due to the peculiarities of the work architecture. Installing suEXEC

apt install apache2-suexec-custom
a2enmod suexec

It is important that for proper operation of suexec it is required to correctly set the rights to the directories.
You must decide how to arrange the directories yourself, the example will give an instance, and it is not optimal.

The folder hierarchy is as follows:

|--/var/www/ - Root folder, permissions 751 owner root
|----/php-bin - Folder for storing default settings for php
|------/php-5.6.18 - Folder for storing default settings for php-5.6.18
|--------php - Executable file for php-5.6.18
|--------php.ini - Default configuration file
|--------php.ini - Default configuration file
|----/apache-cert - certificate storage folder for apache

Create folders for the user:

mkdir -p /var/www/users/admin
mkdir -p /var/www/users/admin/domain.ru
mkdir -p /var/www/users/admin/apache-log
mkdir -p /var/www/users/admin/php-bin
mkdir -p /var/www/users/admin/temp
mkdir -p /var/www/users/admin/temp/php-session

Copy the configuration files for php:

cp /opt/php/php-5.6.18/fcgi-bin/php /var/www/users/admin/php-bin/php
cp /opt/php/php-5.6.18/fcgi-bin/php.ini /var/www/users/admin/php-bin/php.ini

Create a user (it is essential to remember that all users in the admin group have access to run programs from sudo, so when choosing the name admin, he will automatically have the rights to execute sudo. In this instance, this is not critical, but you should remember this when creating a client) .

useradd -m -s /bin/bash admin
passwd admin

Set the owner of the folder:

chown admin:admin -R /var/www/users/admin

Set the root directory for the user:

usermod -d /var/www/users/admin admin

Setting up virtual hosts in apache:

<VirtualHost *:8080>
ServerAdmin webmaster@localhost
DocumentRoot /var/www/users/admin/domain.ru

SuexecUserGroup admin admin

<IfModule mod_remoteip.c>
RemoteIPHeader X-Forwarded-For
RemoteIPHeader X-Real-IP

<ifmodule mod_rewrite.c>
Rewrite Engine On
RewriteRule .* - [E=REMOTE_USER:%{HTTP:Authorization}]

<IfModule mod_fcgid.c>
IPCCommTimeout 7200
FcgidConnectTimeout 320
MaxRequestLen 25728640
FcgidMaxRequestsPerProcess 0
FcgidBusyTimeout 3600
FcgidOutputBufferSize 0

<FilesMatch "\.ph(p[3-5]?|tml)$">
SetHandler fcgid-script
FCGIWrapper /var/www/users/admin/php-bin/php

ErrorLog /var/www/users/admin/apache-log/error.log
CustomLog /var/www/users/admin/apache-log/access.log combined
<Directory /var/www/users/admin/www>
AllowOverride All
Options +Includes +ExecCGI

In the user's php.ini settings, change session.save_path
session.save_path = /var/www/users/admin/temp/php-session

Restart apache:

service apache2 restart

STEP 4 (Installing Nginx with google's pagespeed module)

Looking ahead, to support pagespeed in Nginx, you need to rebuild Nginx itself with this module, but in order not to climb additionally in the settings later, it's easier to install it first.
Change ports for Apache:

+ Your created virtual hosts

Restart Apache:

service apache2 restart

Install ngix:

apt-get install nginx

Building Nginx with pagespeed

Initial you need to install all the required packages for building:

apt install -y build-essential zlib1g-dev libpcre3 libpcre3-dev unzip libxslt1-dev libgd-dev libgeoip-dev

Create folders for nginx sources:

mkdir -p /opt/source/nginx
cd /opt/source/nginx

Download and unpack pagespeed and psol. Yt cnjbn g

wget https://github.com/pagespeed/ngx_pagespeed/archive/v1.11.33.4-beta.zip
unzip v1.11.33.4-beta.zip
cd ngx_pagespeed-
wget https://dl.google.com/dl/page-speed/psol/
tar -xzvf

The psol itself is downloaded and unpacked in a directory with ngx_pagespeed. Go to the folder with Ngnix

cd /opt/source/nginx

Check the ngnix version (1.10.0 is installed by default in ubuntu 16.0.4):

nginx -V

Download the NGINX version:

wget https://nginx.ru/download/nginx-1.10.0.tar.gz
tar -xvzf nginx-1.10.0.tar.gz

We build nginx with the same parameters as the installed one, but add additional modules at the end:

cd /opt/source/nginx/nginx-1.10.0
--with-cc-opt='-g -O2 -fPIE -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2' --with-ld-opt='-Wl, -Bsymbolic-functions -fPIE -pie -Wl,-z,relro -Wl,-z,now' --prefix=/usr/share/nginx --conf-path=/etc/nginx/nginx.conf --http -log-path=/var/log/nginx/access.log --error-log-path=/var/log/nginx/error.log --lock-path=/var/lock/nginx.lock --pid -path=/run/nginx.pid --http-client-body-temp-path=/var/lib/nginx/body --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --http -proxy-temp-path=/var/lib/nginx/proxy --http-scgi-temp-path=/var/lib/nginx/scgi --http-uwsgi-temp-path=/var/lib/nginx/ uwsgi --with-debug --with-pcre-jit --with-ipv6 --with-http_ssl_module --with-http_stub_status_module --with-http_realip_module --with-http_auth_request_module --with-http_addition_module --with-http_dav_module -- with-http_geoip_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_image_filter_module --with-http_v2_module --with-http_sub_module --with-http_ xslt_module --with-stream --with-stream_ssl_module --with-mail --with-mail_ssl_module --with-threads \
--add-module=/opt/source/nginx/ngx_pagespeed- \

Building Nginx:

make install

The compiled Nginx binary is located in the /opt/source/nginx/nginx-1.10.0/objs/nginx directory. In order to install, you just need to replace the current Nginx executable with the built one.

Stop Nginx, replace the file, and restart it.

service nginx stop

# Rename (just in case) the current nginx to nginx_backup:

mv /usr/sbin/nginx /usr/sbin/nginx_backup

# Move the new built binary to its place:

mv /opt/source/nginx/nginx-1.10.0/objs/nginx /usr/sbin/nginx

restart Nginx:

service nginx start

Create a cache storage folder for pagespeed:


Add /etc/nginx/nginx.conf to the http section:

page speed on;
pagespeed FileCachePath "/var/www/temp/page-speed/";
pagespeed EnableFilters combine_css,combine_javascript,rewrite_images,rewrite_css,rewrite_javascript,inline_images,recompress_jpeg,recompress_png,resize_images;
pagespeed JpegRecompressionQuality 85;
pagespeed ImageRecompressionQuality 85;
pagespeed ImageInlineMaxBytes 2048;
pagespeed LowercaseHtmlNames on;

STEP 5 (Configuring Nginx as a reverse proxy)

I will say that there are a lot of articles on the Net for setting up Nginx as a reverse proxy. I'll just give an introductory version of the settings.

server {

listen 80;
server_name domain.ru;
access_log /var/log/nginx.access_log;

location ~* \.(jpg|jpeg|gif|png|css|zip|tgz|gz|rar|bz2|doc|xls|exe|pdf|ppt|tar|wav|bmp|rtf|swf|ico|flv| txt|xml|docx|xlsx)$ {
root /var/www/users/admin/domain.ru;
index index.html index.php;
expires 30d;
error_page 404 = @prox;

location @prox{
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-for $remote_addr;
proxy_set_header Host $host;
proxy_connect_timeout 60;
proxy_send_timeout 90;
proxy_read_timeout 90;
proxy_redirect off;
proxy_set_header Connection close;
proxy_pass_header Content-Type;
proxy_pass_header Content-Disposition;
proxy_pass_header Content-Length;

location ~ /\.ht {
deny all;

location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-for $remote_addr;
proxy_set_header Host $host;
proxy_connect_timeout 60;
proxy_send_timeout 90;
proxy_read_timeout 90;
proxy_redirect off;
proxy_set_header Connection close;
proxy_pass_header Content-Type;
proxy_pass_header Content-Disposition;
proxy_pass_header Content-Length;


On shared hosting, the presence of apache + nginx is still justified. Well, or in the case of Bitrix, but this is a specific case.
Personally, it seems that if you have access to the server, it's better not to pervert,
but to do it with new software and not install too much, leaving only a bunch of nginx + php7.4-fpm - this is enough for the vast majority of frameworks and cms on php.

You need to place several applications that work on the old version - rewrite them so that they are compatible, or put them on a different smaller server and not get confused.


this will reduce the support time - the settings are not so confusing - it is faster and easier to set up and maintain
As a result, you will get a maximum of 2 servers on which everything will fit and work - one with a bunch of nginx + php7.4-fpm
the second is nginx+apache+php5.6
that at a cost, taking into account current tariffs, not so much will come out, and setting up and supporting each will be clear.


Before starting Apache, you need to make some changes to the firewall settings on your webserver. As a simplified interface for setting up a firewall in Ubuntu, Uncomplicated Firewall or UFW is usually used.

To open access to the server from Apache, you need to give this application access permission by registering it with UFW. The list of applications familiar to the UFW utility can be viewed with the command:

$ sudo ufw app list