SWAG and WordPress in a subfolder

Desired setup

A SWAG reverse proxy should forward requests to WordPress running in the official wordpress docker image. The URL which is served by the reverse proxy is not the domain root, but a subfolder “blog”: https://www.example.com/blog.

What does not work

Letting the docker image itself serve wordpress in the root folder and write some clever proxy / rewrite rules. At first it seems to work, but when it comes wp-admin URLs like https://www.example.com/blog/wp-admin a magic redirection happens to https://www.example.com/wp-admin which points to outside the WordPress installation.

Fiddling around with RELOCATE, WP_HOME and WP_SITEURL does not solve the problem.

As it turns out WordPress needs to know the fact that it is installed in a subfolder, quote:

What you’ll want to do is run your WordPress container with WORKDIR set to /var/www/html/lab so it knows it is in a subdirectory and acts accordingly.

Description of setup

In SWAG config add nginx/site-confs/www_example_com.conf with the following content (taken default.conf as base and stripped comments):

server {
    listen 443 ssl;
    listen [::]:443 ssl;

    server_name www.example.com;
    include /config/nginx/ssl.conf;
    client_max_body_size 128M;

    location = / {
        return 301 $scheme://$host/blog/;

    location ^~ /blog/ {
        include /config/nginx/proxy.conf;
        include /config/nginx/resolver.conf;
        set $upstream_app wordpress;
        set $upstream_port 80;
        set $upstream_proto http;
        proxy_pass $upstream_proto://$upstream_app:$upstream_port;

In the WordPress docker image make sure that the WordPress installation is not in /var/www/html but in /var/www/html/blog and that the working directory is set to /var/www/html/blog. Here an example when using Portainer:

Screenshot Portainer working dir setting
Screenshot Portainer volume mapping

In this example a bind mount is used and there is a folder /portainer/Files/AppData/Config/wordpress/blog on the host.