Caddy – The Ultimate Server with Automatic HTTPS
caddyserver.com
caddyserver.com
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!
Strictly speaking it doesn't, unencrypted HTTP2 is allowed per the spec (and Caddy supports that mode) but the browsers chose not to support it so it's only really useful when testing non-browser clients or routing requests between servers. HTTP3 does require encryption for reals though, there's no opting out anymore.
Having said all that, I just copied the certs out of here https://cs.opensource.google/go/go/+/refs/tags/go1.24.0:src/... and use them to do browser/http2 stuff locally. Why steal Go's certificates? Because it took 1 second less than making my own!
I personally use traefik.me for my hobbyist fiddling, and I have a working HTTP/2 local development experience. It's also very nice to be able to build for production and test the performance locally, without having to deploy to a dev environment.
For example, postulate a DNS entry of myTopSecrets mapped to localhost. If you use it, it will be routed to your own computer. If someone else uses it, they would be routed to their own computer. The same follows for IP addresses within your local area network.
Unless you did extra work outside the scope of DNS, nothing in your lan is addressable from outside your lan.
Between this and certificate transparency logs, it seems insane to me that the commonly advised Correct Setup, to be able to experiment and hack random little personal stuff, and have it reliably work on modern browsers, requires you to 1) buy a subscription (domain), 2) enter into another subscription-ish contractual relationship (Let's Encrypt), and 3) announce to the whole world what you're doing (possibly in two places!).
Imagine your computer stops booting up because you repositioned your desk, and everyone tells you the Correct Way to do it is to file a form with the post office, and apply for a free building permit from the local council. That's how this feels.
--
[0] - I'm honestly afraid of DNS. I keep losing too much of my life to random name resolution failures, whose fixes work non-deterministically. Or at least I was until ~yesterday, when I randomly found out about https://messwithdns.net, and there I learned that nameservers are required to have a negative cache, which they use to cache failed lookups, often with absurdly high timeout values. That little bit of knowledge finally lets me make sense of those problems.
I have previously used https://github.com/jsha/minica which makes it at least easy to create a root certificate and matching server cert. How to get that root cert trusted on different array of devices is another story.
If you already own a domain, it's pretty convenient.
Not if you only present that name in local DNS, and use a wildcard certificate to avoid needing to reveal the name via a SAN cert or other externally referable information.
Also, perhaps refrain from calling it myTopSecrets. Perhaps ProjectLooBreak instead.
Yes, a more sane approach is just use replit or the like, but this thread is about keeping it complicated.
> 2) enter into another subscription-ish contractual relationship (Let's Encrypt),
afaik, LE only does certs on machines for which they can see.
Taking a moment to look it up, I'm incorrect, it looks like you can establish LE with a DNS challenge instead of http. [0]
0. https://letsencrypt.org/docs/challenge-types/#dns-01-challen...
127.0.0.1 localhost local.foobar.com
And just use wildcard `*.foobar.com` or SAN cert with anything local like Caddy, Nginx, Haproxy or whatever.A wildcard certificate is safe from that though. Or just choosing names that don't give secrets away.
A certificate signed by a locally trusted CA would work too of course, but unless you already have that setup for other reasons it is a bunch of admin most funny want to touch.
First, all these certificates in the web PKI have SANs in them. X509 was designed for the X500 directory system, so when Netscape repurposed it for their SSL technology they initially used the arbitrary text fields and just wrote DNS names in as text. There are a number of reasons that's a terrible idea, but PKIX, RFC 2459 and its successors, defines a specific OID for "Subject Alternative Names". The word "alternative" here refers to the Internet's names (DNS names and IP addresses) being an alternative to the X500 directory system. PKIX says the legacy names should be phased out and everybody should use SANs.
That rule (you must use SANs in new certificates) was baked into the CA/Browser Forum Baseline Requirements (CA/B BRs or just "BRs" typically) which set the rules for certificates that will actually work in your web browser and thus in practice all the certificates people actually use. Enforcement of this rule was spotty for some time but the advent of CT logging made it possible to immediately spot any cert which violates the rule and so some years ago Google's Chome began to just reject the "legacy" just write it in a text field and hope approach and other browsers followed.
So what you're actually talking about are certificates with two or more specific DNS names rather than a single wildcard.
Secondly though, that's usually all a waste of your time if you're trying to mask the existence of named end points because of Passive DNS. A bunch of providers sell both live and historical feeds of DNS questions and answers. Who asked is not available, so this isn't PII, but if I'm wondering about your "sensitive" names at example.com I can easily ask a Passive DNS service, "Hey, other than www.example.com what else gets asked in similar DNS queries?" and get answers like "mysql.example.com" and "new-product-test.example.com".
Passive DNS isn't free, but then squirrelling away the entire CT log feed isn't free either, it's served free of charge on a small scale, but if you bang on crt.sh hard you'll get turned off.
Yes, and technically true is the best variety of true, but… Usually people don't refer to certificates where “Subject” is equal to the one and only “Subject Alternative Name”, as SAN certificates.
> So what you're actually talking about are certificates with two or more specific DNS names rather than a single wildcard.
If we are going to nitpick over the SAN designation a basic wildcard certificate is usually a SAN cert too, by the same definition. They have (at least mine always have had):
Subject =
“CN = *.domain.tld”
Subject Alternate Name =
“DNS Name: *.domain.tld
DNS Name: domain.tld”
(or similar for a wildcard hung off a sub-domain)> "Hey, other than www.example.com what else gets asked in similar DNS queries?"
True, but only if those queries are hitting public DNS somehow. You can hide this by having your local DNS be authoritative for internal domains — your internal requests are never going to outside DNS servers. There could be leaks if someone who normally has access via VPN tries to connect without, but if you have something so truly sensitive that just knowing the name is a problem¹ then I hope your people are more careful than that (or your devices seriously locked down).
And I still say the easy workaround for this is names that only mean something internally. projectwhatthefuck.dev.company.tld is not going to mean much other than giving an attacker compared to projectousurpcompetitor.company.tld. Yes, they'll know the server name, and if it is publicly addressable they can connect to it, but if you have it properly configured they'll have to give it auth information they hopefully won't have before it hands over any useful information beyond the meaningless (to them) name that they already know.
--------
[1] Some of our contracts actually say that we can't reveal that we work with the other party, so technically² we could be in trouble if we leak the company name via DNS (bigwellknowmultinationalbank.ourservice.tld). Though when we offer a different name, in case the link between us can leak out that way, in those cases they've always declined.
[2] Really they don't care that much. They just don't want us to use their name/logo/other in promotional material.
Localias is built on Caddy; my whole goal is to make local web dev with https as simple as possible.
Vite does use HTTP2 automatically if you configure the cert, which is easy to do locally without Caddy. In that case specifically there's no real reason to use Caddy locally that I can see, other than wanting to use Caddy's local cert instead of mkcert or the Vite plugin that automatically provides a local cert.
This does not sound like the kind of feature I would want in a web server
I think a web server listening on 0.0.0.0 will accept “localhost” connections on 127.0.0.2, 127.0.0.3, 127.0.0.4 … etc., and that you could have six connections to each.
https://superuser.com/questions/393700/what-is-the-127-0-0-2...
( a comment there says “not on macOS” though)
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
Authentik behind Caddy does that too.
I have been looking into doing an ec2 or DO droplet with a static ip with tailscale funnel for the traffic proxy. I just like that its easy to go into the web interface for the ec2/droplet and control which IPs it allows ssh connections.
Especially when my family is using the same services for some stuff. I would rather not hear them complaining that they have to 'again login to access x or y TWICE'. :)
With mobile applications it is also tricky since some of them work on app tokens and require it to setup via some application UI.
So you wold have to login twice, from mobile, which is even less convenient, and from every app since there are no shared system cookies. In summary I would rather block/whitelist IPs or IPs ranges on proxy webserver (like right now with NGINX). Which lacks UI, yes. This is where Pangolin seems much better.
There's also a rules section that allows you to bypass all authentication with a IP, range, URL whitelist. It's all traefik under the hood after all so it's very extensible with crowdsec, fail2ban and there's always the yml if you want to deal with that.
I just have Jellyfin disabled since it has it's own auth and to prevent any issues with family members tv streaming since that's the only thing they care about anyways.
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
- Config so easy you can remember how to do it in a day
Someone recommended I try Caddy, I was surprised I could just `chmod +x caddy; caddy start`, and I had replaced my laborious Nginx configuration + the new reverse proxy I wanted in ten minutes.
If I already knew Nginx in-and-out, I'd not have had the impetus to use Caddy. If Nginx config is a daunting task or something that takes longer than two minutes, I'd recommend taking a few minutes to try out Caddy.
This is your package manager's job, which even Windows has these days. Other operating systems solved this problem decades ago.
(If you don't believe me, consider why exactly Docker got so popular.)
In a way, it's ironic that you need package managers to keep track of software on Linux, compared to Windows, which used to let you get away with the assumption that everything that makes a program lives in a single folder tree; half the software was effectively portable by default.
Where's the irony, you ask? On Windows, you could almost say that an application install is equivalent to its folder. And a folder is a type of file. And per Unix philosophy, everything is supposed to be a file!
Windows way goes back to 8 and 16 bit home computer days, across all systems that is mostly how it worked, applications were placed inside their own directory, or their own floppy, actually.
It's alright — the main upside for me is that it supports parameterized includes, thus letting you reuse large chunks of configuration without relying on something like ansible or bash + envsubst.
I’m perfectly able to configure all of the bits and pieces of nginx or apache, but instead of spending 15 minutes or so doing it I tell caddy “here’s my domain name” and move on with my life. The massive benefit is that the features are easily replaced or replicated so if I do decide I want to use traefik or nginx for a specific feature, I can do it when I care about that. But caddy is just batteries included
you forgot to add on the months or years of experience you already have that lets you do that in 15 minutes. Maybe today with an LLM I could figure out certs but the every time I've tried it in the past there's tons and tons of jargon and tons and tons of options and everything is written from the POV of someone that already knows it all.
A classic example is people thinking self signed certs are a good idea without fully understanding the implications of getting every single piece of your application stack and all its third party dependencies to trust the thing.
Which I guess is a good thing, but also man it does place a lot of power into those root CA’s the internet uses.
Here's one: it does not support dynamically loadable modules, like most (all?) Go programs. So if you need e.g. geoip, you have to build your own, and then maintain it, tracking CVEs, etc. You can't rely on your distribution's package maintainer to do the work.
I need route 53 and a few other DNS providers built in for let's encrypt support and the docs implied that I was going to have to build those plugins myself?!!!
I stopped reading at that point because cert bot is trivial to install and just works with the web server that was also one command to install. At no point did I have to create a ephemeral container just to build nginx or certbot...
Only a POC, supported in Linux and macOS, and basically relies on doing casts from loaded symbols into what they are supposed to mean.
For example to use rate limiting I just have a Dockerfile like this:
FROM caddy:2.9.1-builder AS builder
RUN xcaddy build --with github.com/mholt/caddy-ratelimit
FROM caddy:2.9.1
COPY --from=builder /usr/bin/caddy /usr/bin/caddy
I'm not doing SRE stuff at work anymore (or it's on AWS) - so I've been using caddy for my own stuff for a couple of years with nearly zero problems.
For work I still might use traefik or nginx, my only reason against caddy were bad experiences in their support forum, but that was years ago.
I mostly don't look at the logs outside of dev. Errors are caught by Sentry. Still, I can see the use for that... I'd probably try to ingest it into Grafana or some silly k8s solution if I cared enough.
For the Let's Encrypt certs I use certbot and have my Nginx configs set up to point to the appropriate directories for the challenges for each domain.
The only difficulty I sometimes have is the situation where I am setting up a new domain or subdomain, and Nginx refuses to start all together because I don’t have the cert yet.
It’s probably not too complicated to get the setup right so that Nginx starts listening on port 80 only, instead of refusing to start just because it doesn’t have the cert for TLS needed to start up the listener on port 443.
But for me it happens just rarely enough that I instead first make the config and outcomment the TLS/:443 parts and start it so that I can respond to the request from Let’s Encrypt for the /.well-known/blah blah stuff, and then I re-enable listening on with TLS and restart Nginx.
I also used DNS verification for a while as well, so I’m already aware that’s an option too. But I kind of like the response on :80 method. Even if I’ve managed to make it a bit inconvenient for myself to do so.
I tried the JSON config format that seems to be the recommended format, but most examples on Google use the old format. To make it even more complicated the official documentation mentions configuration options, without informing that it requires plugins that is not necessarily installed on Ubuntu. Apparently they just assume that you will compile it from scratch with all options included. Lots of time was wasted before I found a casual mention of it in some discussion forum (maybe stack overflow, don't remember). I just wanted the path to be rewritten to remove the "/backend" path before proxying it to the service. I guess that is uncommon for a reverse proxy, and have to be placed in a separate module
I may appear overly critical, but I really spent a lot of time and made an honest attempt
I'll go back to nginx. Setting up let's encrypt requires some additional steps, but at least it's well documented and can be found in Google searches if necessary
https://caddyserver.com/docs/caddyfile/directives/handle_pat...
example.com
root /etc/www
reverse_proxy /backend/* 127.0.0.1:8080
file_serverI also had to install a separate module just to get a decent access log...
Could be my fault for going too far down a wrong path, but it could also be a sign of poor documentation
{
"logging": {
"logs": {
"default": {
"level": "INFO",
"encoder": {
"format": "transform",
"template":"{common_log}"
},
"writer": {
"output": "file",
"filename": "/var/log/caddy/access.log",
"roll": true,
"roll_size_mb": 5,
"roll_gzip": true,
"roll_local_time": true,
"roll_keep": 5,
"roll_keep_days": 7
}
},
"dev_access": {
"level": "INFO",
"encoder": {
"format": "transform",
"template":"{common_log}"
},
"writer": {
"output": "file",
"filename": "/var/log/caddy/dev_access.log",
"roll": true,
"roll_size_mb": 5,
"roll_gzip": true,
"roll_local_time": true,
"roll_keep": 5,
"roll_keep_days": 7
}
},
"errors": {
"level": "ERROR",
"writer": {
"output": "file",
"filename": "/var/log/caddy/error.log"
}
}
}
},
"apps": {
"http": {
"servers": {
"srv0": {
"listen": [":443"],
"logs": {
"default_logger_name": "dev_access"
},
"routes": [
{
"match": [
{
"host": ["<redacted>"],
"path": ["/backend/*"]
}
],
"handle": [
{
"handler": "subroute",
"routes": [
{
"handle": [
{
"handler": "rewrite",
"strip_path_prefix": "/backend"
}
]
},
{
"handle": [
{
"handler": "reverse_proxy",
"upstreams": [
{
"dial": "localhost:8080"
}
]
}
]
}
]
}
]
},
{
"match": [
{
"host": ["<redacted>"]
},
{
"file": {
"try_files": ["{path}", "/index.html"]
}
}
],
"handle": [
{
"handler": "file_server",
"pass_thru": true,
"root": "/home/server/web/dist"
}
]
},
{
"match": [
{
"host": ["<redacted>"]
}
],
"handle": [
{
"handler": "rewrite",
"uri": "/index.html"
}
]
}
]
}
}
}
}
}I had the same experience. And also somewhat bothered me that even a very basic and common functionality like rate limiting is not built-in.
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?
https://hn.algolia.com/?dateRange=pastYear&page=0&prefix=fal...
Caddy's writing style isn't necessary big-enterprise-middle-management-friendly, but luckily for big enterprises that want lengthy, dry, and boring, there are plenty of alternatives.
Such companies tend to imply that their product can do anything and tend to have pages of verbiage rather than the brass tacks README with examples you get on a good open source project's github page.
Then I checked out the home page and it's all "The most advanced HTTPS server in the world Raaawwrrr!"
Quite the divergence, but as other comments in the thread say, it's a legit good project.
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)
> single, static binary compiled for any platform
Huh? Aren't these exact opposites?
Look at all these comments put off at the idea that maybe the tiny annoyance of building the software to have the exact features you want is worth it for reducing deployment complexity. It's kinda sad actually, compiling software should not be so scary.
When you have more than one system, it can't be just dismissed away.
Traefik had good potential and momentum at the time. And then Caddy started to gain some momentum too. After that there was a brief moment Caddy made the mistake of taking an ad and including it in the `Server` response header and making it be an opt-out feature. Once that was walked back and the dust has settled, Caddy kept gaining more and more momentum and exposure.
Traefik had a web panel that I thought was cool back then but it tried to be too tightly coupled with containers and insisted on making service discovery be an essential core component of its configuration model.
At least this is what I remember. At this point I am very happy with caddy and it is what I use pretty much on all my services.
Thank you mholt for such a nice project and sorry for being overly critical of the ad in the Server response header very many years ago. :)
Glad they removed it. Caddy is a great piece of software.
at the time I had seem a lot of people talking about caddy as well and considered using it instead, but traefik had better perf/latency benchmarks and caddy seemed a bit too much geared toward or at least better suited for dev environment scenarios.
[0] https://blog.gpkb.org/posts/multiple-web-projects-traefik/
I found traefik to be a small nightmare in k8s. I struggled my way up to a working implementation years ago, then a k8s version change on my k8s hosting service forced me to start from scratch.
The whole thing soured me on traefik and also k8s. I wanted to learn pods and autoscaling while having interservice networking resolved for me. I don't want to spend hours struggling with the ingress and load balancing tools (I thought) k8s is supposed to solve for me.
If I ever try it again, I'd use a different ingress tool for sure.
I think achieving a similar setup in traefik (e.g. https://github.com/tiangolo/blog-posts/blob/master/deploying...) would be more complicated, and I felt like I was not sure what all the labels did or how to adapt the setup.
https://github.com/mholt/caddy-l4?tab=readme-ov-file#introdu...
Especially for its HTTP/2 and HTTP/3 QUIC support.
Support is also good and the developer is quite active.
If resource prioritisation is new, a few references: https://www.youtube.com/watch?v=MV034VqHv5Q https://calendar.perfplanet.com/2022/http-3-prioritization-d... https://github.com/andydavies/http2-prioritization-issues
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).
Let's just say it takes a lot these days to choose something that is not nginx.
The configuration of Traefik, in our case, embedded in the docker-compose file was not clear. What was supposed to be a 'auto-detection' of services ended up looking like a hodge-podge of configs between several files.
The logging was sub-par - we couldn't properly debug issues.
And then we ended up migrating terminating HTTPS on AWS's ELB so the let's encrypt integration became not relevant which catalyzed us going back to 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.
So easy to setup and performs very well.
- 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
Depending on your setup the fact that you have to choose between Caddyfiles (which are easier to reason about than nginx config files) or the REST API for configuration might be a downside to some people. There's a chance I might be wrong about this one though.
But to answer your question directly there are no real alternatives in Rust as of now.
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 :)
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.
What issue/experience stop you from saying "it did great"?
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?
It sounds like it may be worth wading into it a little more if this is what threw you off. Or is there some other reason Caddy doesn't fit your use case?
It has batteries included, so it'll have some things that are a little heavy handed or confusing. On balance I appreciate how simple it is for a user at the end of the day.
Or the CLI that I dont't see myself use much I just start/stop jobs with systemd anyway.
The builtin ACME support I could maybe use but I already have some beautifully handcrafted cron jobs for renewing my certs :) I even managed to more or less hack ACME support into lighttpd using its config syntax.
Caddy actually used to have a very minimal test page, I think they changed it with v2.
I really though lighttpd was perfect for me, very simple unix-like daemon that just requires a config file to run. I wish lighttpd v2 was still in development.
In any case I will probably give Caddy another go and otherwise switch back to nginx. Lighttpd has been giving me too much problems in production, like not correctly logging CGI errors, and crashing when the configuration mentions a hostname that cannot be resolved. Or even when testing simple CGI setups, getting errors to show in stdout requires setting /proc/fd/2 as the error log file...
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.
It really was pretty easy to setup and “just works”
I'm sure you're aware of it, but it might be interesting to others: caddy exposes all of it's internal as library you can easily integrate to your projects: https://github.com/caddyserver/certmagic
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.) @oldPath path_regexp ^/old/([\w-]+)
rewrite @oldPath /new/{re.oldPath.1}.php
Having matching and handling be separate steps are a huge benefit to composability of config, you can have pluggable matchers and handlers.Re you issue with netdata, ask on the forums for help.
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.
nothing wrong with caddy.
Are you using caddy-security? Or is there a better alternative?
https://github.com/vouch/vouch-proxy?tab=readme-ov-file#what...
Can't speak for caddy-security, but the forward_auth feature is the caddy equivalent to nginx's auth_request
One fix is moving session storage to redis <https://oauth2-proxy.github.io/oauth2-proxy/configuration/se...> and the other (if you have control over the nginx config) is bumping its allowed header size "large_client_header_buffers 4 128k;" <https://nginx.org/en/docs/http/ngx_http_core_module.html#lar...>
If you're using nginx as an ingress controller, the annotations support it: <https://kubernetes.github.io/ingress-nginx/user-guide/nginx-...> and/or auth-snippet <https://kubernetes.github.io/ingress-nginx/user-guide/nginx-...>
I'm curious at what would be stored in the session to make it large enough to be a problem, but it's good to know to watch out for it.
Absolute stunner project.
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.
Moreover if you have more of one caddy server deployed it handles TLS certification management in a shared environment, this thing it is not available in the Traefik open source edition (just with the enterprise solution).
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
This is pretty technical, and is an absolute game changer for local TLS setups. Three paragraphs under this quote go into more details.
Then a third of the way down the page there's a way to try it out live by changing your DNS records. Right after that are a few config samples. Then there are links to three different white papers. Then more code samples. Then more more code samples.
You get the idea.
What exactly are you missing here as far as technical stuff? Is it just that they add exciting fonts and stuff on top of the technical stuff?
It took me ten minutes with Caddy to replace five years of Apache+Nginx. That was three years ago.
I wouldn't call it a game changer, because you have to expose port 80 and 443 to public internet to get a real certificate. If you can't do that then Caddy signs its own certificates. That means you have to install the root certificate... this is hard to do in most companies.
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 &