Try Tuts+ Premium, Get Cash Back!
20 Steps to a Flexible and Secure WordPress Installation
basix

20 Steps to a Flexible and Secure WordPress Installation

Tutorial Details
  • Topic: WordPress
  • Difficulty: Easy
  • Estimated Completion Time: 20-30 minutes

A comprehensive WordPress installation, albeit simple to produce, often requires multiple steps — many of which can easily be omitted accidentally. How many times have you forgotten to customize your permalink structure? How about adding in a sitemap plugin? What about changing your timezone? If you’ve installed WordPress more than once, chances are you’ve missed something. Take the following steps and you’ll never miss anything again.

Tutorial now on Wptuts+

Step 1: Get WordPress from SVN

The number one mistake for a flexible WordPress installation happens right from the get-go. I’ve seen numerous developers manually download, unzip, and upload WordPress to their site. This is not only a waste of time, but it also reduces flexibility.

If you download WordPress from SVN, all you need to do is run the following in command-line:

svn co http://core.svn.wordpress.org/tags/3.0 .

Maybe you want the latest developer version. That’s even simpler:

svn co http://core.svn.wordpress.org/trunk/ .

Why is this so useful? For starters, all it takes is one command. Looking at WordPress in a long-term perspective reveals that SVN also provides the simplest, hassle-free way to update to a new stable version (or even downgrade). For example, let’s say you want to update to version 3.0. All you need to do is run the SVN switch command:

svn sw http://core.svn.wordpress.org/tags/3.0/ .

How easy was that? Note that if you’re using the developer version, updating is even easier:

svn up

That’s all it takes. If you ever need the URL to a new stable version repository, visit the WordPress Codex. You can also find full instructions on using SVN there.

“Looking at WordPress in a long-term perspective reveals that SVN also provides the simplest, hassle-free way to update to a new stable version (or even downgrade).”


Step 2: Secure .svn Directories

Directory

Now that you’re using SVN, you must ensure that your .svn directories are protected from the public. One main reason lies in the .svn/entries file, which can give out sensitive information to attackers. For further information regarding this subject, please take a look at Smashing Magazine’s article on the SVN server admin issue.

To secure .svn directories using .htaccess, just apply the following redirect rule:

RewriteRule ^(.*/)?.svn/ - [F,L]

Step 3: Create wp-config.php

As outlined in the famous 5-minute WordPress installation, you’ll need to rename wp-config-sample.php to wp-config.php and add in your database information.


Step 4: Add a Unique Database Prefix and Authentication Keys

Keys

Leaving your wp-config.php file only with database information and no other configuration is a security issue. Make sure to generate authentication keys, as outlined in the comments. To do so, visit https://api.wordpress.org/secret-key/1.1/salt/ and copy-paste the randomly-created keys into the file.

Note that you should also change the default WordPress database table prefix. This is to secure your installation against hacks, such as the recent outbreak of the Pharma Hack. Visit random.org to generate a random prefix string which you’ll need to set as the $table_prefix in wp-config.php. In addition, make sure to add an underscore at the end of the prefix.


Step 5: Install Using wp-admin/install.php

As usual, visit wp-admin/install.php in your browser and follow the instructions. When filling out the form, change the default administrator username (“admin”) in order to increase security. Note that most attackers will target a WordPress installation with default settings. Thus, changing this username is a must.

“Note that most attackers will target a WordPress installation with default settings.”


Step 6: Remove wp-admin/install.php

This is a commonly-omitted step which only takes a few seconds to execute. Simply remove the wp-admin/install.php script after installing WordPress for further security.


Step 7: Login to the Dashboard and Complete User Profile

Login to your WordPress installation at http://example.com/wp-admin, click your username in the top-right corner, and fill out your user profile.


Step 8: Edit Tagline and Timezone

Timezone

Under the Settings > General tab, make sure to edit your blog’s timeline as well as timezone.


Step 9: Review Writing, Reading, and Discussion Settings

Although you might not have to change anything, looking over Settings > Writing, Settings > Reading, and Settings > Discussion is always a good idea. Ensure that the configuration meets your standards.


Step 10: Change Permalink Structure

Permalink

A default WordPress installation comes with query-string permalinks that look like http://example.com/?p=1 for each article. Not only is this not search-engine friendly, but it’s also not even human-friendly. Change this to a permalink structure that contains the title of the post (%postname% if you’re using a custom configuration).


Step 11: Add .htaccess Rules

An .htaccess file is necessary for your WordPress site to function correctly. To begin, turn on the RewriteEngine:

RewriteEngine On

Disable directory listings for security purposes:

Options -Indexes

Add/Remove www to prevent content duplication (replace example.com with your domain):

# Add www (change www.example.com to example.com to remove www)
RewriteCond %{HTTP_HOST} !^www.example.com$ [NC]
RewriteRule ^(.*)$ http://www.example.com/$1 [R=301,L]

WordPress requires you to redirect all non-files and directories to index.php:

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . index.php [PT]

Disable ETags:

Header unset ETag
FileETag None

Suppress PHP errors (note that this might not work on all hosts):

php_flag display_startup_errors off
php_flag display_errors off
php_flag html_errors off
php_value docref_root 0
php_value docref_ext 0

Control caching on files to speed up your site:

ExpiresActive On
ExpiresDefault A0
<FilesMatch ".(gif|jpg|jpeg|png|swf)$">
# 2 weeks
ExpiresDefault A1209600
Header append Cache-Control "public"
</FilesMatch>
<FilesMatch ".(xml|txt|html)$">
# 2 hours
ExpiresDefault A7200
Header append Cache-Control "proxy-revalidate"
</FilesMatch>
<FilesMatch ".(js|css)$">
# 3 days
ExpiresDefault A259200
Header append Cache-Control "proxy-revalidate"
</FilesMatch>

Secure the .htaccess file:

<Files .htaccess>
 Order Allow,Deny
 Deny from all
</Files>

Secure the wp-config.php file:

<Files wp-config.php>
 Order Deny,Allow
 Deny from all
</Files>

Secure .svn directories, as explained in step #2:

RewriteRule ^(.*/)?.svn/ - [F,L]

If you would like to add more configuration for your website and are looking for a general tutorial, consider Nettuts’ Ultimate Guide to htaccess Files or Stupid htaccess Tricks on Perishable Press.


Step 12: Use gzip

Gzip

Applying gzip can compress text files up to 80% and greatly save bandwidth. Making it active on your site only requires a PHP file and a bit of .htaccess. Note that the following code is referenced from a gzip tutorial on Lateral Code.

PHP (gzip.php):

<?php
	if( isset( $_SERVER['HTTP_ACCEPT_ENCODING'] ) && substr_count( $_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip' ) && !preg_match( '/(load-styles|load-scripts).php/', $_SERVER[ 'SCRIPT_NAME' ] ) )
		ob_start( 'ob_gzhandler' );
	else
		ob_start();
?>

This may look a bit daunting at first, but it really isn’t too bad. The large boolean expression checks whether gzip is available and, if so, it’s applied. Unfortunately, I have found that this gzip method doesn’t function well with WordPress’ load-styles.php and load-scripts.php. As a result, the preg_match is used to exclude them.

.htaccess:

<FilesMatch ".js$">
AddHandler application/x-httpd-php .js
php_value default_mimetype "text/javascript"
</FilesMatch>
<FilesMatch ".css$">
AddHandler application/x-httpd-php .css
php_value default_mimetype "text/css"
</FilesMatch>
<FilesMatch ".(htm|html|shtml)$">
AddHandler application/x-httpd-php .html
php_value default_mimetype "text/html"
</FilesMatch>
php_value auto_prepend_file /absolute/path/to/gzip.php

This snippet adds the php handler to .html, .css, and .js files so that they can be gzipped. It also prepends the previously mentioned gzip.php file. Make sure to change /absolute/path/to/gzip.php to the correct path.


Step 13: Apply the 4G Blacklist

Perishable Press’ 4G Blacklist will prevent numerous attacks on your website through .htaccess. I’ve included the code below (edited for WordPress). You can learn about how it works by reading the article on Perishable Press:

### PERISHABLE PRESS 4G BLACKLIST ###

# ESSENTIALS
RewriteEngine on
ServerSignature Off
Options All -Indexes
Options +FollowSymLinks

# FILTER REQUEST METHODS
<IfModule mod_rewrite.c>
 RewriteCond %{REQUEST_METHOD} ^(TRACE|DELETE|TRACK) [NC]
 RewriteRule ^(.*)$ - [F,L]
</IfModule>

# BLACKLIST CANDIDATES
<Limit GET POST PUT>
 Order Allow,Deny
 Allow from all
 Deny from 75.126.85.215   "# blacklist candidate 2008-01-02 = admin-ajax.php attack "
 Deny from 128.111.48.138  "# blacklist candidate 2008-02-10 = cryptic character strings "
 Deny from 87.248.163.54   "# blacklist candidate 2008-03-09 = block administrative attacks "
 Deny from 84.122.143.99   "# blacklist candidate 2008-04-27 = block clam store loser "
 Deny from 210.210.119.145 "# blacklist candidate 2008-05-31 = block _vpi.xml attacks "
 Deny from 66.74.199.125   "# blacklist candidate 2008-10-19 = block mindless spider running "
 Deny from 203.55.231.100  "# 1048 attacks in 60 minutes"
 Deny from 24.19.202.10    "# 1629 attacks in 90 minutes"
</Limit>

# QUERY STRING EXPLOITS
<IfModule mod_rewrite.c>
 RewriteCond %{QUERY_STRING} ../    [NC,OR]
 RewriteCond %{QUERY_STRING} boot.ini [NC,OR]
 RewriteCond %{QUERY_STRING} tag=     [NC,OR]
 RewriteCond %{QUERY_STRING} ftp:     [NC,OR]
 RewriteCond %{QUERY_STRING} http:    [NC,OR]
 RewriteCond %{QUERY_STRING} https:   [NC,OR]
 RewriteCond %{QUERY_STRING} mosConfig [NC,OR]
# RewriteCond %{QUERY_STRING} ^.*([|]|(|)|<|>|'|"|;|?|*).* [NC,OR]
# RewriteCond %{QUERY_STRING} ^.*(%22|%27|%3C|%3E|%5C|%7B|%7C).* [NC,OR]
 RewriteCond %{QUERY_STRING} ^.*(%0|%A|%B|%C|%D|%E|%F|127.0).* [NC,OR]
 RewriteCond %{QUERY_STRING} ^.*(globals|encode|localhost|loopback).* [NC,OR]
 RewriteCond %{QUERY_STRING} ^.*(request|select|insert|union|declare|drop).* [NC]
 RewriteRule ^(.*)$ - [F,L]
</IfModule>

# CHARACTER STRINGS
<IfModule mod_alias.c>
 # BASIC CHARACTERS
 RedirectMatch 403 ,
 RedirectMatch 403 :
 RedirectMatch 403 ;
# RedirectMatch 403 =
 RedirectMatch 403 @
 RedirectMatch 403 [
 RedirectMatch 403 ]
 RedirectMatch 403 ^
 RedirectMatch 403 `
 RedirectMatch 403 {
 RedirectMatch 403 }
 RedirectMatch 403 ~
 RedirectMatch 403 "
 RedirectMatch 403 $
 RedirectMatch 403 <
 RedirectMatch 403 >
 RedirectMatch 403 |
 RedirectMatch 403 ..
# RedirectMatch 403 //
 RedirectMatch 403 %0
 RedirectMatch 403 %A
 RedirectMatch 403 %B
 RedirectMatch 403 %C
 RedirectMatch 403 %D
 RedirectMatch 403 %E
 RedirectMatch 403 %F
 RedirectMatch 403 %22
 RedirectMatch 403 %27
 RedirectMatch 403 %28
 RedirectMatch 403 %29
 RedirectMatch 403 %3C
 RedirectMatch 403 %3E
# RedirectMatch 403 %3F
 RedirectMatch 403 %5B
 RedirectMatch 403 %5C
 RedirectMatch 403 %5D
 RedirectMatch 403 %7B
 RedirectMatch 403 %7C
 RedirectMatch 403 %7D
 # COMMON PATTERNS
 Redirectmatch 403 _vpi
 RedirectMatch 403 .inc
 Redirectmatch 403 xAou6
 Redirectmatch 403 db_name
 Redirectmatch 403 select(
 Redirectmatch 403 convert(
 Redirectmatch 403 /query/
 RedirectMatch 403 ImpEvData
 Redirectmatch 403 .XMLHTTP
 Redirectmatch 403 proxydeny
 RedirectMatch 403 function.
 Redirectmatch 403 remoteFile
 Redirectmatch 403 servername
 Redirectmatch 403 &rptmode=
 Redirectmatch 403 sys_cpanel
 RedirectMatch 403 db_connect
 RedirectMatch 403 doeditconfig
 RedirectMatch 403 check_proxy
 Redirectmatch 403 system_user
 Redirectmatch 403 /(null)/
 Redirectmatch 403 clientrequest
 Redirectmatch 403 option_value
 RedirectMatch 403 ref.outcontrol
 # SPECIFIC EXPLOITS
 RedirectMatch 403 errors.
# RedirectMatch 403 config.
 RedirectMatch 403 include.
 RedirectMatch 403 display.
 RedirectMatch 403 register.
 Redirectmatch 403 password.
 RedirectMatch 403 maincore.
 RedirectMatch 403 authorize.
 Redirectmatch 403 macromates.
 RedirectMatch 403 head_auth.
 RedirectMatch 403 submit_links.
 RedirectMatch 403 change_action.
 Redirectmatch 403 com_facileforms/
 RedirectMatch 403 admin_db_utilities.
 RedirectMatch 403 admin.webring.docs.
 Redirectmatch 403 Table/Latest/index.
</IfModule>

A few of these rules are commented out or edited because they interfere with WordPress. If you are having problems with certain URLs, fix them by prepending a “#” (comment) to the corresponding rule.


Step 14: Activate Akismet

“Activating Akismet is a must in order to prevent comment spam.”

Activating Akismet is a must in order to prevent comment spam. Do so by registering for an API key at akismet.com. Note that a WordPress.com account API key will also work.

Once you obtain a key, visit Plugins > Akismet Configuration in your dashboard and paste it in the corresponding box.


Step 15: Download Plugins

Plugins

The following plugins are a great help to any WordPress blog:

For further security, these plugins, referenced from DigWP’s WordPress lockdown article, are also important:

To make installation easy, you can run the following in command-line under your plugins directory:

wget http://downloads.wordpress.org/plugin/all-in-one-seo-pack.zip 
wget http://downloads.wordpress.org/plugin/google-sitemap-generator.3.2.4.zip
wget http://downloads.wordpress.org/plugin/wordpress-file-monitor.2.3.3.zip
wget http://downloads.wordpress.org/plugin/wp-security-scan.zip
wget http://downloads.wordpress.org/plugin/ultimate-security-check.1.2.zip	
wget http://downloads.wordpress.org/plugin/secure-wordpress.zip
find . -name '*.zip' -exec unzip {} ;
rm *.zip

This will retrieve zip files for the plugins, unzip them, and delete the .zips

These download links may not be correct later on due to plugin updates. As a result, you can visit the wordpress.org plugin pages listed above in order to find the updated links.

After you finish installing the plugins, make sure to enable them through the WordPress dashboard.


Step 16: Configure All in One SEO Pack

Before All in One SEO Pack becomes active, you’ll need to configure it. Go to Settings > All in One SEO to do so. Make sure to mark the “enabled” radio button. In addition, add in a home title, description, and keywords. Finally, set the rest of the options to your liking.


Step 17: Generate a Sitemap

Visit Settings > XML-Sitemap to generate your first sitemap that will be sent to search engines. Before doing so, ensure that the options on the page are what you desire. For example, I often edit the change frequencies, as my posts are modified quite often.

Once you are ready, scroll to the top of the page and click the build link (“Click here”). You might have to create two blank files—sitemap.xml and sitemap.xml.gz—in your root directory depending on the directory permissions. Nevertheless, once you finish building it for the first time, it should automatically update as long as you have “Rebuild sitemap if you change the content of your blog ” checked.


Step 18: Add Security

Security

At this point, you’ve already installed four security plugins. You should now put them into use.

Visit Settings > WordPress File Monitor and add wp-content/uploads in the exclude path. Change the other information if necessary. Note that this plugin will inform you whenever it notices a change in your file system.

Under Settings > Secure WP, check Error Messages and Windows Live Writer for extra protection.

Note that there is a new “Security” tab created by WP Security Scan. Fix items in red under Security > Security and Security > Scanner. When you visit Security > Scanner, make sure to chmod all of your individual plugins with 755 as well. Furthermore, you can use the password tool to generate a strong password.

Finally, fix the errors under Tools > Ultimate Security Check and ensure your site receives an A.


Step 19: Customize Theme and Sidebar

Now that you’ve setup a flexible, secure WordPress installation, you’ll need to make it comprehensive by customizing the theme and sidebar to fit your site’s needs. Of course, there is no set method to accomplish this; each site is unique in it’s own way. Make a theme that appeals to both you and your readers.


Step 20: Write Content

Write

All that’s left now is to write genuine content that appeals to your user base. You now have a flexible, secure, and comprehensive WordPress installation. Use it wisely.


Congratulations! You now have a flexible, secure, and comprehensive WordPress installation. Use it wisely!

Note: Want to add some source code? Type <pre><code> before it and </code></pre> after it. Find out more
  • http://prodevstudio.com Azizur Rahman

    Great Article. This should act as my check-list for go live process for clients.

    I am some what surprised by your suggestions of Disabling ETags in Step 11. I am interested to know your reasons for this?

    Especially when one of the Best Practices for Speeding up your website is to enable etags: http://developer.yahoo.com/performance/rules.html#etags

    • http://www.lateralcode.com Karthik Viswanathan
      Author

      Hey Azizur,

      You make a good point. As stated in the last paragraph of the link you posted, it’s better to disable ETags if you’re not making use of the validation. This is exactly my case.

      In hindsight, I should have removed that from the htaccess snippet and let that decision be up to the user.

      Karthik

  • http://iNov.pl Helid

    First of all change admin username :)

    • http://www.pisyek.com Pisyek

      agreed! :D

    • http://www.ryzalyusoff.com ryzalyusoff

      agree too! :)

  • Gavin

    Wow a lot of great information there.

    I would have loved to see a screen-cast of someone actually going through these processes. For some reason, this is one of the areas I feel like iI might actually ‘break’ something in WordPress. Not sure why, but I dont trust myself??? Maybe its how complex the wordpress folder seems to me?

    Thanks again, will try and make sure I do everything to stay secure.

  • http://visionblend.pl Tomek

    This is what I was looking for from a very very long time! All important things in one place. Thank’s Nettuts!

  • http://www.vagrantradio.com Jason

    Wow, thanks for this. Excellent list of steps to take!

  • http://www.tristarwebdesign.co.uk Tristar

    Really great list. Anything to add more security to WordPress is a must. Keep up the good work =)

  • http://www.playlookit.com Jeff Clark

    Why would you want to disable ETags? ETags are ridiculously handy for front-end optimization when used correctly.

  • wayno

    Thanks, Karthik, a very good list. Looking forward to updating my WP checklist.

  • http://johnharrisdesign.com John Harris

    Great tutorial for locking down a fresh WordPress install. This is a must considering all of the malware and link injections going around. The .htaccess and blacklist are perfect. Thank you!

  • http://www.code-pal.com Sumeet Chawla

    This is by far the most detailed Security post related to wordpress out there on the web! For being just a high school student.. you are impressive man! Great job Karthik .. keep it up ;)

  • http://www.khwebdesign.net Kent

    This is probably the most helpful tutorial I’ve seen on NetTuts yet. All of those .htaccess tips are awesome.

  • http://shailan.com Matt

    Wow, this is one amazing tutorial,
    On the otherhand,
    it’s a pity wordpress need all that fix after installation.
    Somebody should write a php script for this routine!

  • http://www.crearedesign.co.uk Steve Maggs

    I install WordPress on nearly every site I build and probably omit half of these steps normally, there are now a lot more things I’ll build into my install process now thanks to this.

    Best of they don’t add much time but I can see how they’re beneficial.

    • http://www.dwolla.com Ben

      I feel exactly the same. This is a great entry.

  • http://manishkungwani.com Manish Kungwani

    Nice post!!
    Thanks for the information.

    But the .htaccess file is for an apache server!!!

    What about IIS server???

  • ShadowAssassin

    Oh come on! How lame are these tutorials, no offence, but most of them are blindingly obvious, and people will install how they want, there is no secuirty hole from not installing from a svn, and sometimes setting it up is a pain in the a$$.

    Do they seriously pay people for these tutorials, maybe I should start and become a millionaire :)

    • Jason

      Agreed. How much time is really spend downloading a file that is 3.0MB? Less than a minute? To extract? Less than 10 seconds? To upload? Less than 3 minutes?

      I can’t see the argument that you’re wasting time. I could if the difference in time was much more significant.

    • http://www.therustedmusket.com Tony

      Agreed… The only good informative ones is 11,12 and 13… The rest is either common sense (I should hope) or personal opinion. Though to be fair 11-13 are pretty cool…

  • http://loneplacebo.com Tony

    I wish there was an easy way to change the table prefixes after installation. That means no plugin.

    • Philip

      There is a relatively easy way. Export your database into an SQL file, open it in a text editor, do a find and replace, and then re-import.

      Of course if you’re doing a find an replace for “wp_” that might be a little scary, so you’ll have to make sure to do something like find: “CREATE TABLE `wp_” and “INSERT INTO `wp_”

  • http://www.beperceived.com Chris Schmitz

    How do most one-click install services stack up against a manual install following these steps? Would you say that it’s worth avoiding these services and doing things yourself?

    • http://www.therustedmusket.com Tony

      I’ve never liked the one click install services as you have to wait for them to update, or they may do the install strangely. I could see using it for some of the more complex setups, maybe, but for wordpress it makes most sense to do it manually.

    • http://www.lateralcode.com Karthik Viswanathan
      Author

      Hey Chris,

      Good question. As far as I know, most one-click install services simply get a default WordPress installation running on your site. Because defaults are what attackers look for, this is a security vulnerability.

      On the bright side, you can still execute steps #6-20 to secure the installation. Not only that, but you can add authentication keys and change the database prefix (via the WP-Security plugin that I mentioned) as well. Thus, you could use a one-click service and really only miss out on SVN. Nevertheless, I would suggest doing everything manually, as you’re likely to avoid any quirks of the quick install process.

      Karthik

  • hamster

    You might also want to look into TAC for themes to make sure they are clean if you are grabbing them from anywhere other than WP.org.

    http://wordpress.org/extend/plugins/tac/

    • BJ

      Thank you thats a very useful plugin.

      Most of the time i start working on free themes and build from there.

  • http://www.webdevebooks.com Xerces

    Very useful, thanks a lot for sharing !!

  • http://freecss.info CSS Tutorials

    Nice list but is it really necessary?

  • irengba

    Great tips. I didn’t know most of these. Thanks Karthik for sharing.

  • http://www.vaporizerkits.com Zephyr Ion

    Very useful tips, I gotta bookmark this one

  • http://pakeklinux.wordpress.com Budi

    hey, great tutor.. :D
    thanks,

  • http://www.kevinbradwick.co.uk Kevin

    Some good suggestions here. I disagree with installing via SVN though. If, like me, you use subversion to control theme and/or plugin updates that you develop, then it will clash with the svn of the core, leaving possible conflict to deal with further down the line. Instead of checking out from the core repository, you could use the export command that will leave out the .svn folders everywhere.

    • http://www.lateralcode.com Karthik Viswanathan
      Author

      Hey Kevin,

      SVN will only keep core WordPress files and the default plugins (Akismet and Hello Dolly) under revision control. As a result, you can safely keep your themes/plugins under SVN/Git/Mercurial/etc. without conflict.

      Karthik

  • http://www.huwrowlands.id.au/blog/ Huw Rowlands

    Wow great article and will be following most of these pointers out in future! Thanks.

  • http://informed-technology.com/blog Bob

    Be very careful running the WP Security Scan plugin. This plugin can leave you without admin access to your blog, as happened to me last night after running it. This blog provides the SQL code you need to complete the work started by WP Security Scan and regain admin access to your blog.

  • http://www.nfxdesign.com Laurence

    Really helpful checklist. The security section alone helped me greatly.

  • http://www.jsxtech.com Jaspal Singh

    Great tips for securing wordpress installation.
    Thanks for sharing.

  • http://celestial-star.net Melfina

    Found this list very helpful and easy to follow.

    I really didn’t know about the 4G Blacklist, and it’s something I really should check.

  • http://www.tutorial3d.it stefanobeck

    Thank you!!!. I dont knoW SEO plugin.

  • http://www.lifesub.de Stefan Rynkowski

    Useful tips and a really helpful checklist,too. Using gzip is brilliant!

  • Nick

    My current WordPress 3.0 install has the following .htaccess file that was automatically built by wordpress:

    # BEGIN WordPress

    RewriteEngine On
    RewriteBase /
    RewriteRule ^index.php$ – [L]
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule . /index.php [L]

    # END WordPress

    In steps 11 and 13 above, you give 2 different pieces of advice on setting up your .htaccess file. I’m a little confused as to which to use, for instance there are 2 different versions of this:

    RewriteRule . index.php [PT] # from step 11 above

    and

    RewriteRule . /index.php [L] # created by wordpress 3.0

    Nick

  • http://www.marvin-steinberg.de Marvin

    thanks for sharing this useful list!!
    btw: the line 42 of the edited “Perishable Press’ 4G Blacklist” shouldn’t be typed in like this:

    RewriteCond %{QUERY_STRING} ^.*(request|select|insert|union|declare|drop).* [NC]

    cause the “select” in this line generate a 403 error while using the “automated multi-update” funktion for plugins, themes, etc in WP. if u change the line like this:

    RewriteCond %{QUERY_STRING} ^.*(request|insert|union|declare|drop).* [NC]

    it works like it should – at least in my WP blogs.

    have a nice day.
    Marvin

  • http://WordPressVideos.tv Carol

    Thanks for the tips, Mark!

  • http://www.brianbatesd.com Brian

    Thank you for writing this article. I learned a ton.

  • http://nicholascamp.com.br/ Nicholas Camp

    Perfect article! Retweeted, added to favorites in delicious, and others! Thanks!

  • Andrew Fleming

    Can you provide links on how to achieve number 10?

  • BJ

    Difficulty: Easy

    ???

    I feel this was pretty hard to understand for me. i had never worked with htaccess before and i didn’t know what i was doing so i had to ask on some other community why and what..

    I’am normally a login hosting-admin guy that clicks on the one-click installer button and WordPress is ready to go. * but that doesn’t work fine.

    Your Command-Line:
    I don’t know if it was me doing it wrong but at #15 after the command-line in the Terminal i had all my zip file on my computer unzipped. :S
    Now i can clean up again! :S

  • BJ

    Now i have trouble with my sitemap files..

    I think it has everything to do with all the htaccess changes i made.

    I did everything like in step#17.

    First i created one empty tekst-editor file and named it sitemap.txt after that i changed it to sitemap.xml and duplicated it and named it sitemap.xml.gz

    After that i uploaded them to my hosting in the same directory where the index.html / index.php file goes.

    But nothing i get this error!
    There was a problem writing your sitemap file. Make sure the file exists and is writable.
    ** Same line for the Gzip verson ***

    I when looking in my hosting admin, to see what the permissions are on the file.
    and it says the following:
    Owner: read mode, write mode
    Group: read mode
    Others: read mode

    Somebody knows where it goes wrong?

  • http://www.gadgetalbum.com Emas

    Learn lot’s of important things. I must use these to my work.
    thanks fro sharing.

  • http://whistle-dennis.blogspot.com dennis

    thanks you..

  • Dan

    The GZip method is causing me not to be able to install or upgrade plugins directly through WordPress. Is anyone else having this problem?

  • http://www.nebulos.net Nebulos

    I will use it on my site for sure..

    Thanks, great tips.

  • http://www.constanta.ws Constanta

    Great job man, excellent list of steps to take.
    All the best.
    Thank you!

  • http://thedanielrichard.com Daniel

    This article deserves a 2 thumbs up for Step #13 alone.

  • http://www.webdesigncapetown.co.za Mark

    Great write up. Lots of things I wasnt doing on my installations. Thanks

  • http://www.nijlpaard.net Nijlpaard

    Great comment. Applied it to my blog immediatly. One thing.
    The line below

    RewriteRule ^(.*)$ – [F,L]

    Caused the drag and drop of widgets to not work anymore. Otherwise, great post.

  • http://www.creativewebdesignsolutions.co.za Rudi Roux

    Great article on securing wordpress. I love wordpress however the security vunerabilities have always worried me, have had my website attacked by injection attacks several times. Also most NB keep wordpress up to date!

  • http://www.boylecreations.com Aidan Boyle

    I’ve read a lot about some of these steps but its really nice to see them all in one place though. One thing I’d definitely consider is updating as more plugins come out.

    One in particular comes to mind which is WordPress SEO by Yoast. You can check it out here: http://yoast.com/wordpress/seo/

    I used to use All in one SEO and Headspace 2 ( depending on the site ) for various projects, but nowadays I use WordPress SEO for nearly all of my project. This is an incredible plugin that I think should at least be given a look. Definitley for more advanced SEO tracking, but there is a great guide on wpbeginner.com that shows how to optimize it well.

  • http://www.yeahthatapp.com Bioshox

    Good article, it’s just a shame WordPress needs all these fixes, even if it is one of the biggest blogging platforms in the world.

    Shame really.

  • Aria

    The 4G Blacklist breaks some features in admin. Some requests to files like get-scripts.php get black listed and and in some cases jQuery doesn’t load. You can see that in action in widgets area.

    But great article though :)

  • http://alicethetic.com/ Alice

    I’ve returned to this article several times since it was posted. I use it as my go to guide on how to better set up a WordPress installation. Thanks for this!

  • http://www.itutorblog.com paullstanley

    Very nice, in depth article. I cannot believe the wealth of information here. Thank you very much for taking the time to put this together, it is a great reference as mentioned before. I have also put together an article on WordPress security if interested it is here: http://www.itutorblog.com/2011/06/how-to-secure-wordpress/

  • newr

    Very useful post! another tip widely used is removing wp version, not sure the best way is by using plugins or hacks.

  • Nick K

    Very nice article.

    If you’re using TimThumb on your WordPress website, comment the following line out in the 4G Blacklist:

    RewriteCond %{QUERY_STRING} http: [NC,OR]

  • Joost

    Great article, thanks!

    For WordPress 3.2.1, comment out in your htaccess rules
    RewriteCond %{QUERY_STRING} http: [NC,OR]
    WP uses this in string to redirect after login.

    If you’re on https, comment out
    RewriteCond %{QUERY_STRING} https: [NC,OR]
    Same reason as above

    Also, remove drop from this line
    RewriteCond %{QUERY_STRING} ^.*(request|select|insert|union|declare|drop).* [NC]
    or you won’t be able to drop widgets in to sidebars in admin

    If you are developing on localhost, comment in in htaccess
    RewriteCond %{QUERY_STRING} ^.*(%0|%A|%B|%C|%D|%E|%F|127.0).* [NC,OR]
    and remove localhost from
    RewriteCond %{QUERY_STRING} ^.*(globals|encode|localhost|loopback).* [NC,OR]

  • http://www.r4-carta.com r4 ds

    Is this really helpful? My blog alwayles hacked by hacker.

  • http://www.adsgah.com/10000954.html تور زميني ارمنستان ويژه عيد فطر

    thnx its very useful

  • http://www.otreva.com Mike

    I have to agree these aren’t all that great of security tips. I put together a security guide with 10 steps I found to be most useful for protecting my WordPress installs. I have seen many users neglect the steps I outlined on their installs:

    10 Steps for Securing WordPress

  • http://hakre.wordpress.com/ hakre

    You do not need to parse request header to make use of

    ob_start( ‘ob_gzhandler’ );

    Just place that single command in, in case compression is not supported by the browser, it won’t be activated. No need for the if’s around and such. See the php documentation about that command for more info.

  • http://whale.to/b/phelps4.html Ute Helaire

    What you dont know about wireless would fill whole shelves.

  • http://www.adsgah.com/10001880-%D8%AA%D8%AF%D8%B1%D9%8A%D8%B3-%D8%AE%D8%B5%D9%88%D8%B5%D9%8A-%D8%B1%D9%8A%D8%A7%D8%B6%D9%8A.html تدريس خصوصي رياضي

    thnx for useful information of scure of wp

  • http://psvita-forum.com/ ps vita forum

    How do we submit Judge Jimmys if thats still going on?

  • http://www.dailygadgets.net/ gvn

    Nice Tutorial. Currently Applied in my new site. Since it got hacked recently =(

  • http://www.pmbody.com Amir

    Excellent points, Let me add some more points:
    Alot of people use the default Admin and weak passwords like test or 12345.

    My suggestion is to use very strong password comprising of Alphanumeric with special letters.

    Another tip is, do not delete the default admin, rather create a new user with full privileges and restrict the admin to just a subscriber, so even if some one guess your password or some how got access to the Admin account, he/she will have limited access.

    Thanks.

  • http://st8ment.com Nancy Wilson

    oooh don’t understand some things never have done command lines, and was lost at the Add .htaccess Rules section. A video to see how you do these things would help. I’m a bit overwelmed. not much of a techie. darn! think this article would help me seems pretty thourough.

  • Elise

    I’ve been looking for a tutorial on how to set up the .htaccess that I could actually understand! Thank you.

  • http://www.sugihartono.com Sugihartono

    What about extra space for svn file? does it consume much storage?

  • http://englishlc.com/ Barnez

    Thanks for the information. Some tips I’ve come across elsewhere, others like Step 13 ‘The 4G blacklist’ I’ll need to take a closer look at.

  • Sync

    I’m a beginner in wordpress and websites. I was already lost on step 1.
    I think it needs to be more detailed.

  • http://associatestraining.com William C Allen

    Hi Karthik,

    “The number one mistake for a flexible WordPress installation happens right from the get-go. I’ve seen numerous developers manually download, unzip, and upload WordPress to their site. This is not only a waste of time, but it also reduces flexibility.”

    Actually this is what I do, so was very interested in what you had to say. I am not a developer and had never heard of SVN, so right out of the gate I was confused. Just a suggestion, maybe explain a little bit about SVN in the beginning of the article. As I think having the very first thing you mention seem so foreign that a lot of readers that are new will simply leave the page because they figure if they can’t understand step one, their better off using Fantastico – yikes!

    Otherwise, great article. Thanks!