
Having a WordPress website is often great, but it also makes you vulnerable for all kinds of attacks and mischief – Or maybe not vulnerable, but it invites many wrong doers to try and attack you. You’re an easy target. Let’s make it a bit less easy for them!
Recently I’ve been plagued on another website by slowness, the occasional downtime and other annoying stuff. Paying more attention to usage stats and the error_log it turns out there was a bunch of stuff going on. A few of IP Addresses constantly tried something with wp-login.php and some other pages and files being loaded over and over again for no apparent reason.
Another issue was the RSS feed WordPress generates. Sure, it works fine. But if you get almost 10000+ requests on it per hour, that’ll slow things down, too. Sometimes.
So I did some research and have come up with a few things to try and prevent this kind of behavior. Of-course it’s no use blocking IP addresses but you can prevent access to things or if they access those things lessen the load on your server a great deal.
Note: In this article we’ll edit a few files essential to your WordPress site. Namely the .htaccess file and wp-config.php. Doing this wrong will cause your site to malfunction in one way or another. So be sure you make a backup of these files before doing anything. If you’re not comfortable editing such files or you’re not sure how any of this works ask someone to help you!
.htaccess file
The .htaccess file is not a WordPress file, but an important file none-the-less. It allows you to manipulate the server configuration without actually changing the server. This file allows for advanced control over who access what and in which way. This file is therefor very important to your website and server.
wp-config.php file
This is the main configuration file for WordPress. Without it, WordPress doesn’t know what WordPress is. Your login details to the database are in here, as well as security salts and you can manipulate advanced settings and variables here.
Here are 6 ways to keep your WordPress website safer and more faster without using plugins. Because plugins slow your site down as well.
1. Protect your dashboard
Because WordPress is so visible there is a high chance you experience this too. People trying to log in to your site. The occasional dumbass trying a common password on the Admin account is no big deal, but bots and botnets trying this all day long, hundreds of times per hour. That IS a problem.
So to counter this I use the following plugin to hide my dashboard from the world – WPS Hide Login.
Simply set a different login name, something other than
wp-login.php
or
wp-admin
and the intrusions should stop.
2. Use Browser caching
When you visit a site, part of it is downloaded and stored locally on your computer. To be deleted after you leave the site. From your server you can ask the browser to keep certain files for a longer period of time. For example common scripts or images, because they don’t change anyway. This saves bandwidth and requests on your server. Making your site load faster, but also reducing server load to some extent.
I’ve added these rules to my .htaccess file, above all the Rewrite rules stuff from Item 1 and 2. So right at the top of the file.
# Use UTF-8 encoding for anything served text/plain or text/html
AddDefaultCharset UTF-8
AddCharset UTF-8 .atom .css .js .json .rss .vtt .xml
# FileETag None is not enough for every server.
Header unset ETag
FileETag None
# Send CORS headers if browsers request them; enabled by default for images.
SetEnvIf Origin ":" IS_CORS
Header set Access-Control-Allow-Origin "*" env=IS_CORS
# Allow access to web fonts from all domains.
Header set Access-Control-Allow-Origin "*"
Header unset Pragma
Header append Cache-Control "public"
Header unset Last-Modified
# Cache Control
ExpiresActive on
ExpiresDefault "access plus 1 month"
# cache.appcache needs re-requests in FF 3.6
ExpiresByType text/cache-manifest "access plus 0 seconds"
# Your document html
ExpiresByType text/html "access plus 0 seconds"
# Data
ExpiresByType text/xml "access plus 0 seconds"
ExpiresByType application/xml "access plus 0 seconds"
ExpiresByType application/json "access plus 0 seconds"
# Feed
ExpiresByType application/rss+xml "access plus 1 hour"
ExpiresByType application/atom+xml "access plus 1 hour"
# Favicon (cannot be renamed)
ExpiresByType image/x-icon "access plus 1 week"
# Media: images, video, audio
ExpiresByType image/gif "access plus 1 month"
ExpiresByType image/png "access plus 1 month"
ExpiresByType image/jpg "access 1 year"
ExpiresByType image/jpeg "access 1 year"
ExpiresByType video/ogg "access plus 1 month"
ExpiresByType audio/ogg "access plus 1 month"
ExpiresByType video/mp4 "access plus 1 month"
ExpiresByType video/webm "access plus 1 month"
# HTC files (css3pie)
ExpiresByType text/x-component "access plus 1 month"
# Webfonts
ExpiresByType application/x-font-ttf "access plus 1 month"
ExpiresByType font/opentype "access plus 1 month"
ExpiresByType application/x-font-woff "access plus 1 month"
ExpiresByType application/x-font-woff2 "access plus 1 month"
ExpiresByType image/svg+xml "access plus 1 month"
ExpiresByType application/vnd.ms-fontobject "access plus 1 month"
# CSS and JavaScript
ExpiresByType text/css "access plus 1 year"
ExpiresByType application/javascript "access plus 1 year"
# Add correct content-type for fonts
AddType application/vnd.ms-fontobject .eot
AddType font/ttf .ttf
AddType font/otf .otf
AddType font/x-woff .woff
AddType image/svg+xml .svg
# Add a far future Expires header for fonts
ExpiresByType application/vnd.ms-fontobject "access plus 1 year"
ExpiresByType font/ttf "access plus 1 year"
ExpiresByType font/otf "access plus 1 year"
ExpiresByType font/x-woff "access plus 1 year"
ExpiresByType image/svg+xml "access plus 1 year"
3. Gzip Compression
Gzip compression compresses the contents of your site when it’s sent to the browser. This reduces bandwidth and makes your site appear faster. Most modern browsers support this these days and most servers do, too.
I’ve added this to the .htaccess file right below the Browser Caching stuff of the previous item.
# Gzip compression
SetOutputFilter DEFLATE
# Force deflate for mangled headers
SetEnvIfNoCase ^(Accept-EncodXng|X-cept-Encoding|X{15}|~{15}|-{15})$ ^((gzip|deflate)\s*,?\s*)+|[X~-]{4,13}$ HAVE_Accept-Encoding
RequestHeader append Accept-Encoding "gzip,deflate" env=HAVE_Accept-Encoding
# Don’t compress images and other uncompressible content
SetEnvIfNoCase Request_URI \
\.(?:gif|jpe?g|png|rar|zip|exe|flv|mov|wma|mp3|avi|swf|mp?g|mp4|webm|webp)$ no-gzip dont-vary
# Compress all output labeled with one of the following MIME-types
AddOutputFilterByType DEFLATE application/atom+xml application/javascript application/json application/rss+xml application/vnd.ms-fontobject application/x-font-ttf application/xhtml+xml application/xml font/opentype image/svg+xml image/x-icon text/css text/html text/plain text/x-component text/xml
Header append Vary: Accept-Encoding
# Compress compressible fonts
AddOutputFilterByType DEFLATE font/ttf font/otf image/svg+xml
4. Increase the memory limit
Giving WordPress a little more wiggle room can be a good thing. Many hosting providers limit websites to 64MB ram or something similar. Sometimes you can configure this in your hosting dashboard (cPanel, Plesk or whatever). Often times you can not. That doesn’t mean you can’t change the memory limit.
In your wp-config.php, around line 52 (below the salts) I’ve added this line:
define('WP_MEMORY_LIMIT', '192M');
This ups the memory to 192MB. Similar to PC memory, this lets PHP do more stuff at the same time and work a little faster. This is more useful for larger sites, such as this one, or for sites with many plugins or if you use large plugins such as WooCommerce. For a basic, low traffic blog you probably won’t notice a difference.
Note: Increasing memory is fine, but only if you need it, upping the limit because your site is a unoptimized pile of junk code is not a valid reason of-course.
5. Disable WP-Cron
WP-Cron is a system where WordPress deals with background tasks. Plugins and themes can use this for all kinds of stuff. My AdRotate plugin, for example, cleans up stats through it. And my Analytics Spam Blocker plugin downloads new blocklists using wp-cron.
That’s all fine and useful, but does it need to run on every page load? Probably not. However, that’s kinda how wp-cron works. Every time someone accesses your website, wp-cron is triggered and checks if there’s something to do in the background.
In wp-config.php right below the salts, where we added the memory limit from the Item 5 I’ve added this:
define('DISABLE_WP_CRON', 1);
This disables wp-cron. Removing the line, or changing the 1 to 0, enables it again.
To schedule a real cron job you’ll have to log in to your hosting dashboard and schedule one there. Sometimes this is called simply ‘Scheduled tasks’, sometimes it’s called ‘Tasks’ or just ‘Cron Jobs’.
Schedule the job for whatever interval you want. This can be every minute to every hour, or even daily or weekly. It’s up to you really. I have mine set to every 15 minutes.
And for the command, you simply call:
http://www.YOURDOMAIN.com/wp-cron.php?doing_wp_cron
.
In cPanel, for my hosting, I use something like this:
wget -q -O - 'https://example.com/wp-cron.php?doing_wp_cron' >/dev/null 2>&1
If you find this article useful, I’ve written an updated version in 2023: Protect and Speed up your WordPress website.
