14 ms·
Caddy compatibility for zeroserve: 3x throughput and 70% lower latency
- tln 3mo agoNo ACME! That is a dealbreaker https://github.com/losfair/zeroserve/blob/main/CADDY_COMPAT.md#intentional-exclusions https://github.com/losfair/zeroserve/blob/main/CADDY_COMPAT....
- codys 3mo agoYes, I agree it would be very nice to have a way to integrate ACME into zeroserve. I'm not sure if zeroserve's plugin system might allow one to add a plugin to support it?
- codingjoe 3mo ago"Caddy compatible" minus everything that matters, like ACME and plugins. And NGINX still steals the show. Not everything needs to be rewritten.
- BoingBoomTschak 3mo agoInteresting. Trying to get some of the performance advantages of TUX/IIS without as much insecurity makes sense for some big players, I guess. The usual 3400 lines lock file and AGENTS.md raise some questions about the aforementioned security, though.
- dshat 3mo agoNo thanks
- Thaxll 3mo agoAnother vibe coded, dead in 6 month Rust project. People that trully need performance are not going to use a random server that has 0 support/ track record.
- 4ndrewl 3mo agoNever mind cooldowns for dependencies, we need cooldowns for these adhd vibe projects.
- ianm218 3mo agoIsn't there a chicken and egg problem where projects need to start with 0 track record? Nginx had zero track record at one point as well
- chucky_z 3mo agoNginx was developed to scale a lot of Russian sites, starting with Rambler. As a second point, Envoy was made by Lyft. A lot of web server OSS goes back to big (at the time) corps.
- ok123456 3mo agoExposing services that use io_uring is a hard pass. It's only been a handful of weeks since the last security advisory.
- deleted 3mo ago[deleted]
- bastawhiz 3mo agoThe idea of jit compilation of a web server in a small project is pretty terrifying to me. The attack surface here is enormous. And for what? My back end on a single host isn't pumping at 35k qps. If each request is 500 bytes, 35k qps is nearly 20mbps sustained with zero other io (in each direction). And this is using only two threads! I think you'd be hard pressed to find an application where this is meaningfully useful versus just scaling horizontally. On a box that can run many threads in parallel, Caddy still vastly exceeds my ability to respond to pretty much any useful traffic. It's optimizing for a metric that wasn't a bottleneck in the first place.
- eptcyka 3mo agoExcept CDNs, where it is.
- bastawhiz 3mo agoCDNs aren't running Caddy
- 10000truths 3mo ago> The idea of jit compilation of a web server in a small project is pretty terrifying to me. The attack surface here is enormous. Does Spring Boot terrify you, then? Or Lua scripts in nginx? Or PHP? All of these use JIT compilation to run code that handles web requests. Attack surface is a property of the JIT implementation, not of JIT itself. And eBPF is specifically designed to be very simple to implement and audit.
- graynk 3mo ago> Does Spring Boot terrify you, then? It should.
- bastawhiz 3mo agoThere's a big difference between a JIT like luajit which has lots of attention and fuzzing and one that's used by essentially nobody. Would you compile your daily driver kernel with someone else's hobby C compiler that essentially nobody else uses?
- pbohun 3mo agoI looked into writing an http server based on iouring myself, but all the resources I could find said iouring is less safe from a cybersecurity perspective. Is there a safe way to use iouring for a webserver, or is libuv the better way to go, even though it has less performance?
- athrowaway3z 3mo agoA webserver shouldn't be calling io_uring internals without doing its own bound checking and http logic, nor should it be calling io_uring with remote-controlled crafted fd's or access pattern that might still have bugs in them. At the level you'd be exposing io_uring (internals) via external http requests; it's security is perfectly fine.
- stymaar 3mo agoCan someome enlighten me: What's the point of “running eBPF scripts in userspace”? Isn't being run in kernel space the whole point of eBPF in the first place?
- kennethallen 3mo agoI read this post and your post introducing zeroserve. One of the main parts of the original pitch was "no separate config file and scripts". Now you're adding a config file separate from the scripts. Is the pitch now that it's like Caddy but runs eBPF scripts in userspace?
- losfair 3mo agoHi - zeroserve Caddy compat works by compiling Caddyfile to C. Technically I can keep the compiler in a separate binary/repository - but it just feels unnecessary. zeroserve only understand eBPF at runtime. It's always the source-of-truth.
- jauntywundrkind 3mo agoI was very taken by the other recent zeroserve headline that showed up, zeroserve: a zero-config web server you can script with eBPF: > The twist is that you can drop eBPF programs into the tarball and they run on every request, in userspace, as sandboxed middleware - rewriting, authenticating, and rate-limiting requests, or reverse-proxying them to a backend when you want it to act as a gateway in front of your app. https://su3.io/posts/introducing-zeroserve https://su3.io/posts/introducing-zeroserve https://news.ycombinator.com/item?id=48425723 https://news.ycombinator.com/item?id=48425723 (272 points, 9d ago, 66 comments) It's such opposite audiences being targeted here. eBPF is for super nerds, Caddy for "i just want a just works http server". The headline here doesn't do much for me: I don't care about Caddy compatibility and 3x doesn't mean much to me (Caddy feels like it targets friendly and easy not performance). But eBPF scripting? Ok that's cool, that's rad.
- nullstyle 3mo agoFudge, I really need to carve out time today to play with zeroserve. Very cool stuff
- zsoltkacsandi 3mo agoFrom a technical standpoint, these are always impressive projects, but I've always wondered: has anyone ever encountered a use case where the Caddy was the bottleneck?
- keynha 3mo agoFor most apps the backend is slower than the proxy by a wide margin, so Caddy is nowhere near the bottleneck. Where it flips is high connection churn, since TLS handshakes are the expensive part and a flood of short lived connections without session resumption burns proxy CPU well before steady state proxying does. Very high RPS of tiny responses is the other case, where allocation and header parsing start to show.
- tredre3 3mo agoIn my experience Caddy has worse latency and throughput than nginx. I've set up a service that frequently sends 600MB/s (~5gbps) with nginx and the CPU is just chilling at 50%, but Caddy on that machine bottlenecks at 300MB/s despite using 100% of the CPU. AES hardware acceleration was enabled and functional on both software. This is high throughput that most people won't see, but it was also on a far beefier machine than most people would use. Caddy would definitely be a bottleneck when serving media from a raspberry pi. My last attempt was in 2025, Caddy has probably improved since then. That being said nginx has some terrible defaults so if you're just naively benchmarking it as a proxy out of the box, you might find Caddy to be better. For example nginx caches active request bodies (in and out) to temp files in many scenarios (to block the backend/upstream as little as possible), whereas Caddy is more of a transparent proxy.
- dilyevsky 3mo agoIf it's http2 then Go's stdlib is pretty unoptimized to say the least. Huffman decoder is really cache unfriendly (pointer chasing) and I think allocation heavy too. Same probably goes for http1 and http3.
- jeroenhd 3mo agoMy experience mirrors that, but mostly because Caddy does HTTP/2 and http3 by default, natively. HTTP 1.1 is faster for bulk data transfers (while being worse at pipelining and latency in general), so I'm not surprised Caddy is taking more CPU in this case. In my experience, in terms of latency, Caddy is a lot faster, every single time. I don't know what modifications I need to do to nginx to make it comparative but Caddy easily shaves half of the connection and transfer delays on my local network.
- augunrik 3mo agoI am surprised how well nginx holds up?!
- miladyincontrol 3mo agoI mean, nginx dang well should? This is just an incredibly synthetic http(s)/1.1 test for what its worth. Like you totally could turn off garbage collection for caddy especially since this is only testing incredibly short single response queries that would never need GC. Shockingly you would actually get better performance than either nginx or zeroserve, but like the uselessness of this benchmark it'd mean nothing to the real world usage of these web servers.
- chucky_z 3mo agoUnfortunately that is likely untrue. Try it yourself, Go with GC disabled isn’t some magic bullet for performance as much as I’d like it to be.
- phillipseamore 3mo agoWhy? It's one of the most optimized HTTP servers ever. Anything that claims beating nginx in benchmarks should be treated with high suspicion. I think these zeroserve numbers are likely accurate but it doesn't have the features and module ecosystem of nginx so the margins aren't worth it for me.
- augunrik 3mo agoBecause it passes more boundaries and stuff. But hey, I didn’t code a Webserver so far - so what do I know. :D AFAIK eBPF can be hardware offloaded. If you have the use case.
- someothherguyy 3mo ago> But hey, I didn’t code a Webserver so far - so what do I know If you limit the scope, its worth doing and might not take as much effort as you might think. You could possibly find some enjoyment and learn a few things doing so.
- smallerize 3mo agoI still think of eBPF as not being Turing-complete. There is still a complexity limit in the verifier. Even if someone did implement Game of Life by having the program set a timer to run itself. https://isovalent.com/blog/post/ebpf-yes-its-turing-complete/ https://isovalent.com/blog/post/ebpf-yes-its-turing-complete...
- codys 3mo agozeroserve doesn't use the Linux kernel's eBPF runtime to run the eBPF it uses, so the constraints of the Linux kernel's eBPF runtime (chosen because of how the Linux kernel thinks about protecting the Linux kernel from user space) don't apply to zeroserve (or other tools that use the eBPF instruction set but don't use the Linux kernel's particular implementation)
- 1a527dd5 3mo agoAnyone else got a really weird Chorme pop-up asking which cert to use for su3.io:443? Very bizarre, never seen that before. Thumbprints: - 60949a09aab8677f87a0b9eda7099a03ca510fb3 - 1b146798f0dc93773247e86312f1b730c4eeebb3
- embedding-shape 3mo agoHere it attempts to read my personal certificate that sits in the browser that I use for filling my taxes and do government stuff, suspicious indeed.
- cmgbhm 3mo agoThat’s likely just the side effect of supporting mtls. Mutual TLS came around at the same time as Microsoft did implicit network auth. Seemed magical at the time and so hare brained for eons of problems. The user side tls never caught on in most circles and still has the ancient sharp edges
- iknowstuff 3mo agoCould probably buff it with passkeys these days https://www.passkeyprf.com/ https://www.passkeyprf.com/
- jeroenhd 3mo agomTLS supports some protocol level security guarantees that passkeys don't. Because the keys are exchanged during connection setup, there's no need for a login screen and Javascript middleware to begin the authentication process. mTLS is also easy to implement for APIs, you basically get authentication for free. Unfortunately, browsers don't invest into making a good UI for mTLS. If browsers simply put their foot down and said "we will not permit websites to ask for a certificate if the request does not contain the proper requirements" like they do in passkeys, mTLS would be just as easy to use (and even easier to manage and rotate!). When I ran mTLS auth on my intranet, I discovered that a lot of sites will use mTLS support to do fingerprinting, which means a lot of pages will open a blocking popup (sometimes multiple times) when I just want to read an article.