Let’s install a brand new Centos 7 Server along with needed database, web servers and WordPress. We’ll install 2 wordpress sites in one machine but show here only one example
Server Specs: 16GB RAM, 100GB HD, 2 CPU
PREREQUISITES
$ sudo yum update
$ sudo yum install net-tools yum-utils htop autoconf automake bind-utils wget curl unzip gcc-c++ pcre-devel zlib-devel libtool make nmap-netcat ntp pam-devel gd gd-devel perl-ExtUtils-Embed geoip-devel gperftools-devel
There is both public and local ip
$ ifconfig
eno16777728: flags=4163 mtu 1500
inet 50.201.93.40 netmask 255.255.255.224 broadcast 50.201.93.63
inet6 fe80::20c:29ff:fe5b:71b1 prefixlen 64 scopeid 0x20 ether 00:0c:29:5b:71:b1 txqueuelen 1000 (Ethernet)
RX packets 185681 bytes 258376736 (246.4 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 68659 bytes 5327288 (5.0 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0lo: flags=73 mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10
loop txqueuelen 0 (Local Loopback)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
Let’s check the network config file along with IPADDR, DNS1, DNS2, GATEWAY
$ sudo cat /etc/sysconfig/network-scripts/ifcfg-eno16777728
TYPE=”Ethernet”
BOOTPROTO=”none”
DEFROUTE=”yes”
IPV4_FAILURE_FATAL=”no”
IPV6INIT=”yes”
IPV6_AUTOCONF=”yes”
IPV6_DEFROUTE=”yes”
IPV6_FAILURE_FATAL=”no”
NAME=”eno16777728″
UUID=”8845f479-33a9-43d0-a292-84c4c9b281aa”
DEVICE=”eno16777728″
ONBOOT=”yes”
IPADDR=”50.201.93.40″
PREFIX=”27″
GATEWAY=”50.201.93.33″
DNS1=”50.201.93.34″
DNS2=”8.8.8.8″
IPV6_PEERDNS=”yes”
IPV6_PEERROUTES=”yes”
IPV6_PRIVACY=”no”
slow ssh login solution
$ sudo vi /etc/ssh/sshd_config
UseDNS=no
$ sudo systemctl restart sshd
Firewall Settings
$ sudo firewall-cmd --permanent --add-service=http
$ sudo firewall-cmd --permanent --add-service=https
$ sudo firewall-cmd --permanent --add-service=mysql
$ sudo firewall-cmd --reload
$ sudo systemctl restart firewalld.service
$ sudo firewall-cmd --permanent --zone=public --list-sources
$ sudo iptables -L
update selinux
$ sudo vi /etc/sysconfig/selinux
SELINUX=permissive
SETUP MARIADB REPO
select your OS to get the latest MariaDB repo
https://downloads.mariadb.org/mariadb/repositories
you can rename a similar name to MariaDB
$ sudo vi /etc/yum.repos.d/MariaDB.repo
copy paste this:
# MariaDB 10.2 CentOS repository list – created 2017-09-12 16:39 UTC
# http://downloads.mariadb.org/mariadb/repositories/
[mariadb]
name = MariaDB
baseurl = http://yum.mariadb.org/10.2/centos7-amd64
gpgkey=https://yum.mariadb.org/RPM-GPG-KEY-MariaDB
gpgcheck=1
update yum
$ sudo yum update
to install mariadb
$ sudo yum install MariaDB-server MariaDB-client
to start mariadb
$ sudo systemctl start mysql
($ sudo /etc/init.d/mysql start)
to enable at startup
$ sudo systemctl enable mysql
run security script
$ sudo mysql_secure_installation
(username: root, password: blabla)
to check status of mariadb
$ sudo systemctl status mysql
to stop mariadb
$ sudo systemctl stop mysql
login database
$ sudo mysql -u root -p
MariaDB [(none)]> show databases;
mysql>exit;
main config file is here
$ sudo vi /etc/my.cnf.d/server.cnf
CONFIGURE NTP
We have Eastern Time, so we need to change it!
$ date
Tue Sep 12 12:44:02 EDT 2017
install ntp (network time protocol) server to synchronize time
$ sudo yum install ntp
first go to official http://www.pool.ntp.org/en/
choose your Continent area where the server physically is located, then search for your Country location
For United Sates:
server 0.us.pool.ntp.org
server 1.us.pool.ntp.org
server 2.us.pool.ntp.org
server 3.us.pool.ntp.org
go to ntp config file
$ sudo vi /etc/ntp.conf
Your date might not match
$ date
Fri Apr 1 08:26:59 CDT 2016
Uncomment initials:
#server 0.centos.pool.ntp.org iburst
#server 1.centos.pool.ntp.org iburst
#server 2.centos.pool.ntp.org iburst
#server 3.centos.pool.ntp.org iburst
copy paste this to the ntp.conf
server 0.us.pool.ntp.org
server 1.us.pool.ntp.org
server 2.us.pool.ntp.org
server 3.us.pool.ntp.org
let’s start ntp for the first time
$ sudo systemctl start ntpdate
$ sudo systemctl enable ntpdate
$ sudo systemctl status ntpdate
$ sudo systemctl restart ntpdate
Unfortunately, it still does not match?!
$ date
Tue Sep 12 12:51:39 EDT 2017
if date still not matching run this manually
$ sudo ntpdate us.pool.ntp.org
12 Sep 12:52:37 ntpdate[4405]: adjust time server 64.113.44.54 offset 0.000242 sec
one more thing we need to do. Check out the date-time, it’s still NewYork Eastern Time
$ timedatectl
Local time: Tue 2017-09-12 12:53:47 EDT
Universal time: Tue 2017-09-12 16:53:47 UTC
RTC time: Tue 2017-09-12 16:53:47
Time zone: America/New_York (EDT, -0400)
NTP enabled: no
NTP synchronized: no
RTC in local TZ: no
DST active: yes
Last DST change: DST began at
Sun 2017-03-12 01:59:59 EST
Sun 2017-03-12 03:00:00 EDT
Next DST change: DST ends (the clock jumps one hour backwards) at
Sun 2017-11-05 01:59:59 EDT
Sun 2017-11-05 01:00:00 EST
Since NTP enabled is no above, you can enable it like this (it will ask for your root password)
$ sudo timedatectl set-ntp yes
then check out date-time again, upppss still same 😦
$ timedatectl
Local time: Tue 2017-09-12 12:54:49 EDT
Universal time: Tue 2017-09-12 16:54:49 UTC
RTC time: Tue 2017-09-12 16:54:49
Time zone: America/New_York (EDT, -0400)
NTP enabled: yes
NTP synchronized: yes
RTC in local TZ: no
DST active: yes
Last DST change: DST began at
Sun 2017-03-12 01:59:59 EST
Sun 2017-03-12 03:00:00 EDT
Next DST change: DST ends (the clock jumps one hour backwards) at
Sun 2017-11-05 01:59:59 EDT
Sun 2017-11-05 01:00:00 EST
if you still see a different timezone
$ sudo timedatectl set-timezone America/Chicago
if you want to restart ntp, then you need to first unrelate ntp from timedatectl
$ sudo timedatectl set-ntp no
$ sudo systemctl restart ntpdate
$ sudo systemctl enable ntpdate
$ sudo ntpdate us.pool.ntp.org
$ sudo timedatectl set-ntp yes
make sure your timezone is also correct
(please follow http://www.putorius.net/2015/04/setting-time-and-date-in-red-hat-7.html to play with timedatectl command)
list all the timezones just for curiosity
$ timedatectl list-timezones
Finally!!!! Date looks now fine in Central Time
$ date
Tue Sep 12 11:58:00 CDT 2017
$ timedatectl
Local time: Tue 2017-09-12 11:58:58 CDT
Universal time: Tue 2017-09-12 16:58:58 UTC
RTC time: Tue 2017-09-12 16:58:58
Time zone: America/Chicago (CDT, -0500)
NTP enabled: yes
NTP synchronized: yes
RTC in local TZ: no
DST active: yes
Last DST change: DST began at
Sun 2017-03-12 01:59:59 CST
Sun 2017-03-12 03:00:00 CDT
Next DST change: DST ends (the clock jumps one hour backwards) at
Sun 2017-11-05 01:59:59 CDT
Sun 2017-11-05 01:00:00 CST
INSTALL PHP7.1
Let’s first install epel-release and web static repository, then update repository
$ sudo yum install epel-release
$ sudo rpm -Uvh https://mirror.webtatic.com/yum/el7/webtatic-release.rpm
$ sudo yum update
$ sudo yum search php71w
if you see them, then install php7.1
$ sudo yum install php71w-bcmath php71w-cli mod_php71w php71w-common php71w-dba php71w-devel php71w-embedded php71w-enchant php71w-fpm php71w-gd php71w-imap php71w-interbase php71w-intl php71w-ldap php71w-mbstring php71w-mcrypt php71w-mysqlnd php71w-odbc php71w-opcache php71w-pdo php71w-pdo_dblib php71w-pear php71w-pecl-apcu php71w-pecl-apcu-devel php71w-pecl-geoip php71w-pecl-igbinary php71w-pecl-igbinary-devel php71w-pecl-imagick php71w-pecl-imagick-devel php71w-pecl-libsodium php71w-pecl-memcached php71w-pecl-mongodb php71w-pecl-redis php71w-pecl-xdebug php71w-pgsql php71w-phpdbg php71w-process php71w-pspell php71w-recode php71w-snmp php71w-soap php71w-tidy php71w-xml php71w-xmlrpc
check if php 7.1 installed
$ php -version
PHP 7.1.8 (cli) (built: Aug 9 2017 19:19:49) ( NTS )
Copyright (c) 1997-2017 The PHP Group
Zend Engine v3.1.0, Copyright (c) 1998-2017 Zend Technologies
with Zend OPcache v7.1.8, Copyright (c) 1999-2017, by Zend Technologies
with Xdebug v2.5.5, Copyright (c) 2002-2017, by Derick Rethans
upload max filesize
$ sudo vi /etc/php.ini
upload_max_filesize = 1024M
memory_limit = 2048M
post_max_size = 128M
max_input_vars = 5000
max_execution_time = 0
cgi.fix_pathinfo=0
allow_url_include = On
SSH2 SOLUTION FOR PHP7 ON CENTOS 7
First make sure you have gcc, php71w-devel, libssh2, libssh2-devel, wget and unzip packages installed
$ sudo yum install gcc php71w-devel libssh2 libssh2-devel wget unzip
go to opt folder
$ cd /opt/
download php7 branch source of php ssh2
$ sudo wget https://github.com/Sean-Der/pecl-networking-ssh2/archive/php7.zip
unzip and enter the folder
$ sudo unzip php7.zip
$ cd pecl-networking-ssh2-php7/
prepare build environment for this extension using phpize which will create the needed file and folder structure and configure file
$ sudo phpize
Configuring for:
PHP Api Version: 20160303
Zend Module Api No: 20160303
Zend Extension Api No: 320160303
check the configuration
$ sudo ./configure
…….
now make the extension, you should see build complete.
$ sudo make
…..
…..
Build complete.
Don’t forget to run ‘make test’.
finally install the extension
$ sudo make install
Installing shared extensions: /usr/lib64/php/modules/
put the extension manually
$ sudo vi /etc/php.d/ssh2.ini
extension=ssh2.so
restart web server and php-fpm
$ sudo systemctl restart nginx
$ sudo systemctl restart php-fpm
check php info, you’ll see the ssh2 module
$ php -i
ssh2
SSH2 support => enabled
extension version => 0.12+dev
libssh2 version => 1.4.3
banner => SSH-2.0-libssh2_1.4.3
or re-check php modules, you’ll see ssh2 module enabled
$ php -m
You can install nginx either from repo or manually.
INSTALL NGINX
When you search, you don’t see nginx
$ sudo yum search nginx
So after you install epel-release
$ sudo yum install epel-release
check it again, you’ll see the packages
$ sudo yum search nginx
let’s install nginx
$ sudo yum install nginx
nginx commands
$ sudo systemctl start nginx
$ sudo systemctl stop nginx
$ sudo systemctl restart nginx
$ sudo systemctl enable nginx
$ sudo systemctl status nginx
php-fpm commands
$ sudo systemctl start php-fpm
$ sudo systemctl stop php-fpm
$ sudo systemctl restart php-fpm
$ sudo systemctl status php-fpm
check it out, you should see the default nginx page
INSTALL NGINX MANUALLY (PREFERRED)
let’s remove nginx completely if pre-installed
$ sudo systemctl stop nginx
$ sudo systemctl stop php-fpm
$ sudo yum remove nginx
install the development tools
$ sudo yum groupinstall "Development Tools”
$ sudo yum install pcre-devel zlib-devel openssl-devel
download latest version of nginx manually from http://nginx.org/download/
the purpose with source code is we want to compile ngx_cache_purge along together
$ cd /tmp/
$ sudo wget http://nginx.org/download/nginx-1.13.5.tar.gz
$ sudo wget http://labs.frickle.com/files/ngx_cache_purge-2.3.tar.gz
nginx-1.13.5 and ngx_cache_purge-2.3 will be created
$ sudo tar -xzf nginx-1.13.5.tar.gz
$ sudo tar -xzf ngx_cache_purge-2.3.tar.gz
$ cd nginx-1.13.5
$ sudo ./configure --sbin-path=/usr/sbin --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --pid-path=/var/run/nginx.pid --lock-path=/var/lock/nginx.lock --http-log-path=/var/log/nginx/access.log --http-client-body-temp-path=/var/lib/nginx/body --http-proxy-temp-path=/var/lib/nginx/proxy --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --with-debug --with-http_stub_status_module --with-http_flv_module --with-http_ssl_module --with-http_dav_module --add-module=/tmp/ngx_cache_purge-2.3 --with-http_geoip_module --with-http_image_filter_module --with-http_gunzip_module --with-threads --with-file-aio --with-http_sub_module --with-http_gzip_static_module --with-http_auth_request_module --with-http_random_index_module --with-http_secure_link_module --with-http_slice_module --with-http_degradation_module --with-http_perl_module --with-mail --with-mail_ssl_module --with-stream --with-stream_ssl_module --with-google_perftools_module --with-cpp_test_module
make root
$ sudo su
$ make && make install
now let’s check it out
$ nginx -V
nginx version: nginx/1.13.5
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-16) (GCC)
built with OpenSSL 1.0.2k-fips 26 Jan 2017
TLS SNI support enabled
configure arguments: –sbin-path=/usr/sbin –conf-path=/etc/nginx/nginx.conf –error-log-path=/var/log/nginx/error.log –pid-path=/var/run/nginx.pid –lock-path=/var/lock/nginx.lock –http-log-path=/var/log/nginx/access.log –http-client-body-temp-path=/var/lib/nginx/body –http-proxy-temp-path=/var/lib/nginx/proxy –http-fastcgi-temp-path=/var/lib/nginx/fastcgi –with-debug –with-http_stub_status_module –with-http_flv_module –with-http_ssl_module –with-http_dav_module –with-ipv6 –add-module=/tmp/ngx_cache_purge-2.3
create the system file so that you can use the start, stop, enable and status commands
Source: https://www.nginx.com/resources/wiki/start/topics/examples/systemd/
$ vi /lib/systemd/system/nginx.service
[Unit]
Description=The NGINX HTTP and reverse proxy server
After=syslog.target network.target remote-fs.target nss-lookup.target[Service]
Type=forking
PIDFile=/run/nginx.pid
ExecStartPre=/usr/sbin/nginx -t
ExecStart=/usr/sbin/nginx
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true[Install]
WantedBy=multi-user.target
check syntax
$ nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
enable and start nginx
$ sudo systemctl enable nginx
$ sudo systemctl start nginx
let’s check the ngx_cache_purge module again
$ nginx -V 2>&1 | grep ngx_cache_purge -o
ngx_cache_purge
TUNE UP KERNEL
https://www.digitalocean.com/community/tutorials/how-to-optimize-nginx-configuration
First tune up Kernel
get the total number of CPU cores of the machine
$ grep processor /proc/cpuinfo | wc -l
2
let’s become root to change the kernel
$ sudo -s
see how much open files the kernel can retreive
$ ulimit -a
assume 1024 for 0.5 Gig (512 MB) RAM so for 16 Gig change it to 32768
$ ulimit -n 32768
check the limit
$ ulimit -Hn
32768
worker_connections tells our worker processes how many people can simultaneously be served by Nginx The default value is 1024; however, we’ll change it according to our max concurrent process size 32768 Considering that every browser usually opens up at least 2 connections/server, this number can half 32768/2
$ sudo vi /etc/nginx/nginx.conf
events {
worker_connections 16384;
}#we have 2 cpu cores
worker_processes 2;
Note:
max_clients = worker_processes * worker_connections ==> 2 * 16384 = 32768 for moodle https://docs.moodle.org/29/en/Performance_recommendations MaxClients = Total available memory * 80% / Max memory usage of apache process Memory usage of apache process is usually 10MB but WordPress can easily use up to 100MB per process max_clients = 16 (Gig RAM) x 1024 * 80% /100 = 131.072 So for moodle the concurrent connections is decreased from 16384 to 131
$ ps -ylC nginx --sort:rss
NGINX AND PHP-FPM CONFIGURATIONS CONTINUED
PHP-FPM SETTINGS
let’s update php-fpm config
$ sudo vi /etc/php-fpm.d/www.conf
user = nginx
group = nginx
#listen = 127.0.0.1:9000
listen = /var/run/php-fpm/php-fpm.sock
listen.owner = nginx
listen.group = nginx
listen.mode = 0660
listen.allowed_clients = 127.0.0.1
pm = static
pm.max_children = 131
pm.max_requests = 1000
security.limit_extensions = .php .php3 .php4 .php5 .php7#the below is not important because we use static, just keep them
pm.start_servers = 15
pm.min_spare_servers = 5
pm.max_spare_servers = 35
NGINX SETTINGS
first create the wpnau folder (wordpress for nau), will use it later
$ sudo mkdir /usr/share/nginx/html/wpnau
then create the wpgls folder (wordpress for gls), will use it later
$ sudo mkdir /usr/share/nginx/html/wpgls
create cache folder, we’ll use it later for cache purposes
$ sudo mkdir /etc/nginx/cache
give full access
$ sudo chmod 777 /etc/nginx/cache
create a test page under wpnau, we’ll test this for cache purposes
$ sudo vi /usr/share/nginx/html/wpnau/time.php
create a test page under wpgls, we’ll test this for cache purposes
$ sudo vi /usr/share/nginx/html/wpgls/time.php
that’s the main nginx configuration file, no need to update, just check it out
$ sudo vi /etc/nginx/nginx.conf
#let’s store all config files here
include /etc/nginx/conf.d/*.conf;
SPLIT CONFIGS
retrieved from http://www.ehowstuff.com/setup-wordpress-nginx-with-fastcgi-caching-in-centos-7/ updated according to our needs. Splitting the configs makes it easier to read
let’s create the config files, first the create the most common configs
$ sudo vi /etc/nginx/conf.d/common.conf
# Global configuration file. # ESSENTIAL : Configure Nginx Listening Port listen 80; # ESSENTIAL : Default file to serve. If the first file isn't found, index index.php index.html index.htm; # ESSENTIAL : no favicon logs location = /favicon.ico { log_not_found off; access_log off; } # ESSENTIAL : robots.txt location = /robots.txt { allow all; log_not_found off; access_log off; } # ESSENTIAL : Configure 404 Pages error_page 404 /404.html; # ESSENTIAL : Configure 50x Pages error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; } # SECURITY : Deny all attempts to access hidden files .abcde location ~ /\. { deny all; } # PERFORMANCE : Set expires headers for static files and turn off logging. location ~* ^.+\.(js|css|swf|xml|txt|ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|rss|atom|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf)$ { access_log off; log_not_found off; expires 30d; # expires max; add_header Pragma no-cache; add_header Cache-Control "public"; }
then create the gzip config
$ sudo vi /etc/nginx/conf.d/gzip.conf
gzip on; gzip_comp_level 6; gzip_proxied any; gzip_min_length 1100; gzip_buffers 16 8k; gzip_disable "MSIE [1-6]\.(?!.*SV1)"; gzip_types text/css text/x-component application/ecmascript application/json application/pdf application/javascript application/x-javascript text/javascript application/postscript text/x-js text/richtext image/svg+xml text/plain text/xsd text/xsl text/xml image/x-icon; gzip_http_version 1.1; gzip_vary on;
then create the fast-cgi and other option configs
$ sudo vi /etc/nginx/conf.d/option.conf
## FAST-CGI Configurations fastcgi_cache_path /etc/nginx/cache levels=1:2 keys_zone=WPCACHE:1024m inactive=60m; fastcgi_cache_key "$scheme$request_method$host$request_uri"; fastcgi_cache_use_stale error timeout invalid_header http_500; fastcgi_ignore_headers Cache-Control Expires Set-Cookie; add_header X-Fastcgi-Cache $upstream_cache_status; ## Other server option server_tokens off; keepalive_requests 100000; reset_timedout_connection on; port_in_redirect off; client_body_timeout 1460; client_header_timeout 1460; client_max_body_size 10m; send_timeout 1460;
let’s create the main nau wordpress file
$ sudo vi /etc/nginx/conf.d/wordpress.conf
# WORDPRESS : Rewrite rules, sends everything through index.php and keeps the appended query string intact location / { try_files $uri $uri/ /index.php?q=$uri&$args; } # SECURITY : Deny all attempts to access PHP Files in the uploads directory location ~* /(?:uploads|files)/.*\.php$ { deny all; } # REQUIREMENTS : Enable PHP Support location ~ \.php$ { # SECURITY : Zero day Exploit Protection try_files $uri =404; # ENABLE : Enable PHP, listen fpm sock fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock; fastcgi_index index.php; fastcgi_send_timeout 300s; fastcgi_read_timeout 300s; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_buffer_size 512k; fastcgi_buffers 1024 16k; fastcgi_busy_buffers_size 1024k; fastcgi_temp_file_write_size 1024k; fastcgi_intercept_errors on; ##Added below for fastcgi_cache fastcgi_cache_bypass $no_cache; fastcgi_no_cache $no_cache; fastcgi_cache WPCACHE; fastcgi_cache_valid 200 60m; fastcgi_cache_valid 404 60m; fastcgi_max_temp_file_size 16m; fastcgi_cache_use_stale updating; fastcgi_cache_methods GET HEAD; # Only GET and HEAD methods apply add_header X-Fastcgi-Cache $upstream_cache_status; } # Deny access to .php files in the /wp-content/ directory (including sub-folders) location ~* ^/wp-content/.*.(php|phps)$ { deny all; } #added by Mehmet Sen location ~ /purge(/.*) { fastcgi_cache_purge WPCACHE "$scheme$request_method$host$1"; } ## Block SQL injections location ~* union.*select.*\( {access_log /var/log/nginx/*.*.log blocked; deny all;} location ~* union.*all.*select.* {access_log /var/log/nginx/*.*.log blocked; deny all;} location ~* concat.*\( {access_log /var/log/nginx/*.*.log blocked; deny all;} # ### Block common exploits #disabled by Mehmet Sen because it was giving invalid number of arguments error #location ~* (|%3E) {access_log /var/log/nginx/*.*.log blocked; deny all;} location ~* base64_(en|de)code\(.*\) {access_log /var/log/nginx/*.*.log blocked; deny all;} location ~* (%24&x) {access_log /var/log/nginx/*.*.log blocked; deny all;} location ~* (%0|%A|%B|%C|%D|%E|%F|127\.0) {access_log /var/log/nginx/*.*.log blocked; deny all;} location ~* \.\.\/ {access_log /var/log/nginx/*.*.log blocked; deny all;} location ~* ~$ {access_log /var/log/nginx/*.*.log blocked; deny all;} location ~* proc/self/environ {access_log /var/log/nginx/*.*.log blocked; deny all;} location ~* /\.(htaccess|htpasswd|svn) {access_log /var/log/nginx/*.*.log blocked; deny all;} # ### Block file injections location ~* [a-zA-Z0-9_]=(\.\.//?)+ {access_log /var/log/nginx/*.*.log blocked; deny all;} location ~* [a-zA-Z0-9_]=/([a-z0-9_.]//?)+ {access_log /var/log/nginx/*.*.log blocked; deny all;} # ### wordpress security location ~* wp-config.php {access_log /var/log/nginx/*.*.log blocked; deny all;} location ~* wp-admin/includes {access_log /var/log/nginx/*.*.log blocked; deny all;} location ~* wp-admin/setup-config.php {access_log /var/log/nginx/*.*.log blocked; deny all;} location ~* wp-app\.log {access_log /var/log/nginx/*.*.log blocked; deny all;} location ~* (licence|readme|license)\.(html|txt) {access_log /var/log/nginx/*.*.log blocked; deny all;} # PLUGINS : Enable Rewrite Rules for Yoast SEO SiteMap rewrite ^/sitemap_index\.xml$ /index.php?sitemap=1 last; rewrite ^/([^/]+?)-sitemap([0-9]+)?\.xml$ /index.php?sitemap=$1&sitemap_n=$2 last; rewrite ^/sitemap(-+([a-zA-Z0-9_-]+))?\.xml$ "/index.php?xml_sitemap=params=$2" last; rewrite ^/sitemap(-+([a-zA-Z0-9_-]+))?\.xml\.gz$ "/index.php?xml_sitemap=params=$2;zip=true" last; rewrite ^/sitemap(-+([a-zA-Z0-9_-]+))?\.html$ "/index.php?xml_sitemap=params=$2;html=true" last;
configure Cache Exceptions
$ sudo vi /etc/nginx/conf.d/fastcgi_no_cache.conf
set $no_cache 0; # POST requests and URLs with a query string should always go to PHP if ($request_method = POST) { set $no_cache 1; } if ($query_string != "") { set $no_cache 1; } # Don't cache URIs containing the following segments if ($request_uri ~* "/wp-admin/|/xmlrpc.php|wp-.*.php|/feed/|index.php |sitemap(_index)?.xml") { set $no_cache 1; } # Don't use the cache for logged-in users or recent commenters if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass |wordpress_no_cache|wordpress_logged_in") { set $no_cache 1; }
The application config files, remember we have 2 wordpress sites!
nau config
$ sudo vi /etc/nginx/conf.d/wpnau.conf
server { listen 80; server_name na.edu; rewrite ^/(.*)$ http://www.na.edu/$1 permanent; } server { server_name www.na.edu; root /usr/share/nginx/html/wpnau; access_log /var/log/nginx/wpnau.access.log; error_log /var/log/nginx/wpnau.log; #include config files include /etc/nginx/conf.d/common.conf; #nginx for WordPress and security include /etc/nginx/conf.d/wordpress.conf; #Configure Nginx Fast-CGI Cache Exceptions include /etc/nginx/conf.d/fastcgi_no_cache.conf; }
gls config
$ sudo vi /etc/nginx/conf.d/wpgls.conf
server { listen 80; server_name gls.edu; rewrite ^/(.*)$ http://www.gls.edu/$1 permanent; } server { server_name www.gls.edu; root /usr/share/nginx/html/wpgls; access_log /var/log/nginx/wpgls.access.log; error_log /var/log/nginx/wpgls.log; #include config files include /etc/nginx/conf.d/common.conf; #nginx for WordPress and security include /etc/nginx/conf.d/wordpress.conf; #Configure Nginx Fast-CGI Cache Exceptions include /etc/nginx/conf.d/fastcgi_no_cache.conf; }
the main nginx config file, delete any server block, we’ll create it ourself
and also realize that the user is ‘nginx’ here which we’ll set the same ‘nginx’ user to phpmyadmin later as well
$ sudo vi /etc/nginx/nginx.conf
user nginx; worker_processes 2; error_log /var/log/nginx/error.log; error_log /var/log/nginx/error.log notice; error_log /var/log/nginx/error.log info; pid /run/nginx.pid; # Load dynamic modules. See /usr/share/nginx/README.dynamic. include /usr/share/nginx/modules/*.conf; events { worker_connections 16384; } http { include /etc/nginx/mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; #added by Mehmet Sen log_format blocked '$time_local: Blocked request from $remote_addr $request'; access_log /var/log/nginx/access.log main; sendfile on; tcp_nopush on; tcp_nodelay on; #updated to 1300 by Mehmet Sen keepalive_timeout 1300; types_hash_max_size 2048; ######## added by Mehmet Sen include /etc/nginx/conf.d/gzip.conf; #FastCGI Cache and other configuration options include /etc/nginx/conf.d/option.conf; # default worpress entry page include /etc/nginx/conf.d/default.conf; # nau wordpress config file include /etc/nginx/conf.d/wpnau.conf; # gls wordpress config file include /etc/nginx/conf.d/wpgls.conf; ########## }
verify syntax
$ sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful
restart nginx and php-fpm
$ sudo systemctl restart nginx
$ sudo systemctl restart php-fpm
INSTALL PHPMYADMIN
Search first for phpmyadmin, if you don’t see it then install epel-release first.
$ sudo yum search phpmyadmin
To install phpMyAdmin easily on CentOS 7, first install extra packages for enterprise linux (epel)
$ sudo yum install epel-release
finally install phpMyAdmin
$ sudo yum install phpMyAdmin
create the symlink named “puma” of phpmyadmin
$ sudo ln -s /usr/share/phpMyAdmin/ /usr/share/nginx/html/default/pma
check it out
$ ls -l /usr/share/nginx/html/
….
lrwxrwxrwx. 1 root root 22 Sep 13 15:07 phpmyadmin -> /usr/share/phpMyAdmin/
….
fix session and blowfish_secret problem on phpmyadmin login page
$ sudo chown -R root:nginx /var/lib/php/session
$ sudo chown -R root:nginx /etc/phpMyAdmin/
restart nginx and php-fpm
$ sudo systemctl restart php-fpm
$ sudo systemctl restart nginx
create a default config
$ sudo vi /etc/nginx/conf.d/default.conf
server { listen 80 default_server; listen [::]:80 default_server; server_name wordpress.na.edu; root /usr/share/nginx/html/default; index index.php index.html index.htm; location / { try_files $uri $uri/ index.html index.php =404; } error_page 404 /404.html; location /40x.html { root /usr/share/nginx/html/default; } error_page 500 502 503 504 /50x.html; location /50x.html { root /usr/share/nginx/html/default; } location ~ \.php$ { try_files $uri =404; fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } #phpmyadmin location /pma { alias /usr/share/phpMyAdmin; index index.php; } access_log /var/log/nginx/default.access.log; error_log /var/log/nginx/default.log; }
let’s put one more security layer on before phpmyadmin login page, type Nau@blabla
$ sudo openssl passwd
Password:
Verifying – Password:
Warning: truncating password to 8 characters
zRaBVt.gAB6ok
create the authentication file along with username and generated password above
$ sudo vi /etc/nginx/pma_pass
admin:zRaBVt.gAB6ok
now go back to default config file and update accordingly
$ sudo vi /etc/nginx/conf.d/default.conf
server { listen 80 default_server; listen [::]:80 default_server; server_name wordpress.na.edu; root /usr/share/nginx/html/default; index index.php index.html index.htm; location / { try_files $uri $uri/ index.html index.php =404; } error_page 404 /404.html; location /40x.html { root /usr/share/nginx/html/default; } error_page 500 502 503 504 /50x.html; location /50x.html { root /usr/share/nginx/html/default; } location ~ \.php$ { try_files $uri =404; fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } #phpmyadmin location /pma { alias /usr/share/phpMyAdmin; index index.php; auth_basic "Admin Login"; auth_basic_user_file /etc/nginx/pma_pass; } access_log /var/log/nginx/default.access.log; error_log /var/log/nginx/default.log; }
restart nginx
$ sudo systemctl restart nginx
now try url again, it will require authentication username and password!
http://wordpress.na.edu/pma (‘admin’ and ‘Nau@blabla’)
Go and create a new database ‘wp_nau’ and ‘wp_gls’ along with new user and password, give it all privileges on each database at localhost
user: usrwp, passw: Nau@blabla
TEST CACHE ON GLS
to test the cache on gls first update the gls config
$ sudo vi /etc/nginx/conf.d/wpgls.conf
server { listen 80; server_name gls.edu; rewrite ^/(.*)$ http://www.gls.edu/$1 permanent; } server { server_name www.gls.edu; root /usr/share/nginx/html/wpgls; access_log /var/log/nginx/wpgls.access.log; error_log /var/log/nginx/wpgls.log; #include config files include /etc/nginx/conf.d/common.conf; #nginx for WordPress and security #include /etc/nginx/conf.d/wordpress.conf; #Configure Nginx Fast-CGI Cache Exceptions #include /etc/nginx/conf.d/fastcgi_no_cache.conf; location ~ \.php$ { try_files $uri =404; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass unix:/var/run/php-fpm/php-fpm.sock; fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; } }
create a time.php file
$ sudo vi /usr/share/nginx/html/wpgls/time.php
restart nginx and php-fpm
$ sudo systemctl restart php-fpm
$ sudo systemctl restart nginx
now go to the gls page and refresh it many times, you’ll see different results
http://www.gls.edu/time.php
1505410696
1505410727
1505410737
1505410747
1505410764
change the gls config back to its original format where the fastcgi cache is enabled
$ sudo vi /etc/nginx/conf.d/wpgls.conf
server { listen 80; server_name gls.edu; rewrite ^/(.*)$ http://www.gls.edu/$1 permanent; } server { server_name www.gls.edu; root /usr/share/nginx/html/wpgls; access_log /var/log/nginx/wpgls.access.log; error_log /var/log/nginx/wpgls.log; #include config files include /etc/nginx/conf.d/common.conf; #nginx for WordPress and security include /etc/nginx/conf.d/wordpress.conf; #Configure Nginx Fast-CGI Cache Exceptions include /etc/nginx/conf.d/fastcgi_no_cache.conf; }
restart nginx and php-fpm
$ sudo systemctl restart php-fpm
$ sudo systemctl restart nginx
now go again to the gls page and refresh it many times, you’ll see only one result on each refresh, try from another browser you’ll see the same result
http://www.gls.edu/time.php
1505411049
the pages and other files will be cached here
$ sudo ls /etc/nginx/cache/
ANOTHER CACHE TEST METHOD
$ curl -X GET -I http://www.gls.edu
HTTP/1.1 200 OK
Server: nginx
Date: Mon, 18 Sep 2017 17:28:11 GMT
Content-Type: text/html; charset=UTF-8
Transfer-Encoding: chunked
Connection: keep-alive
Vary: Accept-Encoding
X-Powered-By: PHP/7.1.8
Expires: Wed, 11 Jan 1984 05:00:00 GMT
Cache-Control: no-cache, must-revalidate, max-age=0
Link: ; rel=”https://api.w.org/”
X-Fastcgi-Cache: HIT
INSTALL WORDPRESS
finally, let’s install wordpress, first go to the opt folder
$ cd /opt/
download the latest version
$ sudo wget http://wordpress.org/latest.tar.gz
extract the archived files
$ sudo tar xzvf latest.tar.gz
make sure the gls root folder is empty, if not clean it
$ sudo rm -R /usr/share/nginx/html/wpgls/*
then move the wordpress files to the gls root folder
$ sudo rsync -avP wordpress/ /usr/share/nginx/html/wpgls/
create an upload directory
$ sudo mkdir /usr/share/nginx/html/wpgls/wp-content/uploads
give the right permission to the files
$ sudo chown -R root:nginx /usr/share/nginx/html/*
go to the gls root folder
$ sudo cd /usr/share/nginx/html/wpgls/
copy the config file from the sample file
$ sudo cp wp-config-sample.php wp-config.php
confgure wordpress
$ sudo vi wp-config.php
// ** MySQL settings – You can get this info from your web host ** //
/** The name of the database for WordPress */
define(‘DB_NAME’, ‘wp_gls’);
/** MySQL database username */
define(‘DB_USER’, ‘dbusername’);
/** MySQL database password */
define(‘DB_PASSWORD’, ‘dbpassword’);
/** MySQL hostname */
define(‘DB_HOST’, ‘localhost’);
give the right permissions
$ sudo chmod 755 -R /usr/share/nginx/html/wpgls/
$ sudo chown -R nginx:nginx /usr/share/nginx/html/wpgls/
now go to the gls.edu, you’ll see the welcome page along with admin form, fill it out and click Install WordPress button
It will create the tables and show you a login button page, click Log In
After you login, it will take a little while and then you are in!!!
YEEEEYYYYYY!!!
But we are not finished yet!!!
UPDATE CURL
check curl version
$ curl -V
curl 7.29.0 (x86_64-redhat-linux-gnu) libcurl/7.29.0 NSS/3.21 Basic ECC zlib/1.2.7 libidn/1.28 libssh2/1.4.3
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtsp scp sftp smtp smtps telnet tftp
Features: AsynchDNS GSS-Negotiate IDN IPv6 Largefile NTLM NTLM_WB SSL libz unix-sockets
update curl
$ sudo yum update curl.86_64
if no new version create a new repository
$ sudo vi /etc/yum.repos.d/city-fan.repo
[CityFan] name=City Fan Repo baseurl=http://www.city-fan.org/ftp/contrib/yum-repo/rhel$releasever/$basearch/ enabled=1 gpgcheck=0
enable EPEL repository
$ sudo yum install epel-release
rerun the updater
$ sudo yum update curl.86_64
CONFIGURE FTP USER FOR GLS
update yum repo
$ sudo yum update
install ftp
$ sudo yum install vsftpd
allow_writeable_chroot=YES is added manually
$ sudo vi /etc/vsftpd/vsftpd.conf
anonymous_enable=NO
ascii_upload_enable=YES
ascii_download_enable=YES
write_enable=YES
local_enable=YES
chroot_local_user=YES
ftpd_banner=Welcome to blah FTP service.
allow_writeable_chroot=YES
$ sudo systemctl restart vsftpd
$ sudo systemctl enable vsftpd
$ sudo firewall-cmd --permanent --add-port=21/tcp
$ sudo firewall-cmd --permanent --add-service=ftp
$ sudo firewall-cmd --reload
$ sudo yum provides \*/bin/ftp
add new user
$ sudo useradd glsftp
$ sudo passwd glsftp
Changing password for user glsftp.
New password: blabla
Retype new password: blabla
make user writeable
$ sudo chmod a-w /home/glsftp/
$ sudo systemctl restart vsftpd
allow user to access home directory
$ sudo setsebool -P ftp_home_dir on
test ftp account
use any sftp client such as Filezilla
Host: 50.201.93.40
username: glsftp
password: blabla
Port: 22
INSTALL SSL FOR GLS
first install openssl
$ sudo yum install openssl
$ sudo yum install openssl-devel pcre-devel
allow ssl port 443
$ sudo firewall-cmd --permanent --add-port=443/tcp
$ sudo firewall-cmd —reload
$ sudo iptables -L
go to certification folder
$ cd /etc/pki/tls/certs/
create the key file
$ sudo openssl genrsa -out server.key 2048
create the csr file
$ sudo openssl req -new -key server.key -out server.csr
Country Name (2 letter code) [XX]:US State or Province Name (full name) []:TEXAS Locality Name (eg, city) [Default City]:STAFFORD Organization Name (eg, company) [Default Company Ltd]:GULF LANGUAGE SCHOOL Organizational Unit Name (eg, section) []:GLS Common Name (eg, your name or your server's hostname) []:gls.edu Email Address []:msen@na.edu Please enter the following 'extra’ attributes to be sent with your certificate request A challenge password []: An optional company name []:
now verify the car file
$ openssl req -text -noout -verify -in server.csr
After that, I bought a 3 year Standard SSL Certificate from Godaddy and copy pasted the server.csr content to godaddy to get the crt file
Godaddy sent me this Unique ID along with instructions how to verify https://www.godaddy.com/help/verify-domain-ownership-html-or-dns-7452
7ugkvkgldci3nph75535hgneem
to verify through HTML Page create the directories godaddy requested from you
$ sudo mkdir /usr/share/nginx/html/wpgls/.well-known
$ sudo mkdir /usr/share/nginx/html/wpgls/.well-known/pki-validation
copy paste the unique id
$ sudo vi /usr/share/nginx/html/wpgls/.well-known/pki-validation/godaddy.html
7ugkvkgldci3nph75535hgneem
change gls nginx config so that ssl can find gls.edu
$ sudo vi /etc/nginx/conf.d/wpgls.conf
server { listen 80; server_name www.gls.edu; # $scheme will get the http protocol # and 301 is best practice for tablet, phone, desktop and seo return 301 $scheme://gls.edu$request_uri; } server { server_name gls.edu; root /usr/share/nginx/html/wpgls; access_log /var/log/nginx/wpgls.access.log; error_log /var/log/nginx/wpgls.log; #include config files include /etc/nginx/conf.d/common.conf; #nginx for WordPress and security include /etc/nginx/conf.d/wordpress.conf; #Configure Nginx Fast-CGI Cache Exceptions include /etc/nginx/conf.d/fastcgi_no_cache.conf; }
check and restart nginx
$ sudo nginx -t
$ sudo systemctl restart nginx
now disable the block temporarily
$ sudo vi /etc/nginx/conf.d/common.conf
#location ~ /\. {
# deny all;
#}
then go to this link, you should be able to see it. (the http://www.gls.edu would not work if we didn’t change the above wpgls.conf file)
http://gls.edu/.well-known/pki-validation/godaddy.html
go back to the godaddy Certificate Request Verification page and click Check My Update, you should see a green validation response that says
We have verified your domain. Please allow 5-10 minutes for this to take affect.
You’ll also get a verification email along with downloadable crt link
https://certs.godaddy.com/home.pki?AccountUid=60686aa7-9d88-11e7-80fd-3417ebe60eb6
Certificate Details Less info Status Certificate issued (Revoke) Domain name gls.edu Encryption Strength Starfield SHA-2 Validity Period 9/19/2017 - 9/19/2020 Serial Number a7:b5:dd:5a:38:e1:5f:9b
Click Download
Download gls.edu.zip file to your computer, you’ll see 2 crt files;
a7b5dd5a38e15f9b.crt
sfig2_bundle.crt
ftp the first a7b5dd5a38e15f9b.crt to the server’s
/etc/pki/tls/certs with FileZilla
give the same ownership as others in certs folder
$ sudo chown root:root a7b5dd5a38e15f9b.crt
now this step is important, create the pem file
$ sudo bash -c 'cat a7b5dd5a38e15f9b.crt server.key > gls.pem'
after creating the gls.pem file, re-update the wpgls.config file
$ sudo vi /etc/nginx/conf.d/wpgls.conf
server { listen 80; server_name www.gls.edu; rewrite ^ https://$host$request_uri? permanent; } server { listen 443 ssl; ssl on; ssl_certificate /etc/pki/tls/certs/gls.pem; ssl_certificate_key /etc/pki/tls/certs/server.key; server_name gls.edu; root /usr/share/nginx/html/wpgls; access_log /var/log/nginx/wpgls.access.log; error_log /var/log/nginx/wpgls.log; #include config files include /etc/nginx/conf.d/common.conf; #nginx for WordPress and security include /etc/nginx/conf.d/wordpress.conf; #Configure Nginx Fast-CGI Cache Exceptions include /etc/nginx/conf.d/fastcgi_no_cache.conf; }
don’t forget to enable this line
$ sudo vi /etc/nginx/conf.d/common.conf
location ~ /\. {
deny all;
}
restart nginx and php-fpm
$ sudo systemctl restart nginx
$ sudo systemctl restart php-fpm
GLS CloudFlare Account
We purchased Pro Version $20/mo, follow the CloudFlare Instructions and make sure there is no other dns server pointing your ip
INSTALL TMPFS
first check it out
$ sudo df -h
/dev/mapper/centos-root 50G 3.5G 47G 7% /
devtmpfs 7.8G 0 7.8G 0% /dev
tmpfs 7.8G 0 7.8G 0% /dev/shm
tmpfs 7.8G 425M 7.4G 6% /run
tmpfs 7.8G 0 7.8G 0% /sys/fs/cgroup
/dev/mapper/centos-home 42G 33M 42G 1% /home
/dev/sda1 497M 181M 317M 37% /boot
tmpfs 1.6G 0 1.6G 0% /run/user/1000
tmpfs 1.6G 0 1.6G 0% /run/user/1001
mount the nginx cache directory with 6Gig RAM size, tmpfs filesystem is created to serve Nignx cache from RAM
$ sudo mount -t tmpfs -o size=6G tmpfs /etc/nginx/cache
check it out
$ sudo df -ah | grep tmpfs
tmpfs 6.0G 0 6.0G 0% /etc/nginx/cache
configure the nginx cache directory to be created into RAM automatically after reboot
$ sudo vi /etc/fstab
tmpfs /etc/nginx/cache tmpfs defaults,size=6G 0 0
restart nginx and php-fpm
$ sudo systemctl restart nginx
$ sudo systemctl restart php-fpm