Looking for an example for Caddyfile with PHP backend

Hello everybody,

I would like to run a caddy server in front of a php-fpm deployment. The documentation for Caddy directives is great, but unfortunately the documentation is lacking real world examples.

I spend hours on building a proper docker image for the use case and a proper Caddyfile and I am not quiet happy with it yet.

What I am missing is something like an official caddy-php-fpm image or other caddy images that provide more than just the caddy web server.

My current Dockerfile is this one here:

FROM alpine:3.5

RUN apk --update --no-cache add php5-fpm php5-mcrypt php5-soap php5-openssl php5-gmp php5-pdo_odbc php5-json php5-dom php5-pdo php5-zip php5-mysql php5-mysqli php5-sqlite3 php5-apcu php5-pdo_pgsql php5-bcmath php5-gd php5-xcache php5-odbc php5-pdo_mysql php5-pdo_sqlite php5-gettext php5-xmlreader php5-xmlrpc php5-bz2 php5-memcache php5-mssql php5-iconv php5-pdo_dblib php5-curl php5-ctype ca-certificates
COPY data phpinfo.php /app/
COPY caddy start.sh /usr/local/bin/
COPY Caddyfile /etc/caddy/Caddyfile
COPY php.ini /etc/php5/php.ini

RUN chmod +x /usr/local/bin/caddy && chmod +x /usr/local/bin/start.sh

EXPOSE 80
EXPOSE 443
WORKDIR /app
CMD ["start.sh"]

This is really just a POC (so better do not run it in production).
The start.sh script is just starting php-fpm and caddy:

#!/bin/sh

php-fpm
caddy run --config /etc/caddy/Caddyfile --adapter caddyfile

My Caddyfile looks like this:

{
	experimental_http3
}

myfancydomain:80 {
	file_server
	root * /app/
	php_fastcgi localhost:9000
}

I have the following problems right now with my caddyfile:

  1. I would like to disable HTTPS completely. Certificate management will not be done by caddy it will just run as webserver in the cluster behind an ingress like Traefik or Nginx that will do Let’s Encrypt via cert-manager.
  2. I would like to be able to match on all hosts. Right now if I access the website via IP, I see just a blank website. How do I match all hostnames?
  3. I would like to expose metrics, but these metrics should only be accessible on the cluster. How would I do this? I read the documention metrics [matcher], but I have no idea how I can limit the access to the metrics via host rules or anything else.

My ideal Caddyfile should look this (pseudocode ahead… please take it with a grain of a salt):

{
	experimental_http3
}

* {
    file_server
    root * /app/
    php_fastcgi localhost:9000
    tls_enable FALSE
}

metrics {
    allow prometheus.monitoring.svc.cluster.local
}

First of all, HTTP/3 is HTTPS-only. So if you disable TLS, you can’t use HTTP/3.

To just handle any HTTP request without caring what the hostname is, just make your site label :80. Caddy will not enable Automatic HTTPS if it sees that you’re not using the HTTPS port.

Caddy automatically makes metrics available on the admin endpoint, i.e. localhost:2019/metrics. If you need it to be available on more than just localhost, you can either change the admin endpoint to something wider like :2019 to let anything which can reach your Caddy instance on that port (risky because then anything untrusted could mess with your Caddy config), or you can make it available at another port like this:

:8000 {
    metrics
}

Basically this just says “for any request to port 8000, respond with the metrics”.

FYI there’s an example right here of what a config for a PHP app may look like:

I would recommend ordering your Caddyfile directives in the same order as that, because it’s in the same order as the predetermined directive order the Caddyfile adapter uses to sort them:

2 Likes

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