This article will cover how to configure a CentOS 7 minimal installation with internet access to be a well rounded web server, either with local MySQL or network-attached SQL. This guide is most easily followed after SSH has been set up.


Covered in this solution will be:


  1. Installing PHP, Apache, MySQL, Nginx, and basic server tools
  2. Securing the server with some basic security principals, and checking SELinux wont mess up our permissions
  3. Configuring the server to use Nginx as a reverse proxy, and lightening the load on Apache to make it run well
  4. Configuring MySQL (MariaDB 10) to work well out of the gate.

After gaining root access to your server, we'll start with the basics;




~# yum -y install epel-release wget net-tools screen bind-utils mlocate policycoreutils-python setroubleshooting


~# yum -y groupinstall "Development tools"


~# rpm -Uvh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm

~# yum -y update && systemctl reboot

This will update CentOS with the latest and greatest that were not included in your install media, and make it reboot.


~# yum -y install nginx httpd httpd-devel php php-mysql php-fpm php-common php-gd php-intl mod_security mod_ssl openssl # Note some of the php- modules you do not need to install. I've just listed some common ones

~# yum -y install mariadb-server mariadb # Note only do this if you plan on running MySQL locally, otherwise you will do this step on your SQL server


~# systemctl start httpd.service

~# systemctl enable httpd.service


to find any other modules you want to install, you can run the following command;

yum search php-


~# vi /etc/php.ini

find 'cgi.fix_pathinfo', uncomment, and set to "0"

save and quit.


~# vi /etc/php-fpm.d/www.conf

make the following changes:


listen = 127.0.0.1:9000

listen.owner = nobody # Ensure these are not commented out

listen.group = nobody Ensure these are not commented out

user = nginx

group = nginx


Save and Quit

~# systemctl start php-fpm

~# systemctl enable php-fpm


~# cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.orig

~# cp /etc/nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf.orig

~# vi /etc/nginx/conf.d/default.conf

Comment out the following:


    #location / {

    #    root   /usr/share/nginx/html;

    #    index  index.html index.htm;

    #}


Add the following just below the commented location code

         location / {

            proxy_pass http://localhost:8080/;

            root   /usr/share/nginx/html;

            proxy_redirect off;

            proxy_set_header X-Forwarded-Host $host;

            proxy_set_header X-Forwarded-Server $host;

            proxy_set_header X-Real-IP $remote_addr;

            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

         }

Save and Quit


Now we change the Apache Conf to listed on 8080, and remove the SSL conf as we'll handle that with Nginx


~# cp /etc/httpd/conf.d/ssl.conf /etc/httpd/conf.d/ssl.conf.orig


~# vi /etc/httpd/conf.d/ssl.conf


Change the instances of "443" to "8081" - there should be two. Save and quit.


~# cp /etc/httpd/conf/httpd.conf /etc/httpd/conf/httpd.conf.orig


~# vi /etc/httpd/conf/httpd.conf


Replace the "Listen 80" line with "Listen 8080". There should be two.


Add this as the last lines


<FilesMatch \.php$>

    SetHandler "proxy:fcgi://127.0.0.1:9000"

</FilesMatch>



Save and Quit




~# systemctl restart httpd.service 

~# systemctl restart nginx.service 


~# systemctl restart php-fpm.service 



You may get SELinux based permissions errors; at the end of this article is the list of SEmanage changes you need to make, so press on.


Note: if at any point you'll be loading content through apache Outside of /var/www, you'll need to run the following commands:


~# semanage fcontext -a -t http_sys_content_t "/path/to/document_root(/.*)?"


~# semanage fcontext -a -t httpd_log_t "/path/to/logs(/.*)?"



~# semanage fcontext -a -t httpd_cache_t "/path/to/cache(/.*)?"


~# semanage fcontext -a -t httpd_sys_rw_content_t "/path/to/document_root/writable_content(/.*)?"

~# restorecon -Rv /


If you are still getting weird issues - run ~# setenforce 0 to temporarily disable selinux and test. Remember to turn it back on when you're done (setenforce 1)


Lets start configuring Apache and Nginx to be resource smart.


~# vi /etc/nginx/nginx.conf


Make the following changes at the top of the file


user  nginx;

worker_processes  2;   # Set to number of CPU cores of your server

Add the "index" line before the final } of the file *(within the http {})

  include /etc/nginx/conf.d/*.conf;

  index  index.php index.html index.htm;    #add this new line

}


Save and Quit

Create a new files as per below.

Note that when doing SSL for Nginx, you need your Certificate, and your Certificate Authority certificate concatenated into one file. it's best to have the Certificate first, then the Chain / bundle of authorities afterwards, and load them into Nginx as a single file.

We create a secure DHE key first - this takes a while (5 minutes). Dont forget to create the directory/check that it exists

~# mkdir /etc/nginx/ssl

~# openssl dhparam -out /etc/nginx/ssl/dhparam.pem 4096

Now the reverse proxy configuration:

~# vi /etc/nginx/conf.d/reverseproxy.conf

###

#reverse proxy conf

###


server  {


  listen  80 default_server;   # Redirect any port http/80 requests, to https/443

  server_name  _; # Optionally set your domain here, "_" is just a wildcard

  return 301 https://$host$request_uri;

}


server  {

  listen  443 ssl;   

  server_name _; Optionally set your domain here, "_" is just a wildcard

  ssl  on;

  ssl_certificate  ssl/domain.crt;   # Replace with your certificate file, which contains your concatenated CA

  ssl_certificate_key  ssl/domain.key;   # Replace with your certificate key

  ssl_dhparam  ssl/dhparam.pem;   # Remember to create this 

  ssl_session_timeout  5m;

  ssl_prefer_server_ciphers  on;

  ssl_protocols  TLSv1 TLSv1.1 TLSv1.2;

  ssl_ciphers  AES256+EECDH:AES256+EDH:!aNULL;

  ssl_verify_client off;

  ssl_session_cache shared:SSL:1m;

  proxy_ssl_session_reuse off;

  location  / {

            proxy_pass https://localhost:8081/;

            root   /usr/share/nginx/html;

            proxy_redirect off;

            proxy_set_header X-Forwarded-Host $host;

            proxy_set_header X-Forwarded-Server $host;

            proxy_set_header X-Real-IP $remote_addr;

            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

  }

}


#server  {

#  listen  443 ssl;   # You can set up other listeners to do the same thing, but domain specific

#  server_name  sub.domain.com;

#  ssl  on;

#  location  / {

#    Copy the Proxy pass location from above if you need to use this section 

#  }

#}

###
#End conf


###



Remember to make the changes to the SSL configuration.


~# systemctl enable firewalld.service

~# firewall-cmd --permanent --add-service=http

~# firewall-cmd --permanent --add-service=https

~# firewall-cmd --permanent --add-service=ssh

~# firewall-cmd --permanent --add-port={your secure port, e.g. 23456}/tcp

~# firewall-cmd --reload

~# systemctl enable nginx.service

~# systemctl reboot

We'll need to make some changes to SELinux to allow the connection from HTTPD//Nginx

~# cat /var/log/audit/audit.log | grep nginx | grep denied | audit2allow -M nginxlocalconf

~# semodule -i nginxlocalconf.pp

~# cat /var/log/audit/audit.log | grep nginx | grep denied | audit2allow -M httpdlocalconf

~# semodule -i httpdlocalconf.pp

~# setsebool httpd_can_network_connect_db on

~# setsebool httpd_can_network_connect on

~# setsebool -P httpd_enable_cgi on

~# setsebool -P httpd_unified on

~# setsebool -P httpd_builtin_scripting on

# For MySQL Configuration

~# systemctl start mariadb.service

~# mysql_secure_installation

~# systemctl enable mariadb.service

Security!

~# useradd yourusername

~# groupadd wheel

~# usermod -G wheel yourusername

~# passwd yourusername

Configure the password for your new user - this user will be how you ssh to the server, then switch user to root with "su -"

~# vi /etc/sshd/sshd_config

Change PermitRootLogin to no, Change the default port from 22 to something different - [your port]

~# semanage port -a -t ssh_port_t -p tcp [your port]

If you haven't already, make sure you run

~# firewall-cmd --permanent --add-port=[your port]/tcp

~# firewall-cmd --reload

IMPORTANT: Before ending your ssh session test ssh to the localhost