Help needed for nginx rewrite to caddy

1. Output of caddy version:

v2.6.2 h1:wKoFIxpmOJLGl3QXoo6PNbYvGW4xLEgo32GPBEjWL8o=

2. How I run Caddy:

Install caddy via apt and run using systemd.

a. System environment:

OS: Debian GNU/Linux 11 (bullseye) x86_64
CPU: AMD Opteron 63xx class (1) @ 2.499
Memory: 121MiB / 976MiB

b. Command:

systemctl [start/stop/restart/status] caddy

c. Service/unit/compose file

/etc/caddy/Caddyfile

d. My complete Caddy config:

❯ caddy fmt Caddyfile
(httpcats) {
        handle_errors {
                rewrite * /{http.error.status_code}
                reverse_proxy https://http.cat {
                        header_up Host http.cat
                }
        }
}

import /etc/caddy/site/Example
------
❯ caddy fmt site/Example
example.com {
        root * /var/www/example.com/public/
        php_fastcgi unix//dev/shm/php-cgi.sock

        rewrite {
                regexp ^/(.*)$
                to {path} {path} /index.php?q={1}
        }

        file_server

        # import httpcats

        log {
                output file /var/log/caddy/example.com.log
        }
}

3. The problem I’m having:

I’m trying to transfer following nginx rewrite config to caddy, still failed after searching and copying confs on web.

location / {
	if (!-e $request_filename){
		rewrite  ^(.*)$  /index.php?s=$1  last;   break;
	}
}

For the methods I tried in the Community, none works.

4. Error messages and/or full log output:

5. What I already tried:

Method A:

@try_files {
    not path /wp-admin/*
    file {
        try_files {path} {path}/ /index.php
    }
}
rewrite @try_files {http.matchers.file.relative}

Method B:

rewrite {
        regexp ^/(.*)$
        to /index.php?q={1}
 }

And some others lol none works

1 Like

Have you tried just php_fastcgi unix//dev/shm/php-cgi.sock on its own without rewriting?

That should automatically handle rewriting to an index.php file if the requested file doesn’t exist. Check the expanded form: https://caddyserver.com/docs/caddyfile/directives/php_fastcgi#expanded-form

It does pretty much exactly what you’re trying for, built-in.

1 Like

Hi, thanks for your advice.

Here’s my updated config, but still not working.

example.com {
        
        root * /var/www/example.com/public/
        php_fastcgi  unix//dev/shm/php-cgi.sock
        file_server
        
        # import httpcats

        log {
                output file /var/log/caddy/example.com.log
        }
        
}

Hmm. Try modifying your php_fastcgi directive like so:

php_fastcgi unix//dev/shm/php-cgi.sock {
  try_files {path} index.php?s={uri}
}
1 Like

Still doesn’t work. https://example.com returns 404.

Updated config:

example.com {
        
        root * /var/www/example.com/public/
        php_fastcgi unix//dev/shm/php-cgi.sock {
                try_files {path} index.php?s={uri}
        }
        file_server
        
        # import httpcats

        log {
                output file /var/log/caddy/example.com.log
        }
        
}

*domain name reserved

Can you run:

stat /var/www/example.com/public/index.php

❯ stat index.php 
File: index.php
Size: 767             Blocks: 8          IO Block: 4096   regular file
Device: fe01h/65025d    Inode: 39023       Links: 1
Access: (0777/-rwxrwxrwx)  Uid: ( 1002/     www)   Gid: (    0/    root)
Access: 2022-10-17 12:47:46.860260718 +0800
Modify: 2021-03-09 20:04:40.000000000 +0800
Change: 2022-10-15 13:37:28.131835723 +0800
 Birth: 2022-10-15 00:24:27.642948493 +0800

Specifically, could you run:

stat /var/www/example.com/public/index.php

(With the entire path included)

Or otherwise run

pwd
stat index.php

One after the other.

Please enable the debug global option and show Caddy’s logs. It will show more details as to the rewrites it performed, and why it returns a 404.

❯ stat /var/www/example.com/public/index.php 
  File: /var/www/example.com/public/index.php
  Size: 767             Blocks: 8          IO Block: 4096   regular file
Device: fe01h/65025d    Inode: 39023       Links: 1
Access: (0777/-rwxrwxrwx)  Uid: ( 1002/     www)   Gid: (    0/    root)
Access: 2022-10-17 12:47:46.860260718 +0800
Modify: 2021-03-09 20:04:40.000000000 +0800
Change: 2022-10-15 13:37:28.131835723 +0800
 Birth: 2022-10-15 00:24:27.642948493 +0800

I chmoded the file to 777 to prevent some unnecessary permission problem during test, and it’d be changed to normal after this problem solve.

What I’m confuse about is that whether to set the owner to caddy or www.

Used this config and debug mod enabled, here’s the log after I visit https://example.com*.

Oct 18 13:26:38 local.hostname caddy[5642]: {"level":"debug","ts":1666070798.2031229,"logger":"events","msg":"event","name":"tls_get_certificate","id":"1a4530c0-f518-4877-ab94-76935f4e7c42","origin":"tls","data":{"client_hello":{"CipherSuites":[19018,4865,4866,4867,49196,49195,52393,49200,49199,52392,49162,49161,49172,49171,157,156,53,47,49160,49170,10],"ServerName":"example.com","SupportedCurves":[6682,29,23,24,25],"SupportedPoints":"AA==","SignatureSchemes":[1027,2052,1025,1283,515,2053,2053,1281,2054,1537,513],"SupportedProtos":["h2","http/1.1"],"SupportedVersions":[31354,772,771,770,769],"Conn":{}}}}
Oct 18 13:26:38 local.hostname caddy[5642]: {"level":"debug","ts":1666070798.2041628,"logger":"tls.handshake","msg":"choosing certificate","identifier":"example.com","num_choices":1}
Oct 18 13:26:38 local.hostname caddy[5642]: {"level":"debug","ts":1666070798.2046714,"logger":"tls.handshake","msg":"default certificate selection results","identifier":"example.com","subjects":["example.com"],"managed":true,"issuer_key":"acme.zerossl.com-v2-DV90","hash":"ae2f71082ba1059d4d9512410aa92de10804fa015b40510b66788e225cda5e7c"}
Oct 18 13:26:38 local.hostname caddy[5642]: {"level":"debug","ts":1666070798.2051926,"logger":"tls.handshake","msg":"matched certificate in cache","remote_ip":"*.*.*.*","remote_port":"36375","subjects":["example.com"],"managed":true,"expiration":1673568000,"hash":"ae2f71082ba1059d4d9512410aa92de10804fa015b40510b66788e225cda5e7c"}
Oct 18 13:26:38 local.hostname caddy[5642]: {"level":"debug","ts":1666070798.6872675,"logger":"http.handlers.file_server","msg":"sanitized path join","site_root":"/var/www/example.com/public/","request_path":"/appstore","result":"/var/www/example.com/public/appstore"}
Oct 18 13:26:38 local.hostname caddy[5642]: {"level":"debug","ts":1666070798.6882267,"logger":"http.log.error.log0","msg":"{id=tf4xvyqh4} fileserver.(*FileServer).notFound (staticfiles.go:579): HTTP 404","request":{"remote_ip":"*.*.*.*","remote_port":"36375","proto":"HTTP/2.0","method":"GET","host":"example.com","uri":"/appstore","headers":{"Sec-Fetch-Mode":["navigate"],"User-Agent":["Mozilla/5.0 (iPhone; CPU iPhone OS 16_0_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Mobile/15E148 Safari/604.1"],"Accept-Language":["zh-CN,zh-Hans;q=0.9"],"Sec-Fetch-Dest":["document"],"Accept":["text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"],"Accept-Encoding":["gzip, deflate, br"]},"tls":{"resumed":false,"version":772,"cipher_suite":4865,"proto":"h2","server_name":"example.com"}},"duration":0.001305362,"status":404,"err_id":"tf4xvyqh4","err_trace":"fileserver.(*FileServer).notFound (staticfiles.go:579)"}
Oct 18 13:26:39 local.hostname caddy[5642]: {"level":"debug","ts":1666070799.1378458,"logger":"http.handlers.file_server","msg":"sanitized path join","site_root":"/var/www/example.com/public/","request_path":"/appstore","result":"/var/www/example.com/public/appstore"}
Oct 18 13:26:39 local.hostname caddy[5642]: {"level":"debug","ts":1666070799.1379955,"logger":"http.log.error.log0","msg":"{id=qckz78gxf} fileserver.(*FileServer).notFound (staticfiles.go:579): HTTP 404","request":{"remote_ip":"*.*.*.*","remote_port":"36375","proto":"HTTP/2.0","method":"GET","host":"example.com","uri":"/appstore","headers":{"Accept":["*/*"],"Sec-Fetch-Dest":["empty"],"Referer":["https://example.com/appstore"],"Sec-Fetch-Mode":["cors"],"User-Agent":["Mozilla/5.0 (iPhone; CPU iPhone OS 16_0_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Mobile/15E148 Safari/604.1"],"Accept-Language":["zh-CN,zh-Hans;q=0.9"],"Accept-Encoding":["gzip, deflate, br"]},"tls":{"resumed":false,"version":772,"cipher_suite":4865,"proto":"h2","server_name":"example.com"}},"duration":0.00032219,"status":404,"err_id":"qckz78gxf","err_trace":"fileserver.(*FileServer).notFound (staticfiles.go:579)"}
Oct 18 13:26:39 local.hostname caddy[5642]: {"level":"debug","ts":1666070799.138443,"logger":"http.handlers.file_server","msg":"sanitized path join","site_root":"/var/www/example.com/public/","request_path":"/favicon.ico","result":"/var/www/example.com/public/favicon.ico"}
Oct 18 13:26:39 local.hostname caddy[5642]: {"level":"debug","ts":1666070799.1384964,"logger":"http.log.error.log0","msg":"{id=gfppa9541} fileserver.(*FileServer).notFound (staticfiles.go:579): HTTP 404","request":{"remote_ip":"*.*.*.*","remote_port":"36375","proto":"HTTP/2.0","method":"GET","host":"example.com","uri":"/favicon.ico","headers":{"Accept-Encoding":["gzip, deflate, br"],"Accept":["*/*"],"Sec-Fetch-Dest":["image"],"Referer":["https://example.com/appstore"],"Sec-Fetch-Mode":["no-cors"],"User-Agent":["Mozilla/5.0 (iPhone; CPU iPhone OS 16_0_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Mobile/15E148 Safari/604.1"],"Accept-Language":["zh-CN,zh-Hans;q=0.9"]},"tls":{"resumed":false,"version":772,"cipher_suite":4865,"proto":"h2","server_name":"example.com"}},"duration":0.000144442,"status":404,"err_id":"gfppa9541","err_trace":"fileserver.(*FileServer).notFound (staticfiles.go:579)"}

* remote_ip, hostname, domain name reserved.

I’m thinking that the caddy user under which Caddy runs cannot read the files, because they’re owned by www and group root.

When installing via the apt package, the caddy user gets added to the www-data group. You can use that group or the caddy group for all your site’s files, and it should work. Make sure that PHP is configured to be able to read the files as well.

Remember that to be able to read a particular file, every parent directory needs to be “executable” by the given user. So make sure /var and /var/www and /var/www/example.com and /var/www/example.com/public are all executable for the relevant users.

I reconfigured the php-fpm to make sure it has the right permission, and chown caddy -R to the entire folder, but it behaves exactly like before.

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