opensourceprojects.dev

A broadsheet for software that doesn't ask for your email

FrankenPHP embeds PHP directly into Caddy with Early Hints, worker mode, and aut...
GitHub RepoImpressions21

Project Description

View on GitHub

FrankenPHP: A Modern PHP Server Built on Caddy

PHP isn’t dead — it’s just been waiting for a better runtime. FrankenPHP is an embeddable PHP server that sits directly inside Caddy, the popular Go web server. No separate PHP-FPM, no config hacks. Just PHP glued into a fast, HTTPS-by-default server.

If you’ve ever wished PHP could feel more like a modern language runtime (think Node.js or Go’s standard library), this is worth a look.


What It Does

FrankenPHP wraps PHP into Caddy as a native module. You run your PHP app through Caddy’s reverse proxy, but instead of forwarding to a separate PHP-FPM process, Caddy talks directly to an embedded PHP interpreter.

The core idea: one binary, one process, zero config for TLS. You get automatic HTTPS via Let’s Encrypt, HTTP/2, HTTP/3, and a PHP worker mode that keeps your app in memory between requests.


Why It’s Cool

A few things stand out:

  • Worker mode – Instead of spawning a new PHP process per request (like traditional mod_php or FPM), FrankenPHP keeps your PHP app running persistently. Your bootstrap code runs once. No more loading Laravel or Symfony from scratch on every page load. Think of it like PHP-FPM’s pm = static on steroids.

  • Early Hints (103 status code) – Caddy sends 103 Early Hints to the browser before your PHP script finishes. The browser can start preloading CSS, JS, or images while PHP is still generating the response. This can shave off significant time for real-world pages, especially on slower connections.

  • Automatic HTTPS, HTTP/2/3, and config-as-code – This is Caddy’s superpower, but now it’s married to your PHP app. You don’t need a separate reverse proxy or TLS manager. Write a simple Caddyfile and go.

  • Single binary deployment – With CGO_ENABLED=1, you can compile a static binary that includes both Caddy and PHP. No dependencies. No “install PHP 8.2, enable extensions, configure FPM.” Just drop the binary on a server and run.

  • Compatible with existing frameworks – Works with Laravel, Symfony, WordPress, Drupal, etc. No code changes needed. If it runs on PHP-FPM, it runs on FrankenPHP.


How to Try It

The easiest way is via Docker:

docker run -v $PWD:/app -p 80:80 -p 443:443 dunglas/frankenphp

This serves your current directory as a PHP app. Caddy will automatically handle HTTPS if you have a domain pointed at it.

Or if you want to play locally without a domain name:

docker run -v $PWD:/app -p 8080:80 -p 8443:443 -e SERVER_NAME=localhost dunglas/frankenphp

Then open http://localhost:8080 (or https://localhost:8443 if you accept the self-signed cert).

For a production setup, check the GitHub README — it covers running bare-metal, using a custom Caddyfile, and compiling your own binary.


Final Thoughts

FrankenPHP isn’t going to replace every PHP setup. But if you’re tired of managing a stack of PHP-FPM, nginx, and certbot, it’s a breath of fresh air. Worker mode alone can dramatically improve performance for framework-heavy apps, and Early Hints gives you a cheap front-end speed boost.

It’s still relatively new, but the approach feels right. PHP needs tools that match modern expectations — and embedding it into a server that handles TLS, HTTP/2, and configuration with minimal fuss is a step in that direction.

Try it on a side project. You might not go back.


Follow @githubprojects for more developer tools and open source highlights.

Back to Projects
Project ID: f60599a2-70a9-447a-9635-42e9a34f26eeLast updated: July 10, 2026 at 06:45 AM