Skip to content
Justin SilverTECHNOLOGY, TRAVEL & EVERYTHING IN BETWEEN

Linux

LEMP: CentOS 7, NGINX, PHP7, and Redis for Wordpress

September 23, 2016

Scripts to setup a Wordpress server on CentOS 7 with NGINX, PHP/PHP-FPM 7, Redis and more.
  • Firewalld - allow only HTTP/S and SSH traffic
  • Letsencrypt - free SSL certificates
  • Yum Cron - keep system up to date automatically
  • Redis - persistent, in-memory data store
  • PHP7 + PHP-FPM - PHP Next Generation with php-fpm for compatibility with Nginx
  • NGINX - event based web server
    • NGINX configurations - blacklisted referers, Cloudflare IP forwarding, MIME types, Security features, SSL, Wordpress configuration

Firewalld

Enable the firewalld service and only allow http/s traffic to the server - in addition to the default of just ssh.

systemctl enable firewalld
service firewalld start
firewall-cmd --permanent --zone=public --add-service=http
firewall-cmd --permanent --zone=public --add-service=https
firewall-cmd --reload

Letsencrypt

Use Letsencrypt for free SSL certificates.

yum -y install letsencrypt
openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048

Yum Cron


#!/bin/bash

# make sure the YUM_CRON_EMAIL is set
if [[ -z $YUM_CRON_EMAIL ]]; then
  echo "You must specify an email using \$YUM_CRON_EMAIL";
else
  # install and enable, plus patch for bug fixing
  yum -y install yum-cron patch
  chkconfig yum-cron on

  # configure via sed replacements
  sed -i "s|^email_to = root|email_to = ${YUM_CRON_EMAIL}|" /etc/yum/yum-cron.conf
  sed -i 's|^update_messages = no|update_messages = yes|' /etc/yum/yum-cron.conf
  sed -i 's|^download_updates = no|download_updates = yes|' /etc/yum/yum-cron.conf
  sed -i 's|^apply_updates = no|apply_updates = yes|' /etc/yum/yum-cron.conf
  sed -i 's|^emit_via = stdio|emit_via = email|' /etc/yum/yum-cron.conf

  sed -i "s|^email_to = root|email_to = ${YUM_CRON_EMAIL}|" /etc/yum/yum-cron-hourly.conf
  sed -i 's|^update_cmd = default|update_cmd = security|' /etc/yum/yum-cron-hourly.conf
  sed -i 's|^update_messages = no|update_messages = yes|' /etc/yum/yum-cron-hourly.conf
  sed -i 's|^download_updates = no|download_updates = yes|' /etc/yum/yum-cron-hourly.conf
  sed -i 's|^apply_updates = no|apply_updates = yes|' /etc/yum/yum-cron-hourly.conf
  sed -i 's|^emit_via = stdio|emit_via = email|' /etc/yum/yum-cron-hourly.conf   

  egrep '^email_to|^update_messages|^download_updates|^apply_updates|^emit_via' /etc/yum/yum-cron.conf
  egrep '^email_to|^update_cmd|^update_messages|^download_updates|^apply_updates|^emit_via' /etc/yum/yum-cron-hourly.conf
  
  # fix bug in yum-cron nightly updates
  if [[ $(grep -q "# success, dependencies resolved" /usr/sbin/yum-cron) -ne 0 ]]; then
    patch /usr/sbin/yum-cron <<PATCHFILE
--- yum-cron.orig 2016-10-23 19:24:57.099859931 +0000
+++ yum-cron  2016-10-23 19:27:58.048784006 +0000
@@ -504,7 +504,13 @@
     except yum.Errors.RepoError, e:
       self.emitCheckFailed("%s" %(e,))
       sys.exit()
-        if res != 2:
+        if res == 0:
+            # success, empty transaction
+            sys.exit(0)
+        elif res == 2:
+            # success, dependencies resolved
+            pass
+        else:
       self.emitCheckFailed("Failed to build transaction: %s" %(str.join("\n", resmsg),))
       sys.exit(1)
PATCHFILE
  fi  
  # (re)start the yum-cron service
  (service yum-cron status > /dev/null && service yum-cron restart) || service yum-cron start
fi

Redis / EPEL

Redis is available via EPEL and provides a great in memory cache.

#!/bin/bash

# install the EPEL repo to access Redis
yum install -y epel-release
yum install -y redis

# fix redis background saves on low memory
sysctl vm.overcommit_memory=1 && cat <<SYSCTL_MEM > /etc/sysctl.d/88-vm.overcommit_memory.conf
vm.overcommit_memory = 1
SYSCTL_MEM

# increase max connections
sysctl -w net.core.somaxconn=65535 && cat <<SYSCTL_CONN > /etc/sysctl.d/88-net.core.somaxconn.conf
net.core.somaxconn = 65535
SYSCTL_CONN

sysctl -w fs.file-max=100000 && cat <<SYSCTL_FILEMAX > /etc/sysctl.d/88-fs.file-max.conf
fs.file-max = 100000
SYSCTL_FILEMAX

sed -i "s|^tcp-backlog [[:digit:]]\+|tcp-backlog 65535|" /etc/redis.conf

# enable redis service on reboot
systemctl enable redis

# start service
(service redis status > /dev/null && service redis restart) || service redis start
#!/bin/bash

# Create Service to disable THP
cat <<DISABLE_THP > /etc/systemd/system/disable-thp.service
[Unit]
Description=Disable Transparent Huge Pages (THP)

[Service]
Type=simple
ExecStart=/bin/sh -c "echo 'never' > /sys/kernel/mm/transparent_hugepage/enabled && echo 'never' > /sys/kernel/mm/transparent_hugepage/defrag"

[Install]
WantedBy=multi-user.target
DISABLE_THP

sudo systemctl daemon-reload
sudo systemctl start disable-thp
sudo systemctl enable disable-thp

PHP / PHP-FPM

Install PHP and PHP-FPM from the Remi Safe Repo. Some config files and binaries will need to be symlinked for compatibility.

# install the remi-safe.repo
cat &lt;&lt;REMISAFE &gt; /etc/yum.repos.d/remi-safe.repo
# This repository is safe to use with RHEL/CentOS base repository
# it only provides additional packages for the PHP stack
# all dependencies are in base repository or in EPEL

[remi-safe]
name=Safe Remi's RPM repository for Enterprise Linux \$releasever - \$basearch
#baseurl=http://rpms.remirepo.net/enterprise/\$releasever/safe/\$basearch/
mirrorlist=http://rpms.remirepo.net/enterprise/\$releasever/safe/mirror
enabled=1
gpgcheck=1
gpgkey=http://rpms.remirepo.net/RPM-GPG-KEY-remi
REMISAFE

# install php7 and modules
yum install -y \
  php70 \
  php70-php-fpm \
  php70-php-gd \
  php70-php-json \
  php70-php-mbstring \
  php70-php-mysqlnd \
  php70-php-pdo \
  php70-php-pecl-apcu \
  php70-php-pecl-apcu-bc \
  php70-php-pecl-igbinary \
  php70-php-pecl-imagick \
  php70-php-pecl-redis \
  php70-php-xml

# start php-fpm at boot
systemctl enable php70-php-fpm

# link the systemd service to &quot;php-fpm&quot;
[[ -f /usr/lib/systemd/system/php-fpm.service ]] || ln -s /usr/lib/systemd/system/php70-php-fpm.service /usr/lib/systemd/system/php-fpm.service

# link the binaries
[[ -f /usr/bin/php ]] || ln -s `which php70` /usr/bin/php
[[ -f /usr/bin/php-cgi ]] || ln -s `which php70-cgi` /usr/bin/php-cgi
[[ -f /usr/bin/php-phar ]] || ln -s `which php70-phar` /usr/bin/php-phar

# link the php-fpm configs
[[ -f /etc/php-fpm.conf ]] || ln -s /etc/opt/remi/php70/php-fpm.conf /etc/php-fpm.conf
[[ -d /etc/php-fpm.d ]] || ln -s /etc/opt/remi/php70/php-fpm.d /etc/php-fpm.d

mkdir -p /var/log/php-fpm &amp;&amp; chown -R nginx.nginx /var/log/php-fpm
mkdir -p /var/lib/php/session &amp;&amp; mkdir -p /var/lib/php/wsdlcache &amp;&amp; mkdir -p /var/lib/php/opcache
chown -R nginx.nginx /var/lib/php/*
sed -i -e 's/user = apache/user = nginx/' /etc/php-fpm.d/www.conf
sed -i -e 's/group = apache/group = nginx/' /etc/php-fpm.d/www.conf
sed -i -e 's|/var/opt/remi/php70/log/php-fpm/www-error.log|/var/log/php-fpm/www-error.log|' /etc/php-fpm.d/www.conf
sed -i -e 's|/var/opt/remi/php70/lib/php/session|/var/lib/php/session|' /etc/php-fpm.d/www.conf
sed -i -e 's|/var/opt/remi/php70/lib/php/wsdlcache|/var/lib/php/wsdlcache|' /etc/php-fpm.d/www.conf
sed -i -e 's|/var/opt/remi/php70/lib/php/opcache|/var/lib/php/opcache|' /etc/php-fpm.d/www.conf

NGINX

Install NGINX with HTTP2 support.

# install nginx repo
cat &lt;&lt;REPO &gt; /etc/yum.repos.d/nginx.repo
[nginx]
name=nginx repo
# default repo
#baseurl=http://nginx.org/packages/centos/\$releasever/\$basearch/
# mainline &quot;dev&quot; repo for http2 support
baseurl=http://nginx.org/packages/mainline/centos/\$releasever/\$basearch/
gpgcheck=0
enabled=1
REPO
 
# install and enable nginx
yum install -y nginx
systemctl enable nginx
 
# enable httpd in selinux
semanage permissive -a httpd_t
 
# test your configuration and reload
nginx -t &amp;&amp; service nginx start

Included via symlink in conf.d

Add a bunch of config files for Nginx.

# includes for nginx configurations
mkdir -p /etc/nginx/includes

# ssl settings for virtual hosts
cat &lt;&lt;BLACKLIST &gt; /etc/nginx/includes/blacklist.conf
#  ██████╗ ██╗      █████╗  ██████╗██╗  ██╗██╗     ██╗███████╗████████╗
#  ██╔══██╗██║     ██╔══██╗██╔════╝██║ ██╔╝██║     ██║██╔════╝╚══██╔══╝
#  ██████╔╝██║     ███████║██║     █████╔╝ ██║     ██║███████╗   ██║   
#  ██╔══██╗██║     ██╔══██║██║     ██╔═██╗ ██║     ██║╚════██║   ██║   
#  ██████╔╝███████╗██║  ██║╚██████╗██║  ██╗███████╗██║███████║   ██║   
#  ╚═════╝ ╚══════╝╚═╝  ╚═╝ ╚═════╝╚═╝  ╚═╝╚══════╝╚═╝╚══════╝   ╚═╝   
                                                                    
#-*- mode: nginx; mode: flyspell-prog; ispell-local-dictionary: &quot;american&quot; -*-
### This file implements a blacklist for certain user agents and
### referrers. It's a first line of defense. It must be included
### inside a http block.

## Add here all user agents that are to be blocked.
map \$http_user_agent \$bad_bot {
    default 0;
    ~*^Lynx 0; # Let Lynx go through
    libwww-perl                      1;
    ~*(?i)(httrack|htmlparser|libwww|JikeSpider|proximic|Sosospider|Baiduspider|msnbot|BBBike|WWWOFFLE|Widow|SuperHTTP|BlackWidow|HTTrack|Java|Pixray|CPython|Spinn3r|Abonti|MSIECrawler|Baiduspider|Yandex|Siteimprove|Aboundex|80legs|360Spider|^Java|Cogentbot|^Alexibot|^asterias|^attach|^BackDoorBot|^BackWeb|Bandit|^BatchFTP|^Bigfoot|^Black.Hole|^BlackWidow|^BlowFish|^BotALot|Buddy|^BuiltBotTough|^Bullseye|^BunnySlippers|^Cegbfeieh|^CheeseBot|^CherryPicker|^ChinaClaw|Collector|Copier|^CopyRightCheck|^cosmos|^Crescent|^Custo|^AIBOT) 1;
}

## Add here all referrers that are to blocked.
map \$http_referer \$bad_referer {
  default 0;
  ~*(?i)(adult|babes|click|diamond|forsale|girl|jewelry|love|nudit|organic|poker|porn|poweroversoftware|sex|teen|webcam|zippo|casino|replica|en.savefrom.net|7makemoneyonline.com|acunetix-referrer.com|adcash.com|bithack.ru|buttons-for-website.com|cenokos.ru|cenoval.ru|cityadspix.com|darodar.com|econom.co|edakgfvwql.ru|gobongo.info|iedit.ilovevitaly.com|ilovevitaly.com|ilovevitaly.co|ilovevitaly.info|ilovevitaly.org|ilovevitaly.ru|iskalko.ru|luxup.ru|make-money-online.7makemoneyonline.com|maps.ilovevitaly.com|myftpupload.com|savefrom.net|savetubevideo.com|screentoolkit.com|semalt.com|seoexperimenty.ru|shopping.ilovevitaly.ru|slftsdybbg.ru|socialseet.ru|srecorder.com|st3.cwl.yahoo.com|superiends.org|vodkoved.ru|websocial.me|ykecwqlixx.ru|yougetsignal.com|priceg.com|responsinator.com|o-o-6-o-o.ru|o-o-8-o-o.ru|12masterov.com|4webmasters.org|acads.net|adviceforum.info|affordablewebsitesandmobileapps.com|anal-acrobats.hol.es|anticrawler.org|bard-real.com.ua|best-seo-offer.com|best-seo-solution.com|bestwebsitesawards.com|billiard-classic.com.ua|blackhatworth.com|brakehawk.com|buttons-for-your-website.com|buy-cheap-online.info|buy-forum.ru|cardiosport.com.ua|ci.ua|customsua.com.ua|delfin-aqua.com.ua|dipstar.org|domination.ml|drupa.com|dvr.biz.ua|e-kwiaciarz.pl|este-line.com.ua|europages.com.ru|event-tracking.com|forum20.smailik.org|forum69.info|free-share-buttons.com|free-social-buttons.com|generalporn.org|get-free-traffic-now.com|ghazel.ru|googlsucks.com|guardlink.org|hulfingtonpost.com|humanorightswatch.org|ico.re|iloveitaly.ro|iloveitaly.ru|iminent.com|it-max.com.ua|kabbalah-red-bracelets.com|kambasoft.com|makemoneyonline.com|maridan.com.ua|masterseek.com|mebeldekor.com.ua|med-zdorovie.com.ua|mirobuvi.com.ua|ok.ru|onlywoman.org|o-o-6-o-o.com|palvira.com.ua|pornhub-forum.ga|pornhub-forum.uni.me|prodvigator.ua|ranksonic.info|ranksonic.org|rapidgator-porn.ga|resellerclub.com|sanjosestartups.com|search-error.com|sexyteens.hol.es|shop.xz618.com|simple-share-buttons.com|social-buttons.com|theguardlan.com|trion.od.ua|webmaster-traffic.com|websites-reviews.com|youporn-forum.ga|youporn-forum.uni.me|наркомания.лечениенаркомании.com|непереводимая.рф|floating-share-buttons.com|traffic2money.com|site7.free-floating-buttons.com|sexyali.com|get-free-social-traffic.com|site2.free-floating-buttons.com|success-seo.com|trafficmonetizer.org|chinese-amezon.com|free-social-buttons.com) 1;
}

## Add here all hosts that should be spared any referrer checking.
geo \$bad_referer {
  127.0.0.1 0;
  192.168.1.0/24 0;
  217.23.7.130 0;
  78.110.60.230 0;
  193.227.240.37 0;
  193.227.240.38 0;
}

map \$http_user_agent \$limit_bots {
  default 0;
  ~*(google|bing|yandex|msnbot) 1;
  ~*(AltaVista|Googlebot|Slurp|BlackWidow|Bot|ChinaClaw|Custo|DISCo|Download|Demon|eCatch|EirGrabber|EmailSiphon|EmailWolf|SuperHTTP|Surfbot|WebWhacker) 2;
  ~*(Express|WebPictures|ExtractorPro|EyeNetIE|FlashGet|GetRight|GetWeb!|Go!Zilla|Go-Ahead-Got-It|GrabNet|Grafula|HMView|Go!Zilla|Go-Ahead-Got-It) 2;
  ~*(rafula|HMView|HTTrack|Stripper|Sucker|Indy|InterGET|Ninja|JetCar|Spider|larbin|LeechFTP|Downloader|tool|Navroad|NearSite|NetAnts|tAkeOut|WWWOFFLE) 2;
  ~*(GrabNet|NetSpider|Vampire|NetZIP|Octopus|Offline|PageGrabber|Foto|pavuk|pcBrowser|RealDownload|ReGet|SiteSnagger|SmartDownload|SuperBot|WebSpider) 2;
  ~*(Teleport|VoidEYE|Collector|WebAuto|WebCopier|WebFetch|WebGo|WebLeacher|WebReaper|WebSauger|eXtractor|Quester|WebStripper|WebZIP|Wget|Widow|Zeus) 2;
  ~*(Twengabot|htmlparser|libwww|Python|perl|urllib|scan|Curl|email|PycURL|Pyth|PyQ|WebCollector|WebCopy|webcraw) 2;
}
BLACKLIST

cat &lt;&lt;CLOUDFLARECONF &gt; /etc/nginx/includes/cloudflare.conf
#   ██████╗██╗      ██████╗ ██╗   ██╗██████╗ ███████╗██╗      █████╗ ██████╗ ███████╗
#  ██╔════╝██║     ██╔═══██╗██║   ██║██╔══██╗██╔════╝██║     ██╔══██╗██╔══██╗██╔════╝
#  ██║     ██║     ██║   ██║██║   ██║██║  ██║█████╗  ██║     ███████║██████╔╝█████╗  
#  ██║     ██║     ██║   ██║██║   ██║██║  ██║██╔══╝  ██║     ██╔══██║██╔══██╗██╔══╝  
#  ╚██████╗███████╗╚██████╔╝╚██████╔╝██████╔╝██║     ███████╗██║  ██║██║  ██║███████╗
#   ╚═════╝╚══════╝ ╚═════╝  ╚═════╝ ╚═════╝ ╚═╝     ╚══════╝╚═╝  ╚═╝╚═╝  ╚═╝╚══════╝
                                                                              
set_real_ip_from 199.27.128.0/21;
set_real_ip_from 173.245.48.0/20;
set_real_ip_from 103.21.244.0/22;
set_real_ip_from 103.22.200.0/22;
set_real_ip_from 103.31.4.0/22;
set_real_ip_from 141.101.64.0/18;
set_real_ip_from 108.162.192.0/18;
set_real_ip_from 190.93.240.0/20;
set_real_ip_from 188.114.96.0/20; 
set_real_ip_from 197.234.240.0/22;
set_real_ip_from 198.41.128.0/17;
set_real_ip_from 162.158.0.0/15;
set_real_ip_from 104.16.0.0/12;
set_real_ip_from 172.64.0.0/13;
set_real_ip_from 2400:cb00::/32;
set_real_ip_from 2606:4700::/32;
set_real_ip_from 2803:f800::/32;
set_real_ip_from 2405:b500::/32;
set_real_ip_from 2405:8100::/32;

set_real_ip_from 127.0.0.1;
real_ip_header X-Forwarded-For;
CLOUDFLARECONF

cat &lt;&lt;MIMETYPESCONF &gt; /etc/nginx/includes/mime.types.conf
#  ███╗   ███╗██╗███╗   ███╗███████╗    ████████╗██╗   ██╗██████╗ ███████╗███████╗
#  ████╗ ████║██║████╗ ████║██╔════╝    ╚══██╔══╝╚██╗ ██╔╝██╔══██╗██╔════╝██╔════╝
#  ██╔████╔██║██║██╔████╔██║█████╗         ██║    ╚████╔╝ ██████╔╝█████╗  ███████╗
#  ██║╚██╔╝██║██║██║╚██╔╝██║██╔══╝         ██║     ╚██╔╝  ██╔═══╝ ██╔══╝  ╚════██║
#  ██║ ╚═╝ ██║██║██║ ╚═╝ ██║███████╗       ██║      ██║   ██║     ███████╗███████║
#  ╚═╝     ╚═╝╚═╝╚═╝     ╚═╝╚══════╝       ╚═╝      ╚═╝   ╚═╝     ╚══════╝╚══════╝
                                                                              
types {
  application/x-font-ttf ttf;
  font/opentype otf;
}
MIMETYPESCONF



# use a conf file to include our sites-enabled conf files
mkdir -p /etc/nginx/sites-available
mkdir -p /etc/nginx/sites-enabled
cat &lt;&lt;SITESENABLED &gt; /etc/nginx/includes/sites-enabled.conf
#  ██╗    ██╗███████╗██████╗ ███████╗██╗████████╗███████╗███████╗
#  ██║    ██║██╔════╝██╔══██╗██╔════╝██║╚══██╔══╝██╔════╝██╔════╝
#  ██║ █╗ ██║█████╗  ██████╔╝███████╗██║   ██║   █████╗  ███████╗
#  ██║███╗██║██╔══╝  ██╔══██╗╚════██║██║   ██║   ██╔══╝  ╚════██║
#  ╚███╔███╔╝███████╗██████╔╝███████║██║   ██║   ███████╗███████║
#   ╚══╝╚══╝ ╚══════╝╚═════╝ ╚══════╝╚═╝   ╚═╝   ╚══════╝╚══════╝
                                                                                                                                                             
include /etc/nginx/sites-enabled/*.conf;
SITESENABLED

ln -s /etc/nginx/includes/blacklist.conf /etc/nginx/conf.d/_.blacklist.conf
ln -s /etc/nginx/includes/cloudflare.conf /etc/nginx/conf.d/_.cloudflare.conf
ln -s /etc/nginx/includes/mime.types.conf /etc/nginx/conf.d/_.mime.types.conf
ln -s /etc/nginx/includes/sites-enabled.conf /etc/nginx/conf.d/_.sites-enabled.conf

Included in server block

These Nginx include files are meant to be using inside virtual server blocks.

# ssl settings for virtual hosts
cat &lt;&lt;SSLCONF &gt; /etc/nginx/includes/ssl.conf
#  ███████╗███████╗██╗     
#  ██╔════╝██╔════╝██║     
#  ███████╗███████╗██║     
#  ╚════██║╚════██║██║     
#  ███████║███████║███████╗
#  ╚══════╝╚══════╝╚══════╝
                        
# Use TLS (so don't use old version of SSL)
ssl_protocols TLSv3 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';
ssl_dhparam /etc/ssl/certs/dhparam.pem; 
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_stapling on;
ssl_stapling_verify on;
SSLCONF

# use a conf file to include our sites-enabled conf files
cat &lt;&lt;SECURITY &gt; /etc/nginx/includes/security.conf
#  ███████╗███████╗ ██████╗██╗   ██╗██████╗ ██╗████████╗██╗   ██╗
#  ██╔════╝██╔════╝██╔════╝██║   ██║██╔══██╗██║╚══██╔══╝╚██╗ ██╔╝
#  ███████╗█████╗  ██║     ██║   ██║██████╔╝██║   ██║    ╚████╔╝ 
#  ╚════██║██╔══╝  ██║     ██║   ██║██╔══██╗██║   ██║     ╚██╔╝  
#  ███████║███████╗╚██████╗╚██████╔╝██║  ██║██║   ██║      ██║   
#  ╚══════╝╚══════╝ ╚═════╝ ╚═════╝ ╚═╝  ╚═╝╚═╝   ╚═╝      ╚═╝  

if (\$bad_referer){
  return 444;
}

location ~* (readme|changelog)\\.txt\$ {
  return 444;
}

# don't show this as it can leak info
location ~* /(\\.|(wp-config|xmlrpc)\\.php|(readme|license|changelog)\\.(html|txt)) {
  return 444;
}

location ~ /mu-plugins/ {
  return 444;
}

# no PHP execution in uploads/files
location ~* /(?:uploads|files)/.*\\.php\$ {
  deny all;
}

# hide contents of sensitive files
location ~* \\.(conf|engine|inc|info|install|make|module|profile|test|po|sh|.*sql|theme|tpl(\\.php)?|xtmpl)\$|^(\\..*|Entries.*|Repository|Root|Tag|Template)\$|\\.php_ {
  return 444;
}

# don't allow other executable file types
location ~* \\.(pl|cgi|py|sh|lua)\$ {
  return 444;
}

location = /robots.txt {
  if ( \$limit_bots != 1 ) {
    return 444;
  }
  expires 30d;
  add_header Cache-Control public;
  try_files /robots.txt @shared;
}

location @shared {
  root /var/www/shared;
}
SECURITY

# use a conf file to include our sites-enabled conf files
cat &lt;&lt;WORDPRESSCONF &gt; /etc/nginx/includes/wordpress.conf
#  ██╗    ██╗ ██████╗ ██████╗ ██████╗ ██████╗ ██████╗ ███████╗███████╗███████╗
#  ██║    ██║██╔═══██╗██╔══██╗██╔══██╗██╔══██╗██╔══██╗██╔════╝██╔════╝██╔════╝
#  ██║ █╗ ██║██║   ██║██████╔╝██║  ██║██████╔╝██████╔╝█████╗  ███████╗███████╗
#  ██║███╗██║██║   ██║██╔══██╗██║  ██║██╔═══╝ ██╔══██╗██╔══╝  ╚════██║╚════██║
#  ╚███╔███╔╝╚██████╔╝██║  ██║██████╔╝██║     ██║  ██║███████╗███████║███████║
#   ╚══╝╚══╝  ╚═════╝ ╚═╝  ╚═╝╚═════╝ ╚═╝     ╚═╝  ╚═╝╚══════╝╚══════╝╚══════╝
                                                                           
# include standard security file
include /etc/nginx/includes/security.conf;

# allow CORS for fonts
location ~* \\.(ttf|ttc|otf|eot|woff2?|font.css|css|svg)\$ {
  add_header Access-Control-Allow-Origin *;
}

#Yoast sitemap
location ~ ([^/]*)sitemap(.*)\\.x(m|s)l\$ {
  ## this redirects sitemap.xml to /sitemap_index.xml
  rewrite ^/sitemap\\.xml\$ /sitemap_index.xml permanent;
  ## this makes the XML sitemaps work
  rewrite ^/([a-z]+)?-?sitemap\\.xsl\$ /index.php?xsl=\$1 last;
  rewrite ^/sitemap_index\\.xml\$ /index.php?sitemap=1 last;
  rewrite ^/([^/]+?)-sitemap([0-9]+)?\\.xml\$ /index.php?sitemap=\$1&amp;sitemap_n=\$2 last;
  
  ## The following lines are optional for the premium extensions
  ## News SEO
  rewrite ^/news-sitemap\\.xml\$ /index.php?sitemap=wpseo_news last;
  ## Local SEO
  rewrite ^/locations\\.kml\$ /index.php?sitemap=wpseo_local_kml last;
  rewrite ^/geo-sitemap\\.xml\$ /index.php?sitemap=wpseo_local last;
  ## Video SEO
  rewrite ^/video-sitemap\\.xsl\$ /index.php?xsl=video last;
}

index index.php;

location / {
  try_files \$uri \$uri/ /index.php\$is_args\$args;
}

location ~ ^/(fpm-status|ping)\$ {
  include fastcgi_params;
  fastcgi_pass 127.0.0.1:9000;
  fastcgi_param SCRIPT_FILENAME \$document_root\$fastcgi_script_name;
  break;
}
                                  
location ~ \\.php\$ {
  # zero-day exploit defense.
  try_files \$uri =404;

  # logging vi PHP-FPM
  fastcgi_intercept_errors on;

  # pass request to fastcgi/php-cgi via spawn-fcgi
  fastcgi_pass unix:/var/run/php-fpm.sock;

  # default fastcgi_params
  include fastcgi_params;

  # max timeouts (should match php.ini)
  fastcgi_connect_timeout 600s;
  fastcgi_send_timeout 600s;
  fastcgi_read_timeout 600s;

  # override fastcgi_params
  fastcgi_param SERVER_NAME \$host;
  fastcgi_param SCRIPT_FILENAME \$document_root\$fastcgi_script_name;

  break;
}

location ~ /purge(/.*) {
  #fastcgi_cache_purge WORDPRESS &quot;\$scheme\$request_method\$host\$1&quot;;
}
WORDPRESSCONF

HTTPS Virtual Host

This is an example of a virtual host running Wordpress.

# use a conf file to include our sites-enabled conf files
cat &lt;&lt;VIRTUALHOST &gt; /etc/nginx/sites-available/virtualhost.conf
server {
  # Domain validation is on port 80
  listen 80;
 
  # Hostnames to listen on, you will pass each of these to letsencrypt with &quot;-w www.example.com&quot;
  server_name www.example.com;
  
  # Your document root, you will pass this path to letsencrypt with &quot;-w /var/www/www.example.com/html/&quot;
  root /var/www/www.example.com/html/;
  
  # handle letsencrypt domain validation
  location ~ /.well-known {
      allow all;
  }
  
  # permanently redirect everything else
  location / {
    return 301 https://$server_name$request_uri;
  }
}
    
server {
  # All SSL is served on 443. If available include &quot;http2&quot;, otherwise remove it.
  listen 443 ssl http2;

  # Hostnames to listen on
  server_name www.example.com;

  # Add SSL Keys here once they are generated
  #ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
  #ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

  include /etc/nginx/includes/ssl.conf;
  
  # Wordpress Sites
  # include /etc/nginx/includes/wordpress.conf;
  # include /var/www/www.example.com/html/nginx.conf;

  # handle all requests...
  # location / {
  # }
}
VIRTUALHOST

# link the virtual host using full pathnames for source and target!
# ln -s /etc/nginx/sites-available/virtualhost.conf /etc/nginx/sites-enabled/virtualhost.conf

nginx -t &amp;&amp; service nginx reload

Generating Barcodes


yum install -y barcode barcode-devel php-tcpdf.noarch
cd /usr/local/src
wget https://ashberg.de/php-barcode/download/files/genbarcode-0.4.tar.gz
tar -xzvf genbarcode-0.4.tar.gz
cd genbarcode-0.4
make &amp;&amp; make install

# use to generate via php
wget https://ashberg.de/php-barcode/download/files/php-barcode-0.4.tar.gz

Conversation 3

BrunoDecember 7, 2016
Excelente artigo Justin Silver. Parabéns e continue produzindo conteúdo ricos de informação e relevantes.
Joshua HauptFebruary 28, 2018
This is absolutely beautiful! Thank you so much for posting these scripts.
Joshua HauptFebruary 28, 2018
The CloudFlare IP list your have appears to be out of date. Here is the link to the latest one: https://www.cloudflare.com/ips/