WordPress Pretty Permalinks in Caddy v2

1. Caddy version:

v2.6.4 h1:2hwYqiRwk1tf3VruhMpLcYTg+11fCdr8S3jhNAdnPy8=

2. How I installed, and run Caddy:

apt install caddy
caddy start

a. System environment:

Distributor ID: Linuxmint
Description: Linux Mint 21.1
Release: 21.1
Codename: vera

Linux persephone 5.15.0-56-generic #62-Ubuntu SMP Tue Nov 22 19:54:14 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux

b. Command:

caddy start

c. Service/unit/compose file:

Paste full file contents here.
Make sure backticks stay on their own lines,
and the post looks nice in the preview pane.

d. My complete Caddy config:

beaststore.localhost {
        root * /home/james/Development/beaststore.net
        encode gzip
        php_fastcgi unix//var/run/php/php8.1-fpm.sock
        file_server

        log {
                output file /home/james/Development/beaststore.net/errors.log
        }
}

3. The problem Iā€™m having:

According to this forum post, Caddy supports WordPress Pretty Permalinks out-of-the-box.

However, all of my URLs are prepended with index.php e.g. https://beaststore.localhost/index.php/my-account/

The Permalinks page in WordPress shows the index.php file for every Permalink structure option, except the plain permalinks.

4. Error messages and/or full log output:

Please see below, the error for what Iā€™ve already tried.

Error: adapting config using caddyfile: parsing caddyfile tokens for 'rewrite': Caddyfile:7 - Error during parsing: Wrong argument count or unexpected line ending after 'rewrite'

5. What I already tried:

I have tried some of the try_files and rewrite directives, but I havenā€™t found one that works. Either I get formatting errors, or it doesnā€™t rewrite the URLs correctly. I think that this may be because they were for Caddy v1?

e.g.

rewrite / {
            to {path} {path}/ /index.php?{query}
        }

6. Links to relevant resources:

https://caddy.community/t/development-caddy-considerations-when-using-permalinks-in-wordpress/13351/6

Per https://caddyserver.com/docs/caddyfile/directives/php_fastcgi#expanded-form, the php_fastcgi directive already does exactly what WordPress needs in order to run with pretty permalinks:

	# 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 {file_match.relative}

So you donā€™t need to do anything special with your config. It does, in fact, work with just the normal directive by default.

Does the ā€˜Custom Structureā€™ option allow you to edit it to remove /index.php/?

If not - does the Site Address (URL) in Settings ā†’ General have /index.php/ on the end for you to remove?

Hey @Whitestrake thanks for your prompt reply.

I canā€™t remove the the index.php from the custom structure, nor can I remove it from the site address.

Screenshot attached.

Thatā€™s not a problem with Caddy, thatā€™s a problem with whatever WordPress config youā€™re using.

1 Like

Hey @francislavoie Iā€™ve done a completely fresh install of WordPress and still having this issue.

Iā€™ve included the Caddyfile and wp-config.php below. Iā€™ve also checked the database to confirm there arenā€™t any strings including index.php. The only one I could see was the permalink_structure key in the wp_options table, set to /index.php/%postname%/ but this is the same as in my previous screenshot, I canā€™t change this value via the WP dashboard.

I am using wp core download to fetch the WordPress files, then wp config create to generate the wp-config.php file. I have also tried creating the config file via the WordPress UI, but the result is the same.

Caddyfile

example.localhost {
	root * /home/james/Development/example.com
	encode gzip
	php_fastcgi unix//var/run/php/php8.1-fpm.sock
	file_server
}

wp-config.php

<?php
/**
 * The base configuration for WordPress
 *
 * The wp-config.php creation script uses this file during the installation.
 * You don't have to use the web site, you can copy this file to "wp-config.php"
 * and fill in the values.
 *
 * This file contains the following configurations:
 *
 * * Database settings
 * * Secret keys
 * * Database table prefix
 * * ABSPATH
 *
 * @link https://wordpress.org/support/article/editing-wp-config-php/
 *
 * @package WordPress
 */

// ** Database settings - You can get this info from your web host ** //
/** The name of the database for WordPress */
define( 'DB_NAME', 'example' );

/** Database username */
define( 'DB_USER', 'root' );

/** Database password */
define( 'DB_PASSWORD', 'password' );

/** Database hostname */
define( 'DB_HOST', 'localhost' );

/** Database charset to use in creating database tables. */
define( 'DB_CHARSET', 'utf8mb4' );

/** The database collate type. Don't change this if in doubt. */
define( 'DB_COLLATE', '' );

/**#@+
 * Authentication unique keys and salts.
 *
 * Change these to different unique phrases! You can generate these using
 * the {@link https://api.wordpress.org/secret-key/1.1/salt/ WordPress.org secret-key service}.
 *
 * You can change these at any point in time to invalidate all existing cookies.
 * This will force all users to have to log in again.
 *
 * @since 2.6.0
 */
define( 'AUTH_KEY',         ' Y~Wy[3HlHbH;FytH.aa2}Y<cu>++jwk0I:x}R/oMe!UP$`X rq4h^gfhIbFZphx' );
define( 'SECURE_AUTH_KEY',  'SV1Yp#4]/1=y&%PG<cdU}YUst^xccaYT2>+@xl5tC=v)<pn(Si zd4L*L/<mE|JF' );
define( 'LOGGED_IN_KEY',    'm28y.<UH~KfDNhLd$k2lJ,wL_:ZwMIZeY`_6Ym$<A2^lmOF8dVf4(g{13+p;{=U7' );
define( 'NONCE_KEY',        'j?!><8Mv9!gWgq@|lsrli8L_}G@AjLe.G~RZ@Ha!,0A~*@}<*JCE-@VZT6bcIrWk' );
define( 'AUTH_SALT',        'Z=Z$T8}VV;WMx 5NhHdYsfR`9?7gQP|rOd[-|bfL<TgIei+ptwCs/YKz23 @ ,di' );
define( 'SECURE_AUTH_SALT', 'c~I:LJQ393xSs%(~Hd@2Tm2G9Q93iGj&zA4ZIg<m+>Iv08f+/Ous<`MI{z*T+qAU' );
define( 'LOGGED_IN_SALT',   'qV9i6n=<Fv2BjLh~F|FL36?.Z_ harH/zx1J>Zlem~Q/j9], s,f#]g[P03McF~4' );
define( 'NONCE_SALT',       'v}URPPas<[M*8Y[M&@YlF8nz5<W8[=-gB(yG~*1o~H+r<7l~Yd<Lsx;7Q> ^Oi`@' );

/**#@-*/

/**
 * WordPress database table prefix.
 *
 * You can have multiple installations in one database if you give each
 * a unique prefix. Only numbers, letters, and underscores please!
 */
$table_prefix = 'wp_';

/**
 * For developers: WordPress debugging mode.
 *
 * Change this to true to enable the display of notices during development.
 * It is strongly recommended that plugin and theme developers use WP_DEBUG
 * in their development environments.
 *
 * For information on other constants that can be used for debugging,
 * visit the documentation.
 *
 * @link https://wordpress.org/support/article/debugging-in-wordpress/
 */
define( 'WP_DEBUG', false );

/* Add any custom values between this line and the "stop editing" line. */



/* That's all, stop editing! Happy publishing. */

/** Absolute path to the WordPress directory. */
if ( ! defined( 'ABSPATH' ) ) {
	define( 'ABSPATH', __DIR__ . '/' );
}

/** Sets up WordPress vars and included files. */
require_once ABSPATH . 'wp-settings.php';

Well, we have no evidence that this is a problem with Caddy. Many other users run WordPress without issue. I suggest you ask on WordPress support forums for help.

Ok thank you @francislavoie.

Iā€™ll continue investigating and get back to you if I can find out what the issue is.

Hey @francislavoie, good morning.

So Iā€™ve been doing a bit of debugging, and I may have found something related?

In WordPress thereā€™s this function got_url_rewrite() in /wp-admin/includes/misc.php:45. I can see itā€™s checking for the presence of Apacheā€™s mod_rewrite, nginx, and IIS permalinks, but nothing related to Caddy specifically.

If I modify this function to always return true, or detect Caddy via headers, it appears to be working, and the URLs no longer have the index.php string.

Appreciate that this isnā€™t part of Caddy directly, but perhaps an additional check could be included as part of this function, in order to detect Caddy?

/**
 * Returns whether the server supports URL rewriting.
 *
 * Detects Apache's mod_rewrite, IIS 7.0+ permalink support, and nginx.
 *
 * @since 3.7.0
 *
 * @global bool $is_nginx
 *
 * @return bool Whether the server supports URL rewriting.
 */
function got_url_rewrite() {
	$got_url_rewrite = ( got_mod_rewrite() || $GLOBALS['is_nginx'] || iis7_supports_permalinks() );

	/**
	 * Filters whether URL rewriting is available.
	 *
	 * @since 3.7.0
	 *
	 * @param bool $got_url_rewrite Whether URL rewriting is available.
	 */
	return apply_filters( 'got_url_rewrite', $got_url_rewrite );
}

:man_shrugging:

Thatā€™s more of a question for WordPress developers. I donā€™t know what mechanism theyā€™re using to check the presence of web servers.

Yes, I understand, Iā€™ll reach out to the WordPress team about it.

Itā€™s a bit odd though as I would have thought it would have been an issue for other WordPress sites if itā€™s due to this got_url_rewrite call, but if they arenā€™t having the same issue as me with the permalinks, then Iā€™m not sure what else it might be.

Anyway, thanks again for your help!

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.