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.
Is that because you have 18 years of experience, or would it be as easy for a new developer?
It really is very easy.
So I would say, knowing these two languages, PHP really is that easy to setup.
A newbie is more likely to use the built-in development server and then SFTP a 'git archive' to a shared host.
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.
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!
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).
Related reading:
https://blog.tjll.net/reverse-proxy-hot-dog-eating-contest-c...
Tell that to Stripe and Framer and numerous other businesses using it very seriously and very much professionally! ;)
> 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?
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.
Because it’s Go, you can tune garbage collection to be super aggressive, at the expense of speed.
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.
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.
Keepalived is not really bound to Nginx by any means and should perfectly fine work with Caddy too.
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.
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.
With reverse proxy in front of such setup is - much better in terms of performance. For shared hosting - yet again, may be not optimal if one needs to support multiple system users.
It's a security nightmare. https://www.php.net/manual/en/security.apache.php
Even Apache httpd discourages the usage of mod_php. If installed, Apache recommends some extra configuration to limit memory leaks. https://cwiki.apache.org/confluence/display/HTTPD/php
- "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.
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
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.
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=37443911There 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.
Also, having a binary makes it easy to bundle in an Electron app.