Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web

Wordpress, Permalinks & LAMP with 404's

0.00/5 (No votes)
5 Nov 2012CPOL20 min read 24.1K  
Fixing mod_rewrite access to .htaccess files for Wordpress Pretty Permalinks and 404 errors.

Introduction

The purpose of this article is to help guide the user into solving the dreaded 404 link errors when using the "Pretty Permalinks" setting in Wordpress with a LAMP install. This is not limited to just Wordpress. Any LAMP server using mod_rewrite and the .htaccess file will need the same changes for the rewriter to work.

Background

While trying to resolve this exact problem on our servers we could not find the exact reason this functionality would not work. We made all the changes that we could find on the web but none fixed the issue. It also seemed that no one was able to help the people that were stuck with these 404 errors. Normal links will work just fine. It seemed to be the Rewriter was not doing it’s job. Most people blamed PHP others blamed Wordpress but after 20 years of software I assumed that it must be our configuration we were just missing something.

Step 1

So that this article has all the information you need to set up permalinks please use the following link that already has a full description on setting this up for the majority of people. http://codex.wordpress.org/Using_Permalinks. We will refer to this document in this article. Here is a snapshot of the original:


Permalinks are the permanent URLs to your individual weblog posts, as well as categories and other lists of weblog postings. A permalink is what another weblogger will use to link to your article (or section), or how you might send a link to your story in an e-mail message. The URL to each post should be permanent, and never change — hence permalink.

Permalink Types

There are three basic types of WordPress permalinks:

mod_rewrite: "Pretty Permalinks"

Using mod_rewrite or lighttpd you can produce much nicer permalinks (see Pretty Permalinks). There are many different formats, but the most common, and most versatile looks like

http://example.com/2012/post-name/

or

http://example.com/2012/12/30/post-name

Pretty permalinks are available under:

  • Apache web server with the mod_rewrite module
  • Microsoft IIS 7+ web server with the URL Rewrite 1.1+ module and PHP 5 running as FastCGI
  • Microsoft IIS 6+ using ASAPI_Rewrite
  • Lighttpd using a 404 handler or mod_rewrite (see See Also)

PATHINFO: "Almost Pretty"

PATHINFO permalinks look very much like mod_rewrite permalinks but for one exception: they have /index.php inserted before them, like so:

http://example.com/index.php/yyyy/mm/dd/post-name/

Otherwise, they are the same as the "pretty" mod_rewrite permalinks, and are similarly flexible. Anything that mod_rewrite permalinks can do, PATHINFO permalinks can do, with the help of that /index.php part.

There is a helpful plugin that displays the type of permalinks being used and detailed information on the internal rewrite rules used by WordPress.

Choosing your permalink structure

In the Settings → Permalinks panel (Options → Permalinks before WordPress 2.5), you can choose one of the "common" structures or enter your own in the "Custom structure" field using the structure tags.

Please note:You never, ever put your site url in the permalinks slot. You must use one of the structure tags, or a combination of tags only.

To activate PATHINFO permalinks, start your permalink structure with index.php/.

Image 1

Please note:

You never, ever put your site url in the permalinks slot. You must use one of the structure tags, or a combination of tags only. 

You can use these tags to customize your "Pretty" or "Almost Pretty" permalinks. A few hints:

  • Make sure to end your structure with either %post_id% or %postname% (e.g. /%year%/%monthnum%/%day%/%postname%/) so that each permalink points to an individual post.

%year%
The year of the post, four digits, for example 2004
%monthnum%
Month of the year, for example 05
%day%
Day of the month, for example 28
%hour%
Hour of the day, for example 15
%minute%
Minute of the hour, for example 43
%second%
Second of the minute, for example 33
%post_id%
The unique ID # of the post, for example 423
%postname%
A sanitized version of the title of the post (post slug field on Edit Post/Page panel). So “This Is A Great Post!” becomes this-is-a-great-post in the URI.
%category%
A sanitized version of the category name (category slug field on New/Edit Category panel). Nested sub-categories appear as nested directories in the URI.
%author%
A sanitized version of the author name.

Category base and Tag base

The Category base and Tag base are prefixes used in URLs for category and tag archives, which look like this:

example.net/wp/<var>category_base/<var>category_name
example.net/wp/<var>tag_base/<var>tag_name</var>

The default values for these are category and tag. You can change them, but you can't remove them from the URLs altogether.

Custom permalinks work on most systems without any problems, but there are still some conditions where problems occur.

Using %category% with multiple categories on a post

When you assign multiple categories to a post, only one can show up in the permalink. This will be the lowest numbered category (see Manage Categories). The post will still be accessible through all the categories as normal.

Using "Pretty" permalinks

Requirements:

  • Apache web server with the mod_rewrite module installed
  • In WordPress's home directory,
    • The FollowSymLinks option enabled
    • FileInfo directives allowed (e.g. AllowOverride FileInfo or AllowOverride All)
    • An .htaccess file (if this file is missing, WordPress will try to create it when you activate "pretty" permalinks)
    • If you want WordPress to update the .htaccess file automatically, WordPress will need write access to the file.
  • For lighttpd, see below.
  • Mac Users running WordPress locally must edit their httpd.conf file editing the AllowOverride line to read AllowOverride All in the Directory "/Library/WebServer/Documents" host instructions. For Mac OS X 10.5.x and up this file is located in /private/etc/apache2/users/[your-username].conf, otherwise it is located at /etc/httpd/httpd.conf.

When you create or update a "pretty" permalink structure, WordPress will generate rewrite rules and attempt to insert them into the proper .htaccess file. If it can't, it will say something like You should update your .htaccess now and print out the rules for you to copy and paste into the file (put them at the end).

In WordPress 2.0+ versions, you'll probably need to do this only once, because WordPress does the rewriting internally. If you ever move your WordPress home directory (Site address), you'll need to repeat this step.

WordPress will play nice with an existing .htaccess and will not delete any existing RewriteRules or other directives. If you have other mod_rewrite rules, put yours before WordPress's.

Where's my .htaccess file?

WordPress's index.php and .htaccess files should be together in the directory indicated by the Site address (URL) setting on your General Options page. Since the name of the file begins with a dot, the file may not be visible through an FTP client unless you change the preferences of the FTP tool to show all files, including the hidden files. Some hosts (e.g. Godaddy) may not show or allow you to edit .htaccess if you install WordPress through the Godaddy Hosting Connection installation.

Creating and editing (.htaccess)

If you do not already have a .htaccess file, create one. If you have shell or ssh access to the server, a simple touch .htaccess command will create the file. If you are using FTP to transfer files, create a file on your local computer, call it 1.htaccess, upload it to the root of your WordPress folder, and then rename it to .htaccess.

You can edit the .htaccess file by FTP, shell, or (possibly) your host's control panel.

The following permalink rewrite code should be included in your .htaccess file (since WordPress 3.0):

# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress

If your .htaccess file contains errors that bring down your site ("Internal Server Error (500)"), you will need to use FTP or your host's control panel to delete the rogue .htaccess file.

Automatically updating .htaccess

If WordPress can't update your .htaccess file automatically, it will tell you something like If your .htaccess file were writable, we could do this automatically, but it isn’t… near the bottom of the Settings → Permalinks panel.

If you want to let WordPress do this, you'll need to give WordPress write access to the .htaccess file. The exact permissions necessary depend on your server setup. Try adding write permissions for the owner, then group, then world, testing after each change; once WordPress has edited the file successfully, don't add any further write permissions.

After applying the permalinks, you should change the permissions to something stronger like 660 or 644 to prevent others on the server from potentially having access to it.

Permalinks without mod_rewrite

"Pretty" permalinks usually require mod_rewrite, and IIS (common on Windows servers) does not support mod_rewrite. (If you are using Apache 2.0.54, on Windows, mod_rewrite may work, provided it is enabled in apache\conf\httpd.conf.)

If you are using IIS 7 and have admin rights on your server, you can use Microsoft's URL Rewrite Module instead. Though not completely compatible with mod_rewrite, it does support WordPress's pretty permalinks. Once installed, open the web.config file in the WordPress folder and add the following rule to the system.webServer element

<rewrite>
    <rules>
        <rule name="Main Rule" stopProcessing="true">
            <match url=".*" />
            <conditions logicalGrouping="MatchAll">
                <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
                <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
            </conditions>
            <action type="Rewrite" url="index.php/{R:0}" />
        </rule>
    </rules>
</rewrite>

There's a full installation guide on the IIS site. The module is available for x64 and x86 systems.

If this isn't an option, you can try PATHINFO permalinks; put index.php/ at the start of your custom permalink structure:

/index.php/%year%/%monthnum%/%day%/%postname%/

This option may not always work, especially in cases of WordPress running on IIS 6. To make this option work on IIS, add these 2 lines to a php.ini file and store that file in your webroot :

cgi.fix_pathinfo = 1
cgi.force_redirect = 0

Another solution exists using IIS' custom 404 redirects. It requires that your web host allows you to add a custom 404 redirect, but it doesn't require you to install any 3rd party mod_rewrite software and it also doesn't require that your permalink structure begin with /index.php/.

Fixing Permalink Problems

Fixing .htaccess Generation Issues

If your installation of WordPress does not generate a .htaccess file or if it does not write the new rules onto your existing .htaccess file then there are a couple reasons that could be causing this. Work step by step and continue to the next step only if the previous step does not work.

  1. Change File Permissions: You must chmod the .htaccess file to 666 to edit it with the WordPress template editor, but this is not recommended, since if you do that, any user of your blog, who can edit templates will be able to edit it. You can change the permissions to 660 to make it server-writable, which again will have the same limitation.
  2. Server Blockage: Your host might have blocked the SERVER_SOFTWARE variable and this will cause WordPress' .htaccess generation to fail. If you are sure that your server is running Apache, you can force WordPress to believe that your server is running Apache by changing your wp-includes/vars.php file. Follow the steps below to implement these changes.
    • Open the wp-includes/vars.php file using the built in file editor in your WordPress Admin panel. To navigate to this panel, login to WordPress, click on "Manage", then on "Files", scroll to the bottom and type in wp-includes/vars.php into the text box under the "Other Files" title. Look for
      $is_apache = strstr($_SERVER['SERVER_SOFTWARE'], 'Apache') ? 1 : 0;
      and replace it with
      // $is_apache = strstr($_SERVER['SERVER_SOFTWARE'], 'Apache') ? 1 : 0;
    • Add a new line under
      // $is_apache = strstr($_SERVER['SERVER_SOFTWARE'], 'Apache') ? 1 : 0;
      and type in
      $is_apache = 1;
  3. Users of XAMPP (Windows): Some versions of XAMPP do not enable mod_rewrite by default (though it is compiled in Apache). To enable it — and thus enable WordPress to write the .htaccess file needed to create pretty permalinks — you must open apache/conf/httpd.conf and uncomment the line LoadModule rewrite_module modules/mod_rewrite.so (i.e., delete the hash/pound sign at the front of the line).
  4. Users of WAMP (Windows): Some versions of WAMP (all versions?) do not enable mod_rewrite or permit following SymLinks by default. To enable the required functionality navigate to the apache/conf/httpd.conf file, open with a text editor and uncomment the line LoadModule rewrite_module modules/mod_rewrite.so (i.e., delete the hash/pound sign at the front of the line). Then further down in the same file there is a section that starts with the line "Options FollowSymlinks". Change the second line in that section from "AllowOverride none" to AllowOverride all. Save edited httpd.conf and restart all WAMP modules. Your permalinks should now work.

Permalinks, .htaccess, and MS Frontpage

A note about Microsoft Frontpage: many servers (shared and dedicated) maintained and built by various hosting companies come with mod_frontpage compiled with the apache build, and in many cases with the Frontpage Server Extensions installed, on each virtual server. This is more common than not, many/most binary distributions used in the server build process at most hosting companies these days include both mod_fronpage and the server extensions. Even if you're not using Frontpage, because of the way that the extensions interact with apache (and the httpd.conf file) you'll likely get something like a 500 error or blank white page when trying to view your WP install (although the admin panel may operate correctly) simply because extensions/mod_frontpage exist on your server.

WordPress will operate correctly with the Frontpage Extensions installed, however permalinks will not function at all and ANY change to the permalinks section from the WordPress admin interface will cause corruption of the Frontpage server extensions due to the addition of the mod_rewrite rules to the .htaccess file. There is however now a fix for this situation.

Quick Fixes, Frontpage or Permalinks

Frontpage Extensions Fix: If you don't care about permalinks and just want to make the MS Frontpage server extensions work again, simply edit your .htaccess file and remove the WordPress section with the rewrite rules.

To Use Permalinks: If you don't care about Frontpage(but your hosting company has the extensions installed)

You will need to remove (or have your hosting company do so) the MS Frontpage server extensions, or simply edit the .htaccess file to removed all of the Frontpage Lines, leaving only the WordPress mod_rewrite code.

Using FrontPage AND Permalinks Together

Finally, A solution.

There have been a number of threads on this issue in the support forums, and until now, no solution to the problem.

Normally, on a Unix server with the Microsoft FrontPage Server extensions installed WordPress works just fine and you are able to edit and publish pages (with Microsoft FrontPage) — until — you make a change to the permalinks (for example to the date based kind that I like /2005/04/etc). I often suggest that type of URI to folks asking about permalinks etc, as that is the method recommended by the w3c (see http://www.w3.org/Provider/Style/URI ).

Now, the problem is that FrontPage uses the .htaccess file (which the WordPress mod_rewrite rules must access) for its "publishing" and "web authoring" configuration. As soon as the WordPress mod_rewrite code is added to the file, two things happen — the permalinks don't work and the Frontpage Server extensions become corrupt.

I have tried countless ways to get around this, including trying to use rewrite rules that "ignore" the %{HTTP_USERAGENT)% used by FrontPage, to using a second AccessFilename .wpaccess to the httpd.conf file, and a host of other things, and nothing worked to allow use of FrontPage and management and use of permalinks in WordPress at the same time.

The solution is actually simple, and I figured it out by accident.

If you are using, or wish to use FrontPage (or if your hosting package is pre-configured that way) along with WordPress, you'll need to take the following simple steps on your server or have your hosting company do them for you.

Microsoft FrontPage creates the following directory

_vti_bin

Nested within that it creates both

_vti_adm

and

_vti_aut

In addition to in your site (or WordPress) root folder in all of those directories you will find additional .htaccess files.

In all three of these directories AND in the root directory, at the top of ALL of the .htaccess files you simply need to add one line:

Options +FollowSymlinks

There may or may not already be a line in each like

Options None

Edit and save each .htaccess file and you're done. Now everything works perfectly, including FrontPage, AND the permalinks of your choosing.

Long Permalinks

When using extra long permalinks in email and posting in comments and chats, some long permalinks are "chopped off" or only the first section is actually recognized as a link and the end seen as text. Here is an example.

Can result in:

To click on the lower link, the user would get a 404 Page Not Found Error. If you have a tendency to use very long permalink post titles, take these steps to prevent this problem.

1. Check that you are indeed using Permalinks.

2. Edit your .htaccess file and add the following:

RewriteRule ^post/([0-9]+)?/?([0-9]+)?/?$ /index.php?p=$1&page=$2 [QSA]

3. Test it. Find a post's ID number and type the following (with your information) in your browser and you should be redirected to your post:

http://yourdomain.example.com/post/(the ID #)

It is also worth noting that most email software will not cut off URLs that have been delineated with angle-brackets (< and >), so when pasting URLs into emails, you should write them as so:

Additionally, some decent email clients offer a "preformat" option when composing plain-text emails. Using the "preformat" option when pasting links will force the email client not to insert linebreaks inside the links.

Fixing Other Issues

If your .htaccess file is being generated correctly, but Permalinks still do not function, the following might be a problem. If problems persist, post a note in the WordPress Forum's How To section.

AllowOverride Not Enabled
Your server may not have the AllowOverride directive enabled. If the AllowOverride directive is set to None in your Apache httpd.config file, then .htaccess files are completely ignored. In this case, the server will not even attempt to read .htaccess files in the filesystem. When this directive is set to All, then any directive which has the .htaccess Context is allowed in .htaccess files. Example of enabled AllowOverride directive in httpd.config:
<Directory />
   Options FollowSymLinks
   AllowOverride All
</Directory>

You may also have to enable the AllowOverride directive in your DocumentRoot:

<Directory /var/www/html>
   # ... other directives...
   AllowOverride All
</Directory>
You may also have to change the AllowOverride settings for the site. This is surely the case when using Mac OS X Server, but might be likewise with other systems. Usually you can find the site configuration files in /etc/httpd/sites/
If you don't want to set AllowOverride to all (as it is above) then your AllowOverride list must include the FileInfo directive. You must restart your Apache server for any httpd.config file changes to take effect. For more information on which overrides are allowed, read about Apache Core Features.
Paged Navigation Doesn't Work
Sometimes navigation to second (and subsequent) pages of posts does not work as expected. Your page may generate a link to a page with one of these URIs:
http://www.example.com/page/2/
http://www.example.name/category/categoryname/page/2/
http://www.example/year/month/day/page/2/
http://www.example/year/month/page/2/
The result of clicking one of those links is that the page loads with all the surroundings (header, footer, sidebar), but instead of a page of posts, there is an error message: "Sorry, no posts match that criteria."
This is due to a glitch in the .htaccess file that WordPress generates. To fix it, delete the contents of your .htaccess file and re-create it.
  1. In the Control Panel, go to Manage > Files (More Info on Editing Files)
  2. Click the link to your .htaccess file to edit its contents
  3. Copy the contents of the file and paste it to a text file in a text editor. This is a precaution in case your .htaccess file has manual entries for redirects, denials or other handy htaccess tricks
  4. Delete all contents from your .htaccess file and click the Update File button.
  5. In the Control Panel, go to Options > Permalinks.
  6. Click the Update Permalink Structure button to freshly generate new rewrite rules for your permalinks.
  7. Test the results using a link that had previously broken.
  8. Add any manual htaccess entries back in your file (Place manual htaccess entries before the # BEGIN WordPress or after # END WordPress lines.)
You may also perform similar steps by deleting the .htaccess files from the server, creating a fresh empty .htaccess file, changing its permissions to 666, and then in Options > Permalinks generate a new set of htaccess rules by clicking the Update Permalinks Structure button.
If that still doesn't work, take a look at the WordPress support forums, specifically, this support post.
Permalinks to pages don't work
If you've tried to navigate to a newly created page and encounter an error, you likely need to update your Permalink structure. Remember, each time you add a new static Page to WordPress, new rules must be generated and updated to .htaccess (WordPress 1.X) or to the internal rewrites array (WordPress 2.X).
Permalinks to Ultimate Tag Warrior tag pages don't work
If you get 404 errors on local tag URLs when using the UltimateTagWarrior plugin on WordPress 2.X, it's because the internal rewrites generated by WordPress are being overly greedy and getting invoked before UTW's rewrite rules have a chance. This usually occurs only when using a custom permalink structure (like /%postname%/). To fix it, either switch your Permalink structure to "Date and name based" or hack the UTW plugin to place the UTW rewrites at the top of the internal rewrites array.
Permalinks work but no pages are returned
Some versions of PHP 4.4.x and 5.x have a bug that causes mod_rewrite to fail when used with some versions of Apache 2.x. More details at http://bugs.php.net/bug.php?id=35096 and http://bugs.php.net/bug.php?id=35059.

More Help

If these steps do not work, search for your problem in the Codex, Troubleshooting, or in the Support Forum. As a last resort, file a bug report.

Tips and Tricks

Avoiding interpretation as an archive link

Note that even though one might never make more than one posting a day, and thus wishes to use e.g., %year%%monthnum%%day%, links so generated will however be interpreted as the archive of all posts for that day. One needs at least %year%%monthnum%%day%%hour% to target an individual post.

Check for permalink structure

A way to check if the blog has a permalink structure is:

<?php if ( get_option('permalink_structure') ) { echo 'permalinks enabled'; } ?>



For the majority of people this will resolve the issue with your Permalinks.

Step 2 - It still does not work!

If you are like some step 1 did not resolve the issue then this might just be your key to fixing it.

Lets focus on the section titled "AllowOverride Not Enabled" from the linked article.  If this is not enabled it will make no difference what you have in your .htaccess file as apache does not have access to use any settings in it.  The .htaccess file is an overide file and if AllowOverride is not enabled then it will be ignored.

Like most of us we edited the appache2.conf or httpd.conf file and added the correct settings but what most people overlook is the site settings folder.

On ubuntu these are not located in the "/etc/httpd/sites/" folder. They are in the "/etc/apache2/sites-available/", Other systems might have other paths. These files do not have extensions so they don’t tend to stand out. Edit these in your favorite text editor and change the <Directory> AllowOverride as described in the linked article for the site you have Wordpress on or which site you are using mod_rewrite.   Again these changes are really for mod_rewrite but are widley used for the wordpress application.

Find the site config file for your current application:

Image 2

In ubuntu we use the "sudo" comand to execute using admin rights and vi as an editor.  Look for a <Directory key for the application root.  If missing then add it like bellow.

<Directory /var/www/>
   # ... other directives...
   AllowOverride All
</Directory>


Image 3

In this instance the second directory path was missing for the "/var/www/" we added this and set AllowOverride to All.  Other keys secure folders such as the cgi-bin folder.

This should get you up and running. Such a simple solution for such a pesky problem.

If you still have issues with mod_rewrite not working then you will need to walk through your apache config file and find all includes that it uses.  most likly in one of these files you are overwriting the <Directory config and AllowOverride.  Remember that the config file starts at the top and makes changes as it moves down the file.  Each include will change settings back and forth so just keep moving down the file untill you find where the settings are being moved back from AllowOverride All.  Good luck!

Finaly

So what does this article tell us. Never stop looking for your answer and never assume that it is faulty code or applications. We found that the Site settings were overriding the apache2 server settings and thus we were not able to get the mod_rewrite functions to work. Just another example of failure only comes when you give up. In this case we succeeded.

History

        11/05/2012 - Corrected invalid links.


License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)