Hacker News new | comments | show | ask | jobs | submit login
Caddy – a modern web server (vs. Nginx) (medium.com)
62 points by n1try 375 days ago | hide | past | web | favorite | 47 comments

Shortcomings of the article aside, I'd like to say that I use Caddy for a set of small websites and I couldn't really be happier with it.

I'm a longtime Windows developer who doesn't have much patience with nerdy complexities. I started in 1996 with a buggy, gawd-awful Netscape webserver, moved to the late-lamented O'Reilly WebSite (even had a T-Shirt) and reluctantly settled on MS IIS, with occasional Apache encounters. Caddy has been an absolute breath of fresh air.

I currently run 4 sites from a system at my home, using Namecheap dynamic DNS. Caddy serves the basic web pages and static content and also reverse proxies to an internal Python server for dynamic content. Sounds a little complicated, but believe me, configuration is dead-simple thanks to Caddy. Plus I get full HTTPS from Let's Encrypt for the cost of supplying my email address and agreeing to a EULA - no configuration needed at all.

I've never used a webserver that was easier to configure or had such low resource requirements.

>I'm a longtime Windows developer who doesn't have much patience with nerdy complexities.

That is funny because I have setup Apache, Nginx, and IIS web servers before and by far the one I found to have the most nerdy complexities is IIS.

I think it's often easier because most of the nerdy complexities are via a GUI... though the web.config offers a lot more in more recent versions. And adding in Application Request Routing (reverse-proxy) and the like can get complicated quickly, it's not nearly as bad as either nginx or apache tend to be. I do like what nginx can do combined with lua though, it's pretty damned cool.

All in all, I do like Caddy's defaults and out of the box for newer tech. I haven't really tried it much, mostly out of complacency with nginx/iis in Linux/windows. And I will definitely never run Apache on a new box again.

I agree with both posts above me. While I normally prefer a GUI configuration facility, I wouldn't make the argument that IIS is particularly simpler than Apache.

Getting back to Caddy, configuration is so simple, a GUI would be overkill.

Here's an (entire) example of how to configure a reverse proxy in Caddy...

  proxy / {
    except /favicon.ico /robots.txt /assets /plainpages /staticstuff /test1
    proxy_header X-Forwarded-Proto {scheme}
The "except" line is a list of files and directories that are statically served by Caddy.

All other content comes from a local server on port 8080.

The "proxy_header" line lets the 2nd server know when contents are being sent as secured (HTTPS)

Isn't that nice? I think so.

I think you want header_upstream instead of proxy_header, at least in newer versions of Caddy, and the transparent[0] preset sets Host, X-Forwarded-For, and X-Forwarded-Proto for you!

  proxy / {
    except /favicon.ico /robots.txt /assets /plainpages /staticstuff /test1
0. https://caddyserver.com/docs/proxy

Thanks! I didn't notice transparent. I added the proxy_header based on documented requirements of the 2nd server.

>The configuration is not that intuitive and you really need to get into the syntax and concepts to get an understanding of knobs to turn in order to achieve a certain goal.

Personally I found Nginx configuration much simpler than Apache. I think Nginx is pretty intuitive, it certainly is much supplier than IIS, which is a nightmare.

> every middleware you want to use needs to be included into the binary and if it’s not, you need to re-compile the program

Having to recompile to add functionality that alternatives provide as dynamically loaded plugins is insane. This is 2017. Linux has had loadable kernel modules since 1995, and I worked on them for other versions of UNIX as far back as 1991. I understand that it's hard for a Go program to support plugins written in other languages using a more conventional runtime. No problem there. However, there's just no excuse for relying on recompilation instead of dynamically loading modules also written in Go and thus using the same runtime. I really want to like Go, but as long as the Go community clings to long-discredited ideas regarding things like packaging and distribution and symbol versioning I just don't feel like I can depend on it to build infrastructure that will remain robust over time.

One of the advantages of Caddy is its purely static binaries. You don't even need libc to run Caddy, and that goes for any platform. The dynamic loading of plugins is at odds against this advantage.

> However, there's just no excuse for relying on recompilation instead of dynamically loading modules also written in Go and thus using the same runtime.

Actually there is.

Go plugins are something we're looking at, but it's complicated and the technology is currently immature. Please read this forum thread in full: https://forum.caddyserver.com/t/go-1-8-plugin-model/934?u=ma...

Good to hear that Caddy might support real plugins, either optionally or by default. Please note that my criticism was not targeted at the Caddy developers. It's not your fault that the Go core developers have dragged their feet so long on making such basic functionality available, or that the Go community in general has enabled such dereliction. Writing Go code seems like it might be quite pleasant. Integrating Go code into the rest of that ecosystem is what gives me a huge "this isn't a safe way to do things" vibe.

Nice to see you on here, Mr Holt. Thank-you for the great work you've done with Caddy.

Like the rest of Caddy, I find the plug-in system to be simple and solid. Some people just seem to like complexity. (smile)

Is there any way to query what plug-ins are bound into a Caddy exe? (given that I'm a non-Go-programming, Windows guy)

An idea I had for the website was to allow us to sign in and have accounts. Downloads and plug-in preferences could be tracked. (It might even lead to a way to pry some money out of cheapskates like me with premium plug-ins and whatnot.)

Glad you like Caddy!

> Is there any way to query what plug-ins are bound into a Caddy exe?

Run `caddy -plugins`.

The new Caddy website -- coming out hopefully later this month -- will allow developers to create accounts and release their plugins themselves, without me having to do it manually. I have given some thought to allow anyone to create an account but I need to work out some details for monetization first, if that's the route it takes. Thank you!

Hmm... I don't think I've ever in my life worked on a platform where I couldn't get libc.

It sound like a neat project where there are some good defaults and where most weaknesses (performance, flexibility, etc) come from golang. It would be interesting to see a rewrite in another language.

Why is this seen as a benefit? If a severe security issue is found in libc, I have to recompile all software to take advantage of it? Who thought that was a good idea?

AFAIK, Go doesn't use libc.

Anyway, it is still a problem if you encounter a bug in any dependencie: you have to recompile every application using it.

Bare containers don't have libc, for instance.

> I really want to like Go, but as long as the Go community clings to long-discredited ideas regarding

I'm confused, aren't Go plugins exactly the feature you want? And on that note, it was just introduced as of 1.8, wasn't it?

Seems a bit harsh to criticize a project for not using (during it's development time) unfinished and not production ready features.

See my response to mholt in this thread. I wasn't criticizing Caddy so much as Go itself. Go has been around for about seven years now. While it's nice that such an obvious and serious shortcoming has been addressed recently, it has still taken way too long IMO. Plus, we're still stuck with "vendoring" and other community-embraced practices that are bad for long-term maintainability. People have been led in a bad direction, and I'm not about to let the leaders off the hook for that.

The Caddy web site provides a helpful download link where you can select your architecture and addons/features and receive a binary. You can easily point a script at it, like in this Ansible role[0], for instance.

0. https://github.com/antoiner77/caddy-ansible

Yes, I agree with you that this is not very helpful, especially for larger production environments. I don't know if they might refactor the middleware system to a more dynamic way some time.

The next Go version will provide dynamic plugins to be loaded on runtime (not unloaded though).

Caddy dev's are probably going to be all over that.

I like caddy, but the dreamhost benchmark re apache vs nginx isn't really telling, as it doesn't mention fundamental apache config properties. I'm assuming they were benchmarking an unoptimized MPM/prefork setup, but you can use event-based request processing (and other process models) with apache as well. There's nothing magical with nginx.

I'd also like to see a benchmark vs. H2O which seems to have the most advanced HTTP/2 support right now (its running the nghttp2 web site for some time now).

Any experiences with running h2o on production sites? The documentation is a bit lacking sometimes, luckily the code is well written.

No experience with h2o yet. I'm not keen on having to pickup Ruby which would be just one more thing to take care of for me.

The code is mainly written in C (https://github.com/h2o/h2o) with some Perl testing. The Mruby for small (header/push) logic isn't that bad, and not bad in terms of performance either (https://h2o.examp1e.net/configure/mruby.html), although I'm also not a Ruby fan.

I'd be interested in such experiences, too. H2O look promising at first sight.

Some of your links to https://caddyserver.com/ are relative and not absolute, leading me to https://ferdinand-muetsch.de/caddyserver.com - Something you should consider fixing.

All in all however, I like the look of Caddy. The best bit I feel has been left out though:

"That is why, effective this release, Caddy will automatically serve all live sites over HTTPS without user intervention."

Which I think is just brilliant.

Thanks for that hint, I fixed the link! I think I mentioned that HTTPS is on by default, didn't I? But anyway, yes it's very useful and a good practice.

> You don’t need to run any script. You don’t even need to create a Let’s Encrypt account or install the certbot.

How is this done? Ie, to not need any account and still get new/valid certs.

And, on that note, what is the difference between having an account and not? Eg, how might using no accounts harm a production environment?

Just trying to wrap my head around that. Really cool UX for side stuff!

edit: Ah, looks like there is an account involved - it creates one, possibly using your email address. This makes more sense now.

Yes, right. Maybe I should've mentioned that. But I didn't want to talk to much about the certs.

I've been experimenting with Caddy over the past few days and it's great, if somewhat immature and quirky. The plugin ecosystem is rich but in dire need of some oversight and QC. What I like most about Caddy is its very sane behavior out of the box: it just does the right thing in most cases, and requires much less configuration than NGINX, Apache, HAProxy, etc. (It also has fewer features, so there's a trade-off.)

I posted a gist[0] with my Caddy+Varnish+PHP-FPM configuration and a README explaining the hows and whys. I'm moving a bunch of WordPress sites from Apache/mod_php to this configuration (each site's PHP-FPM instance is Dockerized, but that's out of the scope of the gist). Hopefully someone finds it helpful!

0. https://gist.github.com/mwpastore/f42f6f1309a7b067519f4c08e1...

The graph is marked as 'Apache2 vs. nginx memory usage ' but that's not what it shows at all - it's 'Requests per second on Apachev2 vs nginx' - did you mean to show https://objects-us-west-1.dream.io/kbimages/images/Webserver... instead?

Also, this article is really odd. It starts with a performance based analysis comparison of a bunch of web servers, and then decides to add a third completely unknown option, and then decides it's better, based on it's configuration being 'better' (in a way that's not shown), despite it's performance being ~ 1/3 of the competitor....

And there's no comparison of what he was using for NGINX config vs the Caddy config. He simply states that Caddy is easier to use with little acknowledgment of what the config would actually look like.

Googling around for a Caddy file[0], it looks fairly similar, and not so much easier or harder to configure or understand that NGINX config.

[0] https://caddyserver.com/docs/caddyfile

Indeed, in some of my own benchmarks, Caddy performed better than nginx in recent versions of Go. (Using "out of the box" configurations, anyway.) I know tuning is possible, as it is with Caddy depending on your situation. There are so many dimensions to performance of a web server, though, and I don't give much weight to benchmarks. https://gist.github.com/mholt/3f613740ceb417bf63fa

My goal was to point some attention to Caddy as well as to outline why I switched from nginx (as well as the tradeoff between simplicity and performance). Maybe you're right and mentioning Apache and IIS was confusing.

It wasn't that confusing, but I guess it's not clear what the takeaway should be from the article.

Since you started off by talking about apache's memory usage, it would have made sense to include a graph showing Caddy's memory usage vs apache.

Since neither apache nor Caddy can touch nginx in terms of performance, the tradeoff between nginx and Caddy is clear: speed vs ease of setup. It's not clear where Caddy falls relative to apache.

You sort of explained why you didn't do this stuff (apache still doesn't support http2), but perhaps you could rewrite the conclusion and maybe make some guesses as to how apache and Caddy will compare, once apache gets http2? And try to answer the question -- "should I use Caddy now or wait for apache to support http2?"

It's not clear that Caddy wins on speed of setup though over nginx though. More that the author wanted something...different.

He might have wanted something written in a trendier language.

Yes, right, that was a mistake. Thank you very much!

I like caddy and I use in inside of docker for my private home/cloud setup but lately I've been rethinking even that. I agree it's almost magical in how easy it is to setup (especially with HTTPS) but I use nginx for serious projects and a large part of me says it's better to use the same thing everywhere to keep me up to date and aware of potential issues or features and not mix the two.

This looks awesome. I'd switch away in a heartbeat if the Let's Encrypt integration could handle multi-server deployments.

Does Caddy support client certificates?

Is the certificate or its parameters (subject/issuer/alt names/etc) available to set downstream headers (for proxy/fastcgi)? I'm sure I'm missing it, but can't see anything like that in the docs. Or is this something that is more suitable for a plugin?

I'm not sure I understand the question. You want a TLS certificate to set HTTP headers?

Yes - X.509 client certificates are the authentication mechanism (TLS mutual authentication). How this generally works with other HTTP servers (i.e. nginx) is the proxy validates that the client's certificate are issued by a given authority and valid/not revoked, then injects headers with the certificate subject or other certificate fields (commonly a UPN in the subject alternative name) to tell the proxied application the identity of the user. nginx's TLS implementation populates variables with the various client certificate variables for use elsewhere (the $ssl_client* variables here: http://nginx.org/en/docs/http/ngx_http_ssl_module.html#varia... )

In other cases, the entire client certificate is injected into a header (in PEM format) for the downstream application to process as it pleases.

This is a common use case in US Government since everyone carries X.509 certificates around their neck (ID badge is also a PIV smartcard). US Government usually implements this with F5 BIG-IP appliances but I usually use nginx.

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | DMCA | Apply to YC | Contact