Installing Linux, Nginx, MySQL, PHP (LEMP Stack) from A to Z- on CentOS 8

With the lemp stack we will install the following components: Nginx, MySQL, PHP, phpmyadmin.

VPS requirements are ram> = 512MB, the operating system is brand new CentOS 8.

Turn off Selinux

Edit the following file: / etc / selinux / config

sudo nano /etc/selinux/config

Find the Configuration line SELINUX to disabled:


Finally reboot VPS to update selinux with the command:


Install nginx

We install nginx with the dnf library

dnf install nginx

Start Nginx service:

systemctl start nginx

Check nginx is working or not:

systemctl status nginx


nginx.service - The nginx HTTP and reverse proxy server
Loaded: loaded (/usr/lib/systemd/system/nginx.service; disabled; vendor preset: disabled)
Active: active (running) since Sat 2019-11-02 01:22:01 UTC; 26s ago
Process: 8867 ExecStart=/usr/sbin/nginx (code=exited, status=0/SUCCESS)
Process: 8865 ExecStartPre=/usr/sbin/nginx -t (code=exited, status=0/SUCCESS)
Process: 8864 ExecStartPre=/usr/bin/rm -f /run/ (code=exited, status=0/SUCCESS)
Main PID: 8869 (nginx)
Tasks: 2 (limit: 11543)
Memory: 6.8M
CGroup: /system.slice/nginx.service
├─8869 nginx: master process /usr/sbin/nginx
└─8870 nginx: worker process

If status is Active: active (running) ie nginx has been installed and started correctly.

Set nginx to run every time the system boots:

systemctl enable nginx

Open HTTP firewall port 80,443 if using firewalld:

firewall-cmd --zone=public --permanent --add-service=http
firewall-cmd --zone=public --permanent --add-service=https

firewall-cmd --reload

Now you can access the format http: // IP access results ie installation is correct.


For optimal nginx you add the following to the configuration file /etc/nginx/nginx.conf right after the last closing parenthesis.

server_tokens off;
server_names_hash_max_size 10000;
server_names_hash_bucket_size 1024;
keepalive_requests 100000;
gzip on;
gzip_min_length 1100;
gzip_disable "msie6";
gzip_buffers 4 32k;
gzip_vary on;
gzip_types text/plain text/css application/json application/javascript application/x-javascript text/javascript text/xml application/xml application/rss+xml application/atom+xml application/rdf+xml;
ignore_invalid_headers on;

client_header_timeout 3m;
client_body_timeout 3m;
send_timeout 3m;

reset_timedout_connection on;
connection_pool_size 256;

client_header_buffer_size 1k;
large_client_header_buffers 4 4k;
client_max_body_size 100M;
client_body_buffer_size 128k;
request_pool_size 32k;
output_buffers 1 32k;
postpone_output 1460;



Then you restart nginx.

Install mariadb 10.4

create file:
/etc/yum.repos.d/mariadb.repoWith the following content:

# MariaDB 10.4 CentOS repository list - created 2019-11-02 01:37 UTC
name = MariaDB
baseurl =

After creating the file, install mariadb with the following commands

sudo dnf install boost-program-options
sudo dnf install MariaDB-server MariaDB-client --disablerepo=AppStream
sudo systemctl start mariadb
sudo systemctl enable mariadb

So mariadb has installed, now next you set up for mariadb with the command:


The initial setup part you just need to change the root mysql, other options do not affect much so you can option as desired.


Install php-fpm

Install php

sudo dnf install php php-fpm php-common -y

Install the php library

sudo dnf install php*

Start php-fpm

systemctl start php-fpm && systemctl enable php-fpm

Set up vhost for websites

To add a website to your VPS, follow these steps.

Delete default pool:

mv /etc/php-fpm.d/ww.conf /etc/php-fpm.d/ww.conf.bak

Add php pool for website.

For example, I need to add a website

Creating a user nguyenvanphong can only operate on site

useradd -M nguyenvanphong

Create file:

nano /etc/php-fpm.d/


listen = /run/php-fpm/;
user = nguyenvanphong
group = nguyenvanphong
listen.owner = nginx = nginx
listen.mode = 0660
pm = dynamic
pm.max_children = 15
pm.start_servers = 5
pm.min_spare_servers = 3
pm.max_spare_servers = 10
pm.max_requests = 500

You note: You instead into your domain name, your user / group so that each domain is managed by each individual user, this will be convenient for debugging, checking the process flow as well as avoiding the problem of malicious code being run by different users.

Finally restart php-fpm and check.

systemctl restart php-fpm

systemctl status php-fpm

● php-fpm.service - The PHP FastCGI Process Manager
Loaded: loaded (/usr/lib/systemd/system/php-fpm.service; enabled; vendor preset: disabled)
Active: active (running) since Sat 2019-11-02 02:46:04 UTC; 5s ago
Main PID: 13600 (php-fpm)
Status: "Ready to handle connections"
Tasks: 6 (limit: 11543)
Memory: 33.4M
CGroup: /system.slice/php-fpm.service
├─13600 php-fpm: master process (/etc/php-fpm.conf)
├─13602 php-fpm: pool
├─13603 php-fpm: pool
├─13604 php-fpm: pool
├─13605 php-fpm: pool
└─13606 php-fpm: pool

The php-fpm result is created and run with the pool as you configured it properly. As an example above this pool creates and listens on the sock: /run/php-fpm/; This sock you will use to handle php from nginx passed down.

Change upload file size php.

Default load site on php-fpm is configured as 2MB, You run the following command to change, assuming I want to raise the maximum to 512MB.

sed -i '/upload_max_filesize/s/= *2M/=512M/' /etc/php.ini
sed -i '/post_max_size/s/= *8M/=512M/' /etc/php.ini

Restart php-fpm to get new configuration.

systemctl restart php-fpm

Add Vhost nginx

By default, when installing nginx, you will configure a default vhost and upstream, but you need to need each website works with different directories so you need to remove the default vhost and configure vhost for each domain.

Delete Vhost and default upstream.

Delete default vhost by editing the file.


You insert # in front of the default vhost configuration command line.


Delete upstream and the default php handler location by:

mv /etc/nginx/default.d/php.conf /etc/nginx/default.d/php.conf.bak

mv /etc/nginx/conf.d/php-fpm.conf /etc/nginx/conf.d/php-fpm.conf.bak

Declare and add a new vhost domain on nginx.

This vhost I will add both upstream and location inside php processing.

nano /etc/nginx/conf.d/

For the content (here you use the sock created in the upper pool section):

server {
listen 80;
root /home/nguyenvanphong/;

# Load configuration files for the default server block.
# pass the PHP scripts to FastCGI server
# See conf.d/php-fpm.conf for socket configuration
index index.php index.html index.htm;

location ~ .(php|phar)(/.*)?$ {
fastcgi_split_path_info ^(.+.(?:php|phar))(/.*)$;

fastcgi_intercept_errors on;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_pass unix:/run/php-fpm/;

location / {

error_page 404 /404.html;
location = /40x.html {

error_page 500 502 503 504 /50x.html;
location = /50x.html {

Create a directory containing the website as configured on vhost.

mkdir -p /home/nguyenvanphong/

restart nginx, here site will be controlled by nguyenvanphong user and the website containing directory is: /home/nguyenvanphong/

systemctl restart nginx


After configuration is complete and point the domain to IP VPS, as above I use domain to configure.

You create the file info.php

nano /home/nguyenvanphong/

With the following content to test:




If you visit the website link showing the php content, you have configured it correctly.


If you want to add another website, you create a new vhost including creating a new pool and also vng nginx vhost for the new domain as above.

SSL settings:

After creating a vhost, adding a website and pointing to the IP, you can install ssl as follows.

Install ssl configuration tool automatically.

Run the following command to install:

curl | sh
alias --upgrade --auto-upgrade

Install ssl for domain --issue -w /home/nguyenvanphong/ -d -d  -k 4096

You use the above command to change to suit your website.

  • /home/nguyenvanphong/ is the path of the root directory containing the source code of site

  • You can remove the www if you do not want to install ssl for the www prefix if so the command is: --issue -w /home/nguyenvanphong/ -d -k 4096

The result will produce ssl configuration file that looks like:

(Sat Nov 2 06:59:46 UTC 2019) Your cert is in /root/ 
(Sat Nov 2 06:59:46 UTC 2019) Your cert key is in /root/
(Sat Nov 2 06:59:46 UTC 2019) The intermediate CA cert is in /root/
(Sat Nov 2 06:59:46 UTC 2019) And the full chain certs is there: /root/

Open the domain's vhost nginx configuration file and redirect it to https, as an example file to edit is:


You edit the whole file to:

server {
listen 80;
return 301$request_uri;

Next add the vhost file of the domain configuring https with port 443.

Create new file: /etc/nginx/conf.d/

nano /etc/nginx/conf.d/


 server {
listen 443 ssl http2;
root /home/nguyenvanphong/;
index index.php index.html index.htm;

ssl_certificate "/root/";
ssl_certificate_key "/root/";
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 10m;
ssl_ciphers PROFILE=SYSTEM;
ssl_prefer_server_ciphers on;

# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;

location ~ .(php|phar)(/.*)?$ {
fastcgi_split_path_info ^(.+.(?:php|phar))(/.*)$;

fastcgi_intercept_errors on;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_pass unix:/run/php-fpm/;
location / {

error_page 404 /404.html;
location = /40x.html {

error_page 500 502 503 504 /50x.html;
location = /50x.html {

In which you replace the content ssl_certificate, ssl_certificate_key matching ssl installation results for the domain you just installed. Also change the domain name to your domain name.

Finally restart nginx and try to access the link domain with https.

systemctl restart nginx


Install WordPress

I will install the latest wordpress template on the newly established domain.

First I download and extract the installation wordpress source code with the following command.

cd /home/nguyenvanphong/

mv wordpress/* .

rm -rf
chown -R nguyenvanphong:nguyenvanphong *

In which /home/nguyenvanphong/ is the directory containing the domain source code.

About the chown command, you are similarly reauthorizing the original user you configured for the domain.

Next I create a database. For simplicity I use the mysql command. To access using the mysql command, type the following command.

mysql -u root -p

Then you enter the original mysql root password you have set for mariadb.

Finally, create a new database with the following syntax:

CREATE USER [email protected];
SET PASSWORD FOR [email protected]= PASSWORD("123456");
GRANT ALL PRIVILEGES ON wordpress. * TO [email protected] IDENTIFIED BY "123456";


wordpress: là tên database muốn tạo.
wordpress_user: là tên user quản lý database muốn tạo.
123456: là mật khẩu của database.

You replace the above values ​​to suit your desires.

Finally, I accessed the website and installed the new wordpress as usual with the newly created database.


Run the trial with the default demo flastsome theme.


Install Phpmyadmin.

The article here is also quite complete and comprehensive for you to manage a website.

However, there are some users who cannot use the mysql command line to create a database or simply do not like it.

You can install the shortened version on any website directory. For example, I choose to install in website.

Access to the directory containing website

cd /home/nguyenvanphong/

Download and extract

unzip phpMyAdmin-*.zip

Finally, you can access phpmyadmin in your browser with the link.

Note: You replace with your domain accordingly.

Good luck.