Process check: Spreading the Caddy Word

Doesn’t it have to be this way? Without these lines…

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d

or, in the case of Caddy, not file, files in the root path would become inaccessible, wouldn’t they? Unless, by design, this is a desirable outcome?

Yes, you’re correct about that.

But, think; what’s the goal with relocating WordPress into its own neat little subdirectory, anyway?

What purpose would one possibly have for moving WP down the hierarchy within the webroot… other than the intent to serve other things in the webroot without mixing them up with WP files?

If the goal was simply to only have WordPress and WordPress alone in your webroot - you could pick any arbitrary folder on disk, set the webroot there, and not have to worry about rewriting at all. Things would be much cleaner that way!

You might even pick /var/www/html as your “arbitrary folder on disk”. :thinking:

But, no, I have to assume the point of this is neatly sideloading other files, which that rewrite exemption allows for.


P.S. Other than slipstreaming other assets, this also allows the other behaviour specified in the document - that is, installing separate versions in other subdirectories of the web root.

The “default” becomes whichever one you rewrite to, and you can manually select for specific versions by prepending them yourself. That way, if you navigate to a version of the site that actually exists on disk, you get that version, ELSE you get the “default”.

Without this rewrite exemption, this behaviour would break, since you can specify the subdirectory for a given version but the web server would still prepend it with the “default” subdirectory - resulting in a nonexistent URI.

2 Likes

Maybe the clue for the ‘correct’ approach in any particular context is revealed by examining this section of the article htaccess modification.

For historical reasons, I might take an annual snapshot of the site (and WordPress version at the time?) and keep separate versions under the root folder in subdirectories /2020, /2021, etc. To access the current version, the matcher and rewrite in the Caddyfile might look like this:

@subdir {
  not path /2021/*
  not file
}
rewrite @subdir /2021{uri}

In this situation, I wonder whether not file is appropriate? I feel, in this case, that the other versions shouldn’t be accessible.

The beauty of the Caddy construct is that it provides a really neat way to access earlier versions of the site (and WordPress?). All that’s required is to alter the pointers to the subdirectory and reload Caddy.

EDIT: I just spotted the additions to your post. What I’ve stated may no longer be relevant.

Depends entirely on whether or not the web admin wants them to be accessible!

Like, with not file present, you could manually request /2020/ and get the 2020 index, but if you request / you’ll get 2021’s index.

Ultimately I don’t think people go around manually prefixing possible version numbers to their URIs, so the risk of a user mistakenly finding your other versions are low; unless you need to keep them inaccessible as a security measure, I’d leave not file present for the sheer accessibility of the web admin / maintainer being able to easily see them.

2 Likes

Right, time to test out the theory. I set up a test WordPress site. By default, the installation method I use placed the WordPress files in the webroot. Before moving the files to a subdirectory, I made sure I could access various parts of the site. No problems here.

It’s worth noting what appears in the address bar in the second screenshot.

Next, I move the WordPress files into the subdirectory my_subdir. I confirm that I no longer have access to the site
.

I update the site block in the Caddyfile with the code below and reload Caddy.

@subdir {
  not path /my_subdir/*
  not file
}
rewrite @subdir /my_subdir{uri}

Refreshing the browser, the site bursts into life. However, I now have a problem accessing subpages of the site.

There’s some other issue going on. After further research, I find the issue has to do with permalinks. This extract from the WordPress support article Using Permalinks.

When you create or update a “pretty” permalink structure, WordPress will generate rewrite rules and attempt to insert them into the proper .htaccess file. If it can’t, it will say something like You should update your .htaccess now and print out the rules for you to copy and paste into the file (put them at the end).

You’ll probably need to do this only once, because WordPress does the rewriting internally. If you ever move your WordPress home directory (Site address), you’ll need to repeat this step.

I have a look in the permalinks section of the test site and note the following.

A closer look at the rewrite rules…

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>

Some bits I recognise; some bits I don’t.

I also notice there is the (one and only!) WordPress reference to Caddy in the permalinks article. This extract…

Pretty permalinks are available under:

  • Apache web server with the mod_rewrite module
  • Nginx using try-files, e.g. according to this tutorial
  • Hiawatha web server with UrlToolkit support enabled.
  • Lighttpd using a 404 handler or mod_rewrite
  • Caddy using rewrite, e.g. according to this tutorial

Clicking the link to the tutorial takes me to a Caddy V1 article. (Looks like the WordPress permalinks article is the next one I should try to convert). This is the V1 rewrite rule: I don’t really understand what it’s telling me (e.g. what is this {query} bit?). I’m now stuck again. Help!

    # Routing for WordPress
    rewrite /{
        to {path} {path}/ /index.php?{query}
    }

EDIT: I’ve just made the test site https://xxx.udance.com.au accessible online.

1 Like

Essentially that’s the try_files pattern.

The php_fastcgi directive should already be doing that for you though. See the expanded form (the rewrite @indexFiles is the “long form” of the try_files directive… which uses the file matcher with the try_files option)

The {query} part is to preserve the request query (the bit after ? in a URL) after the rewrite, because otherwise it would be lost (i.e. copy it from the original URL into the rewritten URL)

1 Like

@francislavoie Thanks for responding :smiley:

Does this mean I shouldn’t have to take any further action i.e. the permalinks issue should inherently be addressed in Caddy V2? If so, ideas on how to proceed from here e.g. debug?

OK. I’m still getting my head around this. Sometimes {URI} is used as in…

rewrite @subdir /my_subdir{uri}

I’ve recently become comfortable with this after you explained it to me in Www handling - Use the same multiple site definition or use redirection? - #10 by francislavoie
Now you’re indicating sometimes I need to be more specific and use a subset of the URI. I need to think about this a bit more. How do I decide when I should use one or the other?

{uri} is the entire URI (path + query). Use that if you want to prefix it with something. {path} is just the path. {query} is just the query.

The way the fastcgi transport works, Caddy sends the entire original URI as requested by the client (browser) as an environment variable to php-fpm, among many other environment variables.

But index.php is the actual script that runs. That script is the entrypoint to the PHP app. It will do routing based on multiple different factors, some apps do it differently than others. Sometimes the apps want the query to be preserved in the rewritten path, others will just look at the original request URI.

I don’t think {query} will make a difference in this case; I was just explaining what that Caddyfile snippet from v1 did.

Hopefully. I don’t use WordPress so I can’t say for sure. You’ll have to try it to find out. (IMO WordPress is badsadbad, I very much prefer frameworks like Laravel, or just rolling my own from well maintained, modern libraries)

This part:

	# If the requested file does not exist, try index files
	@indexFiles file {
		try_files {path} {path}/index.php index.php
		split_path .php
	}
	rewrite @indexFiles {http.matchers.file.relative}

Might need to be overwritten in this case as we’ve put the main site in an arbitrary subdirectory. e.g.

try_files {path} {path}/index.php /my_subdir/index.php

OK. I’ve learnt something new.

You may very well be right, but if this infografic is to be believed:

  1. WordPress powers 40% of the internet.
  2. Around 64% of CMS sites are WordPress.
  3. Around 28% of WordPress sites run e-commerce.
  4. Around 75% of hacked CMS sites were built on WordPress :flushed:

On that last point, I’d like to add that I’m so glad I have my WP sites sitting behind Caddy!

I think the reason WP is so popular is that it’s accessible to the average person (like myself) who isn’t comfortable rolling their own site.

To follow up, I think you might be most grateful people who have no business coding are using WordPress instead of trying to roll their own site :laughing:

1 Like

Yeah. I realize why it’s popular… but I just wish it wasn’t. It’s pretty terribly maintained and is full of holes.

I’ll just uh, recommend https://statamic.com/ as an alternative. See Statamic vs WordPress

2 Likes

Right, time to refocus on the primary objective of this exercise and that is to try to figure out a way to get the Caddy word out there (for good and bad apps!) . I’m going to try Mathew’s suggestion and I’ll report back shortly, but first, an early morning cuppa :coffee:

This is what I love about you. You’re such a purist. Thank goodness for this trait! Without it, Caddy wouldn’t be the amazing product that it is. :heart:

Not only is the WP app less than ideal, but the support documentation is woeful as I’ve indicated in an earlier post Process check: Spreading the Caddy Word - #6 by basil. There’s been a recent and positive development though. I’m one step closer to the WP documentation team, which should make it easier to sell the idea of linking to Caddy wiki articles. Check out the WordPress forum thread Giving WordPress Its Own Directory.

3 Likes

I’m assuming I have to use the expanded form of php_fastcgi?

I’ve created a snippet to hide the detail

(php_fastcgi2) {
  route {
    # Add trailing slash for directory requests
    @canonicalPath {
      file {path}/index.php
      not path */
    }
    redir @canonicalPath {path}/ 308

    # If the requested file does not exist, try index files
#    @indexFiles file {
#    try_files {path} {path}/index.php index.php
#      split_path .PHP
#    }
#    rewrite @indexFiles {http.matchers.file.relative}
    try_files {path} {path}/index.php /my_subdir/index.php

    # Proxy PHP files to the FastCGI responder
    @phpFiles path *.php
    reverse_proxy @phpFiles {arg.0} {
      transport fastcgi {
    	split .PHP
      }
    }
  }
}

I’m not sure how to include environmental variables within this structure? e.g.

  php_fastcgi 127.0.0.1:9000 {
    env SERVER_PORT 80
  }

They go inside transport fastcgi.

Yes, but make sure you keep the same structure as the expanded form (long form of try_files). The split_path .php is important for it to actually work properly.

2 Likes

I believe you mean like this?

(php_fastcgi2) {
  route {
    # Add trailing slash for directory requests
    @canonicalPath {
      file {path}/index.php
      not path */
    }
    redir @canonicalPath {path}/ 308

    # If the requested file does not exist, try index files
    @indexFiles file {
#    try_files {path} {path}/index.php index.php
      try_files {path} {path}/index.php /my_subdir/index.php
      split_path .PHP
    }
    rewrite @indexFiles {http.matchers.file.relative}

    # Proxy PHP files to the FastCGI responder
    @phpFiles path *.php
    reverse_proxy @phpFiles {args.0} {
      transport fastcgi {
        env SERVER_PORT 80
    	split .PHP
      }
    }
  }
}

Yeah probably. I think you need lowercase .php though for both split parts. Linux filesystems are case sensitive.

1 Like

Reviewing post Process check: Spreading the Caddy Word - #15 by basil

When the WordPress files were relocated from the webroot to a subdirectory, and the site block in the Caddyfile updated to do an internal redirect…

@subdir {
  not path /my_subdir/*
  not file
}
rewrite @subdir /my_subdir{uri}

…the home page of the site remained accessible, but sub-pages became inaccessible. The issue wasn’t with permalinks. php_fastcgi handles permalinks intrinsically. For the sub-pages to become accessible again, the rewrite required an expanded version of php_fastcgi to be used.

This ‘hard-coding’ of ‘my_subdir’ causes a further problem though. Returning to an earlier discussion…

This breaks as a consequence. Can this be accommodated as well given that a reason for relocating WordPress files out of the webroot was to enable versioning? It seems to me like the hard-coding needs to be replaced with something relative, but I don’t know what that might be.

These are tests I undertook to confirm the issue:

My webroot is defined as root * /usr/local/www/wordpress. From the root, I set up the test environment.

cp -r my_subdir 2020
chown -R www:www 2020
echo "Hello from root!" >> sample.txt
echo "Hello from 2020!" >> 2020/sample.txt
echo "Hello from my_subdir!" >> my_subdir/sample.txt
echo "Hello from default!" >> my_subdir/default.txt

Test 1

Confirm that this Caddy structure worked as intended:

@subdir {
  not path /my_subdir/*
  not file
}
rewrite @subdir /my_subdir{uri}

c14

c15

Yep, that looks good.

Test 2

Check that the modified php_fastcgi works for my_subdir.

That looks good too.

Test 3

Check that versioning works.

Oops!

At the beginning of this post, I created a ‘version’ of the WP site.

cp -r my_subdir 2020
chown -R www:www 2020

This was a gross oversimplification of what WP versioning entails. Refer to this independent article Moving a WordPress Root Install to a Subdirectory Install and Vice Versa for a sense of what might be involved… For this exercise, I don’t really want to go any further down the rabbit’s hole. From tests 1 and 2, I’m satisfied the Caddy equivalent code for the WP article is working correctly.

Next step: Writing the wiki article.

The wiki article has been drafted for review Using Caddy to give WordPress its own directory.

The final step is to lobby the WordPress documentation team to have it referenced on a WordPress support page.

1 Like