Title: Hardening and speeding up a Wordpress blog
Slug: hardening-and-speeding-up-a-wordpress-blog
Date: 2011-09-02 07:13:00
Author: Kartones
Lang: en
Tags: Security, PHP, Development, Wordpress
Description: Tips on how to optimize and secure a Wordpress blog.

 <p>PHP is a fast scripted language, but when you build any reasonably sized website there are always optimizations and tricks you can do to make it go faster. Wordpress is no exception, and sometimes the extensibility, ease of customization and plugin framework it provides add overhead to the page loading time (and internal use of resources).</p> <p>Also, Wordpress has a certain fame of not being too secure, having security bugs from time to time, so reinforcing the blog security is never a bad idea.</p> <p>With this post I will provide a few points to improve both areas. Some like disabling login errors come from google searches and I can't remember the source (there are many results), others are my personal findings and <a href="http://codex.wordpress.org/">Wordpress Codex</a> readings.</p> <p> </p> <p>All of this changes can be easily done either to the <b>functions.php</b> file of your theme. If the file doesn't exists feel free to create it, Wordpress will always check for it and parse it before rendering the page, or to the theme files in the case of literal substitutions and similar modifications.</p> <p> </p> <p>On the <b>security</b> side:</p> <ul> <li>Disable PHP error reporting &amp; display  <p><font face="Courier New">ini_set('display_errors', 0);<br>ini_set('error_reporting', 0);</font></p> </li><li>Remove Wordpress version from &lt;meta&gt;. This way if a critical security bug appears (which is not uncommon with WP) you don't give clues to possible attackers of if your blog is vulnerable or not.<br><font face="Courier New">remove_action('wp_head', 'wp_generator');</font> <br> </li><li>Disable login errors. Do not output if the username was correct but not the password. Just say "login failed".<br><font face="Courier New">add_filter('login_errors', create_function('$a', "return null;"));</font> <br> </li><li>Want to filter user login to a specific IP? Add the following function with the desired address:</li> <p><font face="Courier New">function CheckLoginIP($user, $username, $password) {<br>    return $_SERVER['REMOTE_ADDR'] == '192.168.1.1' ? get_userdatabylogin($username) : null;<br>}<br>add_filter('authenticate', 'CheckLoginIP', 10, 3);</font></p></ul> <p> </p> <p>On the <b>performance</b> side:</p> <ul> <li>Remove the <a href="http://en.wikipedia.org/wiki/Really_Simple_Discovery">RSD</a> &lt;meta&gt; if you don't need it or use the inline editor. Remember that this metas are sent on every request, so it's a few more bytes wasted.<br><font face="Courier New">remove_action('wp_head', 'rsd_link');</font> <br> </li><li>Remove the <a href="http://explore.live.com/windows-live-writer">Windows Live Writer</a> &lt;meta&gt; if you don't use that tool.<br><font face="Courier New">remove_action('wp_head', 'wlwmanifest_link');</font> <br> </li><li>Not using multilanguage and have a static design/theme that you don't plan to change more? Remove all _e() calls and place instead the literals.<br>Change this: <font face="Courier New">&lt;div&gt;&lt;?php _e( 'Archives', 'twentyeleven' ); ?&gt;&lt;/div&gt;<br></font>To this: <font face="Courier New">&lt;div&gt;Archives&lt;/div&gt;<br></font> </li><li>Don't want all the admin dashboard widgets? Remove those you don't fancy.  <p><font face="Courier New">function remove_dashboard_widgets(){<br>    global $wp_meta_boxes;<br>    unset($wp_meta_boxes['dashboard']['normal']['core']['dashboard_incoming_links']);<br>    unset($wp_meta_boxes['dashboard']['side']['core']['dashboard_recent_drafts']);<br>}<br>add_action('wp_dashboard_setup', 'remove_dashboard_widgets');</font></p> </li><li>If you don't have any strange hook for the header and footer rendering, using <font face="Courier New">get_header();</font> <font face="Courier New">get_footer();</font> and the like add some hook checks, file presence checks, backwards compatibility checks... and at the end by default they do a require_once (which by design and by logic shouldn't be ever created twice and thus is not needed).<br>So, you can squeeze more CPU cycles by using this code for template loading instead:<br><font face="Courier New">load_template(TEMPLATEPATH . '/header.php', false);<br>load_template(TEMPLATEPATH . '/sidebar.php', false);<br>load_template(TEMPLATEPATH . '/footer.php', false);</font><br> </li><li>You can replace some calls that refer to your app path by their value if your domain is not going to change. For example:<br><font face="Courier New">&lt;link rel="stylesheet" type="text/css" media="all" href="&lt;?php bloginfo( 'stylesheet_url' ); ?&gt;" /&gt;</font><br>If the domain is going to be fixed (and the statics file path), why not placing the href directly?<br> </li><li>Why not leverage some caching plugin? <a href="http://www.google.com/search?q=wordpress+cache+plugins">There are many</a>, and if you want a custom made one, is also <a href="https://blog.kartones.net/post/building-a-simple-cache-system-for-wordpress-3-0">easy to develop</a> </li></ul>
