Covered in this solution will be:
- Installing PHP, Apache, MySQL, Nginx, and basic server tools
- Securing the server with some basic security principals, and checking SELinux wont mess up our permissions
- Configuring the server to use Nginx as a reverse proxy, and lightening the load on Apache to make it run well
- 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
Add the "index" line before the final } of the file *(within the http {})user nginx;
worker_processes 2; # Set to number of CPU cores of your server
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