https://stavrovski.net/blog/install-and-configure-nginx-mariadb-php-fpm-in-centos-7-rhel7
The following is a quick-N-dirty write-up on how to install and configure the LEMP stack (Nginx, MariaDB and PHP-FPM) in CentOS 7. I use this as a reference/guide whenever I need to deploy the LEMP stack on RHEL based machines.
TABLE OF CONTENTS
- Enable EPEL Repository
- Update CentOS 7
- Install and configure MariaDB
- Install and configure Nginx
- Install and configure PHP-FPM
- Enable and restart the services
ENABLE EPEL REPOSITORY
Install wget
and vim
using yum
if they’re not present on the CentOS 7 system:
if ! type -path "wget" > /dev/null 2>&1; then yum install wget -y; fi
if ! type -path "vim" > /dev/null 2>&1; then yum install vim -y; fi
Next, download the rpm
package and install it using yum
as in:
wget -P /tmp http://dl.fedoraproject.org/pub/epel/beta/7/x86_64/epel-release-7-0.2.noarch.rpm
yum install /tmp/epel-release-7-0.2.noarch.rpm
rm -f /tmp/epel-release-7-0.2.noarch.rpm
UPDATE THE SYSTEM
Ok, first thing to do before installing LEMP, is to make sure the CentOS 7 system is fully up-to-date by running the following command in your terminal:
yum update
if there is a kernel update, make sure you’re booted into it before proceeding further.
INSTALL AND CONFIGURE MARIADB DATABASE SERVER
Default database server in CentOS 7 (RHEL 7) is MariaDB
now. It is a drop in replacement for MySQL
and can be installed using yum
, so install MariaDB using:
yum install mariadb mariadb-server
once installed, restart MariaDB using systemctl
:
systemctl restart mariadb
systemctl status mariadb
optionally, set-up MariaDB server using the mysql_secure_installation
post-installation script:
mysql_secure_installation
answer the questions when prompted, for example in my case:
- Enter current password for root (enter for none):
- Set root password? [Y/n] y
- Remove anonymous users? [Y/n] y
- Disallow root login remotely? [Y/n] y
- Remove test database and access to it? [Y/n] y
- Reload privilege tables now? [Y/n] y
next, edit /etc/my.cnf.d/server.cnf
and add bind-address = 127.0.0.1
within the [mysqld]
block:
vim +/^[mysqld /etc/my.cnf.d/server.cnf
[mysqld]
bind-address = 127.0.0.1
restart MariaDB for the changes to take effect:
systemctl restart mariadb
systemctl status mariadb
verify MariaDB is listening on localhost only using the ss
command:
ss -tnlp | grep 3306
LISTEN 0 0 127.0.0.1:3306 *:* users:(("mysqld",1159,14))
INSTALL AND CONFIGURE NGINX
Install Nginx on the CentOS 7 system using yum
:
yum install nginx
next, navigate to /etc/nginx
and backup your original Nginx configuration file
cd /etc/nginx
cp nginx.conf{,.orig}
and edit /etc/nginx.conf
to look like the one below:
cat > nginx.conf
## NGINX MAIN CONFIGURATION FILE ##
user nginx nginx;
worker_processes 2;
error_log /var/log/nginx/error.log info;
events {
worker_connections 1024;
use epoll;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main
'$remote_addr - $remote_user [$time_local] '
'"$request" $status $bytes_sent '
'"$http_referer" "$http_user_agent" '
'"$gzip_ratio"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
ignore_invalid_headers on;
keepalive_timeout 30;
server_tokens off;
connection_pool_size 256;
client_header_buffer_size 1k;
large_client_header_buffers 4 2k;
request_pool_size 4k;
output_buffers 1 32k;
postpone_output 1460;
client_header_timeout 10m;
client_body_timeout 10m;
send_timeout 10m;
gzip on;
gzip_disable "MSIE [1-6].(?!.*SV1)";
gzip_http_version 1.1;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_buffers 16 8k;
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript text/x-js;
include /etc/nginx/sites-enabled/*.conf;
}
## NGINX MAIN CONFIGURATION FILE ##
of course, feel free to change anything you think should be changed in order to suit your needs. for example, you may want to change the user/group nginx runs under or you may want to set the worker_processes
option, which is determined by the number of CPU’s the machine has.
you can use the following command to find what number to use there:
grep -c 'model name' /proc/cpuinfo
also as you may noticed, there is include /etc/nginx/sites-enabled/*.conf
inside the Nginx main configuration file. This means, include all available configuration files in/etc/nginx/sites-enabled/
which end with .conf
. The idea here is to store Nginx server-blocks that are going to be set-up later on, playing the Debian-way
by having the files created in sites-available and then linking the ones I want enabled to sites-enabled
mkdir /etc/nginx/{sites-available,sites-enabled}
DEFAULT NGINX SERVER BLOCK (VHOST)
set-up default Nginx server block in /etc/nginx/sites-available/default.conf
cat > /etc/nginx/sites-available/default.conf
server {
listen 80 default_server;
server_name _;
root /srv/www/default;
location / {
index index.html index.htm;
}
error_page 404 /404.html;
location = /404.html {
root /srv/www/default;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /srv/www/default;
}
}
create the document root for the default Nginx server-block and set-up the default html files:
mkdir -p /srv/www/default
CONTENT='<!DOCTYPE html>
<html lang="en">
<head>
<title>ViruSzZ</title>
</head>
<body style="background:#000;color:#fff;">
<div style="color:#fff;width:100%;">
<h1 align="center">you feel the silence?</h1>
</div>
</body>
</html>'
echo ${CONTENT} > /srv/www/default/index.html
#------#
CONTENT='<!DOCTYPE html>
<html lang="en">
<head>
<title>404</title>
</head>
<body style="background:#000;color:#fff;">
<div style="color:#fff;width:100%;">
<h1 align="center">404 straight in your face</h1>
</div>
</body>
</html>'
echo ${CONTENT} > /srv/www/default/404.html
#------#
CONTENT='<!DOCTYPE html>
<html lang="en">
<head>
<title>Whoooopsssss</title>
</head>
<body style="background:#000;color:#fff;">
<div style="color:#fff;width:100%;">
<h1 align="center">Whoooopssssssy... Something wrong happend back here!</h1>
</div>
</body>
</html>'
echo ${CONTENT} > /srv/www/default/50x.html
unset CONTENT
LARAVEL NGINX SERVER BLOCK (VHOST)
set-up Nginx server block for Laravel (PHP) based web application, served using d.stavrovski.net
cat > /etc/nginx/sites-available/d.stavrovski.net.conf
server {
listen 80;
server_name d.stavrovski.net www.d.stavrovski.net daniel.stavrovski.net;
return 301 http://d.stavrovski.net$request_uri;
access_log /var/log/nginx/d.stavrovski.net.log;
error_log /var/log/nginx/d.stavrovski.net-error.log error;
root /srv/www/d.stavrovski.net/public;
index index.html index.php;
### ROOT DIRECTORY ###
location / {
try_files $uri $uri/ /index.php?$args;
}
### SECURITY ###
error_page 403 =404;
error_page 404 /404-not-found.html;
location /404-not-found.html {
internal;
}
location ~* ^/uploads/.*.(html|htm|shtml|php)$ {
types { }
default_type text/plain;
}
location ~* ^/cache/.* {
return 404;
}
# location ~* admin {
# allow <YOUR_IP>;
# allow 127.0.0.1;
# deny all;
# }
### DISABLE LOGGING ###
location = /robots.txt { access_log off; log_not_found off; }
location = /favicon.ico { access_log off; log_not_found off; }
### CACHES ###
location ~* .(jpg|jpeg|gif|css|png|js|ico|html)$ { access_log off; expires max; }
location ~* .(woff|svg)$ { access_log off; log_not_found off; expires 30d; }
location ~* .(js)$ { access_log off; log_not_found off; expires 7d; }
location /uploads/ {
valid_referers none blocked d.stavrovski.net *.stavrovski.net;
if ($invalid_referer) {
return 403;
}
}
fastcgi_buffers 256 16k;
fastcgi_buffer_size 32k;
fastcgi_connect_timeout 300;
fastcgi_send_timeout 300;
fastcgi_read_timeout 300;
### PHP BLOCK ###
location ~ .php?$ {
fastcgi_keep_conn on;
try_files $uri =404;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_intercept_errors on;
fastcgi_split_path_info ^(.+.php)(.*)$;
fastcgi_hide_header X-Powered-By;
# fastcgi_pass 127.0.0.1:9000;
fastcgi_pass unix:/var/run/d.stavrovski.net.socket;
# fastcgi_pass unix:/var/run/hhvm/hhvm.sock;
}
}
WORDPRESS NGINX SERVER BLOCK (VHOST)
set-up Nginx server block for WordPress based web application, served using wordpress.stavrovski.net
cat > /etc/nginx/sites-available/wordpress.stavrovski.net.conf
server {
listen 80;
server_name wordpress.stavrovski.net www.wordpress.stavrovski.net;
client_max_body_size 5m;
client_body_timeout 60;
access_log /var/log/nginx/wordpress.stavrovski.net.log;
error_log /var/log/nginx/wordpress.stavrovski.net-error error;
root /srv/www/wordpress.stavrovski.net;
index index.html index.php;
### ROOT DIRECTORY ###
location / {
try_files $uri $uri/ /index.php?$args;
}
### SECURITY ###
error_page 403 =404;
location ~ /. { access_log off; log_not_found off; deny all; }
location ~ ~$ { access_log off; log_not_found off; deny all; }
location ~* wp-admin/includes { deny all; }
location ~* wp-includes/theme-compat/ { deny all; }
location ~* wp-includes/js/tinymce/langs/.*.php { deny all; }
location /wp-includes/ { internal; }
#location ~* wp-config.php { deny all; }
location ~* ^/wp-content/uploads/.*.(html|htm|shtml|php)$ {
types { }
default_type text/plain;
}
# location ~* wp-admin {
# allow <YOUR_IP>;
# allow 127.0.0.1;
# deny all;
# }
### DISABLE LOGGING ###
location = /robots.txt { access_log off; log_not_found off; }
location = /favicon.ico { access_log off; log_not_found off; }
### CACHES ###
location ~* .(jpg|jpeg|gif|css|png|js|ico|html)$ { access_log off; expires max; }
location ~* .(woff|svg)$ { access_log off; log_not_found off; expires 30d; }
location ~* .(js)$ { access_log off; log_not_found off; expires 7d; }
### php block ###
location ~ .php?$ {
try_files $uri =404;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_intercept_errors on;
fastcgi_split_path_info ^(.+.php)(.*)$;
fastcgi_hide_header X-Powered-By;
#fastcgi_pass 127.0.0.1:9001;
fastcgi_pass unix:/var/run/wordpress.stavrovski.net.socket;
}
}
with all that in place, let’s proceed with enabling the server-blocks and starting Nginx up:
cd /etc/nginx/sites-enabled/
for d in ../sites-available/*; do ln -s /etc/nginx/sites-available/${d##*/}; done
nginx -t
systemctl restart nginx
systemctl status nginx
INSTALL AND CONFIGURE PHP-FPM
Install PHP support on the CentOS 7 system using yum
as in
yum install php-fpm php-mysql php-mcrypt
also, install any other PHP module that your application requires. the list is shown below or you can use yum search php-
in the command line to get the list of available PHP modules on your CentOS 7 system:
php-bcmath
– A module for PHP applications for using the bcmath libraryphp-cli
– Command-line interface for PHPphp-common
– Common files for PHPphp-dba
– A database abstraction layer module for PHP applicationsphp-devel
– Files needed for building PHP extensionsphp-embedded
– PHP library for embedding in applicationsphp-enchant
– Enchant spelling extension for PHP applicationsphp-fpm
– PHP FastCGI Process Managerphp-gd
– A module for PHP applications for using the gd graphics libraryphp-imap
– A module for PHP applications that use IMAPphp-intl
– Internationalization extension for PHP applicationsphp-ldap
– A module for PHP applications that use LDAPphp-mbstring
– A module for PHP applications which need multi-byte string handlingphp-mcrypt
– Standard PHP module provides mcrypt library supportphp-mysql
– A module for PHP applications that use MySQL databasesphp-mysqlnd
– A module for PHP applications that use MySQL databasesphp-odbc
– A module for PHP applications that use ODBC databasesphp-pdo
– A database access abstraction module for PHP applicationsphp-pear.noarch
– PHP Extension and Application Repository frameworkphp-pecl-memcache
– Extension to work with the Memcached caching daemonphp-pgsql
– A PostgreSQL database module for PHPphp-process
– Modules for PHP script using system process interfacesphp-pspell
– A module for PHP applications for using pspell interfacesphp-recode
– A module for PHP applications for using the recode libraryphp-snmp
– A module for PHP applications that query SNMP-managed devicesphp-soap
– A module for PHP applications that use the SOAP protocolphp-xml
– A module for PHP applications which use XMLphp-xmlrpc
– A module for PHP applications which use the XML-RPC protocol
SET-UP PHP CONFIGURATION FILE
next, set-up PHP’s main configuration file /etc/php.ini
vim /etc/php.ini
:%s#;cgi.fix_pathinfo=1#cgi.fix_pathinfo=0#
:%s#;date.timezone =#date.timezone = Europe/Skopje#
:%s#memory_limit = 128M#memory_limit = 64M#
:%s#expose_php = On#expose_php = Off#
SET-UP PHP-FPM CONFIGURATION FILE
and edit PHP-FPM’s main configuration file /etc/php-fpm.conf
vim /etc/php-fpm.conf
:%s#;emergency_restart_threshold = 0#emergency_restart_threshold = 10#
:%s#;emergency_restart_interval = 0#emergency_restart_interval = 1m#
:%s#;process_control_timeout = 0#process_control_timeout = 10#
SET-UP PHP-FPM POOLS
OK, now I’m going to create PHP-FPM’s pools
in /etc/php-fpm.d/
that I used in the server-blocks before. feel free to tune these to suit your needs.
cd /etc/php-fpm.d/
cp www.conf{,.orig}
FPM pool for d.stavrovski.net
which serves a Laravel based web application:
cat > www.conf
[LARAVEL]
;listen = 127.0.0.1:9000
listen = /var/run/d.stavrovski.net.socket
;listen.mode = 0660
user = nginx
group = nginx
request_slowlog_timeout = 5s
slowlog = /var/log/php-fpm/slowlog.log
listen.allowed_clients = 127.0.0.1
pm = dynamic
pm.max_children = 15
pm.start_servers = 7
pm.min_spare_servers = 7
pm.max_spare_servers = 15
pm.max_requests = 400
listen.backlog = -1
pm.status_path = /status
request_terminate_timeout = 120s
rlimit_files = 131072
rlimit_core = unlimited
catch_workers_output = yes
php_value[session.save_handler] = files
;php_value[session.save_path] = /var/lib/php/session
php_admin_value[error_log] = /var/log/php-fpm/error.log
php_admin_flag[log_errors] = on
FPM pool for wordpress.stavrovski.net
which serves a WordPress based web application:
cat > wordpress.conf
[WORDPRESS]
;listen = 127.0.0.1:9000
listen = /var/run/wordpress.stavrovski.net.socket
;listen.mode = 0660
user = nginx
group = nginx
request_slowlog_timeout = 5s
slowlog = /var/log/php-fpm/slowlog.log
listen.allowed_clients = 127.0.0.1
pm = dynamic
pm.max_children = 8
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 8
pm.max_requests = 400
listen.backlog = -1
pm.status_path = /status
request_terminate_timeout = 120s
rlimit_files = 131072
rlimit_core = unlimited
catch_workers_output = yes
php_value[session.save_handler] = files
;php_value[session.save_path] = /var/lib/php/session
php_admin_value[error_log] = /var/log/php-fpm/error.log
php_admin_flag[log_errors] = on
ENABLE AND RESTART SERVICES
check Nginx’s configuration file and restart the server by running
nginx -t
systemctl restart nginx
systemctl status nginx
restart MariaDB (MySQL)
systemctl restart mariadb
systemctl status mariadb
restart PHP-FPM
systemctl restart php-fpm
systemctl status php-fpm
enable the services on system startup
systemctl enable nginx mariadb php-fpm
enjoy and take care