Www to non-www, listen and bind IPv4/IPv6

Hello,

I’m using Caddy 0.10.4, WordPress and PHP7.1-FPM

  1. WordPress Network Admin Area doesn’t work => Error 500

my Caddyfile:

fastcgi / /var/run/php/php7.1-fpm.sock php {
	ext     .php
	split   .php
	index   index.php
}
rewrite / {
 	if {path} not_match ^(wp-(content|admin|includes).*)
 	to {path} {path}/ /index.php?_url={uri}
 }

The website path (URI) /wp-admin/network doesn’t work. The WordPress recommendation for Apache:

RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]

# add a trailing slash to /wp-admin
RewriteRule ^wp-admin$ wp-admin/ [R=301,L]

RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
RewriteRule ^(wp-(content|admin|includes).*) $1 [L]
RewriteRule ^(.*\.php)$ $1 [L]
RewriteRule . index.php [L]

How to reproduce into Caddyfile rewrite?

  1. Caddy 502 and/or 504 Bad Gateway

Caddy works properly with PHP7.1-FPM? All PHP requests works, /wp-admin also. But, all requests for themes or plugins area returns a “Bad Gateway”. I have to alternate to NGINX (mainline, indeed) and works like a charm, not into Caddy.

Ok, I’ve checked Github issues and googled, tho. But I do not know how to fix it. Suggestions?

Thank you very much.

I’d probably do the Caddyfile a little differently. This should be faster than using regex, and I think more readable. The php preset at the end of the fastcgi directive also makes the ext, split, and index subdirectives redundant.

fastcgi / /var/run/php/php7.1-fpm.sock php
rewrite {
	if {path} not_starts_with /wp-content
	if {path} not_starts_with /wp-admin
	if {path} not_starts_with /wp-includes
	to {path} {path}/ /index.php
}

That said, either approach is equivalent to the Apache recommendation. It seems unlikely that the issue is with the Caddyfile.

A 502 error means that Caddy received an inappropriate response from upstream. A 504 means a timeout. The upstream in this case is /var/run/php/php7.1-fpm.sock.

It could be an issue with php7.1-fpm, or perhaps with /wp-admin/network/index.php. It may even be an issue with Caddy’s fastcgi. You might try changing PHP verisons, trying FastCGI over a port instead of unix socket, or redownloading WordPress.

1 Like

Thank you very much about your feedback.
In fact, 502 means a inappropriate response from upstream and 504 a timeout.

I"ve been changed my Caddyfile.
Assuming a WordPress multisite and multidomain

rewrite {
	if {path} not_match ^\/wp-admin
	to {path} {path}/ {path}/index.php /index.php/{uri_escaped}
}
rewrite {
	r ^([_0-9a-zA-Z-]+/)?(wp-(content|admin|includes).*)
	to ${2}
}
rewrite {
	if {path} not_match ^\/wp-admin
	r ^([_0-9a-zA-Z-]+/)?(.*\.php)$
	to ${2}
}

For now, works like a charm. Anyway, I’ve still 3 problems.

1. I’d like a global redirect

assuming all sites will not work with 80, only HTTPS, no-www
* www to non-www - PENDING
* 80 to 443 - SOLVED

2. Resolv and bind both => IPv4 and IPv6

Yeah, I’ve checked Github Issues: #864 at Caddy Server already and #9334 at Golang
a. if possible
* how to bind?
* bind domain?
* bind address only?

b. if not possible
* Can I use NGINX to proxy with Caddy?
* NGINX with 80 and 443 port => Caddy with another port?
* How to use the same certificate automatically created by Caddy?

3. Remove /index.php/ from permalinks into WordPress

Assuming the Domain.com actually
I know… I can use only %postname% as permalink
* Using NGINX, I do not have this /index.php/, what happens? Why?
* Is it abnormal behavior? How to remove it from path structure?

Suggestions?
Thank you very much.

After reading Caddy Docs:
I’m trying to create a generic rules to redirect all www to non-www

https://www.* { <=== Is it correct?
	redir 308 {
		if {hostonly} ___ wat?
		to ___ wat?
		/  https://{host}{uri} ___dunno
	}
}

From redir config, with bit adjust:
@matt

:80 { <=== It's enough, tho... really?
	redir 308 {
		if {>X-Forwarded-Proto} is http
		/  https://{host}{uri}
	}
}

It’s work flawlessly, I guess.


About listen and bind IPv6 and IPv4 at same time, I do not have idea.

If you leave the host portion off the address, it will listen on all interfaces. :slight_smile: i.e. :80 or :443

For this one specifically, handle the www labels for your site like this:

http://www.example.com, https://www.example.com {
	redir https://example.com
}

Specifying both http and https labels will help Caddy issue the right redirect the first time for the HTTP request, instead of double bouncing the client by redirecting to HTTPS and then redirecting to canonical.

Thank you, @Whitestrake

I have been tried this solution alike. Anyway, I just tried something like NGINX can do it.

server {
         server_name "~^www\.(.*)$" ;
         return 301 $scheme://$1$request_uri ;
         # can use https:// instead $scheme
}

@matt I have tried to use only :80 but using netstat -latn, doesn’t work properly. Suggestions?

tcp        0      0 my.ip1.v4.address:80       0.0.0.0:*               LISTEN
tcp        0      0 my.ip2.v4.address:80       0.0.0.0:*               LISTEN

Anyway, the /etc/hosts is correct, /etc/resolv.conf also.

Here:

  • Ubuntu 16.04 (xenial)
  • 64bit
  • custom Caddy (from site)
  • version Caddy: 0.10.6

@Whitestrake and @matt, I’ve two changes:

  1. [::]:80 to :80

  2. edit /etc/gai.conf - Ubuntu 16.04 64bit (Xenial), remove comments below and change value to 1:

    label 2002::/16      1
    label 2001:0::/32    1
    

Listening on port 80 and 443, IPv4 and IPv6 at same time. It works properly and fine.

1 Like

@Whitestrake, I can use regex into rewrite on Caddy. Ok. Caddy allow a regular expression instead server name - as NGINX? I do not try it yet and I didn’t see something like that on docs.

No, the site name does not allow regular expressions per-se, except some limited use of wildcard: https://caddyserver.com/docs/http-caddyfile

Thanks for answer, @matt.
Using net.host, placeholders and rewrite, maybe? Or … is it better to forget? :slight_smile:

The closest you’ll get to that behaviour would be, in a default site, selecting for your host in an if statement.

:80, 443 {
	redir {
		if {host} match [REGEX]
		# go somewhere
	}
}

The problem is that you can’t get match groups out of it, so it’s not very useful. You’d need to know the hostname you want to go to, without the www, in advance, which is why I made the recommendation above (which only redirects www for the sites you know in advance).

I thought briefly about using rewrite, but you can’t manipulate the host value with that, only the request URI.

1 Like

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