The future of Nginx: Getting back to our open source roots
nginx.com
nginx.com
It would be interesting to scorecard the progress made on promises made then. There is a lot of repetition. Feels a little hollow.
0. https://www.nginx.com/blog/nginx-sprint-2-0-clear-vision-fre...
I switched to Caddy because I just got so sick of the constant pain of certificates. Caddy does certificates automatically.
I also was sick of the complexity of nginx configuration. I could get the things done that I needed to do but it was always painful and time consuming.
I've worked out how to do in Caddy everything that I did in nginx though that took alot of time and effort, but I tend to create quite sophisticated web server configs.
At this stage there's nothing really that nginx could offer that would bring me back from Caddy.
I'm old enough to remember the same complaints about Apache, and nginx being the simpler alternative.
Something about systems evolving to a level of complexity/sophistication until they collapse under its own weight...
A competitor comes along who's designed for y + z, and everyone loves how nice and simple it is. Then use case u comes along...
Was about to comment the same !
What is that saying:
"You either die early, or live long enough to see yourself become the villain" ?
It's about bad configuration file design, little thought put to usabillity and ergonomics, and, actually, a total lack of knowledge in that domains (usability) on behalf of the devs...
To my knowledge the nginx config hasn't gotten more complex.
I don't know caddy but I suspect it's just simpler.
Nginx is still far simpler than Apache.
It just so happens that subsequent projects picked specific usecases to work on their happy paths to make them far simpler. Certificates is one of them.
> Something about systems evolving to a level of complexity/sophistication until they collapse under its own weight...
This is nothing of the sort. It's a matter of newer and better options popping up, not that old options got worse.
I think a shell script with certbot and "nginx reload" is much easier than some closed service I can't take a look at.
The thing with certificates is that most tutorials are terrible. A very seamless way is to use the webroot method. Create a nginx configuration file that places LE's challenges to a specified folder on your system, include that config into your server blocks. Then you instruct certbot to use that folder. Really quite easy.
“Your ideas are intriguing to me, and I wish to subscribe to your newsletter.”
Is there a detailed writeup on this? This sounds great, but I don't want to faff about with it.
/etc/nginx/letsencrypt.conf:
location /.well-known/acme-challenge {
default_type "text/plain";
try_files $uri $uri/ =404;
root /tmp/letsencrypt-auto;
}
/etc/nginx/sites-enabled/default: server {
[...]
include letsencrypt.conf;
[...]
}
Reload nginx.Invoke certbot for the new domain once with:
certbot certonly --webroot -w /tmp/letsencrypt-auto/ [--must-staple] -d example.comDNS challenges are a bit more seamless, but I personally don't like giving access to entire zones to a single machine. Like most DNS APIs force you to.
https://serverfault.com/questions/822484/nginx-444-error-eqi...
I've honestly never had any sort of "constant pain" by using nginx and acme.sh. Certbot is an actual abomination.
I have a script just as a shortcut for these two commands:
acme.sh --issue --dns dns_cf -d "$1" -d "*.$1"
acme.sh --installcert -d "$1" -d "*.$1" --certpath /foo/$1/cert --keypath /foo/$1/key --fullchainpath /foo/$1/fullchain --reloadcmd "/usr/local/bin/docker-compose -f /foo/docker-compose.yml exec -T nginx nginx -s reload"
You just have to run those commands once per domain and it'll keep that wildcard certificate valid forever, acme.sh sets up a cronjob to renew the cert when needed and will automatically reload my nginx container after.Even though I've set up nginx and certbot before, I'm happy I don't need to think about that stuff with caddy. Total waste of mental resources. I just want to get stuff on the Web.
No disrespect to the good people behind nginx. Caddy is simply part of a new generation of web servers.
I feel old now, as I continue to deploy Apache :-)
we wrote bash scripts backends. don't worry about being old. keep going ;)
some even had their cgi code running in kernel.. all the more reason to be merrier.
e.g:
FROM caddy:2-builder AS builder
RUN xcaddy build \
--with github.com/greenpau/caddy-security
FROM caddy:2
COPY --from=builder /usr/bin/caddy /usr/bin/caddy
You can keep your container image, and just do the "COPY --from=builder" step in there. We do this in CI/CD on every build.Building on separate computer will work, of course, but it makes everything more complex.
Have it run on a schedule to keep it updated, if necessary. Alternatively, GH Actions allows you to set a manual trigger so you can rebuild whenever.
I had the same problem as you. Here is me whining about it on the Caddy frum:
https://caddy.community/t/wildcard-certificates-building-fro...
But in the end I managed to get the pre built stuff.
Their download section is extremely unclear about whether or not you need to build Caddy. You don't.
but coming from apache it was the freshest breath of air possible. i still prefer it to any yaml/json alternatives newer products like envoy use. a pure ymmv point.
i don't think that having a manual or reference open while doing more involved setups is a sign of bad design. some things are simply complicated...
Documenting things that took time for you to grasp is a great way to learn, in my experience.
For instance, should `upstream` be defined at the top-level or under `stream`? If you have another server doing a proxy_pass to that upstream, does it also need to be under `stream`? This is in no way obvious by either looking at nginx configs or by reading the docs.
And then what if you have a web server? Does it need to be under `http`, or can it be top-level? It can be either one depending on who's config you're looking at. But if your server you're pointing to is already an HTTP server, why would you want nginx to use its own http serving on top of your HTTP server?
That's just a couple of examples. And yes, there are absolutely logical answers to those, but I do not believe that the nginx config format speaks for itself.
Performance?
I don't think the difference in performance between Nginx and Caddy would mean you need 3 servers versus 1 of the same spec. But of course, you need to run your own benchmarks on your own config to determine which is best _for you_.
Benchmarks cannot be done generally, because the config drives so much of what happens at runtime, and everyone has different needs.
That may be fine if you only use those certificates for port 443 but it falters where certificates are used for the remaining 65533 ports. Instead of leaving certificate request and renewal to individual tools I prefer to centralise it in one spot - a small container or VM is sufficient - which deals out ready-to-run certificates to those systems which need them. When dealt with this way nginx actually has no problems whatsoever with certificates, all it takes is those three (or more depending on your protocol needs) lines in the config file:
listen 443 ssl http2;
ssl_certificate /etc/letsencrypt/live/site.example.org/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/site.example.org/privkey.pem;
The /etc/letsencrypt/live tree gets pushed to the relevant machines by the certificate handling container/VM with certificate files in the form and shape needed by whatever program is to use them.So, in short, the Caddy approach may be fine for those who only run web things but it 'fails' (as in 'adds additional complications') for those who venture beyond port 443.
Also you can cluster Caddy by making sure the filesystems are synced, or using a storage module like Redis. Then any of the Caddy instances can do any step of the issuance phase (one can start it, another can complete it).
You can use these certificates for sites on non-443 ports as well, once you have the cert. Nothing special at all to do there, you just configure Caddy to serve a site with a different port, e.g. `example.com:65533`
You also get numerous other benefits, like OCSP stapling, issuer fallback (if LE is down, it'll try ZeroSSL), etc.
1. HTTP server is production ready.
2. autocert fetches certificate automatically from LetsEncrypt.
3. Graceful restarts (zero downtime) using signals.
I think the the biggest advantage of languages which enable portable applications like Go is not having to mess with web servers anymore, At least for most common use cases.
Seems like a poor tradeoff for a slower, less configurable web server.
The correct thing with Caddy is to _not configure anything at all_ for TLS. The defaults are the correct thing to use. If you override the defaults, then you're more at risk of bitrot due to not remembering to update your own config. Let Caddy (and the Go stdlib, really) choose what's secure.
I still think that Nginx is pretty good, however there are a few annoying things about it, certificates being just one of them.
Personally, I also found that attempting to use it as a reverse proxy kills the entire instance when there is no DNS record for one of the sites (say, 1 out of 20 that are proxied). I ran into this when running containers that hadn't passed health checks and therefore didn't have any traffic routed to them, which meant that if any of them went down, all of them would be unreachable. Furthermore, the popular suggestion of using a variable for the proxy URL just broke redirects in some apps: https://blog.kronis.dev/everything%20is%20broken/nginx-confi...
Caddy is pretty good, though I couldn't get the equivalents of all the options that are available in other web servers, for example allowing encoded slashes when hosting a Sonatype Nexus instance like what you can do with Apache. Things might have changed, but last I tried, it didn't quite seem to work: https://help.sonatype.com/repomanager3/planning-your-impleme...
Furthermore, there were issues with certificates as well: if the configuration for one of the aforementioned 20 sites was bad and the certificate couldn't be renewed, then the entire instance went down. What does this mean? Well, if I run Caddy as a container, I'll get the "fail fast" approach, which will sadly then mean that I'll get a restart, that will still fail with the bad configuration and eventually will hit Let's Encrypt rate limits. Sure, I can have some alerting (extra work) or have restart backoff/delays (though this will be bad for restart times if the instance were to ever crash for other reasons, e.g. load), but neither seems like an actual solution. Very annoying, especially because everything will once again go down, instead of being built for resiliency.
In the end, I kind of just went with Apache for the time being, because despite being a bit awkward at times, it's still an okay web server for the scales that I work at and is okay to deploy inside of containers. I wrote about it more on my blog, "How and why to use Apache httpd in 2022": https://blog.kronis.dev/tutorials/how-and-why-to-use-apache-...
It even has Let's Encrypt (well, ACME) support built in, thanks to mod_md nowadays: https://httpd.apache.org/docs/trunk/mod/mod_md.html
Of course, I still use Nginx + PHP-FPM with supervisord for containers where I need to run PHP, because of some other weirdness when you try to get it working with Apache, which probably has something to do with how I build container images. That said, I couldn't actually find what the problem was, so it was easier for me to just use Apache on the edge and Nginx for the apps (PHP, or maybe even serving static assets), about which I wrote on yet another blog post, "Containers are broken": https://blog.kronis.dev/everything%20is%20broken/containers-...
In short, it's nice to have a choice of web servers and being able to pick whatever is the best suited for your needs. It's just that there's a lot of weirdness going on with what should be simple configurations.
It's much smarter now.
Caddy also doesn't stop if a certificate can't be obtained. When did you last try? Maybe a big was fixed but it would have been YEARS ago.
I'll probably check out the more recent versions of Caddy as well, admittedly they're most likely a rather painless experience for most folks when compared with Apache/Nginx, though I've also heard good things about Traefik, which is even integrated in K3s as an ingress.
I guess most web servers are workable for a variety of use cases with a bit of effort, though I definitely reminded myself why people weren't exactly the biggest fans of the Apache config syntax just recently.
multiple back end proxies
authorization sub requests
for multiple domains
CORS
and other stuff I can't recall offhand
Invest in:
0. Automation
1. Documentation
2. Take away SSH
3. Except for data stores, ephemeralize servers so they can be blown away and automatically reprovisioned
4. Have tested backups (untested aren't backups)
5. Save time
6. Solve other, bigger problems
Would you care to give an example or two?
Let's Encrypt has a much better track record at preventing people from issuing certs for random domains compared to many other commercial entities.
"part of f5" is written on the logo in almost imperceptible font, that it may evade the PTSD of managers familiar with f5 licenses.
A per node, per core, per something license at a much lower rate would've saved them a lot of problems. Because $5 a month per node might get expensive quickly when scaling up, but thats a simple expense I can throw on the corporate credit card and then go "look, now the project is delivered".
In the end it hurts them because a developer or consultant may find a problem that is worth the license fee to solve - but with no hands on experience of the product due to the cost, it's hard to recommend it and take the reputational risk in case it doesn't live up to its promises.
If they have modules - why not sell these modules and attach a "reasonable" price to it?
Not sure what my point is. But NGNIX has a special place in my developer heart and it’s really encouraging to hear this.
Apache had mod_fastcgi for half a decade before nginx even existed, and then got mod_fcgi, but it was not much good without any support from PHP (which was an even bigger deal back then).
The fastcgi thing was true: I don't for a minute deny what you are saying. But it also stranded some "less agile" minds like me.
I know significant sites using Perl use::CGI; still.
I was working in managed webhosting at the time, and it was just amazing how much could be done in Nginx without needing to track down some abandoned module like had to be done with Apache all the time.
What it actually means: "As part of this commitment to modernize, we are adding an NGINX Community channel on Slack"
Oh right. It completely makes sense that open source roots involve a proprietary communication platform.
Using Matrix would definitely be preferred for me since I have Element/Fractal open all day, everyday.
These choices matter.
https://drewdevault.com/2022/03/29/free-software-free-infras...
> We realize it complicated matters when we created [...] an open source Ingress controller for Kubernetes, [...] different from the community Ingress solution (also built on NGINX).
> It’s pretty clear that the Gateway API is going to take the place of the Ingress controller in the Kubernetes architecture. So we [...] will make the NGINX Kubernetes Gateway – which will be offered only as an open source product[...]
... but these two bits very much give me a feeling like they're planting their flag here and offering an open source version so that there's no "need" to go making another one that they don't control.
Here’s a summary (from F5 Nginx) of the key difference between nginxinc/kubernetes-ingress and kubernetes/ingress-nginx:
https://github.com/nginxinc/kubernetes-ingress/blob/main/doc...
That’s the main reason we no longer use it for our multi-tenant SaaS systems.
Caddy powers our thousands of domains - although I will never be a fan of its JSON config file option, it works very very well for us.
Otherwise… it’s great.
Well, if you use a Caddyfile, the JSON config is just an implementation detail. That decision shouldn't matter to you. The fact is, JSON is the best option for Caddy _at runtime_ to manage its config in memory, especially because Go has first-class support for unmarshaling JSON documents onto a tree of structs.
And also if not doing it by hand, it means additional tooling to create the JSON file. Another layer to deal with with so many layers already.
Also Go's first class support for JSON is not a reason for supporting JSON in configuration files. Pretty much every language supports JSON anyway, so whether it's "first class" or "second class" does not really matter.
Anyway, we love and use Caddy here. We just don't use the JSON config file.
Now the dynamic configuration API is going open this will give Envoy a good run for its money. The big thing Envoy doesn’t do is static file serving and for smaller (anything but the largest…) deployments Nginx makes a ton more sense.
PS. Have you seen Caddy's on-line config API? https://caddyserver.com/docs/api
When people say "production", they mean things like "QoS for a shared-multitenant system, in the presence of customers with really badly tuned and spiky request workloads, whose traffic you must nevertheless mostly accept."
I keep telling people "tens of thousands" when I probably should be saying "hundreds of thousands"...
How do you know how many requests are silently lost?
I would like to read more about how reliability is actually measured on high-traffic sites.
> QoS for a shared-multitenant system, in the presence of customers with really badly tuned and spiky request workloads, whose traffic you must nevertheless mostly accept.
Yah, we see that sometimes. Caddy usually handles it fine, sometimes with a bit of massaging the config.
It would be great if you would like to finish the work on this project and make it part of the Caddy default distribution.
Honestly I do not understand how people run high-traffic sites without rate limiting. [D]DOS attacks and other misuse (e.g. spambots etc.) are daily issues on the internet, do you just ignore that?
https://news.ycombinator.com/item?id=31439457
Appreciative of all the work regarding caddy, but the rate limiting seems to be chicken and egg, as few people seem to be willing to test it out in order for it to be accepted into core, and people are unwilling to test it out, because it's not in core.
It's also a blocker for me, so nginx wins by force of inertia.
1) Nginx configs are (from my experience) easier to template (in our Nomad & Consul cluster architecture) 2) From what I could gather, Nginx is more stable and performant 3) I don’t trust Caddy’s codebase security. It simply has too many dependencies, and Go makes it very easy to get into dependency hell
Honestly if 3) wouldn’t be an issue, and stability from 2) would be proven, I would probably give Caddy a try in production.
Pro tip: Did you know you can use any config format you want to configure Caddy [1]? So if templating the Caddyfile is hard for you, use something else! You can use YAML, TOML, or even NGINX configs.
On 2, that's been pretty well debunked at this point. Caddy is written in Go, and is only a very thin wrapper over the Go standard library, which heartily powers much of Cloudflare's, Netflix's, and Google's infrastructure. Plus you gain memory safety and are exempt from a whole class of vulnerabilities with Caddy. We've seen numerous instances where Caddy has kept sites up while nginx let other sites go down, due to Caddy's resilience in the face of certificate problems, for example.
On 3, sure, I can understand that -- but this is true of any open source project. And it IS open source, so you can "own" your own code base. You're in control. And actually, Go's module proxy protects Go projects more than most C projects. Caddy's extensible architecture means that you can add all the features you need without bloating the code base.
I think the ACME integration in Caddy was a really smart move, it's great to see some competition.
I host some stuff at home and moving from nginx to Caddy v1 was a huge breath of fresh air. V2 made the product extremely good.
I tried a bit to use the API to automate my deployments (which are, again, home deployments) but it stopped to make sense when i discovered that Caddy has the ability to read config files via wildcards.
To be fair, that was several years ago. But can you explain the logic behind that decision?
I use it with ansible for 18 months with no issue
> dns.providers.azure wraps the provider implementation as a Caddy module.
Well great what does the provider implementation do? It’s the same for all DNS and not so useful if I’m coming from Apache or Nginx. At least explain what I’ll be able to do with this module.
From http.handlers.push:
> http.handlers.push is a middleware for manipulating the request body.
That’s a bit generic - any examples? There’s a lot of ways to modify the request body so what can I do with this?
There are 2 http.authentication.providers.jwt - both unofficial and both with 0 documentation. There has to be some standards here, why link to blank docs from your site?
All-in-all it just feels meh. I like to read docs that’ll give me the technical ins and outs of every function with some examples ideally.
Microsoft does a decent job of this as does Postgres (and others but these two come to mind immediately). Envoy is pretty nice here too and Nginx close.
Re "http.handlers.push", fair point, that one's lacking/misleading. But this is a feature that was just added to satisfy a specific need, then fell by the wayside. Mostly because now Chrome is removing support for Server Push, so we'll need to deprecate this feature, in favor of HTTP 103 Early Hints which is the effective replacement for it.
Also, in general, we tend to spend more effort on maintaining the Caddyfile docs than the JSON docs, because the large majority of users use the Caddyfile. See https://caddyserver.com/docs/caddyfile/directives/push for the push handler, complete with examples.
Re "http.authentication.providers.jwt", well again, I think that's an issue with the module's maintainer not sufficiently using godoc comments. The maintainer registered the module under two different module paths (renamed repo) so it caused a duplicate. We'll need to manually remove the duplicate from the database, I think. It might be because there's conflicting ones that no docs are shown (cause the backend which serves the API docs is confused, I dunno, it's a bug clearly, will need to dig deeper).
Useful for example for staging environments, whitelisted from certain ips, but allowing access via user-name/password from other IPs and/or the Internet.
@needsAuth not remote_ip private_ranges
basicauth @needsAuth {
user pass
}
This uses a named matcher[0] `@needsAuth` with the `not` and `remote_ip` matchers, to match all public IP ranges (change `private_ranges` to a list of CIDRs if you prefer), then applies that request matcher to the `basicauth` handler[1], and pass in user/pass pairs to it (passwords are bcrypt hashed).If the user fails authentication, then they won't be able to get in, as you'd expect. But users inside your allowed IP ranges will get through without basicauth.
[0]: https://caddyserver.com/docs/caddyfile/matchers
[1]: https://caddyserver.com/docs/caddyfile/directives/basicauth
log_format main '$remote_addr - - [$time_local] "$request" '
'$status $body_bytes_sent "$host" '
'"$http_user_agent" $http_content_length $request_time '
'"$resp_body" *$connection $connection_requests';
server {
set $resp_body "";
location ~ "^/api/v1/...$" {
# Append response to resp_body until it reaches max_len.
# - ngx.arg[1] is input chunk.
# - ngx.arg[2] is eof flag (response is done).
# - ngx.ctx.resp_body holds partial result between calls
# - ngx.var.resp_body holds final result.
# From:
# - https://gist.github.com/morhekil/1ff0e902ed4de2adcb7a
# - https://github.com/openresty/lua-nginx-module/
body_filter_by_lua_block {
local max_len = 256
local resp_body = (ngx.ctx.resp_body or "")
if string.len(resp_body) <= max_len then
resp_body = resp_body .. string.sub(ngx.arg[1], 1, max_len)
ngx.ctx.resp_body = string.sub(resp_body, 1, max_len)
end
if ngx.arg[2] then
ngx.var.resp_body = ngx.ctx.resp_body
end
}
}
But there are many scenarios where being able to extend the HTTP server via Lua is more convenient than writing a plugin I would think?I've also used Lua in the past with haproxy and with Redis. It's a powerful, performant, light-weight, and flexible escape hatch/extension mechanism.
Well, Caddy is written in Go, so it's only natural to write a plugin in Go. Statically compiled into your binary. We provide a tool called `xcaddy` which is used to produce builds of Caddy with any plugins you need. You just need Go installed on your system to run it, no other dependencies.
The reason why Lua is used for OpenResty is because writing plugins in C is... not fun.
You can absolutely do what you described with an HTTP handler module in Caddy. You'd just wrap the req.Body with a reader that watches the bytes as they're copied through the stream, and when you see the part you want to log, you do that.
We have a replace-response plugin which takes a similar approach, except it manipulates the response as it's being streamed back to the client. https://github.com/caddyserver/replace-response The whole plugin is just one file of Go code.
Wasn't dynamic configuration always available through OpenResty? It's based on Nginx too with extra Lua modules to fill the feature gaps
Also they should have stayed away from erstwhile Ballmer phrases like “open source is not production ready”, who thinks that way? Tells me that this is not written by someone that contributes or understands open source at all.
Why does everything have to be modernized? Nginx is awesome not because it tried to keep up with the ilks of ill-thought servers that came and went faster than a flash in the pan. No let’s not put it on GitHub and have every literal person contribute. Elegant architectures and code like this don’t just happen because someone “modernized”.
All I ask is a Caddy style JSON configuration format for Nginx. And don't just implement some random JSON schema either, please create a well designed schema that is extensible. Take Prometheus [1] or Alertmanager [2] as examples of well designed and extensible schemas.
Just give me some basic features first, easy HTTPS, easy reverse proxy, easy rate limiting. You can release the rest of the advanced features in your own time.
[1] https://prometheus.io/docs/prometheus/latest/configuration/c...
[2] https://prometheus.io/docs/alerting/latest/configuration/
Ability to do basically control and rewrite all your ingress AND egress and have some state via Redis over UNIX sockets.
What's not to love? After all, it's what powers the bulk of internet.
Granted, it sounds dreamier than it is, since a lot of the contraptions you could come up with might be better placed at application layer. But having operational ability to do these things ad-hoc, security advantages of manipulating at your own infra edge or performance boosts, sure does come in handy!
Am I crazy or did they really change the licensing situation? Cause it definitely looks pretty interesting, looking at current docs.
Edit: Found it - they did switch to Apache 2.0, remove all usage restrictions and open-sourced it all https://github.com/caddyserver/caddy/issues/2786
But licensing is hard. AWS abused the leniency of Elasticsearch's original OSS license, so now the industry is set back 10 years with new entrants trying to find the balance between inviting community participation and getting gob smacked by big corporate interests.
Im not saying Elastic.co is an angel but its a lesson OSS projects have to take to heart, unfortunately. Thanks Amazon.
AWS has no problems with giving away the code for any managed-X service they. The magic that they charge for is the managed part - deployment, autoscaling, upgrade management, and other Operations stuff that no FOSS license can compel them to make public.
They did not abuse anything. Elastic chose a license that allowed everything AWS did. It is Elastics problem if they don't understand licenses.
Thank you for the info, rather curious about trying it out at this point then. I was about to whip out nginx for a server I wanted to setup over the weekend, guess I'll play around with Caddy then!
Caddyfile is pretty basic, anything advanced doesn't work, and community resources arent even close to Nginx.
So I stick with nginx, even though its annoying to handle Let's encrypt auto renew in containers with normal Nginx, since SWAG doesn't support separate certificates per domain.
> anything advanced doesn't work,
Can you be more specific? I'm sure that's not true because I'm in touch with large companies like Stripe who use some of the most advanced features.
I didn't find a better word for it, I'm not an English native.
I disagree. I think we're at about 95%-ish of usecases supported by the Caddyfile. We're continually improving on this.
It's just a reality of having to maintain a config adapter, when the actual underlying config at runtime is JSON. But it's fine, we make it work :)
If you have something specific you find you can't do with the Caddyfile, please open an issue. If you're just not sure, please open a topic on our community forums and we'll help you out.
How can I do this with Caddy?
But that said, from a quick Google search... was this an RTMP stream? If so, I suppose you'd want to use https://github.com/mholt/caddy-l4 which is a plugin for Caddy that lets you do TCP-layer things. Caddy's standard distribution just ships an HTTP server (plus TLS and PKI, etc), which is layer-7
You might be able to use caddy-l4's "tee" handler to pipe into multiple "proxy" handlers. But I'm not sure anyone's tried this yet, I had no idea people did this sort of thing. I'd be interested to hear if it does work though.
I don't like its community much either. The top guys are pretty arrogant. You can meet them in discord.
They spent months trying to get away from adding forward proxy support claiming another project provided support for it. (That project changed three times in that time frame) Now they added the feature like somebody just asked for it and they added it.
When starting with Caddy (v1) I missed part of the docs and asked questions in the community - I never got a RTFM answer. It is difficult to embrace a new product and these guys understand it.
The Go community, on the other hand... :)
That is not what happened. We did not understand what people were asking for at the time, partly because it wasn't clearly explained to us.
> Now they added the feature like somebody just asked for it and they added it.
It being added recently was because of other changes to the codebase that made it possible to implement easily. We didn't have response intercepting working correctly in the reverse_proxy module until more recently, and it took some careful refactors to get it right.
Once we were made aware of an issue in Authelia's issue tracker (one of the top open source auth servers) asking for Caddy support, we looked into it more closely. Nobody reached out to us about that issue being open, for whatever reason. We got a massive amount of help from James Elliott at Authelia who did extensive testing and helped us design the config layer so that it would match general expectations.
The issue I think you're talking about is this one: https://github.com/caddyserver/caddy/issues/2894. Early on in v2 betas, we opened the discussion to get community feedback about the "Authenticator" interface, i.e. https://github.com/caddyserver/caddy/blob/master/modules/cad... and what would be needed to support everyone's needs. Nobody ever suggested "forward auth" in that issue. It was all very handwavey suggestions with nothing truly actionable. So the discussion stagnated, and we closed the issue.
> Their one major disadvantage is the chasm between version 1 and 2. Most info you can find is about version 1 and does not apply to version 2.
Caddy v2's been out for 2.5 years now. I think the balance has shifted on this, it's much easier to find info for v2 than some time ago. That came naturally. It's to be expected for _any_ major change in a project's direction. It's not unique to Caddy in any way.
> I don't like its community much either. The top guys are pretty arrogant.
With all the above said, I think it's moreso that we feel the need to defend Caddy and its reputation, especially because it keeps getting attacked due to misinformed comments, for example the question of licensing; the licensing issue people had was mostly invented based on a misunderstanding.
But feel free to elaborate on what you think we're being "arrogant" about. I'd be glad to clarify any misunderstandings.
Reminds of the days that Varnish + Apache was a thing and you had to invalidate cache more or less manually.
That sounds pretty similar (in spirit, at least) to mod_perl etc. in Apache.
Does anybody happen to know a writeup that compares the two?
https://clouddocs.f5.com/training/community/nginx/html/class...
This is a must have feature for todays workloads (kubernetes or just very busy webservers) in production, and nginx will likely continue to lose market share to Envoy based alternatives where everything is configured through APIs, without needing to reload the server.
I agree with your sentiment though! I hope they do follow through as nginx is generally an easy sell to others when trying to fill holes in your tech stack and otherwise pretty bulletproof.
For rolling deployments, it can cause repeated configuration changes exacerbating the problem, some workloads more affected from this than others of course. The nginx ingress controller makes this clear
https://docs.nginx.com/nginx-ingress-controller/intro/nginx-...
> Every time the number of pods of services you expose via an Ingress resource changes, the Ingress Controller updates the configuration of the load balancer to reflect those changes. For NGINX, the configuration file must be changed and the configuration subsequently reloaded. For NGINX Plus, the dynamic reconfiguration is utilized, which allows NGINX Plus to be updated on-the-fly without reloading the configuration. This prevents increase of memory usage during reloads, especially with a high volume of client requests, as well as increased memory usage when load balancing applications with long-lived connections (WebSocket, applications with file uploading/downloading or streaming).
edit: formatting
> Once the master process receives the signal to reload configuration, it checks the syntax validity of the new configuration file and tries to apply the configuration provided in it. If this is a success, the master process starts new worker processes and sends messages to old worker processes, requesting them to shut down. Otherwise, the master process rolls back the changes and continues to work with the old configuration. Old worker processes, receiving a command to shut down, stop accepting new connections and continue to service current requests until all such requests are serviced. After that, the old worker processes exit.
So something you are making money from? How do you propose to keep it secure and maintained as FOSS? Someone else's donations?
If it is so critical, surely paying a few dollars won't break your business model.
I've worked with nginx in the past, and didn't have a great experience, so I was apprehensive diving in, but this time was very different. I think njs (their custom JS scripting environment) was a game changer. Support is built in to nginx core, and available by default in their docker containers, so it's much easier to get started with than Lua scripting. Their JS feature support has some quirks (no optional chaining, array destructuring, console.log's don't show up in logs, are some examples of things that threw me off) but overall nothing that blocked me from implementing the functionality I needed, and the integration points within the nginx config felt a lot more natural than I remember with Lua modules.
I did run into a number of things that were locked behind their commercial offering that made me a bit uncomfortable betting on it for the long term compared to purely open source alternatives. Off the top of my head:
- DNS discovery. There's a thread on the Fly example repo accompanying the blog post that describes the use case and proposes some workarounds: https://github.com/fly-apps/nginx-cluster/issues/2. Life would be a lot simpler if DNS discovery from the commercial offering was just available (i.e. we can outright delete a brittle bash script that makes DNS queries and reloads nginx on a 5 second interval). This was mentioned in the article as something they're planning to open source.
- Access to some kind of shared key-value store for custom caching logic in njs scripts. With Lua we could just connect to Redis, but njs can't seem to establish persistent network connections for now, so that's off the table. This wasn't mentioned in the article, but they did mention in this Github issue that they're planning on open sourcing their keyval module for this use case: https://github.com/nginx/njs/issues/437. I have some use cases where being able to connect to Redis would be ideal, since I'm already using Redis for caching across a bunch of other services, and syncing keyval across a cluster seems to be eventually consistent (https://docs.nginx.com/nginx/admin-guide/high-availability/z...), but for most of my caching use cases it should be sufficient.
So this article, along with their overall willingness to work with the community to identify and bring commercial features into open source (at least from what I've observed across their responses to Github issues) does a lot to alleviate those concerns.
Though at the end of the day, I don't necessarily need every nginx feature to be in open source. I have no problems with paying for great software like nginx to support its development. But as a small bootstrapped founder, their current pricing structure (from what I could gather on the internet is ~ 2k-5k per running instance) is completely prohibitive. It'd probably require a revamp to the way they sell the software (i.e. self-serve onboarding and automatic license provisioning for smaller customers instead of having customers of all sizes go through expensive sales people), but I'd love to see a more progressive pricing structure with a lower barrier to entry for their commercial product.
That’s the main reason we no longer use it for our multi-tenant SaaS systems.
Otherwise… it’s great.
But then again, that seems painful in any scenario.
#### Videos
- The Internet just changed with Robin Marx and David Bombal https://www.youtube.com/watch?v=cdb7M37o9sU
- QUIC 101 with David Schinazi https://www.youtube.com/watch?v=dQ5AND4DPyU
- Decrypting TLS, HTTP/2 and QUIC with Wireshark https://www.youtube.com/watch?v=yodDbgoCnLM
It's a great pleasure to read/watch Robin Marx and David Bombal
#### HTTP3 core concepts
- HTTP/3 From A To Z: Core Concepts Part 1 https://www.smashingmagazine.com/2021/08/http3-core-concepts...
- HTTP/3: Performance Improvements Part 2 https://www.smashingmagazine.com/2021/08/http3-performance-i...
- HTTP/3: Practical Deployment Options Part 3 https://www.smashingmagazine.com/2021/09/http3-practical-dep...
- https://thenewstack.io/http-3-is-now-a-standard-why-use-it-a...
### Test Learn QUIC
I don't say this to be ungrateful about what nginx has provided for free, it's great, thank you. But the post also feels like a cynical take about what the value of open source truly is.
Many of those features have gone from fancy to expected, and they transitioned too late to making them open source.
The free product went through a slow decline from excellent to artificially crippled, and they’re changing course, which should be applauded. On top of that they didn’t take away features to cripple their product for money, just what is basically necessary these days is so much more than it was years ago.
I love the fact that Caddy is a single binary I can run for simple use cases without configuration file. Plus the built-in Let’s Encrypt support. Nginx is definitely on defence here unless you need “web scale” servers.
The real killer feature for me is the Cloudflare module. It allows you to use the acme DNS challenge, which means you can test your SSL setup without exposing your server to the public internet.
Such a smart design and incredibly useful piece of software!
"we recognize that many critical features which developers now view as table stakes are on the wrong side of the paywall for NGINX Open Source and NGINX Plus. For example, DNS service discovery is essential for modern apps. Our promise is to make those critical features free by adding them to NGINX Open Source. We haven’t yet decided on all of the features to move and we want your input. Tell us how to optimize your experience as developers. We are listening."
"The NGINX Kubernetes Gateway is also something of an olive branch we’re extending to the community. We realize it complicated matters when we created both a commercial and an open source Ingress controller for Kubernetes, both different from the community Ingress solution (also built on NGINX). The range of choices confused the community and put us in a bad position.
It’s pretty clear that the Gateway API is going to take the place of the Ingress controller in the Kubernetes architecture. So we are changing our approach and will make the NGINX Kubernetes Gateway – which will be offered only as an open source product – the focal point of our Kubernetes networking efforts (in lockstep with the evolving standard). It will both integrate and extend into other NGINX products and optimize the developer experience on Kubernetes."
It sounds pretty honest and positive to me. And I'm the first person to call bullshit on corporate doublespeak. Most other companies would just put more money into B2B sales rather than courting OSS devs/free users and admitting when their strategy was stupid (actually their language is evasive, but w/e).
Of course hindsight's 20/20; let's see if they make good on these promises.
friendly tip - not everything is on Github, not everyone is on Github, everything can be on Github but that's not the only place everything can be
"all open source work that I know of, is on Github"
Where did you look for source code, on Github. Where is the source code you found after looking? Github. Where is "almost all open source work" that I saw? on Github. etc..
No, GitHub is where I was linked to from the project's homepage, or the package's page on the package manager, or from a Google search result.