Install NGINX on Ubuntu with MySQL and PHP FPM

Introduction

In this post, I will go over details of how to install NGINX web server, MySQL Server and PHP on an Ubuntu Server. I will also go over the details of setting up SSL and Virtual Host Configuration for NGINX.

Let’s start with our installation on the Ubuntu version of Linux.

NGINX HTTPD Web Server

NGINX webserver files and all related documentation is located on the NGINX Server website.

Since NGINX is an open source server, you can download the NGINX source code and browse user, admin and developer documentation on the NGINX website.

Before starting to install run update the package manager using the following command.

root@d1:~# sudo apt update

Install NGINX Web Server

Once the update is done use the command below to install the NGINX web server.

root@d1:~# sudo apt install nginx

Once the above command completes, the default install of NGINX web server will be installed. You can check NGINX version using the command:

root@d1:~# nginx -v

To validate the installation you can use one of the following two methods.

Validate Install with CURL

Use the following curl command to check if the NGINX web server is installed and working.

root@d1:~# curl http://localhost  -i

The output should be similar to what is shown below.

HTTP/1.1 200 OK
Server: nginx/1.18.0 (Ubuntu)
Date: Wed, 08 Feb 2023 02:04:39 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Wed, 08 Feb 2023 01:04:05 GMT
Connection: keep-alive
ETag: "63e2f505-264"
Accept-Ranges: bytes
......

Note: After line 11 will be the content of the index.html installed with NGINX. I have deleted those lines for brevity.

Validate Install with Browser

Open your favorite browser and enter the URL http://localhost. The default webpage will open.

Nginx default webpage on Windows
Nginx default webpage on Ubuntu

NGINX Important Files and Folders

Now that I have gone over the steps of installing the NGINX web server and ensuring it is working, let’s take a few moments to review the important files and folders installed.

NGINX configuration files are installed in the folder /etc/nginx. During ls shows the following structure.

oot@d1:/etc/nginx# ls
conf.d        fastcgi_params  koi-win     modules-available  nginx.conf    scgi_params      sites-enabled  uwsgi_params
fastcgi.conf  koi-utf         mime.types  modules-enabled    proxy_params  sites-available  snippets       win-utf

conf-* Folders

The conf-available folder has all files that are available for you to configure NGINX behavior. You will find the PHP fpm configuration and security files.

Do note that not all files in this folder are currently being used. The enabled configuration files are linked through the conf-enabled folder.

modules-* Folders

modules-available contains configuration files of all modules available for configuration. With the default this folder usually has no configuration files.

modules-enabled contains configuration files of all available modules.

sites-* Folders

sites-* folders are used to manage virtual server configurations for multiple websites. Available virtual host (domain a server will be hosting) configuration will be in the sites-available folder and activated (aka live) virtual hosts are in the sites-enabled folder.

For NGINX activating or enabling a virtual host needs a symbolic link to be created from /etc/nginx/sites-enabled to a config file in /etc/nginx/sites-available folder.

Important Files

  • nginx.conf: This file has many server level configuration parameters. These allow you to configure server level configuration options. For example to turn on gzip compression for all sites you will add the line gzip on; to nginx.conf.
  • fastcgi_params: In this file you setup variables that will be passed from NGINX to backend dynamic processing modules such as PHP.
  • proxy_params: When NGINX is configured to work as a proxy server then instead of setting those in each of the server{} block you can add the headers in this file and it will forward those to all backend servers.

HTML Files Folder

Ubuntu installs all web files below the /var/www/ folder, which is the root of all virtual host site folders.

The default localhost files are located in the folder /var/www/html.

When you set up a new virtual host example.com, then you may want to copy the files in the folder /var/www/example and use this path in the virtual host configuration. I will go over this in a later section.

Log Folder

Ubuntu installs the log file in /var/log/nginx folder. When configuring a new virtual host on NGINX you should point all access and error log files to be stored in this folder.

Starting and Stop NGINX Web Server

When you install the server using the apt command, the script automatically starts the NGINX web server.

But during routine management and configuration changes, you will need to manually start or stop the NGINX web server. There are also cases where you don’t need to restart the NGINX web server but simply need the configuration changes to be reloaded.

The following commands are available for you to manage the NGINX web server.

root@d1:/etc/nginx# sudo service nginx stop
root@d1:/etc/nginx# sudo service nginx start
root@d1:/etc/nginx# sudo service nginx restart
root@d1:/etc/nginx# sudo service nginx reload

NGINX SSL Configuration

To use SSL with NGINX I will need to have a SSL certificate. Luckily with Ubuntu in the /etc/ssl/certs folder there are a few available that I can use for testing.

The default install did create a virtual server with the name default that serves all requests for localhost and 127.0.0.1 IP address.

root@d1:/etc/nginx# ls -l sites-available/
total 4
-rw-r--r-- 1 root root 2412 Jul 26  2022 default
root@d1:/etc/nginx# ls -l sites-enabled/
total 0
lrwxrwxrwx 1 root root 34 Feb  7 17:03 default -> /etc/nginx/sites-available/default

As I have mentioned above there is a default config in the sites-available folder. Then a link from sites-enabled was created to this file.

To create a secure SSL NGINX server I will create a new webserver configuration file default-ssl in the /etc/nginx/sites-available folder.

The contents of this file will be:

server {
        listen 443 ssl default_server;
        listen [::]:443 ssl default_server;

        gzip off;
        ssl_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem;
        ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key;

        root /var/www/html;

        index index.html;

        server_name _;

        location / {
                # First attempt to serve request as file, then
                # as directory, then fall back to displaying a 404.
                try_files $uri $uri/ =404;
        }
}

Let me go over the important parts of the server block in the configuration file.

  • Line 2 & 3: NGINX listening port is set with the listen directive. Here I have configured NGINX to serve all requests for default server, localhost in this case coming in on secure port 443 to be served as configured for this server.
  • Line 5: NGINX documentation suggests that gzip is disabled for SSL secured websites.
  • Line 6 & 7: Using the ssl_certificate and ssl_certificate_key directive, I use file system paths to the actual certificate and key.
  • Line 9: Specifies the document root folder for this domain. Static files and other static content such as media files can be located here. You can also use this folder to store dynamic PHP script files will be stored here.
  • Line 11: Specify the index files with the index directive. In case of multiple index files, as with using PHP, separate multiple values with a comma(,).
  • Lines 15-18: Define how to process requests coming to the root of the domain. You can have multiple location blocks. Later I will be setting up another location block to process dynamic web requests for PHP.

After creating the SSL server config file, I will create a symbolic link from the sites-available folder to this file.

The location block in the server block is pointing to the root from which NGINX will be serving static files from.

root@d1:/etc/nginx/sites-enabled# ln -s /etc/nginx/sites-available/default-ssl default-ssl

Restart NGINX after enabling the mods and the SSL VirtualHost site.

root@d1:~$ sudo service nginx restart

Run the curl command from the shell to ensure everything is running.

root@d1:~# curl -I https://localhost -k

This will show the headers only. If you want to view all headers with data on TLS including the contents of the page being served then use the following.

root@d1:~# curl -v https://localhost -k

Note, that if you opened the URL in the browser then you will get the following error message.

Browser Error Message for a Non Production SSL Certificate
`Browser Error Message for a Non Production SSL Certificate

This is normal because the SSL certificate used is not for production. To bypass this message click on Advanced button and click on the Accept the Risk and Continue button.

This will take you to the actual page.

NGINX SSL Site

Install MySQL on Ubuntu Server

After installing NGINX, the next step is to install MySQL. Run the following command.

root@d1:~# sudo apt install mysql-server

Once MySQL server install completes you can check the version using the command,

root@d1:~# mysql  Ver 8.0.32-0ubuntu0.20.04.2 for Linux on x86_64 ((Ubuntu))

How to Login to new MySQL Install on Ubuntu

In the latest versions of MySql, there is no built-in account that you can log in using username/password combo. There is however a root account created with auto login enabled for the current user.

To login to MySQL user the following command:

root@d1:~# sudo mysql

Create MySQL Test Database and New User

Now that I have installed MySQL and have logged in to the MySQL shell, I will create a new user and database for testing with PHP.

Run the following SQL commands.

mysql> CREATE DATABASE fsmtest CHARACTER SET UTF8MB4;
Query OK, 1 row affected (0.01 sec)

mysql> CREATE USER 'fsmuser'@'localhost' IDENTIFIED BY 'nopass';
Query OK, 0 rows affected (0.02 sec)

mysql> GRANT ALL ON fsmtest.* to 'fsmuser'@'localhost';
Query OK, 0 rows affected (0.01 sec)

mysql> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.00 sec)

Basically, with the SQL commands shown above I first create a database, then a new user and after that I grant the user all privileges or access on the newly created database.

I also issue the flush SQL command, which is optional.

Now I am ready to install PHP to complete the software stack.

Installing PHP FPM on Ubuntu Server

To install PHP run the following command.

root@d1:~# sudo apt install php-fpm

This will install or configure PHP to run in FPM mode.

To check if PHP-FPM is running, use the command below:

root@d1:~# ps -eaf | grep fpm
root       20966       1  0 18:42 ?        00:00:00 php-fpm: master process (/etc/php/8.1/fpm/php-fpm.conf)
www-data   20967   20966  0 18:42 ?        00:00:00 php-fpm: pool www
www-data   20968   20966  0 18:42 ?        00:00:00 php-fpm: pool www
root       21027   19370  0 18:42 pts/1    00:00:00 grep --color=auto fpm

Enabling Additional PHP Extensions

To make sure PHP can talk with MySQL you will need to install the relevant extension.

root@d1:~# sudo apt install php-mysql

Once the MySQL extension is installed run the following command to ensure that the extension is loaded by PHP.

root@d1:~# php -i | grep mysql

The output will show in multiple lines configuration settings for MySQL extension.

Although PHP MySQL is installed, you will need to restart PHP-FPM to pickup the new changes.

root@d1:~# sudo systemctl restart php8.1-fpm.service

Other commands for PHP-FPM are:

root@d1:~# sudo systemctl start php8.1-fpm.service
root@d1:~# sudo systemctl stop php8.1-fpm.service
root@d1:~# sudo systemctl reload php8.1-fpm.service

With this our basic setup of NGINX, MySQL and PHP are complete.

PHP Configuration Files

PHP configuration files are in the folder /etc/php/{version}. Form example if PHP version 8.1 is installed then the path will be /etc/php/8.1. Doing an ls show the following:

root@d1:~# /etc/php/8.1$ ls
apache2  cli  fpm  mods-available

The apache2 folder has the php.ini file when PHP is being used as a module with Apache. If PHP is being used in FPM mode then the fpm folder has the relevant php.ini file.

Setup NGINX and PHP Integration in Server

Here I am going to modify the virtual server file default-ssl and add lines to support NGINX to forward .php file requests to the PHP-FPM process.

The content of the final defaul-ssl will be:

server {
        listen 443 ssl default_server;
        listen [::]:443 ssl default_server;

        gzip off;
        ssl_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem;
        ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key;

        root /var/www/html;

        index index.html;

        server_name _;

        location / {
                # First attempt to serve request as file, then
                # as directory, then fall back to displaying a 404.
                try_files $uri $uri/ =404;
        }

        # pass PHP scripts to FastCGI server
        location ~ \.php$ {
              include snippets/fastcgi-php.conf;

              fastcgi_pass unix:/run/php/php8.1-fpm.sock;
        }
}

One change you will see in the above server configuration is the addition on a new block (lines 22-25). This tells NGINX to forward all PHP script requests to the PHP FPM process.

Now I will restart the NGINX web server process.

root@d1:~# sudo service nginx restart

Create a PHP Test File

With the changes in place, let’s create a PHP test file to view PHP configuration.

Go to the folder /var/www/html and create a new file config.php and copy the following text and save it.

<?php
phpinfo();

In this file I am using a built-in PHP funtion phpinfo(), which prints PHP configuration as HTML text.

NGINX with SSL on Ubuntu showing PHP Configuration Info
NGINX with SSL on Ubuntu showing PHP Configuration Info

Testing Complete NGINX, MySQL & PHP Setup

Now that NGINX, MySQL and PHP correctly installed and configured with validation that all needed extensions and modules are installed and configured correctly, I will now create a PHP script to get some data from MySQL.

Add Table and Data to MySQL

Earlier while setting up MySQL I created a database fsmtest for validating integration of my setup.

First I will create a new table.

user@d1:~$ mysql -u fsmuser -p
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.

mysql> use fsmtest;
Database changed
mysql> CREATE TABLE city ( name varchar(255));
Query OK, 0 rows affected (0.01 sec)

With the table in place let’s add a single record.

mysql> INSERT INTO city (name) VALUES ('San Francisco');

I have added a single record to the database.

Now create a PHP page to get this data from MySQL and display in a browser.

Add a file at /var/www/html/ and name it mysqltest.php. Copy the following content and save the changes.

<?php
// Create connection
$connection = mysqli_connect("localhost","fsmuser","nopass","fsmtest");

// Check connection
if ($connection->connect_error) {
  die("Connection failed: " . $conn->connect_error);
}

$result = mysqli_query($connection,"SELECT * FROM city");
while($row = mysqli_fetch_array($result))
    print_r($row['name']);
mysqli_close($connect);

If everything is configured correctly a web page similar to the one below displays the single city name I entered earlier. will be shown.

Apache PHP MySQL Example on Ubuntu
NGINX, MySQL and PHP FPM on Ubuntu

NGINX Configure and Enable Virtual Host aka Server(Bonus)

In this section, I will go over an example of how to create a new NGINX VirtualHost server configuration in Ubuntu.

First, I need to add a domain to the local hosts file. The path is /etc/hosts.

Add the following line to the end.

127.0.0.1       mydomain.local

Let’s create a new webserver configuration for our new domain.

In the folder /etc/nginx/sites-available and create a file mydomain and copy the below contents to it and save all changes.

server {
        listen 80;
        listen [::]:80;

        server_name mydomain.local;

        root /var/www/mydomain;
        index index.html;

        location / {
                try_files $uri $uri/ =404;
        }
}

Note: In this configuration, I have setup the server_name directive to serve my custom domain.

Next you will have to link to this file from the /etc/nginx/sites-enabled folder and then restart NGINX.

root@d1:/etc/nginx/sites-enabled# ln -s /etc/nginx/sites-available/mydomain mydomain
root@d1:/etc/nginx/sites-enabled# ls -l
total 0
lrwxrwxrwx 1 root root 34 Feb  7 17:03 default -> /etc/nginx/sites-available/default
lrwxrwxrwx 1 root root 38 Feb  7 18:35 default-ssl -> /etc/nginx/sites-available/default-ssl
lrwxrwxrwx 1 root root 35 Feb  7 19:08 mydomain -> /etc/nginx/sites-available/mydomain
root@d1:/etc/nginx/sites-enabled# sudo service nginx restart

Create the website folder for this domain in the path /var/www. I will be naming the folder mydomain. Inside this folder create a file index.html. In this file, I will add only the text “MyDomain.local”.

Once the folder is created I will restart the NGINX web server.

You can use the following set of commands to do all of the above changes.

root@d1:~# sudo mkdir /var/www/mydomain
root@d1:~# sudo echo MyDomain.local > /var/www/mydomain/index.html
root@d1:~# sudo service nginx restart

Open the browser and enter the URL http://mydomain.local and view the index.html page contents.

Ubuntu Apache Virtual Domain Index Page

Conclusion

This completes the setup of NGINX, MySQL and PHP FPM on the Ubuntu platform. In addition, I went over the details of how you can set up a virtual host on NGINX.

This is only a start and there is a lot more you can do. I have many tutorial posts on my NGINX page. Check out my post on how to scale your NGINX install with Load Balancing, reverse proxy and caching, read the post on our website as well.

NGINX server is an excellent choice for a low memory usage web server providing high concurrency using an event driven approach.