Install WordPress

WordPress is one of the most popular blogging platforms. It is a free, open-source software package developed in PHP by the WordPress Foundation. Over the years, so many plugins and add-ons have been developed for WordPress that it has become somewhat more of a content management system (CMS) than just a blogging platform. This article covers installing WordPress to a LEMP web server set up according this site's series of articles, which can be reviewed in the Steps to create a UNPM Server.

WordPress can be installed to a website's root directory or to a sub-directory, referred to as  in this article. Installing to a subdirectory allows for using subdomains such as  http://blog.example.com  and for having a non-WordPress landing page for the website.

Create package-configs files
Create the  files   and  :

username@servername:~$ sudo nano /etc/nginx/package-configs/wordpress.conf

Add the following:

location /blog/ { try_files $uri $uri/ /blog/index.php?$args; location ~* ^/wp-content/uploads/.*.(html|htm|shtml|php)$ { types { } default_type text/plain; }    location ~ (index|wp-comments-post|xmlrpc|wp-tinymce).*\.php$ { include global-configs/php.conf; }    location ~ wp-cron.php$ { allow ; deny all; include global-configs/php.conf; }    location ~ ^/wp-admin/includes/ { return 403; }    location ~ ^/wp-includes/theme-compat/ { return 403; }    location ~ \.php$ { deny all; } }

The  directive setting will allow for 'pretty' URLs to work in WordPress.

The  file is necessary for WordPress to function properly, but it is not required that the file be publicly accessible. The  should be the server's IP address. Note that WordPress will use an IPv6 address when one is assigned to the server. Check the  file to determine if one is assigned to the server. Also check the error logs regularly to determine if  or any other php file is being blocked when using and logging into WordPress.

Now create the corresponding https version:

username@servername:~$ sudo nano /etc/nginx/package-configs/wordpress_https.conf

Add the following:

location /blog/ { try_files $uri $uri/ /blog/index.php?$args; location ~* ^/wp-content/uploads/.*.(html|htm|shtml|php)$ { types { } default_type text/plain; }     location ~ (index|wp-comments-post|wp-login|xmlrpc|wp-tinymce|update-core|edit|post-new|edit-tags|post|profile|media-new|user-new|upload|edit-comments|comment|themes|customize|widgets|nav-menus|theme-install|plugins|admin|users|user-edit|tools|import|export|options-general|options-writing|options-reading|options-discussion|options-media|options-permalinks|media-upload|setup-config|install).*\.php$ { include global-configs/php_https.conf; }    location ~ wp-cron.php$ { allow ; deny all; include global-configs/php_https.conf; }    location ~ ^/wp-admin/includes/ { return 403; }    location ~ ^/wp-includes/theme-compat/ { return 403; }    location ~ \.php$ { deny all; } }

The configuration passes only the specific php files necessary to PHP-FPM for WordPress to function. If a page fails to load correctly, check for errors in  and add blocked php files to the include statement in the above configuration file.

Edit sites-available file
Open the sites-available file for the domain:

username@servername:~$ sudo nano /etc/nginx/sites-available/example.com

In the HTTP server block, add:

include package-configs/wordpress.conf;

In the HTTPS server block, add:

include package-configs/wordpress_https.conf;

Test and Restart nginx
Test and reload nginx.

username@servername:~$ sudo nginx -t nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful username@servername:~$ sudo service nginx reload

Serving WordPress from the root directory
The WordPress package makes it very easy to serve WordPress from the  directory of a site, even when the package itself has been installed to the   directory. Create two new  files, identical to the other WordPress files except for the addition of a new   block:

username@servername:~$ sudo nano /etc/nginx/package-configs/wordpress_root.conf

Add:

location ~ index.php$ { include global-configs/php.conf; } location /blog/ { try_files $uri $uri/ /blog/index.php?$args; location ~* ^/wp-content/uploads/.*.(html|htm|js|shtml|php)$ { types { } default_type text/plain; }    location ~ (index|wp-comments-post|xmlrpc|wp-tinymce).*\.php$ { include global-configs/php.conf; }    location ~ wp-cron.php$ { allow ; deny all; include global-configs/php.conf; }    location ~ ^/wp-admin/includes/ { return 403; }    location ~ ^/wp-includes/theme-compat/ { return 403; }    location ~ \.php$ { deny all; } }

username@servername:~$ sudo nano /etc/nginx/package-configs/wordpress_root_https.conf

Add:

location ~ index.php$ { include global-configs/php_https.conf; } location /blog/ { try_files $uri $uri/ /blog/index.php?$args; location ~* ^/wp-content/uploads/.*.(html|htm|js|shtml|php)$ { types { } default_type text/plain; }    location ~ (index|wp-comments-post|wp-login|xmlrpc|wp-tinymce|update-core|edit|post-new|edit-tags|post|profile|media-new|user-new|upload|edit-comments|comment|themes|customize|widgets|nav-menus|theme-install|plugins|admin|users|user-edit|tools|import|export|options-general|options-writing|options-reading|options-discussion|options-media|options-permalinks|media-upload|setup-config|install).*\.php$ { include global-configs/php_https.conf; }    location ~ wp-cron.php$ { allow ; deny all; include global-configs/php_https.conf; }    location ~ ^/wp-admin/includes/ { return 403; }    location ~ ^/wp-includes/theme-compat/ { return 403; }    location ~ \.php$ { deny all; } }

username@servername:~$ sudo nano /etc/nginx/sites-available/example.com

In the HTTP section, change:

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

In the HTTPS section, change:

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

Alternatively, if just one site on the server is expected to be the only one serving WordPress from the root directory, the  block added in the   files can be added to the respective   block.

Create WordPress database and database user
Create a WordPress database and database user:

username@servername:~$ sudo mysql -uroot -p MariaDB [(none)]> create database databasename default character set utf8 default collate utf8_general_ci; MariaDB [(none)]> grant all on databasename.* to 'databasenameusername'@'localhost' identified by 'databasenameusernamepassword'; MariaDB [(none)]> exit

Note that the,   and   will be required for the WordPress configuration process.

Install WordPress
Download and extract the latest version of WordPress.

username@servername:~$ wget https://wordpress.org/latest.zip username@servername:~$ unzip -d /var/www/example.com/public/ latest.zip username@servername:~$ mv /var/www/example.com/public/wordpress /var/www/example.com/public/blog username@servername:~$ rm latest.zip username@servername:~$ find /var/www/example.com/public/blog/ -type d | xargs -d '\n' chmod 775 username@servername:~$ find /var/www/example.com/public/blog/ -type f | xargs -d '\n' chmod 664 username@servername:~$ sudo chown -R www-data /var/www/example.com/public/blog/

Navigate to secure  https://www.example.com/blog/wp-admin/install.php  and follow the WordPress installation setup.

Securing WordPress
Edit :

username@servername:~$ nano /var/www/example.com/public/blog/wp-config.php

Note that if WordPress is installed to the root directory,  would be used.

Above the line that reads, add:

// Require https login define('FORCE_SSL_ADMIN', true); // Prevent editing php files from dashboard define('DISALLOW_FILE_EDIT', true);

forces the dashboard to always load through an encrypted session.

prevents editing of PHP files from within WordPress, a potential security threat.

Serve WordPress from the root directory
To serve WordPress from the site's  directory, copy   to the   directory and make one small edit:

username@servname:~$ cp /var/www/example.com/public/blog/index.php /var/www/example.com/public username@servname:~$ nano /var/www/example.com/public/index.php

Change:

require( dirname( __FILE__ ) . '/blog/wp-blog-header.php' );

Through the WordPress dashboard, navigate to Settings->General and change 'Site Address (URL)' to  http://www.example.com .

Pretty URLs
From the WordPress dashboard, navigate to Settings->Permalinks and select the radio button 'Day and name', which is probably the most popular configuration of pretty URLs (/%year%/%monthnum%/%day%/%postname%/).

WordPress caching
Caching will allow WordPress to perform considerably faster while reducing server load.

Install APC Object Cache Backend and Batcache
Download the plugin files directly to the  directory:

username@servername:~$ wget -O /var/www/example.com/public/blog/wp-content/object-cache.php https://plugins.svn.wordpress.org/apc/tags/2.0.6/object-cache.php username@servername:~$ wget -O /var/www/example.com/public/blog/wp-content/advanced-cache.php https://plugins.svn.wordpress.org/batcache/tags/1.4/advanced-cache.php username@servername:~$ sudo chown www-data /var/www/example.com/public/blog/wp-content/{object-cache.php,advanced-cache.php}

Enable caching in
Edit :

username@servername:~$ nano /var/www/example.com/public/blog/wp-config.php

Above the line that reads, add:

// Enable caching define('WP_CACHE', true);

Verify caching works
Navigate to a blog page in a browser session that is not logged into WordPress and refresh the page several times. In the page source should be a message similar to:

generated 13 seconds ago generated in 0.047 seconds served from batcache in 0.000 seconds expires in 287 seconds

WYSIWYG editor blank
Occasionally, installs of WordPress will result in a WYSIWYG editor that appears to not function, though it is actually functioning with white letters on a white background, and the buttons above the editor will not be present. If this happens, add  above   in the   file.

Plugins
It is generally beyond the scope of this article to discuss plugins, though there are a few useful plugins which are generally desired by many users.

Security
The most common vectors for attack against WordPress come from old plugins. The WordPress.org plugin pages even warn users when a plugin has not been updated for over 2 years.

Another common vector is to brute force WordPress login sites. Installing a plugin such as Login Security can reduce the success rate of such attacks.

Hackers can uncover login names by navigating to  http://www.example.com/?author=1  and then brute force those names. To mask this location,, the WP Author Slug plugin may be used. Just be sure that the user's username and nickname are not the same.

Akismet
Akismet is an anti-spam tool that is invaluable for sites that allow comments. It does require a WordPress.com user account to use and will report some site statistics back to WordPress.com.

Minileven
Minileven is a mobile theme developed for WordPress.com and made available to individual WordPress installations through the Jetpack plugin by WordPress.com. To use this plugin, the server must integrate WordPress.com and will report back various statistics to them. For those not desiring to connect their servers to WordPress.com, it is still possible to install the theme. Install and enable the Jetpack plugin, then through the plugin Activate the Mobile Theme (Minileven), then disable the plugin. Add the Minileven theme to WordPress:

username@servername:~$ cp -r /var/www/example.com/public/blog/wp-content/plugins/jetpack/modules/minileven/theme/pub/minileven/ /var/www/example.com/public/blog/wp-content/themes/ username@servername:~$ sudo chown -R www-data /var/www/example.com/public/blog/wp-content/themes/

Even though the plugin is disabled, WordPress will still notify through the dashboard of when the plugin has an update. After each update, copy the directory again to update Minleven, but note that the location of Minileven in the Jetpack plugin directory will change from time to time.

To accompany Minileven, install the Device Theme Switcher plugin to tell WordPress which theme to serve to which devices.

Analytics tools
Piwik is a powerful open source web analytics tool that can run on a server without using any outside services. Integrating Piwik into WordPress is easy with plugins such as WP Analytics Tracking, a very simple plugin to paste tracking code (including the  image tracking code) into a field which the plugin then adds to all WordPress pages.

Change default email sender
By default, WordPress will use the address of wordpress@example.com with the name WordPress</tt> to send emails from. This can be changed through a number of methods, but perhaps the simplest is to add a statement to the  file used by themes. For this to work, the code will have to be added to the  file for every theme used by the site, and added again after a theme is upgraded.

username@servername:~$ nano /var/www/example.com/public/blog/wp-content/themes/themename/functions.php

Paste at the bottom of the file:

/** changing default wordpress email settings */ add_filter('wp_mail_from', 'new_mail_from'); add_filter('wp_mail_from_name', 'new_mail_from_name'); function new_mail_from($old) { return 'address@example.com'; } function new_mail_from_name($old) { return 'emailname'; }

Set return-path
When the  and   headers do not match, emails will be labeled as "via example.com" by major email providers, and it may be impossible to pass DMARC tests.

A simple way to fix this is to install the WH Tweaks plugin and enable the "Set the Return-Path if not already set when sending mail through WordPress." in the plugin options.