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.
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.