How To Host Multiple WordPress Sites On Ubuntu 16.04, NGINX, PHP7-FPM – Part 1

This tutorial sets up a single WordPress installation on a server with the option of adding more websites later.

First, setup your Ubuntu server.

Super-fast Secure WordPress Install on DigitalOcean with NGINX, PHP7, and Ubuntu 16.04 LTS
http://www.morphatic.com/2016/05/21/super-fast-secure-wordpress-install-on-digitalocean-with-nginx-php7-and-ubuntu-16-04-lts/

1. Configure Your Domain Name

First, create your droplet, see here:
https://www.digitalocean.com/community/tutorials/how-to-create-your-first-digitalocean-droplet-virtual-server

Next, login to the site where you registered your domain name and change the nameservers to point to:

  1. ns1.digitalocean.com
  2. ns2.digitalocean.com
  3. ns3.digitalocean.com

Then, go to your DigitalOcean account and go to Networking > Domains. In the form to “Add a Domain” enter your domain name and then select the droplet you created.

We will setup our domain to route email through Mailgun’s servers (free accounts available with no credit card needed). To configure your domain in DigitalOcean, see here:
https://www.digitalocean.com/community/tutorials/how-to-set-up-a-host-name-with-digitalocean

When all done, your settings should look something like this (using Mailgun’s servers):
http://code.krister.ee/mailgun-digitalocean/

2. Install NGINX

$ sudo sh -c "echo 'deb http://download.opensuse.org/repositories/home:/rtCamp:/EasyEngine/xUbuntu_16.04/ /' >> /etc/apt/sources.list.d/nginx.list"

sudo apt-get update

$ sudo apt-get install nginx-custom

$ sudo ufw allow 'Nginx Full'

$ sudo ufw enable

update settings in ‘nginx.conf’ by commenting out all lines in the ‘SSL Settings’ section by putting ‘#’ in from of them (these will conflict with some of the settings we create later):

sudo nano /etc/nginx/nginx.conf

after you have done this, it should look like this:

 ##
        # SSL Settings
        ##

        #ssl_session_cache shared:SSL:20m;
        #ssl_session_timeout 10m;
        #ssl_prefer_server_ciphers on;
        #ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:$
        #ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

CTRL-X to save, then ‘Y’ and ENTER to exit.

3. Install MariaDB

see MySQL vs MariaDB

$ sudo apt-get install software-properties-common
$ sudo apt-key adv --recv-keys --keyserver hkp://keyserver.ubuntu.com:80 0xF1656F24C74CD1D8
$ sudo add-apt-repository 'deb [arch=amd64,i386] http://sfo1.mirrors.digitalocean.com/mariadb/repo/10.1/ubuntu xenial main'
$ sudo apt-get update
$ sudo apt-get install mariadb-server

Set a password for MariaDB (recommended to use a different password than your user/root account).

Next:

$ sudo mysql_secure_installation

Enter ‘no’ when asked to change password (since we just setup a new one) and ‘yes’ to the rest of the prompts.

Login to MariaDB

$ mysql -u root -p

Create a new database, user and assign privileges to the user (replace ‘mydbname’, username and password with something strong, keep apostrophes in place):

MariaDB [(none)]> CREATE DATABASE mydbname DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci;
MariaDB [(none)]> GRANT ALL ON mydbname.* TO 'username'@'localhost' IDENTIFIED BY 'securepassword';
MariaDB [(none)]> FLUSH PRIVILEGES;
MariaDB [(none)]> quit

enter ‘exit’ to exit MariaDB

4. Install PHP7-FPM

$ sudo apt-get install -y php-fpm php-mysql php-xml php-gd php7.0-zip 

Adjust php settings:

$ sudo nano /etc/php/7.0/fpm/php.ini

enter CTRL +W to access search function and type ‘cgi.fix_pathinfo’. Where you see the line ‘cgi.fix_pathinfo=1’, uncomment the line (by deleting the semicolon) and edit as follows:

cgi.fix_pathinfo=0

Enter CTRL +W again and search for ‘post_max_size’ and change this value to whatever size you would like. Do the same for ‘upload_max_filesize’:

post_max_size = 100M

upload_max_filesize = 200M

CTRL-X to save, then ‘Y’ and ENTER to exit.

Restart php:

$ sudo service php7.0-fpm restart

Create a new configuration file for our site (replace yourdomain.com with your domain name and you can also create and add the code below using WinSCP instead of the command line):

$ sudo nano /etc/nginx/sites-available/yourdomain.com

Copy/paste the code below into the file (replace site.com with your domain name):

server {
        listen 80 default_server;
        listen [::]:80 default_server;

        root /var/www/yourdomain.com/html;
        index index.php index.html;

        server_name _;

        location / {
                try_files $uri $uri/ =404;
        }

        location ~ \.php$ {
                include snippets/fastcgi-php.conf;
                fastcgi_pass unix:/run/php/php7.0-fpm.sock;
        }

        location ~ /\.ht {
                deny all;
        }
}

Ctrl-X, ‘Y’, then ‘ENTER’ to save and exit.

Delete the default configuration for NGINX (I always make a backup of this file just in case. Using WinSCP, just drag-and-drop ‘default’ to a local directory):

$ sudo rm etc/nginx/sites-available/default

restart NGINX:

$ sudo service nginx restart

test changes by creating a php file at the root of the web server:

$ echo "<?php phpinfo();" | sudo tee /var/www/yourdomain.com/html/index.php > /dev/null

Next, go to your web browser and type your server url, http://yourdomain.com and you should see the auto-generated PHP info page.

5. Setup SSL Certificates with LetsEncrypt

https://www.digitalocean.com/community/tutorials/how-to-secure-nginx-with-let-s-encrypt-on-ubuntu-16-04

$ sudo apt-get install letsencrypt

Edit the NGINX configuration file:

$ sudo nano /etc/nginx/sites-available/yourdomain.com

Add some extra code to the NGINX configuration file so that the entire file looks like this (I find it easier to edit the code using WinSCP instead of using the command line):

server {
        listen 80 default_server;
        listen [::]:80 default_server;

        root /var/www/yourdomain.com/html;
        index index.php index.html;

        server_name _;

        location / {
                try_files $uri $uri/ =404;
        }

        location ~ \.php$ {
                include snippets/fastcgi-php.conf;
                fastcgi_pass unix:/run/php/php7.0-fpm.sock;
        }
	
	location ~ /.well-known {
                allow all;
        }

        location ~ /\.ht {
                deny all;
        }
	
}

note that we just added the lines below just before the last location code:

location ~ /.well-known {
                allow all;
        }

CTRL-X to save, then ‘Y’ and ENTER to exit.

check to make sure the NGINX syntax is correct:

$ sudo nginx -t

you should see something like:

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

restart NGINX:

$ sudo service nginx restart

Install the LetsEncrypt certificate (replace site.com with your domain name):

$ sudo letsencrypt certonly -a webroot --webroot-path=/var/www/yourdomain.com/html -d yourdomain.com -d www.yourdomain.com

Enter an email address and accept the license.

If everything works OK, you should see something like this:

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at
   /etc/letsencrypt/live/yourdomain.com/fullchain.pem. Your cert
   will expire on 2017-01-22. To obtain a new version of the
   certificate in the future, simply run Let's Encrypt again.
 - If you like Let's Encrypt, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le

To increase security, DigitalOcean’s tutorial recommends setting up a strong Diffie-Hellman Group as follows:

$ sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048

Next, we create a configuration file that contains all of our SSL parameters:

$ sudo nano /etc/nginx/snippets/ssl-params.conf

Then, add this code into the file:

# code below from https://cipherli.st/
# and https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
ssl_ecdh_curve secp384r1;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";
add_header X-Frame-Options SAMEORIGIN;
add_header X-Content-Type-Options nosniff;

ssl_dhparam /etc/ssl/certs/dhparam.pem;

CTRL-X to save, then ‘Y’ and ENTER to exit.

Next we will update our NGINX configuration for our site again to redirect all traffic through HTTPS (replace site.com with your domain name):

$ sudo nano /etc/nginx/sites-available/yourdomain.com

edit the file to look like this (replace site.com with your domain name):

server {
        listen 80 default_server;
        listen [::]:80 default_server;
        server_name yourdomain.com www.yourdomain.com;
        return 301 https://yourdomain.com$request_uri;
}

server {
        listen 443 ssl http2 default_server;
        listen [::]:443 ssl http2 default_server;
        include snippets/ssl-params.conf;

        root /var/www/yourdomain.com/html;
        index index.php index.html;

        server_name yourdomain.com www.yourdomain.com;

        location / {
                try_files $uri $uri/ =404;
        }

        location ~ \.php$ {
                include snippets/fastcgi-php.conf;
                fastcgi_pass unix:/run/php/php7.0-fpm.sock;
        }

        location ~ /.well-known {
                allow all;
        }

        location ~ /\.ht {
                deny all;
        }
}

CTRL-X to save, then ‘Y’ and ENTER to exit.

check to make sure the NGINX syntax is correct:

$ sudo nginx -t

then, restart NGINX:

$ sudo service nginx restart

SSL certificates from LetsEncrypt expire every 90 days. So that you don’t have to log into your server every 3 months to renew your certs, we set up a CRON job to autorenew them:

$ sudo crontab -e

You will be prompted to select an editor, select ‘2’ (nano):

Then add the following lines at the bottom after the commented section:

30 2 * * 1 /usr/bin/letsencrypt renew >> /var/log/le-renew.log
35 2 * * 1 /bin/systemctl reload nginx

CTRL-X to save, then ‘Y’ and ENTER to exit.

This will update the LetsEncrypt client and then attempt to renew and load your certs (if necessary) every Monday.

6. Install WordPress

First, we will install Subversion:

$ sudo apt-get install -y subversion

Then, go to web root directory, remove index.php (if necessary), and note the most recent version of WordPress:

$ cd /var/www/html
$ sudo rm index.php
$ sudo svn co http://core.svn.wordpress.org/tags/4.6.1 .

note the ‘.’ (period) at the end of the last command.

Then, update the ownership of the files:

$ sudo chown -R www-data:www-data .

again, note the ‘.’ (period) at the end of the command.

Now you can visit your domain in a web browser and complete the installation by following the WordPress prompts. Note the database name and user that you created in step 3.

7. Installing WordPress plugins and setting up email.

First install the nginx helper plugin. After logging in to the WP admin panel, go to Plugins > Add New, and in the ‘Search Plugins’ box enter ‘nginx plugin helper’. Click ‘Install Now’ and once completed, click ‘Activate’.

Then, go to Settings > Nginx Helper from the WP dashboard and check the box to “Enable Purge.” The default settings should be fine. Click ‘Save All Changes’.

From Step 1 above, we will use the Mailgun for WordPress plugin.

Go to Plugins > Add New, and in the ‘Search Plugins’ box enter ‘mailgun’. Click ‘Install Now’ and once completed, click ‘Activate’.

Then, go to Settings > Mailgun in the WP dashboard and copy/paste in your Mailgun domain name and API key, then click ‘Save Changes’. Click ‘Test Configuration’ to make sure it is working. You can also use the Check Email plugin just to make sure that emails are being sent correctly.

Inside of your Mailgun dashboard, you may have to go to Domains > yourDomainName, go down the page ‘Security Settings For Outgoing Mail’, click ‘Certificate Verification’ and select ‘Not Required’ (‘TLS Connection’ should already be set to ‘Opportunistic’).


Optional: To allow updates of WordPress without FTP, add this line to the ‘wp-config’ file right before the line ‘That’s all, stop editing!’:

/** auto update without FTP */
define('FS_METHOD','direct');

alternatively, if you would like to only allow file downloads through FTPS, see this post:
http://www.morphatic.com/2016/05/21/super-fast-secure-wordpress-install-on-digitalocean-with-nginx-php7-and-ubuntu-16-04-lts/


8. Optimizing WordPress

Setup caching and purging. Edit NGINX configuration file, replace ‘site.com’ and ‘www.site.com’ with your domain name:

$ sudo nano /etc/nginx/sites-available/yourdomain.com

then copy/paste this in (deleting all other code):

 server {
        listen 80 default_server;
        listen [::]:80 default_server;
        server_name yourdomain.com www.yourdomain.com;
        return 301 https://yourdomain.com$request_uri;
}
 
server {
        listen 443 ssl http2 default_server;
        listen [::]:443 ssl http2 default_server;
        include snippets/ssl-yourdomain.com.conf;
        include snippets/ssl-params.conf;
 
        client_max_body_size 256M;
        root /var/www/yourdomain.com/html;
        index index.php index.html;
 
        server_name yourdomain.com www.yourdomain.com;
 
        set $skip_cache 0;
        if ($request_method = POST) {
                set $skip_cache 1;
        }
        if ($query_string != "") {
                set $skip_cache 1;
        }
        if ($request_uri ~* "/wp-admin/|/xmlrpc.php|wp-.*.php|/feed/|index.php|sitemap(_index)?.xml") {
                set $skip_cache 1;
        }
        if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_no_cache|wordpress_logged_in") {
                set $skip_cache 1;
        }
        autoindex off;
        location ~ /purge(/.*) {
                fastcgi_cache_purge WORDPRESS "$scheme$request_method$host$1";
        }
        location ~* ^.+\.(flv|pdf|avi|mov|mp3|wmv|m4v|webm|aac|ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|css|rss|atom|js|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf)$ {
                expires max;
                log_not_found off;
                access_log off;
        }
 
        location / {
                try_files $uri $uri/ /index.php?$args;
        }
 
        location ~ \.php$ {
                include snippets/fastcgi-php.conf;
                fastcgi_pass unix:/run/php/php7.0-fpm.sock;
                fastcgi_cache_bypass $skip_cache;
                fastcgi_no_cache $skip_cache;
                fastcgi_cache WORDPRESS;
                fastcgi_cache_valid 60m;
                include fastcgi_params;
        }
 
        location ~* ^/wp-includes/.*(?<!(js/tinymce/wp-tinymce))\.php$ {
                internal;
        }
 
        location = /robots.txt {
                access_log off;
                log_not_found off;
        }
 
        location = /wp-config.php {
                deny all;
        }
 
        location ~* /(?:uploads|files)/.*\.php$ {
                deny all;
        }
 
        location ~* ^/wp-content/.*\.(txt|md|exe|sh|bak|inc|php|pot|po|mo|log|sql)$ {
                deny all;
        }

        location ~ /.well-known {
                allow all;
        }

        location ~ /\.(ht|svn)? {
                deny all;
        }
 

}

CTRL-X to save, then ‘Y’ and ENTER to exit.

Edit nginx.conf

$ sudo nano /etc/nginx/nginx.conf

Copy the code below:

fastcgi_cache_path /var/run/nginx-cache levels=1:2 keys_zone=WORDPRESS:100m 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;

And paste into the top of the ‘http’ section, right above ‘EasyEngine Settings’. The beginning of the file should look like this:

user www-data;
worker_processes auto;
worker_rlimit_nofile 100000;
pid /run/nginx.pid;

events {
        worker_connections 4096;
        multi_accept on;
}

http {
        fastcgi_cache_path /var/run/nginx-cache levels=1:2 keys_zone=WORDPRESS:100m 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;
	
        ##
        # EasyEngine Settings
        ##
	
        sendfile on;
        tcp_nopush on;
        tcp_nodelay on;
        keepalive_timeout 30;
        types_hash_max_size 2048;
… … do not edit the rest of the lines of code … …

CTRL-X to save, then ‘Y’ and ENTER to exit.

Enable unattended upgrades:

$ sudo nano /etc/apt/apt.conf.d/50unattended-upgrades

uncomment these lines (delete the forward slashes in beginning of the line) and change values where necessary:

"${distro_id}:${distro_codename}-updates";

Unattended-Upgrade::Mail "admin@yourdomain.com";

Unattended-Upgrade::Remove-Unused-Dependencies "false";

Unattended-Upgrade::Automatic-Reboot "true";

Unattended-Upgrade::Automatic-Reboot-Time "02:00";

Complete file looks like this:

// Automatically upgrade packages from these (origin:archive) pairs
Unattended-Upgrade::Allowed-Origins {
	"${distro_id}:${distro_codename}-security";
	"${distro_id}:${distro_codename}-updates";
//	"${distro_id}:${distro_codename}-proposed";
//	"${distro_id}:${distro_codename}-backports";
};

// List of packages to not update (regexp are supported)
Unattended-Upgrade::Package-Blacklist {
//	"vim";
//	"libc6";
//	"libc6-dev";
//	"libc6-i686";
};

// This option allows you to control if on a unclean dpkg exit
// unattended-upgrades will automatically run 
//   dpkg --force-confold --configure -a
// The default is true, to ensure updates keep getting installed
//Unattended-Upgrade::AutoFixInterruptedDpkg "false";

// Split the upgrade into the smallest possible chunks so that
// they can be interrupted with SIGUSR1. This makes the upgrade
// a bit slower but it has the benefit that shutdown while a upgrade
// is running is possible (with a small delay)
//Unattended-Upgrade::MinimalSteps "true";

// Install all unattended-upgrades when the machine is shuting down
// instead of doing it in the background while the machine is running
// This will (obviously) make shutdown slower
//Unattended-Upgrade::InstallOnShutdown "true";

// Send email to this address for problems or packages upgrades
// If empty or unset then no email is sent, make sure that you
// have a working mail setup on your system. A package that provides
// 'mailx' must be installed. E.g. "user@example.com"
Unattended-Upgrade::Mail "admin@yourdomain.com";

// Set this value to "true" to get emails only on errors. Default
// is to always send a mail if Unattended-Upgrade::Mail is set
//Unattended-Upgrade::MailOnlyOnError "true";

// Do automatic removal of new unused dependencies after the upgrade
// (equivalent to apt-get autoremove)
Unattended-Upgrade::Remove-Unused-Dependencies "true";

// Automatically reboot *WITHOUT CONFIRMATION*
//  if the file /var/run/reboot-required is found after the upgrade 
Unattended-Upgrade::Automatic-Reboot "true";

// If automatic reboot is enabled and needed, reboot at the specific
// time instead of immediately
//  Default: "now"
Unattended-Upgrade::Automatic-Reboot-Time "02:00";

// Use apt bandwidth limit feature, this example limits the download
// speed to 70kb/sec
//Acquire::http::Dl-Limit "70";

CTRL-X to save, then ‘Y’ and ENTER to exit.

Then,

sudo nano /etc/apt/apt.conf.d/10periodic

edit the file to look like this:

PT::Periodic::Update-Package-Lists "1";
APT::Periodic::Download-Upgradeable-Packages "0";
APT::Periodic::AutocleanInterval "7";
APT::Periodic::Unattended-Upgrade "1";

CTRL-X to save, then ‘Y’ and ENTER to exit.

Finally,

$ sudo apt-get update
$ sudo apt-get upgrade
$ sudo apt-get autoclean
$ sudo reboot

9. Installing phpMyAdmin

Some code taken from here, but edited for PHP7-FPM / Ubuntu 16.04:
https://www.digitalocean.com/community/tutorials/how-to-install-and-secure-phpmyadmin-with-nginx-on-an-ubuntu-14-04-server

$ sudo apt-get install phpmyadmin

During the installation, you will be prompted for some information. It will ask you which web server you would like the software to automatically configure. Since Nginx, the web server we are using, is not one of the available options, you can just hit TAB to bypass this prompt.

The next prompt will ask if you would like dbconfig-common to configure a database for phpmyadmin to use. Select “Yes” to continue.

You will need to enter the database administrative password that you configured during the MariaDB installation to allow these changes. Afterward, you will be asked to select and confirm a password for a new database that will hold ~phpMyAdmin’s own data.

We need to address is enabling the mcrypt PHP module, which phpMyAdmin relies on. This was installed with phpMyAdmin so we just need to toggle it on and restart our PHP processor:

sudo apt-get install mcrypt php7.0-mcrypt
sudo service php7.0-fpm restart

The installation will now complete. For the Nginx web server to find and serve the ~phpMyAdmin files correctly, we just need to create a symbolic link from the installation files to our Nginx document root directory by typing this:

sudo ln -s /usr/share/phpmyadmin /usr/share/nginx/html

the above was the recommended method but did not work – when I went to mydomain.com/phpmyadmin only mydomain.com displayed. The solution was found somewhere in the comments, below the section referenced here:
https://www.digitalocean.com/community/tutorials/how-to-install-and-secure-phpmyadmin-with-nginx-on-an-ubuntu-14-04-server?comment=36631

the solution was:

sudo ln -s /usr/share/phpmyadmin /var/www/html

Now let’s make this more secure. We will change the location of the interface from /phpmyadmin to something else to sidestep some of the automated bot brute-force attempts. We will also create an additional, web server-level authentication gateway that must be passed before even getting to the phpMyAdmin login screen. Change ‘nothingtosee’ to anything you want.

cd /var/www/html

sudo mv phpmyadmin nothingtosee

Now to go to phpmyadmin, you must go to https://site.com/nothingtosee

Next we add an authentication prompt that a user would be required to pass before ever seeing the phpMyAdmin login screen.

We first will create a password file that will store our the authentication credentials. Nginx requires that passwords be encrypted using the crypt() function. The OpenSSL suite, which should already be installed on your server, includes this functionality.

To create an encrypted password, type:

openssl passwd

above command produces errors.

Solution:
https://www.digitalocean.com/community/tutorials/how-to-set-up-password-authentication-with-nginx-on-ubuntu-14-04

You can add a username to the file using this command, you can use whatever name you like:

$ sudo sh -c "echo -n 'username:' >> /etc/nginx/.htpasswd"

Next, add an encrypted password entry for the username by typing:

sudo sh -c "openssl passwd -apr1 >> /etc/nginx/.htpasswd"

You can repeat this process for additional usernames. You can see how the usernames and encrypted passwords are stored within the file by typing:

$ cat /etc/nginx/.htpasswd

output is something like:

username:$apr1$wI1/T0nB$j... ...

Next, we need to configure Nginx to check this file before serving our protected content.

$ sudo nano /etc/nginx/sites-enabled/default

You can set restrictions on the server level or inside a specific location. We use the auth_basic directive to turn on authentication and to choose a realm name to be displayed to the user when prompting for credentials. We will use the auth_basic_user_file directive to point Nginx to the password file we created and restrict our phpmyadmin folder/link that we created above ‘nothingtosee’:
https://www.scalescale.com/tips/nginx/protect-directory-user-password-nginx/

location ^~ /nothingtosee/ {
				auth_basic "Restricted Content";
				auth_basic_user_file /etc/nginx/.htpasswd;
					location ~ .php$ {
						root /var/www/yourdomain.com;}
    }

Now the directory is password protected. the entire file looks like this:

fastcgi_cache_path /var/run/nginx-cache levels=1:2 keys_zone=WORDPRESS:100m 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;

server {
        listen 80 default_server;
        listen [::]:80 default_server;
        server_name yourdomain.com www.yourdomain.com;
        return 301 https://$server_name$request_uri;
}

server {
        listen 443 ssl http2 default_server;
        listen [::]:443 ssl http2 default_server;
        include snippets/ssl-params.conf;

        client_max_body_size 256M;
        root /var/www/html;
        index index.php index.html;

        server_name yourdomain.com www.yourdomain.com;

        set $skip_cache 0;
        if ($request_method = POST) {
                set $skip_cache 1;
        }
        if ($query_string != "") {
                set $skip_cache 1;
        }
        if ($request_uri ~* "/wp-admin/|/xmlrpc.php|wp-.*.php|/feed/|index.php|sitemap(_index)?.xml") {
                set $skip_cache 1;
        }
        if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_no_cache|wordpress_logged_in") {
                set $skip_cache 1;
        }
        autoindex off;
        location ~ /purge(/.*) {
                fastcgi_cache_purge WORDPRESS "$scheme$request_method$host$1";
        }
        location ~* ^.+\.(flv|pdf|avi|mov|mp3|wmv|m4v|webm|aac|ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|css|rss|atom|js|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf)$ {
                expires max;
                log_not_found off;
                access_log off;
        }

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

        location ~ \.php$ {
                include snippets/fastcgi-php.conf;
                fastcgi_pass unix:/run/php/php7.0-fpm.sock;
                fastcgi_cache_bypass $skip_cache;
                fastcgi_no_cache $skip_cache;
                fastcgi_cache WORDPRESS;
                fastcgi_cache_valid 60m;
                include fastcgi_params;
        }

        location ~* ^/wp-includes/.*(?<!(js/tinymce/wp-tinymce))\.php$ {
                internal;
        }

        location = /robots.txt {
                access_log off;
                log_not_found off;
        }

        location = /wp-config.php {
                deny all;
        }

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

        location ~* ^/wp-content/.*\.(txt|md|exe|sh|bak|inc|php|pot|po|mo|log|sql)$ {
                deny all;
        }
        location ~ /\.(ht|svn)? {
                deny all;
        }

        location ~ /.well-known {
                allow all;
        }
		
	location ^~ /nothingtosee/ {
		auth_basic "Restricted Content";
		auth_basic_user_file /etc/nginx/.htpasswd;
			location ~ .php$ {
				root /var/www/yourdomain.com;}
    }

}

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.