One area we have found Caddy invaluable is for local testing of APIs with HTTP2 during development. Most dev servers are HTTP1 only, and so you are limited to max of 6 concurrent connections to localhost. HTTP2 requires SSL, which would normally make it a PITA to test/setup locally for development.
Throw a Caddy reverse proxy in front of your normal dev server and you immediately get HTTP2 via the root certificate it installs in your OS trust store. (https://caddyserver.com/docs/automatic-https)
We (ElectricSQL) recommend it for our users as our APIs do long polling, which with HTTP2 doesn't lock up those 6 concurrent connections.
I've also found that placing it in front of Vite for normal development makes reloads much faster. Vite uses the JS module system for loading individual files in the browser with support for HMR (hot module replacement), this can result in a lot of concurrent requests for larger apps, creating a queue for those files on the six connections. Other bundlers/build tools bundle the code during development, reducing the number of files loaded into the browser, this created a bit of a debate last year on which is the better approach. With HTTP2 via Caddy in front of Vite you solve all those problems!
After switching from nginx to caddy-docker-proxy a year ago I just recently made the move to Pangolin[0] and am really enjoying the experience. It's a frontend to traefik with built-in auth and ability to tunnel traffic through Wireguard. I needed the TCP forwarding for my Minecraft server and this made it very simple.
Would recommend it for anyone wanting a better version of Nginx Proxy Manager. The documentation is a little lacking so far but the maintainers are very helpful in their Discord.
A lot of positivity in this thread. I don't have anything bad to say about Caddy, but the only advantage I'm hearing over Nginx is easier cert setup. If you're struggling with that, I can see how that's a benefit.
I configured my kubernetes cluster to automatically create and renew certs a few years ago. It's all done through Ingress now. I just point my Nginx load balancer to my new domain and it figures it out.
I don't often need local https but when I do I also need outside access so Stripe or whatever can ping my dev server (testing webhooks). For that I have a server running Nginx which I use to proxy back to localhost, I just have to run 1 command to temporarily expose my machine under a fixed domain.
Works for me. Maybe not everyone but I'll keep doing this since I don't have any reason to switch
I absolutely love Caddy. Used it for years. Very reliable and so easy to setup once you learn the basics. The documentation is a bit hard to get, but it saved me so much time and energy compared to trying to get letsencrypt working reliable ontop of NGINX.
Reading the website top to bottom, I’m now unsure about the trustworthiness of a project that seems so full of itself. Passage after passage about how great it is leaves a bad aftertaste. Maybe it’s just me—unsure.
I no longer trust the authors to be honest about known shortcomings, let alone be upfront, truthful, and transparent when dealing with security issues and reported vulnerabilities.
I hope I’m wrong. Does anyone know how they’ve handled disclosures in the past?
The friendly licensing (Apache v2) is important too, especially w/ Caddy's modular architecture (single, static binary compiled for any platform).
Meaning ecosystems around Caddy to make it even simpler and more secure, e.g. keep your server private while serving Internet clients. So VPNs like Tailscale (1) or zero implicit trust like OpenZiti (also Apache v2; (2)). Similar to what we have seen with open source k8s ecosystem for example.
(1) https://tailscale.com/blog/caddy (and other VPNs but the proprietary bits in the commercial TS service make it easier to use)
I prefer to keep certificate management separate from individual applications like web servers, mail servers, XMPP servers, database servers and all the other services I run. All of these need certificates so I have centralised certificate management and distribution. This comes down to running certbot in a container with some hook scripts to distribute new or updated certificates to services (running on different containers and machines) which need them, restarting those services when needed. Adding a new site to nginx comes down to copying a template configuration, changing the site name to the correct one, adding whatever configuration needed for the specific service and requesting a new certificate for it. The new certificate automatically gets copied to the container or machine running the service so it is available after reloading the nginx configuration. The same is true for most other services, several of which share certificates because they're running in the same domain. I used the same scheme back when I used lighttpd and will probably use it should I move to another web (or mail or XMPP or whatnot) server.
I migrated all my Nginx hosts to use Caddy a while back. It doesn't do anything Nginx can't, but the default configuration is identical to the way I'd previously manually configured servers. It's so pleasant to get an HTTPS site up and running with 3 lines of setup.
A great alternative is Traefik. We have been using v1 and v2 for several years now in a setup that uses the docker labels for configuration of services.
Caddy coupled with Caddy-Docker-Proxy [0] is a marvelous way to set up a server with multiple docker projects. I have it running on a couple of servers, and it just works!
Caddy is already powerful as it is but with the L4 plugin it can also work on layer 4 and proxy other stuff. I made a cursed config proxying to a website on HTTP request and towards a Minecraft server all other TCP traffic.
Love Caddy! Switched to it 2 years ago from NGINX/OpenResty and it made my config much less verbose and more simple. Previously used lua-resty-auto-ssl with OpenResty but it's kinda deprecated and I will never touch certbot but needed a "fire-and-forget" solution. Serving 70k visitors monthly very well :)
I was reluctant to switch to Caddy because I couldn't understand if does or does not use Linux' sendfile sys call, which made a huge difference for me with Nginx. [0]
Nevertheless, I used Caddy to front our internal Mattermost chat server and it works flawlessly to date. The configuration was really simple, I like it a lot.
I'm surprised no-one has mentioned the admin API [0], which imo is one of the main differentiators of Caddy. I've used it to dynamically change the config without any downtime.
Caddy is pretty nice, I believe Coolify uses it as part of their self-hosted open source PaaS model. Just out of curiosity, are there any alternatives in Rust? I think Pingora is one, as well as River which is built on top of it [0], but I'm not sure how widely used the latter is as a Caddy replacement.
> Automatic HTTPS provisions TLS certificates for all your sites and keeps them renewed. It also redirects HTTP to HTTPS for you!
When I add set the IP of a domain to point to caddy, do I have do tell it some how to Caddy, or the certificate is created on the fly on the first https call?
We moved to caddy as a front end for our unlimited domains offering after some experimentation[0]. ALBs didn't work at the scale we needed them to, so we run our own caddy instances.
Seems to work great. We did run into a rate limiting issue with letsencrypt when we tried to provision too many certs at one time. Ended up having to use wildcard certs to decrease the number of requests. Hardly caddy's fault, though.
I also find their library for Go (https://github.com/caddyserver/certmagic) a major timesaver! We're using it to make it easy for people to self-host our app and it takes care of all the TLS cert set up/renewal.
Last year a coworker mentioned Caddy, so I decided to set it up on a spare box just to see how well it worked with WordPress, PHP etc. It did okay. I didn't do any big tests with it but it seemed to work well enough, and was super simple to configure. It does seem quite niche however.
I'm using caddy as a proxy to various services running node, ruby, or elixir. It's replaced using mkcert and nginx, and I have just about everything i need proxied to ..localhost, with caddy's awesome Step-CA derived certiifcate libraries providing the fun
I am still looking for a dead simple webserver that can serve files, do CGI and reverse proxy.
I have been using lighttpd for much of this. It's configuration is extremely simple although it has some quirks. It also has a few problems like not always correctly logging errors related to CGI, and not being able to proxy to a backend over SSL.
I tried caddy because of its simple configuration syntax and plugin support.
For caddy the sample webpage alone threw me off. It includes a bunch of CSS, custom fonts, and for whatever reason it has tilted text.
I'd like a test webpage to fit on my terminal screen when I SSH to it. Or at least not require a modern browser to render.
Anyway I just don't think Caddy fits my usecase. Are there no dead simple, lightweight alternatives to nginx and apache that actually work?
Caddy is good, especially for super simple static sites. As soon as it gets somewhat complex, the configs start becoming messy and opaque, eg.
Nginx:
rewrite ^/old/((\w|-)+) /new/$1.php;
Caddy:
@oldPath {
path_regexp old ^/old/([\w-]+)
}
rewrite @oldPath /new/{re.old.1}.php
And many things are not even handled by Caddy, or fail silently (for example, we could not get NetData to reverse_proxy behind Caddy no matter what we tried, and the logs were completely useless.)
I moved off of NPM and tried Caddy since Traefik seemed complicated. The paradox was that when I tried to do more complex setups like authentik as a front end and some web books, I could never get them to work with Caddy.
But with Traefik, albeit more complicated, had tons more examples to work from, and a little help with LLMs to clean up my configs when complete just made it much easier in the long run.
I tried Caddy with caddy-docker-proxy and maybe that was my issue? I’m happy with Traefik but for a simple config I can definitely see the advantages of Caddy.
I'm absolutely hooked on Caddy. Just developed an AITM phishing tool like EvilGinx2. Challenging project, but Caddy's modularity really brings it all together. Need encrypted landing pages? Just string together a few modules. Need conditional forward proxies to make sure requests originate from geographic regions? Placeholders to the rescue.
I love love caddy. I only use it for my homelab to get https everywhere, but it’s so much easier than traefik for me I honestly don’t know why everyone prefers it? What am I missing?
I was checking into using Caddy for new projects instead of NGINX or Apache HTTPD, but my new projects require OAuth2/OIDC authentication. It seems there's not built-in support for that kind of thing. There's the caddy-security plugin, but people online have been saying it has disclosed security vulnerabilities that aren't being fixed.
Are you using caddy-security? Or is there a better alternative?
I love caddy! I use it to serve webapps and APIs on my hetzner boxes.
I hate the config file though. It could be 10x safer / more discoverable / nicer to use by just using json with a schema that validates and shows docs in the tooltips similar to tsconfig.
I suspect my typescript lsp addiction and relatively limited (though non-zero) backend experience has spoiled my tolerance for the primal nature of backend tooling.
I switched to Caddy from nginx and Traefik, and never looked back.
Why do I need to write a lot of code to say map example.com to 1.2.3.4?
I get there are headers etc, but in most cases, it should be just one line, with sane defaults. That’s what caddy does. Takes care of SSL automatically, and does the job with minimal code. If you have a special setup, there are options, and you can write more code to achieve that.
I really like Caddy, it used to do reverse proxying and file serving for my homelab, but more recently I've demoted it to just the file serving because of how awesome it is to be able to configure reverse proxying just using container labels, which is what Traefik allows me to do.
> With On-Demand TLS, only Caddy obtains, renews, and maintains certificates on-the-fly during TLS handshakes. Perfect for customer-owned domains.
Does it allow to plug-in into this system so that post-renewal actions are possible, like distributing those certificates to other machines through Python scripts?
My two cents having a respectable amount of infrastructure ops experience: Use Caddy to get going quickly and to get a solid setup with minimal effort. Use Nginx if you know what you're doing and want full and deep control over the web server / proxy layer of your stack.
Caddy is beautifully simple, a joy to setup, configure & use for a simple home server with a few services. I love it! I used nginx before, and it’s great, but caddy makes things easier. I love how easy it makes SSL certificates & reverse proxies.
I use Caddy within FrankenPHP and it is a very good server. Plus the community is really helpful.
I wish it had more informative logs, though. Some subtle errors in Caddyfile may result in the server not communicating, and not telling you that something is wrong.
I'm serving AI models on Lambda Labs and after some trial and error I found having a single vllm server along with caddy, behind cloudflare dns, to work really well and really easy to set up
Caddy – The Ultimate Server with Automatic HTTPS
(caddyserver.com)563 points by huang_chung 16 February 2025 | 227 comments
Comments
Throw a Caddy reverse proxy in front of your normal dev server and you immediately get HTTP2 via the root certificate it installs in your OS trust store. (https://caddyserver.com/docs/automatic-https)
We (ElectricSQL) recommend it for our users as our APIs do long polling, which with HTTP2 doesn't lock up those 6 concurrent connections.
I've also found that placing it in front of Vite for normal development makes reloads much faster. Vite uses the JS module system for loading individual files in the browser with support for HMR (hot module replacement), this can result in a lot of concurrent requests for larger apps, creating a queue for those files on the six connections. Other bundlers/build tools bundle the code during development, reducing the number of files loaded into the browser, this created a bit of a debate last year on which is the better approach. With HTTP2 via Caddy in front of Vite you solve all those problems!
Would recommend it for anyone wanting a better version of Nginx Proxy Manager. The documentation is a little lacking so far but the maintainers are very helpful in their Discord.
[0] github.com/fosrl/pangolin
I configured my kubernetes cluster to automatically create and renew certs a few years ago. It's all done through Ingress now. I just point my Nginx load balancer to my new domain and it figures it out.
I don't often need local https but when I do I also need outside access so Stripe or whatever can ping my dev server (testing webhooks). For that I have a server running Nginx which I use to proxy back to localhost, I just have to run 1 command to temporarily expose my machine under a fixed domain.
Works for me. Maybe not everyone but I'll keep doing this since I don't have any reason to switch
I no longer trust the authors to be honest about known shortcomings, let alone be upfront, truthful, and transparent when dealing with security issues and reported vulnerabilities.
I hope I’m wrong. Does anyone know how they’ve handled disclosures in the past?
Meaning ecosystems around Caddy to make it even simpler and more secure, e.g. keep your server private while serving Internet clients. So VPNs like Tailscale (1) or zero implicit trust like OpenZiti (also Apache v2; (2)). Similar to what we have seen with open source k8s ecosystem for example.
(1) https://tailscale.com/blog/caddy (and other VPNs but the proprietary bits in the commercial TS service make it easier to use)
(2) https://github.com/openziti-test-kitchen/ziti-caddy (disclosure: maintainer...there may be other open source zero implicit trust options with these types of Caddy integrations)
[0] https://github.com/lucaslorentz/caddy-docker-proxy
Especially for its HTTP/2 and HTTP/3 QUIC support.
Caddy is so awesome. I actually have a few other sites on the same server and updating my config is hella simple.
I spent several years optimizing my nginx setup and I haven't touched it in years (I was obsessed about getting a perfect security score).
https://caddy.ninja/
Let's just say it takes a lot these days to choose something that is not nginx.
Nevertheless, I used Caddy to front our internal Mattermost chat server and it works flawlessly to date. The configuration was really simple, I like it a lot.
0 - https://github.com/caddyserver/caddy/issues/4731
So easy to setup and performs very well.
[0] https://caddyserver.com/docs/api
- There's a great tool, localias, which uses Caddy for a local dev server https://github.com/peterldowns/localias
- I use it locally for dev https://github.com/iloveitaly/python-starter-template/blob/m... which aligns tricky bits of a web app like HTTP redirect, cookies, and CORS to work consistently across dev and prod.
- Can be used on GHA for HTTPS as well https://github.com/iloveitaly/github-action-localias
[0] https://github.com/memorysafety/river
When I add set the IP of a domain to point to caddy, do I have do tell it some how to Caddy, or the certificate is created on the fly on the first https call?
It's really important for us https://news.ycombinator.com/item?id=43053955 due to our need to redirec apex domain to www ... which we can solve with the free (great) service provided by https://www.apextowww.com/#get-started ... but, we are just curious since https://www.apextowww.com/#get-started does use Caddy (I see it in their headers) so maybe we would just need Caddy :)
Seems to work great. We did run into a rate limiting issue with letsencrypt when we tried to provision too many certs at one time. Ended up having to use wildcard certs to decrease the number of requests. Hardly caddy's fault, though.
0: https://fusionauth.io/blog/unlimited-domains-fusionauth
I heard about how Caddy did automatic https, and given the searing pain of doing https on Nginx, decided to make the switch.
Never regeretted it. Caddy it always up to the job even for sophisticated reverse proxying configs.
I have been using lighttpd for much of this. It's configuration is extremely simple although it has some quirks. It also has a few problems like not always correctly logging errors related to CGI, and not being able to proxy to a backend over SSL.
I tried caddy because of its simple configuration syntax and plugin support.
For caddy the sample webpage alone threw me off. It includes a bunch of CSS, custom fonts, and for whatever reason it has tilted text.
I'd like a test webpage to fit on my terminal screen when I SSH to it. Or at least not require a modern browser to render.
Anyway I just don't think Caddy fits my usecase. Are there no dead simple, lightweight alternatives to nginx and apache that actually work?
Nginx:
Caddy: And many things are not even handled by Caddy, or fail silently (for example, we could not get NetData to reverse_proxy behind Caddy no matter what we tried, and the logs were completely useless.)It really was pretty easy to setup and “just works”
But with Traefik, albeit more complicated, had tons more examples to work from, and a little help with LLMs to clean up my configs when complete just made it much easier in the long run.
I tried Caddy with caddy-docker-proxy and maybe that was my issue? I’m happy with Traefik but for a simple config I can definitely see the advantages of Caddy.
Absolute stunner project.
Are you using caddy-security? Or is there a better alternative?
I hate the config file though. It could be 10x safer / more discoverable / nicer to use by just using json with a schema that validates and shows docs in the tooltips similar to tsconfig.
I suspect my typescript lsp addiction and relatively limited (though non-zero) backend experience has spoiled my tolerance for the primal nature of backend tooling.
Why do I need to write a lot of code to say map example.com to 1.2.3.4?
I get there are headers etc, but in most cases, it should be just one line, with sane defaults. That’s what caddy does. Takes care of SSL automatically, and does the job with minimal code. If you have a special setup, there are options, and you can write more code to achieve that.
Does it allow to plug-in into this system so that post-renewal actions are possible, like distributing those certificates to other machines through Python scripts?
I wish it had more informative logs, though. Some subtle errors in Caddyfile may result in the server not communicating, and not telling you that something is wrong.
traffic sees dozen of security releases a year... and i always wonder if its less secure or is more secure because people do find the holes there.
I could ask a LLM but I'd prefer the old way for this type of stuff...
since when was hn for ads? there's nothing notably technical on the page
vllm serve ${MODEL_REPO} --dtype auto --api-key $HF_TOKEN --guided-decoding-backend outlines --disable-fastapi-docs &
sudo caddy reverse-proxy --from ${SUBDOMAIN}.sugaku.net --to localhost:8000 &