10

We've recently switched one of our web servers to apache 2.4 and running PHP via php-fpm and mod_proxy_fcgi. Most everything works quite well, but there is one problem that I don't understand yet. One of our sites is running WordPress, which brings along a good list of rewrite rules in its .htaccess file. And it seems that those don't work so well with the ProxyPass directive in the vhost setup.

Our vhost contains the following configuration:

ProxyPassMatch ^/(.*\.php(/.*)?)$ fcgi://127.0.0.2:9126/<path>/$1

This works in most cases.

Now, the htaccess file does, amongst other things, this:

RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
RewriteRule  ^([_0-9a-zA-Z-]+/)?(wp-(content|admin|includes).*) $2 [L]
RewriteRule  ^([_0-9a-zA-Z-]+/)?(.*\.php)$ $2 [L]
RewriteRule . index.php [L]

As the site is a multiblog in subdirectories, I read that the URL /blogname/wp-admin/load-styles.php?xxxx should be rewritten as wp-admin/load-styles.php?xxx (the second rewrite rule). But looking at the mod_proxy log, the request that is passed actually is /blogname/wp-admin/load-styles.php.

I read this as there being a precedence problem – the ProxyPass rule fires before all of the RewriteRules have been worked off.

I'm stymied - what can be the cause?

TheCleaner
  • 32,352
  • 26
  • 126
  • 188
Konrad Neuwirth
  • 223
  • 1
  • 2
  • 6
  • Have you tried putting the rewrites in the vhost rather than in the .htaccess? (Make sure you take care of the leading slash if you do.) – Ladadadada Jun 14 '12 at 16:40
  • This could only be a stopgap solution: The software that writes the rewrite rules is WordPress itself. It is used to updating the rules once in a while (and be it in the process of an update), so I can't totally hide them from the webspace. – Konrad Neuwirth Jun 14 '12 at 16:45
  • @KonradNeuwirth Does it work properly when you switch to proxying via a `RewriteRule` with the `[P]` flag, below the other rules? – Shane Madden Jun 15 '12 at 06:57

3 Answers3

12

I found this solution, I don't know if is the best way, but works for me.

  1. Remove the line:

    ProxyPassMatch ^/(.*\.php(/.*)?)$ fcgi://127.0.0.2:9126/<path>/$1
    
  2. Add this in your directive:

    <Directory /var/www/yoursiste.com>
        Options -Indexes +FollowSymLinks -ExecCGI +MultiViews
    
        AllowOverride All
    
        <IfModule mod_proxy_fcgi.c>
            RewriteEngine On
            RewriteBase /
            RewriteOptions InheritBefore
            RewriteCond %{REQUEST_FILENAME} -f
            RewriteRule ^([^\.]+\.php)$ fcgi://127.0.0.2:9126/var/www/yoursite.com/$1 [L,P]
        </IfModule>
    
        Order allow,deny
        allow from all
    
        <IfVersion >= 2.4>
            Require all granted
        </IfVersion>
    </Directory>
    

    All the real php files will redirect to fcgi proxy.

    And the "RewriteOptions InheritBefore" This forces the current configuration to inherit the configuration of the parent, but are applied before rules specified in the child scope (.htaccess at the directory). Is the only way I found to has compatibility between the fcgi config and the client .htaccess config.

  3. To control other parameters you could need for the proxy:

    <IfModule mod_proxy_fcgi.c>
        <Proxy fcgi://127.0.0.2:9126>
            ProxySet timeout=1800 disablereuse=on
        </Proxy>
    </IfModule>
    
3

With ProxyPassMatch, .htaccess files are ignored. Try using FilesMatch and SetHandler instead, as described here and here.

Peter Nowee
  • 181
  • 6
  • Please don't post the exact same answer multiple times. Instead, when applicable, vote/flag the questions as duplicate. – Sven Aug 04 '16 at 10:45
  • This is what I was looking for. It allows to use mod_rewrite in htaccess context. – David Mar 18 '20 at 17:07
0

Move the rewrite logic into the ProxyPassMatch expressions. Add two additional ProxyPassMatch lines before the one in your vhost config as follows:

ProxyPassMatch ^/([_0-9a-zA-Z-]+/)?(wp-(content|admin|includes)/.*\.php(/.*)?)$ fcgi://127.0.0.1:9000/<path>/$2    
ProxyPassMatch ^/([_0-9a-zA-Z-]+/)?(.*\.php(/.*)?)$ fcgi://127.0.0.1:9000/<path>/$2
ProxyPassMatch ^/(.*\.php(/.*)?)$ fcgi://127.0.0.1:9000/<path>/$1