How to set up a local copy of your WordPress blog

WordPress logoWhy might you want to do this?

This is how I managed to keep my blog up to date while I was “on the road” over the last year, even when I didn’t have access to the internet. As long as I had power (which was not always a given), I was able to compose drafts (usually in a text editor), edit photos (in GIMP), and then layout/revise posts (in my local copy of WordPress). When I was ready to publish, and had access to the internet, it was a trivial process of uploading the photos (via SSH), copy-and-pasting the text over, and pressing “Publish”.

In fact I found it so much faster to compose and revise posts locally, that I’ve continued to use this set up even after returning to fast internet connections. Think about how many times you’ve hit that “Save Draft” button and waited for WordPress to “return” so you could reload the post preview tab—and you probably understand what I mean.

The steps I describe are based on my past experience of setting up a local web development environment on my laptop. Of course I ran into a few gotchas along the way, so I documented the process here for future reference. I don’t necessarily recommend this approach for everyone, but I figured it might offer some interesting insight into how I do things.

Create a fake domain name for your local blog

In the file /etc/hosts, add a line for the name you want to access your blog locally with. For example, if your blog lives at http://example.com/, consider using “example” as the local hostname. This will allow you to access the local copy of your blog as http://example/ in your web browser.

127.0.0.1    example

Install key LAMP components

A minimum you’ll want Apache, MySQL (client and server), and PHP. You’ll also want to enable the userdir and rewrite modules. My post, Setting up a nice LAMP development environment on Ubuntu covers this nicely.

Create an Apache VirtualHost

The purpose of a VirtualHost is to connect the hostname you chose in /etc/hosts above with the intended location of your blog’s web root. I prefer to put my web-accessible content under public_html in my home directory (e.g. /home/username/public_html/example), but really you can put it anywhere.

  1. First create a file to store your virtual host directive (name the file the same as the hostname you chose above)
    sudo touch /etc/apache2/sites-available/example
  2. Then edit the file and add the following Apache conf lines, changing the ServerName and DocumentRoot as necessary
    <VirtualHost *:80>
    ServerName example
    DocumentRoot /home/username/public_html/example
    </VirtualHost>
  3. Create the directory you set as your DocumentRoot above (if it doesn’t already exist)
    mkdir -p ~/public_html/example
  4. Enable the virtual host
    sudo a2ensite example

Allow Apache to use .htaccess files

In order for WordPress to have “pretty permalinks” you need to update the default configuration of Apache to allow you to use .htaccess files. To do so, edit /etc/apache2/mods-available/userdir.conf and change the following two lines:

AllowOverride FileInfo AuthConfig Limit Indexes
Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec

to:

AllowOverride All
Options All

Allow use of PHP in user dirs

This was a very annoying gotcha. Apparently in recent releases of Ubuntu, PHP5 is disabled by default in user dirs. In order to fix this, edit /etc/apache2/mods-available/php5.conf and delete the following lines:

To re-enable php in user directories comment the following lines
(from <IfModule ...> to </IfModule>.) Do NOT set it to On as it
prevents .htaccess files from disabling it.
<IfModule mod_userdir.c>
    <Directory /home/*/public_html>
        php_admin_value engine Off
    </Directory>
</IfModule>

Note: this only applies if you located the DocumentRoot of your Apache VirtualHost in your user dir.

Restart Apache

sudo /etc/init.d/apache2 reload

Tar up all your remote blog files

SSH to your webhost, and tar up all of your blog’s files, including the core WordPress files, your template files, and your uploaded images. The commands below assume that you are in your home directory on your webhost and that the root directory of your webspace is a subdirectory called “example.com”. If that is not the case, then the paths referenced in the commands below will have to be adjusted slightly.

tar czvf example.com.tar.gz example.com/

Then on your local machine, download the tar’d and gzip’d file, and extract it so that it lives in the DocumentRoot you chose above:

scp username@example.com:example.com.tar.gz ~
tar xzvf ~/example.com.tar.gz
mv ~/example.com/* ~/public_html/example
rmdir ~/example.com

Dump your WordPress database

On your webhost, use mysqldump to export the contents of your WordPress database to file.

mysqldump -u username -p -h db_hostname wordpress_db_name > wordpress_db_name.sql

Then on your local machine, create a local database for your WordPress data.

mysql -u root
create database wordpress_db_name;

Then download the mysqldump file and import it into your local database.

scp username@example.com:wordpress_db_name.sql ~
mysql -u root wordpress_db_name < wordpress_db_name.sql

Update wp-config.php

Edit your local wp-config.php (in /home/username/public_html/example/wordpress/wp-config.php) to set the DB_HOST to “localhost”, and the DB_USER and DB_PASSWORD to whatever you’ve set up locally. In my case I use “root” with a blank password for MySQL, since it’s for local development purposes only.

define('DB_NAME', 'wordpress_db_name');
define('DB_USER', 'root');
define('DB_PASSWORD', '');
define('DB_HOST', 'localhost');

Fix hostname in local WordPress database

This is always an annoying gotcha/catch-22. WordPress stores the “canonical” hostname of your blog in the database. The way to change this is through the WordPress’ own General Settings interface, but if you’ve just copied your database from one hostname to another, then it’s impossible to login and update the setting because you keep getting redirected to the original hostname in the database. So your only recourse is to manually run the following query against your local MySQL WordPress database (replacing ‘example.com’ and ‘example’ with your actual and local hostnames, of course).

update wp_options
set option_value = replace(option_value, 'example.com', 'example') 
where option_name in ('siteurl','home');

Lastly, in order to fix any images with absolute source URLs, run the following query:

update wp_posts
set post_content = replace(post_content, 'http://example.com/', 'http://example/');

Test

Cross your fingers and test http://example/ in your web browser. If you don’t have an internet connection at the time, make sure “Work Offline” is disabled in your web browser. If things aren’t working, tail your Apache error log to see if you can get a clue.

tail -f /var/log/apache2/error.log

I ended up have to update a few paths and URLs in my WordPress theme that were pointing to my live blog, as well as fix a few file permissions issues.

2 Comments

This is actually a brilliant idea. I was in Vietnam for a few weeks last month and this solution would have saved me a lot of pain. Just worried it might be above my current WordPress skill level…

James, if you just want a place to draft posts, a less technical alternative would be to set up a simple local install of WordPress, without downloading all your existing posts, theme, etc. Of course that doesn’t help you if you want offline access to your old posts, but there’s a fair number of tutorials out there for setting up WordPress for development using WAMP or MAMP…

Name

Email (optional)

Blog (optional)