WordPress Permalinks & CPTs returning 403 on Apache :: boundary between mod_rewrite and the WP-routing?

dhubs

Active Member
Joined
Nov 5, 2024
Messages
135
Reaction score
68
Credits
2,225
good day dear Linux-experts and friends, :)


first of all - this is one of my first postings in the new year. I am wishing you all a bright and good (and prosperous) new Year 2026

I’m currently debugging a WordPress installation where I’ve hit an interesting (and educational) edge case between Apache, mod_rewrite and WordPress’ internal routing, and I’d love to hear how others reason about this boundary.


Setup ( roughly simplified):

  • Apache 2.4 (mod_rewrite enabled)
  • PHP 8.x
  • WordPress (classic, not Bedrock)
  • Custom Post Type edih (registered via CPT UI, standard settings)
  • Default WordPress .htaccess rewrite rules

the findings and hmm - the symptoms - i currently encounter:

  • /?p=123 works
  • WP Admin works
  • Database + PHP clearly fine
  • .htaccess contains the standard WP catch-all rewrite
  • mod_rewrite is loaded

But wait - there is more - i have got trouble with the following


  • /foo/ → 403 Access denied
  • /foo/addsmart/ → 403
  • at some point even /test.php returned 403

Which strongly suggests Apache blocks path-based requests before WordPress ever sees them.

What makes this interesting to me:
  • Some server-side reasoning expects an explicit rewrite rule for /edih/
  • But in WordPress, CPTs are never mapped via Apache rules – only via the catch-all → index.php


So the real question seems to be to me::

Where exactly does WordPress routing begin, and under which Apache configurations can it be completely bypassed or blocked?

I’m especially interested in:
  • Apache <Directory> / Require / Options pitfalls
  • mod_security / WAF behaviour with extensionless URLs
  • cases where .htaccess exists but is not evaluated as expected

Did any body of you encounter similar things. Currently i am a bit clueless.
I feel this is one of those “you only learn it when it breaks” situations – and I’d love to collect experiences, mental models, and debugging strategies from others.

Thanks in advance – and happy to report back with the final root cause once found.

greetings :)
 


While I use WP quite a bit, this is something that I do not know.

At the same time, I think this is more of a WP question than it is a Linux question. As asked by @Rob above, the various logs may help you.

I figure I'll share this, instead. This is the SE site aimed at WP development questions, which I think would suit this question:


If you don't feel like dealing with the very strict format found at SE, this next link is actually full of some smart people:


Yes, it's Reddit -- but it's not one of the main pages or default subs. So, that means it's not too terrible. In fact, it's pretty good. I sometimes answer questions there, while I don't do so at SE. (I only deal with the Unix and Ubuntu sections of SE.)
 
I have had SElinux and appArmor require some tweaking for things like this in the past.
 
Check or add the AllowOverride setting in your Apache vhost, by default if you haven't allowed override files to be used Apache will block them.
 
hello dear friends, :)


first of all - many many thanks for your replies and for sharing your thoughts - ideas and experience.


here (at the moment) only a very very short reply here - i will answer more thouroghliy later the weekend.

now - after several remarkable errors - i am trying to add the WordPress-Rewrite-Regeln to the vHost-Config, - instead to the .htaccess


Code:
<Directory "/sites/www.my_site.com">
    AllowOverride None
    Require all granted
</Directory>

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


i will write more - later the weekend - now i have to leave the house


- btw: i am so glad that this forum is so great - and that we can discuss all the issues, matters and things - its absolute great to be here.

have a great day..

greetings:)
 
now - after several remarkable errors - i am trying to add the WordPress-Rewrite-Regeln to the vHost-Config, - instead to the .htaccess
Change this: AllowOverride None
To: AllowOverride All

Or pick the specific ones you need.
 
Hi all,

forst of all - many thanks for the replies:

thank you dear Rob, KGIII, dos2unix,:f33dm3bits - :)

happy that you were discussing the issues with me - now i want to share all the insights. -
here - a quick follow-up and thank you to everyone who replied – this turned out to be a very educational boundary case between Apache and WordPress.

Short version:
This was not a CPT or WordPress rewrite issue per se, but a server-level interaction where WordPress never got a chance to route the request.

### What was actually happening

  • /?p=123 worked reliably
  • /wp-admin/ worked
  • but any path-based URL (/edih/, /foo/, even /test.php) returned 403

That combination turned out to be the key signal.

The decisive discovery was:

When .htaccess was temporarily disabled (renamed), the site worked again – including /.

So Apache was reading .htaccess, but something in the rewrite/override chain caused Apache to deny the request before WordPress routing (index.php) could run.


### Root cause (in practice)

It ended up being a misalignment of three layers:

1. Apache directory / override handling

* .htaccess was evaluated, but certain rewrite situations triggered a 403
2. WordPress permalink state

* switching from Plain to Post name while the server config was still inconsistent
3. WordPress URL / HTTPS detection

Code:
   * temporary mismatch between
     `wp_options (home/siteurl)`
     and `WP_HOME / WP_SITEURL`
   * resulted later in a classic `wp-login.php` redirect loop

Once these were brought back into a consistent state, everything snapped into place:

Code:
* Apache rewrite → index.php works
* WordPress routing starts correctly
* CPT archive `/edih/` loads
* `/edih/addsmart/` returns a *proper WordPress 404* (no content yet), which is expected

### Key takeaway (for future readers)

* WordPress CPTs never need explicit Apache rewrite rules

Code:
* If `/?p=ID` works but `/slug/` does not:

* WordPress is innocent

Code:
 * look *below* it (Apache / override / security / rewrite context)
* A WordPress 404 is *good news*
  A 403 means WordPress was never reached

This really was one of those “you only learn it when it breaks” cases.

Thanks again for pointing me in the right directions (logs, AllowOverride, security layers, etc.).

very much appreciated

Happy 2026 to everyone!

greetings :)

keep up the great place - this forum is so awesome - i am very glad to be here..
 
Last edited:


Follow Linux.org

Staff online

Members online


Top