I recalled mention of Acme v2 in the 0.10.12 release blog post. What threw me was that it was the “Do you agree to the terms? (y/n)
” prompt. It allowed entering “y”, but would fail anyway. Oh well, it didn’t take me tooooooo long to figure it out.
Any guidance on the proper Caddyfile syntax for the fpm-alpine variants of the Wordpress Docker images?
I started with the Wordpress Caddyfile example and tried a few variations which all yield 502s.
I read through 10 or so forum posts that kinda sorta deal with similar issues, but wasn’t able to piece it together.
Add errors stdout
to your Caddyfile and let us know what comes up when you get a 502.
I tore this down for now. Is there a working Caddyfile example somewhere that uses Docker (abiosoft/caddy) and fpm? I’m happy to log errors when I rebuild, but a known-to-be-working example would help too.
This is known good:
docker-compose.yml
version: '3'
services:
caddy:
image: abiosoft/caddy:latest
command: ["-log", "stdout", "-agree",
"-email", "letsencrypt@whitestrake.net",
"-conf", "/etc/Caddyfiles/Caddyfile"]
ports:
- "80:80"
- "443:443"
volumes:
- ./certificates:/root/.caddy
- ./caddyfiles:/etc/Caddyfiles
- ./keys:/root/keys
- ./sites:/srv
restart: always
php-fpm:
build: ./php-dockerfile
volumes:
- ./sites:/srv
restart: always
php-dockerfile/Dockerfile
FROM php:fpm-alpine
RUN apk add --no-cache libpng-dev
RUN docker-php-ext-install gd zip
caddyfiles/Caddyfile
http://www.whitestrake.net, https://www.whitestrake.net {
redir https://whitestrake.net{uri}
}
whitestrake.net {
root /srv/whitestrake
git {
repo git@gitlab.com:Whitestrake/whitestrake-home.git
key /root/keys/id_rsa
hook /c3b9edf5e8609ca3419c4a007448cd8d
}
gzip
push
fastcgi / php-fpm:9000 php
}
I made some headway on this. I think the 502 problem was that I was targeting the external directory of the bind-mount. Those errors are gone, but it’s not exactly working.
The Good
wp-main_1 | [23-Apr-2018 00:02:50] NOTICE: fpm is running, pid 1
wp-main_1 | [23-Apr-2018 00:02:50] NOTICE: ready to handle connections
The Bad
When accessing https://blog.example.com I get Access denied.
in the browser, and this in terminal:
403 security.limit_extension errors
wp-main_1 | 172.xx.xx.xx - 23/Apr/2018:00:14:00 +0000 "GET /" 403
wp-main_1 | [23-Apr-2018 00:14:00] WARNING: [pool www] child 57 said into stderr: "NOTICE: Access to the script '/var/www/html' has been denied (see security.limit_extensions)"
caddy_1 | 23/Apr/2018:00:14:00 +0000 [ERROR 0 /] Access to the script '/var/www/html' has been denied (see security.limit_extensions)
Then if I manually enter https://blog.example.com/wp-admin/install.php, I get an html-only page. There’s the expected content, but no .css or .js niceness. This is accompanied by this output:
CSS and JS security.limit_extensions errors
wp-main_1 | 172.xx.xx.xx - 23/Apr/2018:00:16:00 +0000 "GET /" 403
caddy_1 | 23/Apr/2018:00:16:00 +0000 [ERROR 0 /wp-includes/css/dashicons.min.css] Access to the script '/var/www/html/wp-includes/css/dashicons.min.css' has been denied (see security.limit_extensions)
caddy_1 | 23/Apr/2018:00:16:00 +0000 [ERROR 0 /wp-includes/js/jquery/jquery-migrate.min.js] Access to the script '/var/www/html/wp-includes/js/jquery/jquery-migrate.min.js' has been denied (see security.limit_extensions)
wp-main_1 | 172.xx.xx.xx - 23/Apr/2018:00:16:00 +0000 "GET /" 403
wp-main_1 | [23-Apr-2018 00:16:00] WARNING: [pool www] child 57 said into stderr: "NOTICE: Access to the script '/var/www/html/wp-admin/js/language-chooser.min.js' has been denied (see security.limit_extensions)"
caddy_1 | 23/Apr/2018:00:16:00 +0000 [ERROR 0 /wp-admin/js/language-chooser.min.js] Access to the script '/var/www/html/wp-admin/js/language-chooser.min.js' has been denied (see security.limit_extensions)
The Ugly
docker-compose.yml
version: '3.2'
services:
wp-main:
image: registry.gitlab.com/jetatomic/wordpress
depends_on:
- main-db
environment:
WORDPRESS_DB_PASSWORD: n0ne5hallp@55
WORDPRESS_DB_HOST: main-db
WORDPRESS_DB_USER: wpdrone
WORDPRESS_DB_NAME: wordpress
volumes:
- /var/www/main.wp:/var/www/html
restart: always
main-db:
image: mariadb
environment:
MYSQL_ROOT_PASSWORD: n0ne5hallp@55
MYSQL_USER: wpdrone
MYSQL_PASSWORD: n0ne5hallp@55
MYSQL_DATABASE: wordpress
volumes:
- /var/farm/mysql/main-db:/var/lib/mysql
restart: always
caddy:
image: abiosoft/caddy:0.10.12
command: ["-email", "letsencrypt@example.com",
"-conf", "/etc/Caddyfile",
"-agree"]
ports:
- 80:80
- 80:80/udp
- 443:443
- 443:443/udp
volumes:
- /var/farm/caddy/Caddyfile:/etc/Caddyfile
- /var/farm/caddy:/root/.caddy
- /var/discourse/shared/standalone:/sock
restart: always
Caddyfile
blog.example.com {
root /var/www/html
gzip
push
errors stdout
fastcgi / wp-main:9000
}
Dockerfile
FROM wordpress:4.9.5-php7.2-fpm-alpine
RUN apk add --no-cache \
libpng-dev \
wget \
unzip \
nano \
sudo \
&& docker-php-ext-configure gd --with-png-dir=/usr \
&& docker-php-ext-install gd zip
# Then more custom config junk
Since the security.limit_extensions
is a PHP-FPM thing, I suspect there’s a package or config missing in the Dockerfile. Rewrite? Preliminary googling shows methods for tweaking that extension, but everything so far looks sketchy security-wise.
So I’ll keep researching, and update if I get a solution. Until then, I’m open to suggestions.
Edit: Related thread, but no clear solution.
Change this line from your Caddyfile:
fastcgi / wp-main:9000
to:
fastcgi / wp-main:9000 php
otherwise, all requests will be proxied to the PHP-PFM listener (not just .php files).
I believe the security limit_extensions errors are appearing when requests for non-PHP indexes or static files are received, which should be handled directly by Caddy and not by the PHP-FPM listener.
Yes, I had it that way before and after posting that Caddyfile example. I guess I just copy/pasted it between tests. The behavior above happens with php
added to the line.
I understand what those words mean, but I don’t know how to effect that in Caddyspeak (or Nginx, for that matter, though there are a bunch of examples of Nginx rewrites for WP).
The PHP preset should handle that - only PHP scripts should be sent when the preset is added. Here’s what php
does:
ext .php # specifies extensions which will get proxied
split .php # tells Caddy that anything after this goes in PATH_INFO
index index.php # specifies a default file to try for an index request
So you can see with it enabled (or these settings manually specified - php
is just shorthand), no non-PHP file should ever be sent via FastCGI.
Can you double check it’s present in the Caddyfile, restart Caddy, and let me know if the CSS and JS requests still get sent to PHP?
Added this from this write-up:
rewrite {
if {path} not_match ^\/wp-admin
to {path} {path}/ /index.php?_url={uri}
}
Doesn’t resolve the security error, but it helps with the redirect from https://blog.example.com
I’ve seen the form /index.php?_url={uri}
before, but it seems to be a case of some form of citogenesis - I’ve never found in the WordPress documentation that this query parameter should be specified, and don’t believe it has any particular effect. Whenever I use WordPress that isn’t simply the official Docker WordPress image, I just rewrite to {path} {path}/ /index.php?{query}
, which works fine.
Caddyfile:
blog.example.com {
root /var/www/html
gzip
push
errors stderr
log stdout
fastcgi / wp-main:9000 php
}
You’re right, it looks like the security.limit_extensions
errors are gone and replaced by 200s (yay) 404s (boo). This is what I’m seeing currently:
caddy_1 | 172.xx.xx.xx - - [23/Apr/2018:03:52:10 +0000] "GET / HTTP/1.1" 404 38
wp-main_1 | 172.xx.xx.xx - 23/Apr/2018:03:52:23 +0000 "GET /wp-admin/install.php" 200
caddy_1 | 172.xx.xx.xx - - [23/Apr/2018:03:52:23 +0000] "GET /wp-admin/install.php HTTP/1.1" 200 4004
caddy_1 | 172.xx.xx.xx - - [23/Apr/2018:03:52:24 +0000] "GET /wp-admin/css/install.min.css?ver=4.9.5 HTTP/1.1" 404 38
caddy_1 | 172.xx.xx.xx - - [23/Apr/2018:03:52:24 +0000] "GET /wp-includes/css/dashicons.min.css?ver=4.9.5 HTTP/1.1" 404 38
caddy_1 | 172.xx.xx.xx - - [23/Apr/2018:03:52:24 +0000] "GET /wp-includes/css/buttons.min.css?ver=4.9.5 HTTP/1.1" 404 38
caddy_1 | 172.xx.xx.xx - - [23/Apr/2018:03:52:24 +0000] "GET /wp-includes/js/jquery/jquery.js?ver=1.12.4 HTTP/1.1" 404 38
caddy_1 | 172.xx.xx.xx - - [23/Apr/2018:03:52:24 +0000] "GET /wp-admin/js/language-chooser.min.js?ver=4.9.5 HTTP/1.1" 404 38
caddy_1 | 172.xx.xx.xx - - [23/Apr/2018:03:52:24 +0000] "GET /wp-includes/js/jquery/jquery-migrate.min.js?ver=1.4.1 HTTP/1.1" 404 38
Isn’t the rewrite supposed to go there?
rewrite {
to {path} {path}/ /index.php?{query}
}
Caddyfile
blog.example.com {
root /var/www/html
gzip
push
errors stderr
log stdout
fastcgi / wp-main:9000 php
rewrite {
to {path} {path}/ /index.php?{query}
}
}
With that bit in there I get a screen full of 302 errors:
wp-main_1 | 172.xx.xx.xx - 23/Apr/2018:05:27:55 +0000 "GET /index.php" 302
caddy_1 | 172.xx.xx.xx - - [23/Apr/2018:05:27:55 +0000] "GET /wp-admin/install.php HTTP/1.1" 302 23
302s aren’t errors, they’re redirections - specifically, non-cache-able redirections.
Since there are zero redirections in your Caddyfile, the only source of a redirection would logically be the PHP script itself, which seems to indicate that the FastCGI is working, at least. Try a curl -IL example.com
and look for a Location
header in the response.
HTTP/1.1 302 Found
Cache-Control: no-cache, must-revalidate, max-age=0
Content-Type: text/html; charset=UTF-8
Expires: Wed, 11 Jan 1984 05:00:00 GMT
Location: https://blog.example.com/wp-admin/install.php
Server: Caddy
Status: 302 Found
X-Powered-By: PHP/7.2.4
Looks good; seems to be redirecting to first-time setup. Now follow the chain; try curl -IL https://blog.example.com/wp-admin/install.php
?
Results from that query are identical. Isn’t it somewhat of a step backwards since the first-time setup page was loading before (though the CSS and JS was 404)?
This gets rid of the 302 for the /wp-admin/install.php
, but still throws 302s and 404s for the CSS and JS in /wp-include
:
rewrite {
if {path} not_match ^\/wp-admin
to {path} {path}/ /index.php?{query}
}
caddy_1 | xx.xx.xx.xx - - [23/Apr/2018:06:11:04 +0000] "GET /wp-admin/css/install.min.css?ver=4.9.5 HTTP/2.0" 404 38
wp-main_1 | xx.xx.xx.xx - 23/Apr/2018:06:11:04 +0000 "GET /index.php" 302
caddy_1 | xx.xx.xx.xx - - [23/Apr/2018:06:11:04 +0000] "GET /wp-includes/css/dashicons.min.css?ver=4.9.5 HTTP/2.0" 302 23
Yep, looks like that rewrite is causing some issues. It might be rewriting to index.php
when it should be just serving the file off disk?
What do you get from ls -l /var/www/html/wp-includes/css/dashicons.min.css
on the Caddy host?