Setting up WordPress with Custom Permalinks and no .htaccess File?

Hi @Mike Lee:

To answer your question it is helpful to understand how everything works.

Apache Serves URLs that Match Files and Directories

Apache is designed to serve files explicitly matched by URL, or to serve the index.php found in a directory when the directory is explicitly matched.

But Apache Can Serve URLs Matched by Regex with mod_rewrite

If you want Apache to match URLs for where there are no real directories (the case with WordPress and pretty permalinks) then you must have some way to tell Apache how to handle URLs differently. And that’s exactly what mod_rewrite was designed to allow; it gives server administrators the ability to set rules for matching URLs using regular expressions. Those rules route the result to other URLs, often including actually .PHP files and sometimes with URL parameters passed. Ultimately the rules specify that actual files get loaded.

And mod_rewrite is Configured with Either .htaccess or httpd.conf

To configure mod_rewrite you can only do it inside .htaccess or within the httpd.conf file or one of the files it includes, like potentially httpd-vhosts.conf. Actually I’m surprised if you client has the skills to control Apache that they don’t know this already.

WordPress Always Uses the Same Simple .htaccess File

Moving on to what WordPress does, when you set permalinks WordPress writes the following to the .htaccess file, assuming it is writable (and in this first example assuming your website site is served from the root):

# 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

Caveat: When Your WordPress Front Page Directory is Not Root

If your site is instead served from /blog then the .htaccess file written would look like this:

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

WordPress Routes All Non-File/Directory Matching URLs to index.php

So as you can see, the only thing WordPress uses .htaccess for is to map any URL to the domain to /index.php (or /blog/index.php in the 2nd example) except when a URL matches an actual file (such as an .jpg/.gif/.png image, a .css stylesheet, a .js script, etc.) or when it matches an actual directory (which as far as I know is not relevant in a standard WordPress install.)

In PHP WordPress Parses $_SERVER['REQUEST_URI'] To Decide What to Load

Inside its PHP code WordPress grabs the value of $_SERVER['REQUEST_URI'] which contains the full URL request sans the domain and scheme (i.e. scheme is http or https) and it then parses the value to determine what URL was requested and thus what pages it should load.

Bypassing .htaccess? Get Apache to Load Virtual URLs (but good luck with that!)

So if you want to somehow bypass .htaccess your job would be to get Apache to respond to an arbitrary URL then load WordPress and set $_SERVER['REQUEST_URI'] to be the URL path plus parameters; IOW spoofing it but in a good way. That said, I know if know of no ways that are not overly complicated to do that.

Embedding /index.php/ (Maybe?!?)

Even though *Chris_O* is correct about prepending /index.php/ to your URLs I cringe whenever I see that. It adds 10 characters to every URL making them longer and less meaningful to search engines but far worse makes them less sharable and looks cryptic to users. Sorry Chris I know you meant well, but ugh!

Create Real Directories for Every URL (Maybe?)

One way to get pretty permalinks without touching Apache would be to write a script that would generate an actual directory for every URL that you want and then store an index.php there that would load WordPress. Of course that would be huge effort for tiny benefit and it would require the server to have write access which has to be worse than using an .htaccess file.

I hate to admit but this is what I did circa 1998 with an .ASP-based website when IIS didn’t support URL rewriting (and even today it’s still a real PITA!) It was an ugly hack, was a pain to maintain and I hated it but the URLs sure were great for both users and for SEO!

Best Solution? Add Rewrite Rules to httpd.conf

Back to what’s probably your best the solution, and @Simon Brown actually recommended it; add your rewrite rules to httpd.conf or one of the include files like httpd-vhosts.conf (which is how Apache is configured at localhost on my Mac.) Add the following directive making sure to change the directory to match the directory for your site:

<Directory "/home/example_user/public_html/">
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</Directory>

Bonus! With Lockdown Comes Performance Too

This last option should eliminate any .htaccess and put control back in their hands.
Even better it’s slightly more performant since httpd.conf is only loaded once when Apache starts but .htaccess files are loaded and parsed on every URL request!

P.S. One more thing to consider would be to front-end Apache with a caching server like Nginx which I believe is becoming a best practice for high-traffic WordPress sites that really need to be performant. It might take green field tweaking because I don’t think most people have been using Nginx to do the URL rewriting for Apache but if that direction interests you here are some links to pursue:

Leave a Comment