I thought I’d have a crack at providing a Caddy example for Symfony. I chose Symfony because an NginX example is provided on the Symfony site and I’m curious to see how that converts to Caddy. It seems like it would be a more straightforward conversion than translating from Apache to Caddy.
The challenge here is that I don’t use Symfony or NginX so I’m totally reliant on forum members and Caddy core maintainers to help me with the conversion and testing. If any forum members use Symfony and can test the end product of this exercise, that would be super helpful.
The minimum configuration to get your application running under Nginx is:
server {
server_name domain.tld www.domain.tld;
root /var/www/project/public;
location / {
# try to serve file directly, fallback to index.php
try_files $uri /index.php$is_args$args;
}
# optionally disable falling back to PHP script for the asset directories;
# nginx will return a 404 error when files are not found instead of passing the
# request to Symfony (improves performance but Symfony's 404 page is not displayed)
# location /bundles {
# try_files $uri =404;
# }
location ~ ^/index\.php(/|$) {
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
fastcgi_split_path_info ^(.+\.php)(/.*)$;
include fastcgi_params;
# optionally set the value of the environment variables used in the application
# fastcgi_param APP_ENV prod;
# fastcgi_param APP_SECRET <app-secret-id>;
# fastcgi_param DATABASE_URL "mysql://db_user:db_pass@host:3306/db_name";
# When you are using symlinks to link the document root to the
# current version of your application, you should pass the real
# application path instead of the path to the symlink to PHP
# FPM.
# Otherwise, PHP's OPcache may not properly detect changes to
# your PHP files (see https://github.com/zendtech/ZendOptimizerPlus/issues/126
# for more information).
# Caveat: When PHP-FPM is hosted on a different machine from nginx
# $realpath_root may not resolve as you expect! In this case try using
# $document_root instead.
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
fastcgi_param DOCUMENT_ROOT $realpath_root;
# Prevents URIs that include the front controller. This will 404:
# http://domain.tld/index.php/some-path
# Remove the internal directive to allow URIs like this
internal;
}
# return 404 for all other php files not matching the front controller
# this prevents access to other php files you don't want to be accessible.
location ~ \.php$ {
return 404;
}
error_log /var/log/nginx/project_error.log;
access_log /var/log/nginx/project_access.log;
}
A config for Symfony would, by default, look just the same as one for WordPress that you wrote up the other day, except that root will have /public appended (like the nginx config above).
Symfony uses index.php as the routing entrypoint, so the php_fastcgi directive will do the job just fine.
Symfony’s defaults are better in that they recommend a public/ directory as the webroot, where the rest of the code sources are siblings of that directory. That means that actual source files cannot be directly accessed, (unlike WordPress, which does not use a subdirectory as the webroot, which is a modern best-practices no-no).
domain.tld www.domain.tld {
# Set this path to your site's directory:
root * /var/www/project/public
# Enable Gzip compression:
encode gzip
# Serve PHP files through php-fpm:
php_fastcgi unix//run/php/php7.4-fpm.sock
# Enable the static file server:
file_server
# Enable HTTP request logging
log {
output file /var/log/caddy/access.log
}
}
Depending on your PHP-FPM config, the php_fastcgi can also be php_fastcgi 127.0.0.1:9000.
Suggestions for improvement to code or comments? What about the placement of the log directive?
The NginX code has error logging. Where does that happen for Caddy? In the Caddy process log? If so, do I need to include a global section in the Caddy code and reference the process log?
{
# Enable process logging
log {
output file /var/log/caddy/caddy.log
}
}
domain.tld www.domain.tld {
# Set this path to your site's directory:
root * /var/www/project/public
# Enable Gzip compression:
encode gzip
# Serve PHP files through php-fpm:
php_fastcgi unix//run/php/php7.4-fpm.sock
# Enable the static file server:
file_server
# Enable HTTP request logging
log {
output file /var/log/caddy/access.log
}
}
From post #2, NginX has been configured to behave in a certain way and the comments reflect this. Caddy default behaviour is likely to be different. Please comment on Caddy behaviour for each of these NginX comments:
Not necessary if running as a systemd service, because the journal will have your logs already. See Keep Caddy Running — Caddy Documentation. Similar deal with Docker with docker logs <caddy container ID>
NGINX Unit is a totally different app than NGINX proper. It’s a server without config files, configured entirely via a JSON config API. (Sound familiar? API — Caddy Documentation)
I don’t think that’s worth worrying about. Caddy will execute any .php files in public/, defaulting to index.php, but I see no issue with that. Just makes it easier to add some one-off scripts for temporary testing or whatever. Devs rarely do put any other PHP scripts in public though.
They mean to prevent URLs like /index.php/foo/bar which is technically the same as /foo/bar due to the way index.php is used as an entrypoint, using the remainder as the PATH_INFO variable passed to PHP. (Try it with your WordPress app for paths to some blog article for example, put /index.php in front of the path)
Preventing both from working would avoid duplicate possible URLs (for SEO or some possible edge-case security bugs, I guess). Caddy’s default doesn’t prevent this.
It should be trivial to prevent with a path_regexp + redir to force the browser to request without a /index.php, but IMO that’s not worth worrying about, it isn’t worth the added config.
That’s just saying those docs are CC license, which I guess only you need to care about, if you do at all, since you’re authoring these changes.