• Quick summary of situation:
    This is a private blog area which is manually proxied by a route in a custom web app, because the custom app has custom authentication and the client wanted the blog to be behind the same authentication. It’s docker-compose, with an nginx container in front and an ASP.NET Core MVC container behind that (which lives at /app/), and there’s a particular controller route in that MVC app (/app/privateblog/) that just relays requests to the internal docker-compose address for the private blog container.
    (Diagram in case that was hard to follow: )
    This was originally a Ghost blog container, and it worked as designed. But Ghost wasn’t meeting the client’s needs as a blog engine, so we decided to simply switch the Ghost container out for a WordPress container.
    Which I thought would be pretty much drop-in.
    But it’s not.

    The problem is that WordPress doesn’t fully respect a setting telling it what its URL is.

    With Ghost, this was as simple as a single environment line in my docker-compose.yml and everything just worked:

    composename.blog.privateghost:
        image: ghost
        environment:
            url: "https://example.com/app/privateblog"

    So naturally, when I went to switch it over to WordPress, I googled around and I came up with this:

    composename.blog.privatewordpress:
        image: wordpress
        environment:
            WORDPRESS_CONFIG_EXTRA: |
                define('WP_HOME','https://example.com/app/privateblog');
                define('WP_SITEURL','https://example.com/app/privateblog');

    Now, that works well enough to complete the initial installation, but WordPress frequently ignored it and would redirect to https://composename.blog.privatewordpress.
    For example, If you visit /app/privateblog/wp-admin, WordPress feels the need to redirect you just to slap on a trailing /, but in doing so it redirects you to https://composename.blog.privatewordpress/wp-admin/ instead of /wp-admin/ being on the end of the externally facing path defined in WP_HOME and WP_SITEURL.
    (I’m not sure where it’s even getting the composename.blog.privatewordpress URL in order to use it instead, as docker-compose isn’t providing any internal dns or anything, so it must be getting it out of the incoming request headers from the internally forwarded request or something? Why would it DO that if WP_HOME and WP_SITEURL are things?)
    After googling around some more, I found a suggestion to add this line to the wp-config block in my WORDPRESS_CONFIG_EXTRA:
    $${_SERVER}['HTTP_HOST'] = $${_SERVER}['HTTP_X_FORWARDED_HOST'];
    That didn’t seem to improve the situation (although, as I type that, I realize I should probably double-check that the manual proxy controller code is even attaching any X-Forwarded headers; I’ll get back to this on that)…
    I also saw some stuff about doing a str_replace of _SERVER['REQUEST_URI'] in there, but that seemed to be about correcting paths below the domain name and doesn’t fit very well into composename.blog.privatewordpress –> example.com/app/privateblog

    Now way over budget for this simple change, in order to try to put it to bed I went the route of brutely rewriting the Location header in the responses coming back from the proxy to string replace any instance of the URL configured to redirect to (https://composename.blog.privatewordpress) with the path of the proxying controller (https://example.con/app/privateblog).
    I then did the same thing with url-encoded versions, in case it was escaped in a querystring as a redirect_to or anything like that.

    Problem solved?

    Still no.

    Because sometimes it’s not in a redirect header, it’s a link in text on the rendered pages.
    Best example, because it’s 100% consistent:
    The 2nd page of the list of Pages in the dashboard.

    Why does that ignore WP_HOME and WP_SITEURL?? Where does it get its information from instead? Doesn’t this cause problems for all sorts of people who need WP_HOME or WP_SITEURL to work properly?? Is there some setting I can change to make it stop behaving this way???
    I don’t really want to brutely string-replace the response content, that seems way too far down the wrong track ??

Viewing 1 replies (of 1 total)
  • Thread Starter gbowe

    (@gbowe)

    To any poor soul who finds themselves in the same situation:
    There were a couple of keys for me to getting this working as expected.

    One: while copying the request headers, my proxy code was changing the Host header to the internal host, and setting X-Forwarded-Host to the original external Host value.
    This doesn’t work, as it appears that WordPress uses the Host header value to form links on the admin dashboard and its various redirects, instead of constructing them from the WP_HOME value, for some reason that continues to escape my understanding.
    So I removed those two lines from my proxy code, meaning the host header of the internal request had the same value as the external request.
    (I believe this is what ProxyPreserveHost does if you’re using apache mod_proxy as your reverse proxy, or if you’re using nginx proxy_pass I think you say proxy_set_header Host $http_host. I imagine this is also why things suggested to set $_SERVER['HTTP_HOST'] to $_SERVER['HTTP_X_FORWARDED_HOST'] in the wp config, but that didn’t correct WordPress’s behavior when I did that, it seemed to be happening after WordPress had already grabbed that value, so ymmv. Probably easier to do it on the proxy’s side than on WP’s.)

    Two: it complicated matters that the original external and resulting proxied internal urls differed by more than just the host but had a path, /app/privateblog/{whatever} being just /{whatever} to WordPress. There isn’t really any use of or support for a X-Forwarded-Path header in the proxying world, so having a different path inside than outside is ice skating uphill if you can avoid it…
    The easiest way to resolve this while still using the default WordPress image for the container was to just add an Alias in apache to serve the root’s content from the path as well.
    So I added a file binding to the volumes of the privatewordpress in my compose yaml:

    
    - /pathonhost/000-default.conf:/etc/apache2/sites-available/000-default.conf
    

    And the contents of /pathonhost/000-default.conf was just copied from what the contents of that file is in the default WP image, with one line added before the closing </VirtualHost> tag:

    
            Alias '/app/privateblog' '/var/www/html'
    </VirtualHost>
    

    And then obviously I added the /app/privateblog path to the end of my configuration setting for what url to send all proxied requests to.

    With those changes, at least so far it seems to finally be working as expected.

    I’d close this support topic, except that I’d still like to know: why does WordPress use the contents of the Host header to form these redirects and navigation links in the dashboard, instead of the WP_HOME value which it does use to form navigation links in the content?

Viewing 1 replies (of 1 total)
  • The topic ‘Dashboard etc. not obeying WP_HOME/WP_SITEURL??’ is closed to new replies.