return to table of content

FrankenPHP: Modern PHP App Server

harrisonjackson
60 replies
1d13h

I haven't done any php development in maybe 10 years but this landing page almost got me to spin up a hello world.

I like the elephant frankenstein character - goofy and ugly/cute. Design, color scheme, copy, and animations are clean :chefkiss:

The value prop is well highlighted - at least for someone that's been out of php dev for a while. This seems like a nice way to bootstrap something small. Getting started code snippet makes it seem quick and easy.

zer00eyz
58 replies
1d12h

I moved from PHP to Golang a bit over a decade ago... Because binary deploys are the bees knees.

I dont want 8 containers isolating a bunch of bad software or worse messed up dependency's (looking at you python, maybe some ruby and node code as well). Because rather than releasing installable software you packaged up "works for me" and shipped it to the world.

I might play with this out of nostalgia but not so sure that I want these sorts of things in my production environment any more.

francislavoie
24 replies
1d12h

This is PHP running inside a Go server, btw. Compiled with CGO. One binary, one process.

zer00eyz
23 replies
1d12h

Wow the PHP is going to magically get into the binary?

/s

Yes I could build this with c-go + the PHP and statically link everything (and there might need to be a bit of prayer involved...) ... or I could just write GO and accomplish all the same things with fewer steps.

That knotted up mess is why containers are popular.

withinboredom
9 replies
1d11h

There are things Go excels at and there are things PHP excels at. They don’t always overlap. For example, you can write a simple web app in 100 lines of php code, and a process manager in 100 lines of Go code. If you flip the languages around, the number of lines explodes.

zer00eyz
4 replies
1d10h

I started writing PHP back in the 3 and 4 days... I have been writing go for over a decade.

If I had to add a few dynamic elements to a static HTML site, php is still king.

If we're building an API, go will win hands down. Not only in LOC but performance, and reporting.

When you get into whole pages (think blogs or shopping or... ) a lot of that is going to depend on what framework you're grabbing on the PHP side. There arent a lot of "batteries included" solutions on the golang side... You might end up writing fewer lines of code in the first week but by the end of the month were going to be at feature parity and your quickly going to fall behind.

The moment I need a SPA, on page interactive GUI you're going to end up with a JS framework and an API back end... here again, go will shine.

withinboredom
3 replies
1d10h

If we're building an API, go will win hands down.

I'm not so sure of that. Writing business logic in PHP is usually more concise than in Go, and more flexible. Also, I can think of a number of json schemas that are impossible to replicate in Go's type system but work just fine in PHP.

dgb23
1 replies
1d6h

You can't fully replicate JSON schemas in either language without writing logic.

In terms of just static definitions, Go has typed container types while PHP has not. That's a pretty common case for JSON. PHP is more convenient at another common case which is heterogeneous maps. Neither of those languages make me particularly happy in that regard.

It also depends on what you're doing with the JSON. If you want/need to walk through it in a single pass fashion, then Go is definitely more fitting.

withinboredom
0 replies
11h9m

Go has typed container types while PHP has not.

I suggest looking at https://github.com/Crell/Serde, if that is a requirement in PHP.

PHP is more convenient at another common case which is heterogeneous maps.

Or arbitrary, user-defined keys...

If you want/need to walk through it in a single pass fashion, then Go is definitely more fitting.

array_map, array_reduce, array_column is pretty good at walking through arrays very quickly, assuming you parsed the json into arrays instead of objects.

zer00eyz
0 replies
1d9h

> Also, I can think of a number of json schemas that are impossible to replicate in Go's type system but work just fine in PHP.

Not at all. There are some that would be painful to write "by hand". An expansive and nested set of null fields would suck if I had to spell it all out...

https://sqlc.dev << changes everything. If you add in the YAML (and I hate yaml) you can get your JSON to DB mapping in there, as well as your validations (all output as struct tags).

Everything else that you're going to want (transforming inputs to/from json, logging, auth) is some pretty simple middleware.

dgb23
2 replies
1d7h

If you use the std lib you can write a simple web app in Go as well in few lines of code?

The only difference would be a little bit of boilerplate for setting up application state (a few lines) and the necessary type definitions, which you can avoid with PHP if you just deal in "arrays" instead of classes. But I don't think the LOC would explode for Go.

My big counterpoint is this however:

I would wager for a beginner of either languages, it's much more straight forward to get a server running with Go than with PHP/Apache. There's no configuration, you don't need to install multiple things, you don't need to learn about a thousand footguns, error handling is more streamlined and obvious and you wouldn't have version issues and get showered in deprecation warnings down the line. And even though the PHP docs are quite extensive and useful, they are not on the same level as authoritative Go docs and guides. PHP has three advantages over Go in terms of convenience and ease of use: statelessness, little bit easier to deploy (once set up) and very cheap, easy to use hosting products available.

CaptainOfCoit
1 replies
1d6h

If you use the std lib you can write a simple web app in Go as well in few lines of code?

PHP is made for web development though, while Go is made for different use cases. Comparing the standard libraries makes this very clear.

Things PHP comes with that Go doesn't come with (just as some examples about standard library differences): PDO (DB interface), session management, built-in mail sending, localization and internationalization. That's just from the top of my head.

Go has it's places though, and it works well for web development too. But even I who like Go in general more than PHP, can acknowledge that PHP (by default) is better setup for web development out of the box.

That said, I would much prefer Go than PHP too, but hard to argue against PHP for web development without resolving to emotions and feelings.

dgb23
0 replies
1d5h

Apart from localization all of the things you mentioned come with Go as well. There's net/smtp, database/sql. You can implement in-memory sessions in Go with a few lines or use the well established gorilla sessions or similar.

The only thing you _need_ to install via dependencies is a DB driver.

On top of it you are getting a HTML template system with very good security defaults. You are generally better guided and guarded when dealing with HTTP user input. Routing and handling is more explicit and doesn't require you to deal with the Apache configuration syntax etc. There are no arcane configuration footguns like max_input_vars that will silently break your application and so on.

Errors handling and logging are again, more straight forward, universal and explicit.

If you need interactivity, SEE and Websockets are not only easier to use but also a more natural fit for Go.

I think for a language beginner those things are very, very beneficial. Us more experienced programmers sometimes forget how many battle scars we had to earn with languages like PHP.

acheong08
0 replies
1d2h

You can write a simple web app in a tiny number of lines in Go as well. Try templ

francislavoie
9 replies
1d11h

Well, FrankenPHP avoids that prayer, cause it's already done for you lmao

But obviously the point of using PHP is for its ecosystem, frameworks etc. Go is still missing a lot of that, the Go community has a weird aversion to frameworks.

zer00eyz
8 replies
1d11h

I wrote PHP from version 3 to version 6... I remember PHP before it had "frameworks"...

PHP ate perl because the battery's were included, you didn't need CPAN, and it had an amazing manual...

Python (pip), Ruby (gems) and Node (NPM) all looked much more attractive because they had rich library's at their core and symphony wasnt really useful yet.

Yet Go eschews a lot of the same package management issues those other languages have. And a lot of go devs look at the standard library the same way early PHP devs looked at it "I dont need a lot more than this".

It's not that go devs are framework adverse we only want what we need and nothing more. In a language that favors composition frameworks quickly become "baggage".

It's kind of interesting to watch someone come from a language with a strong package ecosystem and watch them build their first go project. They tend to cruise GitHub and throw EVERYTHING in the cart. It takes them 3-4 days of working with all that before they are complaining up a storm! You hand that same dev SQLC, Validator, and point them at middle ware and the standard lib and ask them for API's and they come back 2 days later grinning ear to ear.

Go, done well, is brutalism. Blocky, functional concrete buildings have an amazing charm to them... Go is blocky, its utilitarian, its expressive... You dont write cute code in go, you dont try to make go magical, you want clear easy to read and understand code... Your more likely to come back and add features long before you have to address the performance of go.

seszett
4 replies
1d11h

version 6

PHP6? That was long ago because I don't even remember it!

I don't have much to say otherwise, except you could very well say the same "Go is great" without having to shit on PHP and the project that is being discussed here.

Especially since you don't really come off as very knowledgeable on what you're talking about.

zer00eyz
3 replies
1d9h

It might shock you that I wrote perl before PHP... I have been in the game a LONG time. I was around for php being the language that EVERYONE shit on. I was around when PHP got somewhat huge and respectable. PHP buttered my bread for a number of years and I was one of its bigger advocates.

My lament here isnt about PHP at all.. It's about the instructions here: https://frankenphp.dev/docs/embed/ to generate a monolithic binary... It's about the execution of this script https://github.com/dunglas/frankenphp/blob/main/build-static...

None of that is very go like at all. Having spent a lot of time with PHP I recognize a good portion of what turns up in that shell script. That having been said there are parts of it (the curl of the diff) with NO context that I would pause and go figure out what the hell that was. It really needs a note as to WHY it's there so I dont have to go hunting. It looks like the shell script is meant to work in the docker container... A real build system might be in order here (make, basel, mage).

pierstoval
1 replies
1d8h

It doesn't matter you wrote perl before PHP, actually. You're talking about PHP6 like it's a thing (spoiler alert: it was never released), and you don't seem to have ever used one of the famous frameworks PHP had seen since the 2010s. Even Symfony 1 was here in 2005, and PHP 5.3 brang a complete revolution and growth of the entire ecosystem (thanks to closures and namespaces, at first), which made people embrace PHP more willingly, Composer was released, incredible frameworks were created and used Composer (that's how we got Symfony 2, and Symfony later helped Laravel come as an extremely popular framework). All of this was funded by companies that believed in PHP, while PHP-haters moved to something else (I know that: my older brother, who's also a dev, did some PHP back then, but was more appealed to other techs like Java). You moved to Go? Good: PHP doesn't do everything that Go does, because it wasn't meant for that. We do PHP instead? Perfect: Go wasn't created to develop web-apps in the first place, it's a low-level network-related project, and turned into something way bigger that allows you to code web apps quicker than in Go's early life. PHP has always been about creating web applications, and will always be, even when some people try to tinker with it on some other levels (like servers using async & threads, or desktop apps).

And honestly, FrankenPHP is an incredibly good combination of both worlds: brings all the scalability of Go, with the flexibility of Caddy (which is written in Go too) in the infrastructure, while allowing us to continue coding with all the incredibly powerful frameworks we have in PHP to create the web app. It's the best for all the people that have an interest in that. You can't hate on that unless you just hate for the sake of hating.

zer00eyz
0 replies
1d1h

Wow.

You're talking about PHP6 like it's a thing (spoiler alert: it was never released)

Spoiler alert PHP 6 was a thing. Spoiler alert PHP 6 NOT being released was a blemish on PHP that made a lot of people say "we might not have a future here"... Python spent years going from 2 to 3 while PHP chugged through 4 and into 5. Python ripped the UNICODE bandaid off, the one that PHP could not... https://webcollab.sourceforge.io/unicode.html .

And yes MB strings work... I did a fair bit of I18N work back in the day. PHP string mishandling was in all the dark corners and odd bugs you had to dig out of a codebase. I made good money doing it, it was NOT fun...

> Even Symfony 1 was here in 2005, and PHP 5.3 brang a complete revolution and growth of the entire ecosystem

No one gave a shit about symphony at the time unless you worked for a body shop. We all wanted to build on Zend, and for good reason. Zend server (the opt cache and debug tools) and corporate backing was one of the things that made a lot of companies comfortable with their PHP plunge. "Open source" was still rather novel coming out of the Y2k bubble, and managers were still old guard and wanted an "IBM" style name (to blame if the shit hit thee fan). There is a reason that magento chose to build on top of ZF. (SO much EAV ptsd).

It also became super common in this time to run a Drupal Or WP site for your marketing department. Slapping theses up was a no brainer, and to some degree still is. These tools a bit reason that PHP still has a massive footprint for such a large portion of the web.

Go wasn't created to develop web-apps in the first place, it's a low-level network-related project

Umm NO.

PHP has always been about creating web applications, and will always be

After the 6 debacle and unicode support this limitation is why a LOT of the best php dev's around moved to python, or ruby... Being able to easily reuse your tools in batch processors or cli script in an intuitive way was a boon. RabbitMQ and Sidekiq were eye openers for a lot of early 2010's php devs that things were moving on, that the "pure web" was coming to an end. Yes Composer was a thing, but it seemed pale compared to PIP or Gems (and in a lot of ways still is)...

PHP being on every $10 a month hosting package gave it legs. The fact that it's still so web focused with modern dev is now a short coming... For as much as the langue evolved it needed to evolve here and didn't.

> And honestly, FrankenPHP is an incredibly good combination of both worlds: brings all the scalability of Go, with the flexibility of Caddy ...

From the PHP side it's impressive. From the Go side less so... One of the joys of writing go is being able to deploy a single binary with ease. I can skip "containers" all together with a standard go program.

Frankenphp has directions to accomplish the same thing... using either a docker container (this should be a code smell), or a shell script. Have you read that shell script? If you have then wee both have the same questions (Oh boy does that thing need some comments). Make, Basel, Mage would be much more appropriate here, because that shell script is UGLY AF... but these would all be harder to get working "containerless".

Unless I missed the hook, that build process doesn't even run tests first...

This is the thing with go. Can I run the tests, Can I build, is the build painful, is there a reason for it being "non standard" (the CGO qualifies here) ... is the build process sane (this one needs a lot of work) ...

kdunglas
0 replies
1d5h

This script is entirely optional and is only used to create static builds of FrankenPHP or to create self-executable PHP apps. It doesn't require a Docker image but does need some system dependencies.

It is not necessary to create a standard (dynamically linked) build of FrankenPHP and isn't used in the Docker images we provide: https://frankenphp.dev/docs/compile/

ceejayoz
1 replies
1d3h

I wrote PHP from version 3 to version 6.

There was never a released version 6.

https://wiki.php.net/rfc/php6

867-5309
0 replies
23h13m

for the same reason as Windows 9 - it would have clashed with PHP '68

/j

cess11
0 replies
1d10h

PHP 6 was never released.

eru
2 replies
1d8h

Wow the PHP is going to magically get into the binary?

It's fairly simple to pack assets into a binary. (Not sure, if they are doing that. But it wouldn't involve any magic.)

Compare also https://doc.rust-lang.org/beta/core/macro.include_bytes.html

Btw, making a tarball or a zipfile is also a way to put multiple files into one binary file. You might have even heard of self-extracting zip files? They were very popular, before Windows got a build-in unzipper, I think.

kdunglas
1 replies
1d5h

Optionally, you can embed the PHP scripts in the final binary using a Go feature similar to `include_bytes`: https://frankenphp.dev/docs/embed/

But for PHP, it's even simpler: PHP is available as a C library, and we just use it. (libphp can be embedded using static compilation, or used as a dynamic library, we support both).

eru
0 replies
15h49m

But for PHP, it's even simpler: PHP is available as a C library, and we just use it. (libphp can be embedded using static compilation, or used as a dynamic library, we support both).

Yes, but that's completely independent from whether / how you embed the scripts? (Which you do via the the procedure described in your first link?)

Btw, how does your version of PHP compare to Facebook's Hack? I had opportunity to use Hack a few years ago, and I think it's the best language they could have made (from PHP as the fixed starting point).

conradfr
16 replies
1d12h

This is the one good thing non-Go web developers are jealous about Go.

BartjeD
13 replies
1d11h

.Net and rust and many other languages also support binary deploy. You raise the impression this is a unique property of 'go', how come? You guys have go tunnel vision because you work with it?

withinboredom
4 replies
1d11h

Go started it. Or at least, popularized the static build, single binary docker files.

Naturally, you’ve been able to do this since forever with many languages like C/C++ etc.

pjmlp
3 replies
1d11h

Among people that have used nothing besides scripting languages.

jchw
2 replies
1d3h

To be honest, it was and is pretty rare to see C/C++/etc. self-contained static binaries on Linux. Glibc doesn't even properly support static linking, and musl does not have 1:1 parity with glibc, so it's challenging to even give a "single binary" for C/C++ programs on Linux, less in the past before musl and during musl's infancy. The more popular thing to do on Linux is something more like AppImages where you bundle a bunch of stuff into a single self-executing file, and that ultimately still is a dynamic binary depending on system libraries (and therefore can't be e.g. plopped in an empty Docker container.)

(And yes, Windows and macOS, and probably most of the BSDs, don't really suffer too badly from this issue, since dynamically linking to system libraries/libc is not a problem. Still, not needing libc remains a big advantage for Go since it is possible to cross-compile self-contained Go binaries to any platform Go can target from any other platform; this is challenging to do with C/C++, especially for targets like macOS.)

Even if you do get past the code though, there's the assets. For C/C++, bundling static assets into an executable is oddly challenging. There's been a bunch of different bin2c-type programs over the years, yet somehow not really many "standard" approaches to doing it, and many of them suffer from bad performance (especially approaches that go to a source file instead of an object file). Just now, finally, in the past couple years, there is #embed in C... for embedding a resource file. Meanwhile, Go has had several good options in the ecosystem for embedding entire directory trees and using them inside of VFS layers for ages, and since Go 1.16 (2021) it has support for that as part of the toolchain.

Go didn't invent the concept of making a single self-contained executable, it did however push the status quo quite far. I contend that I have the experience to make this claim.

P.S.: To be clear, I'm definitely not saying you literally can't, and I am aware of Cosmpolitan libc and APE, which are pretty cool. Of course, with effort, you absolutely can make static binaries using C/C++. I just recently did this with a C++ and Rust program using musl; it's tricky, especially since many build setups don't really support these kinds of deviations, but it's possible. One major problem I have with this is that I don't really feel very confident in the stability of the resulting binaries; if something calls dlopen with static musl, it will crash, and behavior of certain things like DNS resolution also changes in ways that may break some programs. The reason why Go's contributions matter is that for basically as long as I can remember, the way to do this in Go is to install the toolchain and run `go build`, any host platform, any target platform, and it's well-supported by virtually everything because it is the default behavior. (And if anything, Zig is closer to bringing this to C than any of the C/C++ toolchains...)

pjmlp
1 replies
1d2h

All self inflected problems in the GNU/Linux ecosystem, that don't change the fact the computing world since FORTRAN was introduced as first compiled language in 1957, static compilation was a thing.

Also embedded resources has been a solved problem in most non UNIX platforms for decades.

jchw
0 replies
1d

Self-inflicted or not, this is what Go solved. 1957 FORTRAN binaries don't really detract from what Go did: nobody is claiming Go invented self-contained binaries, we are claiming it solved problems with single-file deployments that other language ecosystems still struggle with, and I stand by this 100%.

gertop
2 replies
1d11h

.Net only recently added support for it and it's very brittle.

Rust is indeed in the same league as Go, I guess the difference is that Go is batteries included when it comes to web development. You don't have to pull many dependencies, unlike rust.

tracker1
0 replies
1d

Rust isn't so bad... A lot of devs have started to normalize around Axum/Tokio, which is pretty well supported. A lot of boilerplate API stuff is about as easy as it is with Go after a project is up and running.

neonsunset
0 replies
1d7h

No it’s not. Self-contained deploy has been a thing since .NET Core 2.1 (or earlier?), released 6 years ago. Either way, deploying .NET applications has been very easy regardless of deployment mode for as long as they were using Kestrel.

Today, it reached the point where .NET outperforms Go in publishing/packaging of AOT binaries as it can be statically linked together with native dependencies, metadata tables and pointer-heavy structures in the binary are dehydrated and compressed and the resulting binary uses standardized object and symbol format understood by all existing tooling that otherwise works with C, C++ and Rust.

conradfr
2 replies
1d11h

That was not my experience when I worked with .Net, IIS and the whole thing but it was a long time ago so good to know :)

tracker1
0 replies
1d

.Net is a lot more sane now... since Core releases (mostly). Linux deploys with docker are pretty typical these days.

lomase
0 replies
1d5h

How long ago? Nowdays most people dont use ISS for docker builds, it usually runs on Linux containers.

zer00eyz
0 replies
1d10h

Rust and Zig also do compile to binary. They just weren't part of the stack in thee article...

I dont think I would use either of them in the same places I want to use GO... Things that were java, or python are candidates to be written in go. Things that were C or C++ are good candidates for Rust or Zig.

Look at cloudflares nginx replacement, it's written in rust for a GOOD reason. Thats not a place where go will shine being a GC language.

bdd8f1df777b
0 replies
1d11h

Go popularize it, and still leads in the easiness of cross compilation.

rafark
0 replies
1d11h

And charm.sh

pjmlp
0 replies
1d11h

Many non Go Web developers know about static compilation, before shared objects were even a feature in mainstream OSes.

hipadev23
5 replies
1d11h

why would it be 8 (or any N>1) containers for a php/node/python/ruby app?

gertop
4 replies
1d11h

Python is pretty messy to deploy without a container. Sure you can (and should!) use a virtual env, but by that point using docker isn't much more efforts.

Rails and Node and PHP have at least the decency to have the project's dependencies contained inside the project's own directory by default.

hipadev23
2 replies
1d11h

nah not questioning containers. questioning why he wrote 8 (obviously exaggerated) and why it’s not 1.

deergomoo
1 replies
1d10h

Nginx/Apache/Caddy + php-fpm + something like MySQL if your database lives on the same server as your application. PHP in its default form isn’t a persistent process[0], so you will typically have a web server accepting the requests and forwarding them onto PHP to generate a response.

0: it actually usually is these days for performance reasons, with a pool of processes that are reused. But the mental model is one short-lived process per request

hipadev23
0 replies
1d5h

and if the Go dev needs a database, or a cache, or an actual fully-featured HTTP daemon processing the requests?

I’m just confused about their focus on “single binary” when applications in those languages tend to be a single-container plus the same supporting services their single binary is going to need too.

gnz11
0 replies
1d6h

That’s the default of the package managers (i.e. composer, npm, etc) not the language. Setting up a virtual env for Python is a one liner. Hardly messy.

I’d argue that deploying a Python web app with mod_wsgi or gunicorn isn’t any more difficult than deploying a PHP web app with PHP-FPM. If anything I’ve seen far more misconfigured PHP-FPM setups than gunicorn setups.

pjerem
4 replies
1d11h

I’m a total noob in Go but is there something that approaches completeness of the good old monolithic frameworks ?

I’m in a pause in my career and I’m having a great time working on a "side" project in Django currently. Everything just works and makes sense, I just have to write business code and it gives me a nice app.

I’d be happy to try Go for fun and because deploying Python/Diango is a mess (at least without docker) but my project isn’t API first, it’s deliberately a traditional server side rendered app.

Every Go frameworks I stumbled upon looked like they were made to serve APIs and In the case of a 1 man team, it defeats the purpose of easy deployment since you will anyway need to code and deploy a full blown frontend (and front end fatigue is a big reason why my career is currently in pause).

zer00eyz
1 replies
1d11h

GO + HTMX + standard templates... or some folks swear by templ

On the API side (not what you wanted, but good looking) is sqlc + validator

Between all of those you have everything you want for a website.

Week 1 go is going to be a lot slower than Django or Rails. You're going to have a bit of bootstrapping to do for your project. By the end of the first month you will be a week or two behind but performance parity will be the same (you should have roughly the same feature cadence).

A good framework brings a lot to the table. With go you have to "solve" for that yourself. "How do I log a request" would be one of those first questions... the answer is "the standard logger is pretty good" and "Middleware is awesome". It's a question that has a simple, short, very common answer. One that works for web apps or CLI apps or ... It takes a bit but you end up embracing the idea that less is better

tracker1
0 replies
1d

Was going to say the same... Similarly .Net (razor views) + HTMX is pretty nice as well. There's YouTube content for both, on the .Net side, there's some JetBrains extensions to make the HTMX experience relatively seamless.

JodieBenitez
0 replies
1d10h

I’m a total noob in Go but is there something that approaches completeness of the good old monolithic frameworks ?

Some of them try, but it's really hard to beat 20 years of development, real-life use cases, third party tools and docs, etc.

deploying Python/Diango is a mess (at least without docker)

Install your django app in a venv, serve it with gunicorn behind apache/nginx... done. No docker required.

Every Go frameworks I stumbled upon looked like they were made to serve APIs

Indeed, that's pretty much what Go was made for. And it's also the current trend.

my project isn’t API first, it’s deliberately a traditional server side rendered app

Stick with Django then, because it remains an excellent choice for such apps. And these apps remain an excellent solution to a vast array of problems.

front end fatigue is a big reason why my career is currently in pause

I'd argue you don't have to follow this trend to be useful. Actually, something like Django+Unpoly or HTMX probably covers 99% of the use cases with very low frontend development.

CoolCold
0 replies
1d5h

Mind sharing bit more on this?

because deploying Python/Diango is a mess (at least without docker)

I'm playing around with FastUI (disclosure - I'm not a programmer at all), so I'm in "day 0" position and would like to hear more on "day 1" side of things. Coming from Ansible side - it's easy peasy, just install things with pipenv and later `pipenv run ...`

sam0x17
2 replies
1d4h

PHP had the unique fun of when an attacker was able to write files to the server they could literally write new PHP files and get them to execute. I miss that worry somehow

tracker1
0 replies
1d

f-that... read-only containers for the win.

ivanhoe
0 replies
1d3h

You can do that or something similarly bad in pretty much any language if you have write access to where the files are. That's really a server misconfiguration problem, not php problem.

Huge misfortune of php is that because of the timing and huge popularity in relatively early days of web it got to be permanently associated with amateurs doing stupid shit. I was part of that early era, so trust me that php4 as bad as it was, was still fantastic compared to writing CGI scripts in C, or running mod_perl that you had to restart every time you edit some file.

slim
0 replies
1d11h

did you miss this part in Frankenphp website ? :)

  Build standalone, self-executable and dependencies-free binaries for your PHP web applications, and command-line tools.

cess11
0 replies
1d3h

Right, so CGI is quite old by now, which is basically this: a binary in a directory and a proxy that throws packets at it.

It has its pros and cons. In some cases it's actually quite nice to have a platform like Wildfly or the BEAM, or you knew so little about the future load peaks that you started with cheap shared hosting and hence PHP so when you outgrow it FastCGI and nginx is a much better option than a great rewrite to Golang.

Building in the languages and on the platforms you already know will always be much faster and more convenient than betting on someone else's 'bees knees'.

thomasfromcdnjs
0 replies
1d11h

Yeah it has to be one of the best landing pages I have ever seen.

Fun and instantly understood.

jslaby
45 replies
1d14h

Long time C# dev, now I primarily code in PHP8 which is a great language to quickly get things done. This is the kind of direction the language needs to go in, instead of the older LAMP which can require somewhat complex Apache configuration.

hparadiz
38 replies
1d13h

PHP dev of 18 years here.

Use nginx with php-fpm. It takes 5 minutes to configure.

Edit: I'm gonna give this thing a try too but I've never had any bottlenecks with either nginx or Apache. They both take a few minutes to get going at most.

lordofgibbons
13 replies
1d13h

It takes 5 minutes to configure

Is that because you have 18 years of experience, or would it be as easy for a new developer?

njovin
6 replies
1d13h

You can have a a ~20 line docker-compose.yml file that only requires you to `docker compose up` and you're up and running. It's gotten insanely easy to run php-fpm + nginx + [whateverdb] in a set of docker services that require virtually no configuration.

troupo
5 replies
1d12h

And who is going to write that ~20 line compose file with "no configuration"? A newbie?

cess11
3 replies
1d10h

When you're configuring Internet facing Linux services you're kind of out of the newbie area.

A newbie is more likely to use the built-in development server and then SFTP a 'git archive' to a shared host.

troupo
2 replies
12h43m

The original comment was about newbies. Everyone is a newbie at one point.

Just last year I tried a blog engine written in PHP. 24 years programming experience, but I haven't touched PHP for 10 years, and I haven't touched configuring it for 15+ years.

It took me half a day to make it work.

cess11
1 replies
10h31m

What blog engine? Usually with PHP applications you clone the repo, copy .env boilerplate, enter database credentials, run Composer to fetch dependencies and do some setup tasks, then boot the application.

troupo
0 replies
8h58m

I really wish people would maintain conversation context for at more than a single reply.

wruza
0 replies
1d10h

An LLM of course. They are really good at “trivial but you have to find a good tutorial” types of work.

hparadiz
1 replies
1d13h

I just have the right config for both Apache2 and nginx from hundreds of sites. The config itself is only 50 lines. You can find a good one and stick with it.

troupo
0 replies
1d12h

Yup. The process of finding alone will take more than 5 minutes. And is likely to not work for your particular circumstance.

chrisandchris
1 replies
1d13h

I was a long-time PHP dev and then moved on to C#. I was close to writing this nginx/fpm setup lookss very complex compared to "dotnet run". But then I remembered, in ASP.NET you have a Program with 50 lines of code that must have an exact order, otherwise thinks work except they don't.

So I would say, knowing these two languages, PHP really is that easy to setup.

neonsunset
0 replies
1d7h

This has not been true for a long time.

hluska
0 replies
1d2h

You won’t find this answer very satisfying, so feel free to ask questions.

But it depends on what you’re trying to accomplish. If you’re sticking with defaults, it’s very easy - it’s less than ten minutes of work or seconds if you’re comfortable working with Docker.

On the other hand, let’s say that you’re running into problems scaling to handle more requests. You’ll end up having to tweak the max_workers setting. That takes a bit of experience or it can be a lot of ‘fun’ (in the Dwarf Fortress sense).

So yes and no. But a lot of people have been through this, have all the trauma you would receive and tend to be quite helpful.

You can do it!

donatj
0 replies
1d13h

I think it would be roughly that easy for anyone with basic nginx experience. Nginx includes a php fast-cgi snippet that you just `include` from your server block.

It really is very easy.

francislavoie
12 replies
1d13h

Just as a reminder, you can use Caddy + php-fpm as well (with vanilla Caddy, no plugins).

What this does is give you a way to run your webserver + PHP as a single process, or single Docker container (instead of the traditional 2-container approach), and it also unlocks the ability to run PHP in a worker mode, where you have long-running PHP processes that have your framework loaded in memory ready to serve requests, instead of booting the framework on every request (so, much lower request latency).

hparadiz
11 replies
1d13h

Caddy uses more RAM and has no inherent benefit when running a project in production professionally. Caddy is easier for self hosted cause it automatically handles HTTPS where Nginx does not.

Related reading:

https://blog.tjll.net/reverse-proxy-hot-dog-eating-contest-c...

cess11
4 replies
1d10h

I'm a pretty hardcore nginx fan with a decent chunk of rather low level professional experience with it in complex setups. The reason I'd still pick nginx over Caddy for prod is that I know really well how a broader tool set will work together, e.g. keepalived and whatnot.

Caddy kind of feels like a cute toy in comparison with nginx, but it's not, by now it's been seriously battle tested and has proven itself to be quite resource efficient and resilient.

klaussilveira
3 replies
1d6h

keepalived? What do you mean?

CoolCold
1 replies
1d5h

I think that OP really meant that in his/her mental model of things, answers already known and battle tested for numerous cases [by using Nginx] - making HA with keepalived? Check. Making logging to be buffered to save iops? Check. Implementing ratelimits and custom logic? Check.

Keepalived is not really bound to Nginx by any means and should perfectly fine work with Caddy too.

cess11
0 replies
1d5h

Yeah, precisely. I'm sure it works fine with Caddy too, it's just that I haven't had Caddy with me in the trenches, yet.

cess11
0 replies
1d5h

It's a tool you tend to come across when you're building highly available network systems, https://github.com/acassen/keepalived .

You might use it to implement redundancy in the load balancer layer of your system, perhaps your firewall round-robins incoming connections between two IP:s where you have nginx proxying to share load between two mirrored clusters, and those IP:s are virtual and handled by keepalived that will shuffle in a backup virtual server if the one currently serving becomes unhealthy or needs to be switched out due to a config rollout or something.

It's a really neat way to be able to just throw more virtual servers at the problems in availability, redundancy, load balancing and so on. I think it does some ARP messaging to achieve this.

Edit: I've applied it with ProxySQL in one case, it was an application on a trajectory from a simple rig with one virtual web server, one virtual database server to a highly available and resilient system. When I left we had a master-master-cluster with ProxySQL in front, with three ProxySQL-machines keepalived, so in case one went out for some reason there where two more in the stack to fill in. When you aren't sure what kind of peak load you're going to handle it's nice to know that when the alarm comes you have one fresh machine buying you some time while you figure out what you need to do to the third before it is shuffled into service.

withinboredom
2 replies
1d11h

Caddy “uses” more ram because Go is a garbage collected language. It can free tons of it, but that costs cpu cycles. It generally won’t spend too much time freeing memory until the system is under pressure.

Because it’s Go, you can tune garbage collection to be super aggressive, at the expense of speed.

neonsunset
1 replies
21h22m

Can you actually tune GC in Go though? As far as I'm aware, it's still abysmal at throughput optimization.

withinboredom
0 replies
11h6m

Yeah, you can tune it. There's a whole section in their docs about it.

m_sahaf
1 replies
1d12h

Citing that particular blog post isn't making the point you think it makes. To quote:

The most striking piece of new knowledge for me was learning about failure modes. Nginx will fail by refusing or dropping connections, Caddy will fail by slowing everything down.

Do you want your clients failing to load your website at all? Is this the best approach to serving users?

jeroenhd
0 replies
1d11h

Do you want your clients failing to load your website at all? Is this the best approach to serving users?

There are good reasons for picking either. Large services under sudden load sometimes implement queueing, which is just failing but stylish.

For my blog posts, I'd rather throw an error than have people wait for thirty seconds. The contents aren't that important and the end result will probably look bad because of missing CSS anyway.

For API services, I'd want things to slow down rather than fail, unless failure is explicitly documented in the API and can be handled somewhat gracefully.

mholt
0 replies
1d12h

has no inherent benefit when running a project in production professionally

Tell that to Stripe and Framer and numerous other businesses using it very seriously and very much professionally! ;)

ofrzeta
6 replies
1d9h

Apache with mod_php actually takes just "apt install libapache2-mod-php8.2" to work.

ihateolives
3 replies
1d9h

Why use mod-php when you have fcgi and fpm?

netol
2 replies
1d6h

It's simple and there is less overhead. Since PHP runs directly within the Apache process, there is no need for inter-process communication (no TCP, no sockets), reducing the overhead. This can lead to lower latency for individual requests.

cholmon
1 replies
1d4h

mod_php does give you better response times for individual requests, but at the expense of being able to handle a higher load of traffic; you'll run out of memory and/or experience timeouts on mod_php way before you do with php-fpm.

With mod_php, every Apache process has the PHP engine embedded in it, even if PHP isn't needed, e.g., to serve a request for a .css file. When Apache gets a bunch of requests for flat files, it forks all those processes and fills up RAM with copies of the PHP engine that aren't used. That's not only wasteful, but it dramatically increases the chances that you'll run out of memory. You can limit the number of Apache children of course, but you'll see timeouts sooner when you get a traffic spike.

By having Apache proxy over to php-fpm for PHP requests, you can configure Apache to use mpm_event for serving static files, which allows for much leaner Apache workers (memory-wise) since they aren't carrying PHP around on their backs.

While you're at it, you can use haproxy on the same machine for TLS termination, then you can disable mod_ssl thus making Apache workers even lighter.

netol
0 replies
1d2h

With mod_php, every Apache process has the PHP engine embedded in it, even if PHP isn't needed, e.g., to serve a request for a .css file. When Apache gets a bunch of requests for flat files, it forks all those processes and fills up RAM with copies of the PHP engine that aren't used. That's not only wasteful, but it dramatically increases the chances that you'll run out of memory. You can limit the number of Apache children of course, but you'll see timeouts sooner when you get a traffic spike.

Yes, that is true. But most high-traffic websites will cache static files such as CSS files and images, using a reverse proxy (e.g. Varnish, a CDN, or usually both). So I don't think this is a real problem, most of the time (99.9%?), a request for a static file will not hit Apache.

I'm not saying mod_php is better for all scenarios, of course, but I think it can be ok.

ofrzeta
0 replies
1d5h

There are a lot of strange assumptions on that first page:

- "for example, if you are using PHP to access a database, unless that database has built-in access control" - well, of course I will use a database with access control like MySQL

- "It's entirely possible that a web spider could stumble across a database administrator's web page, and drop all of your databases". Of course I won't run PHPMySQLAdmin or Adminer on a production server, nor will I expose it to the public.

- also none of the above has anything to do with the PHP execution model

The second page might raise some valid issues but for instance the bullet point "mod_php is loaded into every httpd process all the time. Even when httpd is serving static/non php content, that memory is in use" - doesn't matter to me when I am running everything through index.php routing anyway.

"mod_php is not thread safe and forces you to stick with the prefork mpm (multi process, no threads), which is the slowest possible configuration" might be true but also a premature optimization.

Maybe mod_php is really bad but the arguments presented here are not very convincing to me.

anonzzzies
1 replies
1d12h

Few seconds with docker. There are fully loaded compose ones that include everything so you don’t need to add anything. It’s lovely. For prod it’s better to only leave the needed extensions etc of course but for dev it’s so easy to get going. And to be honest, for small personal, company internal and less than $1000/mo rev saas, we just use the fully loaded in prod as well.

tommica
0 replies
1d12h

How does your production one look like if I may ask?

n3storm
0 replies
1d13h

I agree. Having separated php processing and http processing brings good practices and helps further scalation.

codegeek
0 replies
1d3h

It takes 5 minutes to configure with the defaults. But once you need to optimize PHP-FPM to handle more requests, you now find yourself fiddling with pm.max_children etc settings and need to know what you are doing. I love working with PHP and Go both btw. But PHP configurations can be a pain if you do anything other than defaults.

augustohp
1 replies
1d5h

I agree. If we can start a culture of relying on SQLite instead of PostgreSQL/MySQL, a whole server-side application can be a simple standalone binary.

Also, having a binary makes it easy to bundle in an Electron app.

francislavoie
0 replies
1d3h

Laravel is defaulting to SQLite now (mainly for ease of development). Also FrankenPHP has SQLite included by default. Going that route is less scalable though, obviously, unless you use one of those third party SQLite cluster solutions.

pathartl
0 replies
1d11h

I cut my teeth as a WordPress dev and left the scene for .NET when it was still popular to use Vagrant to setup your dev environment. While I'm glad things have progressed since then, I have a trauma response to those days. The amount of hours spent getting a proper config with XDebug setup (oh god, what an absolute backwards-ass nightmare) was substantial.

lelanthran
0 replies
1d13h

This is the kind of direction the language needs to go in, instead of the older LAMP which can require somewhat complex Apache configuration.

I hardly every set up PHP (once each time I reinstall my desktop, which was last in ... 2018?) but I recall it being very quick and smooth using apt-get.

I don't recall doing anything else other than restarting apache.

KronisLV
0 replies
1d12h

...instead of the older LAMP which can require somewhat complex Apache configuration.

Is it really that bad? The Apache configuration seems decent with something like PHP-FPM: https://news.ycombinator.com/item?id=40256843

  LoadModule proxy_fcgi_module "/usr/lib/apache2/modules/mod_proxy_fcgi.so"
  <FilesMatch \.(php|phar)$>
    SetHandler "proxy:fcgi://127.0.0.1:9000"
  </FilesMatch>
Here's a more full example of Nginx that's quite conceptually similar to how one would configure Apache, with installing the prerequisite packages: https://news.ycombinator.com/item?id=37443911

There are also prebuilt container images that you can use to achieve similar results, this is just in case you want to do it yourself and have a look at what's under the hood a bit more.

In my eyes, that's certainly easier than configuring the Java app servers of old, like doing manual Tomcat or GlassFish configuration or whatever people spent time on back then. A single run command will usually be better regardless of the environment, but LAMP isn't all that bad either, when compared to the other stacks out there.

El_RIDO
0 replies
1d10h

And to add one more option to the comments (beyond [frontend] + php-fpm):

Nginx Unit https://unit.nginx.org/ - like Apache + mod_php runs as a single service, handles the multiprocessing of php (and other languages), static files, reverse proxy and even lets you configure both itself and php via a single configuration (either as a file or dynamically at runtime, via a socket): https://unit.nginx.org/configuration/#php

Here is an IRL config example: https://github.com/PrivateBin/docker-unit-alpine/blob/master...

The resulting container image can be pretty small: https://hub.docker.com/r/privatebin/unit-alpine

notpushkin
10 replies
1d14h

Copy your PHP files in the document root, that’s all!

sigh

c0wb0yc0d3r
9 replies
1d14h

How would you prefer it to work?

darylteo
8 replies
1d13h

If I understand the top-poster's issue correctly:

https://frankenphp.dev/docs/

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

This mounts the current working directory into "public". Meaning, all .git, .env etc. will be publicly accessible.

Better form would be to mount a $PWD/src directory instead. The documentation needs to be updated better for newbies. Generally ill-advised. Documentation just needs better updating or warnings. Very dangerous to inexperienced devs.

In comparison the Laravel integration, it instructs the following:

https://frankenphp.dev/docs/laravel/

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

While all the sensitive files are mounted in, they have to be to function properly. In this case, they're mounted to a more secure context.

withinboredom
4 replies
1d12h

It literally says “copy your PHP files” note the PHP part. It doesn’t say copy all your secrets and git history too.

huimang
3 replies
1d11h

If you run the above docker command, which is directly from the docs, it copies everything inside of your current working directory. Not just PHP files.

withinboredom
2 replies
1d10h

That docker command isn't "copying" anything; it's mounting, and I really hope people aren't doing that in production. There's a separate section on running in production.

notpushkin
2 replies
1d9h

My primary concern is actually that you have to store code in a directory that is publicly served by default. I haven't looked into the PHP world lately, but I have assumed that by now most PHP frameworks would store code (and associated configs etc) outside the document root, like the Laravel approach you mentioned.

francislavoie
0 replies
1d2h

Yeah, most modern PHP frameworks use a public/ directory which has the index.php entrypoint in it, and any static assets are served from in there (JS/CSS/images) if necessary.

c0wb0yc0d3r
0 replies
1d1h

I see what you mean. I interpreted the getting started one-liner differently. I took it to mean that the docker container is serving from `/app/public` and the user needs to mount their files accordingly.

sandreas
9 replies
1d12h

While I often use the PHP integrated webserver during development:

  php -S 0.0.0.0:8000 public/index.php
it is single threaded, slow and therefore not made for production environments. FrankenPHP looks promising, while the issue with limited Cores / Threads[2] seems also to be a problem when using it in production. However, maybe I'll give it a go for my pure-todo[1] project and see, if it suffers the same problem. The docker image as base looks really promising. Thanks for sharing.

1: https://github.com/sandreas/pure-todo

2: https://github.com/dunglas/frankenphp/discussions/294

rakoo
2 replies
1d4h

not made for production environment

Out of curiosity, is the performance the only blocker for putting this in prod ? If I were to have a small site, intended for a small number of users, what would I miss from other "prod-ready" environments ?

slim
1 replies
1d4h

it's really just for testing. Like for example you can't have a "." (dot) in a URL because it would be interpreted as a static file.

rakoo
0 replies
1d3h

Ok, that's a good thing. I'm more interested in arguments than in "it's just for testing", because the latter doesn't indicate what's the problem (and what prod-ready solutions solve)

PetahNZ
2 replies
1d10h

You can set PHP_CLI_SERVER_WORKERS to make it run multiple threads.

sandreas
1 replies
1d10h

NEAT, didn't know that. Would still not use it in production :)

pierstoval
0 replies
1d8h

FrankenPHP is just Caddy + PHP, but in one binary.

The threads thing, the worker mode, etc., all of it is optional, but basic Caddy + PHP is already production-ready, I've been using this kind of setup for a while, and switching to FrankenPHP when you already have Caddy is completely harmless.

The only thing FrankenPHP does not is providing multiple versions of PHP in the same binary. For that, I'd still use Caddy + PHP-FPM, and it's fine.

lpapez
1 replies
1d10h

The PHP built-in server is explicitly stated not for production use, and is intended for development purposes only.

See the warning at the top of the page: https://www.php.net/manual/en/features.commandline.webserver...

Not sure it's even fair to consider it for comparison in this context.

sandreas
0 replies
1d10h

That's what I meant. But tbh I don't think FrankenPHP is ready for Produktion yet, although it might geht there some day.

Just wanted to mention that using PHP locally, for simple app development you don't need a full fledged nginx, Apache or caddy in all cases

20after4
0 replies
1d11h

it is single threaded, slow and therefore not made for production environments.

I'm pretty sure that this solves those specific issues (and more)

francislavoie
4 replies
1d10h

It's only an alternative if you're running a framework which also supports those (your PHP app has to be set up in a specific way for Roadrunner or Swoole to be usable).

FrankenPHP has the advantage of working with _any_ PHP app (even WordPress) because it's just PHP, but compiled into a Go program with CGO. But it also has a worker mode which makes it behave similarly to those two.

rustatian-me
2 replies
1d1h

You don't need any framework or specific web-server to use RoadRunner. RoadRunner can be used with any modern framework, or let's say naked, using only the PSR-7 (which is framework-agnostic) worker for HTTP, but: RR is not only HTTP, it is waaaay above that: Temporal.io support, various queue drivers, gRPC, TCP, KV, Native WebSockets/Broadcast support, distribute locks (without PHP extensions), etc. RR doesn't need to be somehow specifically set-up. Nothing special, download -> use :)

francislavoie
1 replies
1d1h

PSR-7 is framework agnostic, but not all PHP apps are PSR-7 ready. E.g. WordPress. That's the distinction. You can't just point Roadrunner at any PHP script or legacy PHP app and expect it to just run, but you can with FrankenPHP.

rustatian-me
0 replies
1d

Sure, RR can't serve legacy PHP or WordPress (actually can, but that's not released yet), that's true. But the modern PHP ecosystem leaves lesser and lesser such a non-compatible scripts ;)

ofrzeta
0 replies
1d10h

Ah, I didn't get that. Thanks for the clarification.

CoolCold
5 replies
1d13h

I've tried to do Wordpress benchmark under FrankenPHP and under Apache's Mod-PHP - I couldn't see evidence of winning for FPHP. Have not dug deep enough though and test was in Docker, not on normal setup. Wordpress was basically in default setup - no heavy themes or anything of this sort, not very realistic case too.

Still want to repeat test and understand it better.

mhitza
2 replies
1d12h

Maybe you're using that name because you're accustomed to, but as a standard you should be using proxy_fcgi with Apache. Should squeeze out a bit of extra memory out of Apache and leave room for more PHP requests.

CoolCold
1 replies
1d7h

Not sure where you take this "standard" from - AFAIR, it was mod_php since ~ 2004-2005 and all that lovely mpm_prefork stuff. FastCGI and FPM came a bit later.

should be using proxy_fcgi with Apache

I'd in general use Nginx instead of Apache, until .htaccess handling is needed - which is still a thing in shared hosting and around area mostly from my perspective - if you really care about "squeeze out a bit of extra memory" of course.

mhitza
0 replies
13h5m

I take it as a standard because its the approach recommended above all others in the Apache wiki [1] and probably what distros will do at some point as well (RedHat family distros already do this if you don't explicitly opt-in to use mod_php).

[1] https://cwiki.apache.org/confluence/plugins/servlet/mobile?c...

kdunglas
1 replies
1d11h

Unlike Laravel and Symfony, WordPress doesn't support the worker mode of FrankenPHP (yet?), so there are not many benefits in terms of performance (except the ability to preload assets using 103 Early Hints, which can reduce the latency of a page load by 30%).

That being said, FrankenPHP makes it easy to enable HTTP cache with WordPress and simplifies the deployment story. There is a dedicated project for WordPress and FrankenPHP, that comes with a built-in HTTP cache tailored for WordPress (using the Souin Go library): https://github.com/StephenMiracle/frankenwp

CoolCold
0 replies
1d7h

Unlike Laravel and Symfony, WordPress doesn't support the worker mode of FrankenPHP (yet?), so there are not many benefits in terms of performance (except the ability to preload assets using 103 Early Hints, which can reduce the latency of a page load by 30%).

This part is clear for me, but thank you for mentioning HTTP 103 too. I will not state for sure, but in my blurry memory, FPHP (FrankenPHP) was _slower_ than Apache+mod_php in that tests. But again, I won't say for sure, I just remember I was totally impressed as was expecting otherwise - much likely some subtle differences in setup on my side. If/when I have more precise info - I may ping you.

That being said, FrankenPHP makes it easy to enable HTTP cache with WordPress and simplifies the deployment story. There is a dedicated project for WordPress and FrankenPHP, that comes with a built-in HTTP cache tailored for WordPress (using the Souin Go library): https://github.com/StephenMiracle/frankenwp

Thank you, have not seen that yet - may get idea or two from it. At glance, they just do naive `BYPASS_PATH_PREFIX` handling and that's all.

Beyond tests, I of course do prefer Nginx over Caddy and "simplifies the deployment story" doesn't resonate with my needs much yet - one of that things may change of course.

timvdalen
4 replies
1d10h

What does it mean to get rid of PSR-7 in today's age? Do people really miss $_GET and $_POST?

kdunglas
3 replies
1d10h

This means that in addition to any PSR-7 implementation, you can run apps using HttpFoundation (Symfony, Laravel, Drupal, etc) and "legacy" code using superglobals without the need for an adapter.

timvdalen
2 replies
1d9h

In that case I think I'm missing the value prop here, doesn't that also hold for plain old php-fpm?

kdunglas
1 replies
1d5h

That's not the case with other engines able to keep the booted app in memory to handle several requests (FPM doesn't support this).

timvdalen
0 replies
22h23m

Ah, it's a value-add compared to other engines that keep the app in memory, got it!

thomasfromcdnjs
4 replies
1d11h

It would seem that this is more or less an alternative to Octane but I don't understand why there is documentation to also run Octane -> https://frankenphp.dev/docs/laravel/#laravel-octane/

Why would you run both?

francislavoie
2 replies
1d11h

It's not an "alternative", FrankenPHP is one of the 3 available drivers for Octane. See the Laravel docs https://laravel.com/docs/11.x/octane Octane is basically Laravel's branding for its "worker mode", i.e. running a long-running process which boots the framework and then processes requests, without needing to reboot the framework on every request.

thomasfromcdnjs
1 replies
1d10h

Thanks for the answer.

So you would turn on Frankens worker mode to sit on top of Laravel Octanes workers?

My understanding is that Franken keeps the app running so Laravel wouldn't need to restart anyway?

francislavoie
0 replies
1d10h

No, you use Octane to run FrankenPHP. Octane will download and run FrankenPHP for you.

FrankenPHP is a program which has a webserver (Caddy) and PHP built-in, and worker mode allows it to run a pool of workers which have your Laravel app bootstrapped (all your service providers, middleware, controllers ready to go in memory) and then FrankenPHP feeds it requests as they come in.

yurishimo
0 replies
1d11h

The Go container provides an environment in which to run Octane. Your webserver still needs to know to reroute traffic appropriately. You can think of FrankenPHP as more of a webserver/app server all bundled into one binary.

alberth
4 replies
1d14h

Is this just Caddy + PHP?

CodeCompost
1 replies
1d12h

What is the Go part? It's a PHP interpreter or is PHP still doing all the work?

francislavoie
0 replies
1d12h

Go is acting as the process manager for PHP (either keeping a pool of workers running, or directly invoking PHP via CGO), and as the HTTP/HTTPS server (Caddy, obviously), ACME automation, etc. It's not a "PHP interpreter", it's literally PHP itself (written in C, compiled in with CGO).

francislavoie
0 replies
1d13h

I wouldn't really call it a drop-in replacement for php-fpm. It's more like emulating the way Apache+PHP was run traditionally, i.e. PHP is closer to the webserver instead of being a separate piece as it is with php-fpm (and needing fastcgi as protocol glue).

But yes, from a practical standpoint, your PHP apps should _just work_ if you run it with this instead of php-fpm, provided that you aren't doing anything weird.

If you're using a modern PHP framework (e.g. Laravel, Symfony) then you can use FrankenPHP's worker mode which is a huge boost in performance by keeping workers running which have the framework already warmed up and ready to accept requests right away, instead of having to boot the framework on every request.

zmxz
3 replies
1d10h

There are claims this is faster. It's not. I used it, together with other "alternative" runtimes which are just PHP command line interface long running scripts with some sort of task distribution balancer in front. Just like PHP-FPM is.

The apparent speedup comes from the fact it's not shared-nothing, meaning that objects from previous requests (and variables) are persisted and present in subsequent requests. This makes it work exactly like Node.js, removing the wonderful part of PHP which is that it automatically cleans up all the crap devs created and creates clean slate when next request is to be executed.

All of these "alternative" runtimes are false positives, because they're quick for first few requests but get slower and slower for the subsequent ones. Then, the workers are killed and restarted (precisely what PHP-FPM does too).

Since there's no new engine behind executing PHP, the only way FrankenPHP (and others) can yield any performance is when they're benchmarked against misconfigured PHP-FPM (opcache off, JIT off, persistent connections off).

It's not my cup of tea. I like that there are attempts at doing <something> but turning PHP execution model into Node.js execution model isn't the way to go.

I find it cheaper to throw a few bucks at stronger hardware compared to risking accurate execution to become flaky because shared-nothing is now unavailable.

withinboredom
2 replies
1d10h

The right answer, as always, is: "it depends." There's no definitive "faster" or "slower" anything and the claim is "up to" not "you will get."

Some workloads won't see any benefits, others will. While your anecdata might be useful, it is just that, an anecdote.

zmxz
1 replies
1d10h

It doesn't even depend. The underlying engine that executes opcodes is the same. Minimal speedup from not having to execute several "new objectname" commands isn't even a drop in the sea when it comes to what servers do.

I, for one, would love to be wrong about this and that FrankenPHP with all the other alternative runtimes actually brought benefits.

withinboredom
0 replies
1d10h

It absolutely does depend and "several new" might be "thousands new". It literally depends on what you're doing.

The underlying engine that executes opcodes is the same.

Not exactly. FrankenPHP uses a ZTS build of PHP, which includes thread-support. Meaning you can actually spawn real-life threads in your PHP code with just a bit of work.

I've actually been working on a Parallel drop-in replacement that uses FrankenPHP/go instead of maintaining its own thread system.

mg
3 replies
1d12h

    docker run -v $PWD:/app/public -p 443:443 \
      dunglas/frankenphp
If you want to build a docker container yourself that you can use to serve your app, then running these commands should do the trick to turn a fresh Debian into the container you need:

    apt install -y apache2 libapache2-mod-php
    cat << 'EOF' > /etc/apache2/sites-enabled/000-default.conf
    ServerName mysite.local
    <Directory /app/public>
        AllowOverride All
    </Directory>
    <VirtualHost *:80>
        DocumentRoot /app/public
    </VirtualHost>
    EOF
Friends and I maintain a repo which shows how to go from zero to a running web application via popular languages and frameworks here:

https://github.com/no-gravity/web_app_from_scratch

johnchristopher
1 replies
1d12h

Unless I am mistaken this won't work: does default apache 000-default.conf vhost redirect traffic from 443 to 80 ?

mg
0 replies
1d12h

To support SSL you would add a virtual host section like this:

    <VirtualHost *:443>
        ServerName mysite.local
        SSLEngine on
        SSLCertificateFile    /path/to/cert
        SSLCertificateKeyFile /path/to/key
        DocumentRoot /app/public
    </VirtualHost>
And either use a real cert or add a command to create a self signed one:

    openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout key -out cert

lnxg33k1
0 replies
1d12h

I started working a month ago for a company using mod_php, it's painful, every time you start xdebug, then after the debugging session, you need to restart apache, I started yesterday configuring apache2 to use php-fpm, but I was just wondering if it could work for us, at least in dev, this frankenphp, just can't find how to install php-exts in the docs

lnxg33k1
2 replies
1d4h

Could you integrate the documentation, or point me where it is explained, how to add php extensions? Like xdebug, opcache, etc? If there is something like docker-php-ext-install? Please, thank you

lnxg33k1
0 replies
1d1h

Thank you!

jumperabg
2 replies
1d11h

Are there any benefits on running WordPress on top of FrankenPHP?

withinboredom
0 replies
1d10h

Not yet.

It's possible when combined with some multi-site features of WordPress, an mu-plugin could enable worker mode with WordPress. Though, I'd have to contact my old employer (Automattic) to ask if they would be ok with me using an approach used on WordPress.com, which I'm fairly certain is a 'trade secret.'

francislavoie
0 replies
1d11h

You won't notice much performance benefit (because WordPress doesn't support worker mode yet), but it is simpler to run and deploy (single binary) and you get all the benefits of Caddy out of box too, like TLS automation.

ThinkBeat
2 replies
1d10h

Does this still require running Nginx as a reverse proxy in front of it?

withinboredom
0 replies
1d10h

No, and I'd recommend not doing so unless you need to. Caddy/FPHP supports https3 out of the box, and I don't think nginx does (at least the versions currently packaged in major distros).

elitepleb
0 replies
1d10h

this runs caddy (another famous reverse proxy) for you

NorwegianDude
2 replies
1d13h

I tried it and found it to be really slow, not even using my cores properly. Spent some time in the lacking docs and didn't figure it out...

It says production ready with just a few commands and states 3,5 times the performance of fpm, but it's running at like 1 % of the performance of fpm for me. I also tried the executable, same issue. Was expecting at least 200K rps for hello world...

kdunglas
0 replies
1d11h

Hi,

FrankenPHP author here. We would very much appreciate a reproducer. According to most benchmarks, FrankenPHP is generally much faster (~3 times) than FPM when worker mode is enabled, but there are still some outliers, and we're working with PHP maintainers to fix them.

withinboredom
0 replies
1d11h

If I could reproduce it, I’d happily take two weeks off from work and fix it. Nobody has mentioned how to reproduce it.

blixt
1 replies
1d11h

Reminds me of that time 10 years ago when I tried to make Go more like PHP instead of the other way around: https://github.com/blixt/go-pher

More seriously, happy to see worker mode in this server. PHP does come with several performance downsides, though I’m sure a lot of them have been worked around in the past decade. I don’t think I’d do PHP again though if I’m being honest.

pseudosavant
0 replies
1d9h

There seem to be a lot of us with this PHP sentiment. PHP is like a girlfriend you lived with that was easy going and super cool at first...but by the end she might have been trying to poison you. She's been to therapy since and doing really awesome, but how could you ever go back right?

Like, I'm really happy for the (many) remaining PHP devs that it isn't the shitshow it got to be around PHP6. But it could never tempt me back. Deno, Django, Go, dotnet...plenty of other fish in the sea.

samuell
0 replies
1d2h

"Build standalone, self-executable and dependencies-free binaries for your PHP web applications, and command-line tools."

I'm sold.

pachico
0 replies
1d12h

I enjoy seeing this in the front page of HN.

My feeling is that FPM and its share nothing arquitecture has been both the key of PHPs success many years ago but also its condemnation.

oksteven
0 replies
1d10h

I have been looking for something like this for a while; it's great to see one now. My current approach is to use nginx container as a proxy to another container which run php-fpm, I don't think it's efficient enough. I'll try Frankenphp and see if it can do better.

chuckreynolds
0 replies
1d13h

oooh interesting. been a min since i've needed a php + WP setup but... not bad.

63
0 replies
1d12h

Interesting for sure. My current setup is your basic nginx, fastcgi, php-fpm. I have some custom ngnix config though and I wouldn't want to have to switch web servers. I guess I could still use nginx as a reverse proxy and point it to this but then what's the point? I'll look into it for future projects where I really just need a simple php deployment, but for my needlessly complex project I'm already working on, I don't think it fits.