Difference between revisions of "WordPress"

From Jon's Wiki
Line 3: Line 3:
 
== Optimise PHP ==
 
== Optimise PHP ==
  
See the [[PHP]] page.
+
Use PHP-FPM and use the Opcache. See the [[PHP]] page.
  
 
== Cache all the things ==
 
== Cache all the things ==

Revision as of 19:32, 11 October 2021

WordPress is popular, feature-rich and useful, despite the awful spaghetti state of its PHP code. It is also slow, without a bunch of extra help. Luckily we can speed it up and lock it all down pretty well as follows.

Optimise PHP

Use PHP-FPM and use the Opcache. See the PHP page.

Cache all the things

WordPress is slow. Install and configure WP Super Cache to make it go much faster. Also, configure Apache to gzip all the static assets and use a long cache expiry time.

Allow user-installed plugins and themes

I do not recommend it, but if you're game you can enable WordPress users with admin access to install their own plugins and themes by allowing write access to wp-content/{plugins,themes} and configuring as follows:

# in wp-config.php
define('FS_METHOD', 'direct');

The obvious disadvantage to this approach is you lose control of what god-awful unaudited third-party code they might install.

It is however useful as a temporary measure when starting out, and once the website is nearing a stable production-ready state, you can audit it all, and switch back to maintaining the selection of themes and plugins separately (e.g. in git, using submodules, or using wp-cli on the server) and disallowing user installs.

WP CLI

Use wp-cli, a really useful tool for managing WordPress sites from the command line. Once downloaded you can keep it updated with:

wp cli update

Use SSL

Use Letsencrypt to enforce HTTPS everywhere and dehydrated to maintain the SSL certificate, and use the latest Mozilla SSL Guideline from their configurator to set up strong SSL.

Content security

Use a content security policy. There is a plugin for managing one from within WordPress, but it is straightforward to cobble one and add it to the headers. Here's an example content security policy that allows JavaScript, images and CSS from only certain origins, and denies everything else:

Header always set Content-Security-Policy "base-uri 'self';
     default-src 'none'; media-src 'self';
     connect-src 'self' https://*.wp.com wss://public-api.wordpress.com https://api.stripe.com
         https://checkout.stripe.com;
     font-src 'self' data: https://*.wp.com https://wordpress.com https://fonts.googleapis.com
         https://fonts.gstatic.com;
     form-action 'self';
     frame-ancestors 'self';
     frame-src 'self' https://jetpack.wordpress.com https://*.wp.com https://www.google.com
         https://*.stripe.com https://player.vimeo.com https://www.youtube.com
         https://www.surveymonkey.com;
     img-src 'self' data: https://*.tile.openstreetmap.org https://*.gravatar.com https://*.wp.com
         https://*.wordpress.com https://s.w.org https://maps.googleapis.com https://maps.gstatic.com
         https://q.stripe.com https://secure.surveymonkey.com;
     script-src 'self' 'unsafe-inline' 'unsafe-eval' https://widget.surveymonkey.com https://*.wp.com
         https://public-api.wordpress.com https://*.stripe.com https://maps.googleapis.com
         https://ajax.googleapis.com;
     style-src 'self' 'unsafe-inline' https://*.wp.com https://ajax.googleapis.com
         https://fonts.googleapis.com;"

Other headers can be used to further enforce some secure behaviour:

Header always set X-Content-Type-Options "nosniff"
Header always set X-XSS-Protection "1; mode=block"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
Header always set Access-Control-Allow-Origin "*"

Some more security hardening

There's a lot of written material out there. but for a start, as suggested by WPScan, prevent DDoS attacks on web-accessible cron and XMLRPC endpoints, but allow CLI invocation, and prevent execution of uploaded PHP content:

<Files "xmlrpc.php">
    Require ip 127
</Files>
<Files "wp-cron.php">
    Require ip 127
</Files>
RedirectMatch 404 "/readme\.html"

<Location "/wp-content/uploads">
    SetHandler none
    RedirectMatch 404 ".+\.php"
 </Location>

Do you need an online shop?

Do you need to pay $50 a month to Shopify or any of the other pay-through-the-nose shop services? No. Unless you are actually running some giant operation or department store, you can do it yourself for free in WordPress. You will need:

I have certainly found it sufficiently useful for a small non-profit selling merchandise, a community orchestra selling tickets, or a home business flogging chilli sauce.

If your phone has a NFC chip, then the Stripe app will also let you use your phone as a mobile EFTPOS machine that accepts credit cards for when you're out and about, and there is also a handy WooCommerce app that lets you track orders and sales from the website.