Show HN: Caddy v2.5.0
github.com
github.com
He and several other maintainers, community helpers, distribution team members, and sponsors go a long way to making this project tick. Thanks for all you do!
Is there a place where we can contribute to more up to date docs?
I'm running it on an RPi that's hosting various home automation and hobby projects, all serving HTTP to the loopback interface only, with Caddy acting as a reverse proxy, and I've never even had to think about HTTPS. Adding a new service is adding a single line to my config file, and the rest happens automatically.
Finally, no more "trust this self-signed certificate" even for toy projects, no more port forwarding, copy-paste-ing dubious PEM and CRT files across services and Docker containers etc.
https://gist.github.com/lxgr/303b1a3cd87005edb43b91545c5306b...
I unfortunately can't remember if there is some header/footer I'm omitting here – this file is managed by Ansible for my setup, but I believe it should effectively be the full Caddyfile.
One benefit I found with using nginx is that services are more likely to have nginx proxy example configs, and sometimes these are non-trivial, eg.:
https://docs.mattermost.com/install/config-proxy-nginx.html
I guess with caddy you're on your own, which doesn't look like fun.
But if you need help, we're very active on https://caddy.community/ to answer questions :)
https://caddyserver.com/docs/config-adapters
Now you can use your nginx config with Caddy!
sub.domain.com { reverse_proxy localhost:8080 }
Small random feedback: I like the idea of JSON configuration but most of the common docs/recipes are documented only with the Caddyfile format. I couldn't figure out the full JSON schema that was expected so I wound up generating a Caddyfile string instead for my programatic control. Maybe there is some translation tooling that could help?
./caddy adapt
I hear ya. The JSON config is definitely not trivial. I wrote our JSON docs and strove to made them easy to follow. You can traverse into the module structure piece-by-piece here: https://caddyserver.com/docs/json/
There is also a Caddy plugin by @abiosoft that can generate a JSON schema for your custom Caddy builds, which can then be used by IDEs to give you autocomplete and validation: https://github.com/abiosoft/caddy-json-schema
I also sometimes recommend writing your config by hand in the Caddyfile, then using `caddy adapt` to get the JSON equivalent. (It might not always be the prettiest JSON, since the adapter is only so smart.) But then you can fine-tune the JSON a little easier, possibly. Hope that helps!
caddy-json-schema looks great, I'll try this next time!
not sure if I totally missed `caddy adapt` or if I had troubles with it.
The real reason is the thing you highlighted: "I can see there are some NGINX Plus features that are free in Caddy." Sadly it seems that NGINX is now crippleware. Personally I find it risky to depend on open source organizations who refuse to accept important features to the project, so they can sell those features as proprietary.
Is this still the case?
And to be clear, only builds produced by the official Caddy website used to be commercially licensed (not anymore). But the code has always been open source, and you could always build from source for free for commercial use.
> But the code has always been open source, and you could always build from source for free for commercial use.
Back in the days there were some workaround projects that build for you. Well caddy was relatively new then so I abandoned it for my projects.
https://github.com/lucaslorentz/caddy-docker-proxy
Pretty nice, handles routing to your containers and manages LetsEncrypt for you. Response times are super fast too (<= 100ms for an ASP Web API application which uses Postgres via Entity Framework).
I used to use this https://github.com/nginx-proxy/nginx-proxy (used to be under jwilder's GitHub account) which was also a good tool, and then used behind CloudFlare for free SSL certificates, but the Caddy container with automatic LetsEncrypt is fantastic also.
We're doing our best with the Caddyfile to cover every usecase. If there's something you're struggling with, open an issue if it's clearly missing, or ask on the forums, and we'll get you sorted.
I use Caddy in my production systems with one exception, websockets. Yes it works, yes it is easier to configure compared to nginx. But there is this one bug that I can't really put my finger on that is hard to debug and create an issue for.
Under high load, it seems there are messages that are dropped and then the connection gets lost. It even affects the origin host because it keeps the connections alive and they keep piling up. Killing Caddy brings the upstream service back to life.
With nginx I am not having these issues and the websockets are more stable. It is just harder to set up and needs multiple moving pieces for autossl instead of it being taken care of by Caddy.
But that JSON config file?
It’s a mistake. And I’m Being charitable and nice here.
Especially the part where there is an api to update the JSON file.
Jesus Christ Matt. Just use the caddyfile already. It’s easy, easy to read by everyone. Why make a config file hard to grok or follow by multiple team members?
I don’t get that part.
Like Matt said, I don't understand the problem here. Just use the Caddyfile. What problem do you have with it specifically? If there's a feature you're missing or aren't sure how to use, open an issue or ask for help on the forums.
Also thanks for fixing the slow JSON schema docs pages, really helped a lot.
The docs pages took longer to make than the core of Caddy 2 did, so I'm glad you like those too and find them helpful. That performance fix was a breath of fresh air for me too.
Anyway, nice to hear from another happy JSON consumer. I know several large companies using the JSON exclusively as well.
I really like the slickness of caddy, but I do not understand how a web server without rate limiting can be used for anything serious, you will need that for any website with some exposure.
Not sure if anything else is missing in comparison to nginx, I stopped research at this first very important point. I think streaming would be my next item on the list of things that you might realize nginx is not that bad at...
If tailscale doesn't provide it, anyone know of a DNS server that's caddy-like in simplicity and dead simple ease of running on localhost with minimal config, secure by default, etc?
Basically this is more about grabbing the TLS cert from Tailscale's daemon. How you handle the request is up to you. It's not related to the dynamic upstreams feature.
So yeah, you can write scripts that control Caddy while it's online.
The nice thing about the API is you can code in whatever environment or language you prefer: no need to learn Caddy's scripting language or anything like that. (The config is JSON, so nearly every language can output it.)
You have to realize how painful and annoying it is to see this get brought up every time we have a post here.
I wonder whether it's technically generally feasible (possibly depends on net/http2's capabilities) to handover the connection from the old to the new server instance, comparable to what systemd does in terms of FD passing for socket-activated services.
To be clear, the new config is running at the same time as the old is still tearing down; all new connections get handled by the new config. Listeners are shared and transferred between servers.
We're all ears, though, if someone with deep knowledge of Go's internals can point us in the right direction.
This feature is modular, so other methods of retrieving backends can be implemented as well.
One I found from 2020 shows nginx can handle more RPS in less time for HTTP/2 and HTTP/3: https://caddy.community/t/caddy-v2-http-2-http-3-benchmarks/...
A proxy benchmark from 2021 also shows nginx perform better than Caddy: https://github.com/NickMRamirez/Proxy-Benchmarks
After testing my app with it in local dev I noticed what the benchmark above says: requests per second is about half Nginx. So i switched back to Nginx.
So yeah if you worry about peak throughput on a CPU-bound system Caddy probably isn't the right choice though I'm not sure nginx is, either. A hardware-based load balancer, at least as a pre-stage is probably more sane in those cases. For everything else I would always trade ease of usage for a bit of performance. I would e.g. never dare to touch the nginx codebase, but writing a plugin for Caddy doesn't intimidate me at all.
Are there plans for SMTP or IMAP proxying?
Do you do SNI proxying too?
I would love for Caddy to be my one stop shop for all TLS termination.
https://github.com/mholt/caddy-l4
"Project Conncept is an experimental layer 4 app for Caddy. It facilitates composable handling of raw TCP/UDP connections based on properties of the connection or the beginning of the stream."
But Caddy's http server can also do basic logic around SNI if I recall correctly.
I use distributions because I care about security and I'll be downvoted to oblivion for saying this.
P.S., from the guidelines:
> Please don't comment about the voting on comments. It never does any good, and it makes boring reading.
edit: and an official response https://news.ycombinator.com/item?id=31170881
No thanks.
(Not a Kubernetes user, so my answer is probably not the best.)
However I think in K8s world Caddy would make the most sense as an Ingress Controller. There is even a project as such: https://github.com/caddyserver/ingress
All traffic would terminate first at Caddy. Handling TLS, HTTP1/2/3, etc. Then passing it back to your application service/pod.
I'm not sure how that would differ from SRV though, since Consul supports SRV anyways. I'm not a Consul user though.
"Note that DNS is limited in size per request, even when performing DNS TCP queries.
For services having many instances (more than 500), it might not be possible to retrieve the complete list of instances for the service.
When DNS SRV response are sent, order is randomized, but weights are not taken into account. In the case of truncation different clients using weighted SRV responses will have partial and inconsistent views of instances weights so the request distribution could be skewed from the intended weights. In that case, it is recommended to use the HTTP API to retrieve the list of nodes."
[1] https://www.consul.io/docs/discovery/dns#service-lookups
I'll say that it's unlikely we'll work on this unless a sponsor funds the development. The dynamic upstreams feature was funded by a sponsor requiring improved SRV support (we did have SRV support before v2.5.0, but it was rudimentary and insufficient for many usecases).
If someone needs this and can spend some time developing it, essentially it's just a module which implements this interface: https://pkg.go.dev/github.com/caddyserver/caddy/v2/modules/c...
I can guarantee CertMagic+ACMEz is the best cert management available in the ecosystem. It won't let you down.