1. The problem I’m having:
I am trying to switch my personal server from apache to Caddy. I have solved a number of surprising issues, sometimes by changing the services running instead of the config, but this one has me stumped.
How can I convert this apache directive
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^cache/(.*).ico favicon.php?$1
to Caddyfile syntax? For those unfamiliar with Apache, this says “serve the file in /cache/foo.ico if it exists, and if not, execute favicon.php?foo”.
try_files
seemed the most relevant, and worked earlier, but here it serves the php file instead of executing it, and I’m not quite seeing how to use path_regexp
as a component of other tools; in particular, how else to check for a file.
2. Error messages and/or full log output:
2024/12/22 22:41:43.924 INFO using config from file {"file": "/etc/caddy/Caddyfile"}
2024/12/22 22:41:43.932 INFO adapted config to JSON {"adapter": "caddyfile"}
2024/12/22 22:41:43.935 INFO admin admin endpoint started {"address": "unix//run/caddy/admin.socket", "enforce_origin": false, "origins": ["", "//127.0.0.1", "//::1"]}
2024/12/22 22:41:43.936 INFO tls.cache.maintenance started background certificate maintenance {"cache": "0xc000898e80"}
2024/12/22 22:41:43.936 DEBUG http.auto_https adjusted config {"tls": {"automation":{"policies":[{}]}}, "http": {"servers":{"srv0":{"listen":[":8043"],"routes":[{"handle":[{"handler":"subroute","routes":[{"handle":[{"handler":"vars","root":"/srv/http/iiridayn.info/www"}]},{"handle":[{"handler":"static_response","headers":{"Location":["/filk/"]},"status_code":302}],"match":[{"path":["/filk"]}]},{"group":"group1","handle":[{"handler":"rewrite","uri":"{http.matchers.file.relative}"}],"match":[{"file":{"try_files":["@icon"]}}]},{"group":"group1","handle":[{"handler":"rewrite","uri":"{http.matchers.file.relative}?{http.regexp.icon.1}"}],"match":[{"file":{"try_files":["/favicon.php"]}}]},{"group":"group5","handle":[{"handler":"subroute","routes":[{"handle":[{"handler":"rewrite","strip_path_prefix":"/filk"}]},{"group":"group2","handle":[{"handler":"rewrite","uri":"{http.matchers.file.relative}"}],"match":[{"file":{"try_files":["{http.request.uri.path}"]}}]},{"group":"group2","handle":[{"handler":"rewrite","uri":"{http.matchers.file.relative}?{http.request.uri}\u0026{http.request.uri.query}"}],"match":[{"file":{"try_files":["filk/dumbwiki.php"]}}]}]}],"match":[{"path":["/filk/*"]}]},{"group":"group5","handle":[{"handler":"subroute","routes":[{"handle":[{"handler":"rewrite","strip_path_prefix":"/api"}]},{"group":"group0","handle":[{"handler":"rewrite","uri":"api.php/{http.request.uri}"}]}]}],"match":[{"path":["/api/*"]}]},{"group":"group5","handle":[{"handler":"subroute","routes":[{"handle":[{"handler":"file_server","hide":["/etc/caddy/Caddyfile"]}]}]}]},{"handle":[{"handler":"static_response","headers":{"Location":["{http.request.orig_uri.path}/"]},"status_code":308}],"match":[{"file":{"try_files":["{http.request.uri.path}/index.php"]},"not":[{"path":["*/"]}]}]},{"handle":[{"handler":"rewrite","uri":"{http.matchers.file.relative}"}],"match":[{"file":{"split_path":[".php"],"try_files":["{http.request.uri.path}","{http.request.uri.path}/index.php","index.php"]}}]},{"handle":[{"handler":"reverse_proxy","transport":{"protocol":"fastcgi","split_path":[".php"]},"upstreams":[{"dial":"unix//run/php-fpm/caddy.sock"}]}],"match":[{"path":["*.php"]}]}]}],"terminal":true}],"automatic_https":{"skip":["iiridayn.info"]}}}}}
2024/12/22 22:41:43.940 DEBUG http starting server loop {"address": "[::]:8043", "tls": false, "http3": false}
2024/12/22 22:41:43.940 INFO http.log server running {"name": "srv0", "protocols": ["h1", "h2", "h3"]}
2024/12/22 22:41:43.941 INFO autosaved config (load with --resume flag) {"file": "/root/.local/share/caddy/autosave.json"}
2024/12/22 22:41:43.941 INFO serving initial configuration
2024/12/22 22:41:43.943 INFO tls storage cleaning happened too recently; skipping for now {"storage": "FileStorage:/root/.local/share/caddy", "instance": "0df056e3-34d8-474b-997f-6e16dd3100db", "try_again": "2024/12/23 22:41:43.943", "try_again_in": 86399.999998003}
2024/12/22 22:41:43.944 INFO tls finished cleaning storage units
2024/12/22 22:41:48.112 DEBUG http.handlers.rewrite rewrote request {"request": {"remote_ip": "fe80::daef:18ce:84aa:80e1%enp2s0", "remote_port": "52232", "client_ip": "fe80::daef:18ce:84aa:80e1", "proto": "HTTP/1.1", "method": "GET", "host": "iiridayn.info:8043", "uri": "/cache/example.com.ico", "headers": {"User-Agent": ["curl/8.6.0"], "Accept": ["*/*"]}}, "method": "GET", "uri": "/favicon.php?%3Cnil%3E"}
2024/12/22 22:41:48.112 DEBUG http.handlers.file_server sanitized path join {"site_root": "/srv/http/iiridayn.info/www", "fs": "", "request_path": "/favicon.php", "result": "/srv/http/iiridayn.info/www/favicon.php"}
2024/12/22 22:41:48.112 DEBUG http.handlers.file_server opening file {"filename": "/srv/http/iiridayn.info/www/favicon.php"}
^C2024/12/22 22:41:52.394 INFO shutting down {"signal": "SIGINT"}
2024/12/22 22:41:52.394 WARN exiting; byeee!! 👋 {"signal": "SIGINT"}
2024/12/22 22:41:52.394 INFO http servers shutting down with eternal grace period
2024/12/22 22:41:52.395 INFO admin stopped previous server {"address": "unix//run/caddy/admin.socket"}
2024/12/22 22:41:52.395 INFO shutdown complete {"signal": "SIGINT", "exit_code": 0}
3. Caddy version:
v2.8.4
4. How I installed and ran Caddy:
a. System environment:
OS: Arch Linux
Installed: pacman -S caddy
Server: Bare metal ZBOX-MA320 under my desk
b. Command:
caddy run --config /etc/caddy/Caddyfile
c. Service/unit/compose file:
d. My complete Caddy config:
# The Caddyfile is an easy way to configure your Caddy web server.
#
# https://caddyserver.com/docs/caddyfile
#
# The configuration below serves a welcome page over HTTP on port 80.
# To use your own domain name (with automatic HTTPS), first make
# sure your domain's A/AAAA DNS records are properly pointed to
# this machine's public IP, then replace the line below with your
# domain name.
#
# https://caddyserver.com/docs/caddyfile/concepts#addresses
{
# Restrict the admin interface to a local unix file socket whose directory
# is restricted to caddy:caddy. By default the TCP socket allows arbitrary
# modification for any process and user that has access to the local
# interface. If admin over TCP is turned on one should make sure
# implications are well understood.
admin "unix//run/caddy/admin.socket"
debug
}
http://iiridayn.info:8043 {
# Set this path to your site's directory.
root * /srv/http/iiridayn.info/www
php_fastcgi unix//run/php-fpm/caddy.sock
handle_path /api/* {
rewrite * api.php/{uri}
}
# if not exist RewriteRule ^cache/(.*).ico favicon.php?$1
@icon path_regexp /cache/(.*).ico$
try_files @icon /favicon.php?{re.icon.1}
redir /filk /filk/
handle_path /filk/* {
try_files {path} filk/dumbwiki.php?{uri}&{query}
#if not exist RewriteRule ^(.*)$ dumbwiki.php?$1 [L,QSA,B,BNP]
}
handle {
# Enable the static file server.
file_server
}
# Another common task is to set up a reverse proxy:
# reverse_proxy localhost:8080
# Or serve a PHP site through php-fpm:
# php_fastcgi localhost:9000
# Refer to the directive documentation for more options.
# https://caddyserver.com/docs/caddyfile/directives
}
# Import additional caddy config files in /etc/caddy/conf.d/
#import /etc/caddy/conf.d/*
5. Links to relevant resources:
https://caddyserver.com/docs/caddyfile/matchers#path-regexp
https://caddyserver.com/docs/caddyfile/directives/try_files
https://caddyserver.com/docs/caddyfile/directives/php_fastcgi
https://caddyserver.com/docs/caddyfile/directives/handle_path
https://httpd.apache.org/docs/2.4/rewrite/flags.html#flag_bnp
https://caddyserver.com/docs/caddyfile/matchers#path