No, I would like to be able to generate the httpasswd files (for some of the sites) through ansible and the actual sites configurations to be loaded through docker-proxy module (https://github.com/lucaslorentz/caddy-docker-proxy/plugin).
If the password file for a domain does exist, enable basicauth and use that. If it does not exist, just configure the site withouth basicauth.
Now that I am thinking, maybe a solution would be to be able to define the fallback for the basic auth if it’s empty?
I am VERY curious about caddy-docker-proxy and it would be interesting to see it in how you use it.
If you can upload a minimal sample here on on GitHub/BitBucket/GitLab/Gitea, I was thinking we could write a small custom service that monitors configuration and updates the basicauth settings via the (admin) API
This way, you can continue using the stock basicauth module (in addition to sharing some real worlds use of caddy-docker-proxy), as otherwise it feels like the stock basicauth module will need to updated to behave this way (and it seems risky to do so - imagine the file getting deleted and anyone being able to access an otherwise protected endpoint)
When the s1 container goes up, the @doauth_or_not is true so the basicauth is enabled.
If I change the last label as caddy.1_import: "auth noauth s1", the basic auth will be disabled.
The json config for enabled auth case:
{"admin":{"listen":"tcp/localhost:2019"},"apps":{"http":{"servers":{"srv0":{"listen":[":443"],"routes":[{"handle":[{"handler":"subroute","routes":[{"handle":[{"handler":"authentication","providers":{"http_basic":{"accounts":[{"password":"JDJhJDE0JEU0RVZHSWhobGEuMFIycFlIeVV0SE9nek1yS2RmY2t2c1EvRml2d3dkNkhVcDlqV2xyVWk2","username":"test"}],"hash":{"algorithm":"bcrypt"},"hash_cache":{}}}}],"match":[{"expression":"\"doauth\" == \"doauth\""}]},{"handle":[{"handler":"reverse_proxy","headers":{"response":{"delete":["Server"]}},"upstreams":[{"dial":"10.99.0.36:80"}]}]}]}],"match":[{"host":["s1.t.example.com"]}],"terminal":true}]},"srv1":{"listen":[":80"],"routes":[{"handle":[{"body":"This is not the website you are looking for.","handler":"static_response"}]}]}}}},"logging":{"logs":{"default":{"encoder":{"format":"json","time_format":"iso8601"},"level":"DEBUG","writer":{"filename":"/logs/main.log","output":"file"}}}}}
There’s no way to make it conditional based on the contents of basicauth.
What you should probably do instead is put your basicauth { inside of your /etc/caddy/htpasswd/s1 file instead, and leave it empty if you want no auth.
Well, that’s one way. I was thinking since we have docker-compose here, we write a small custom service that monitors configuration and updates the basicauth settings (stanza?) via the (admin) API
Sure, that would work too, @francislavoie.
Since I plan to generate those files with ansible, it’s easy to add the basicauth block in there.
But what happens in this case if the s1 file does not exists? Will the import statement error throw away the whole server block or it will just complain about the file not being present but still serve unauthenticated content from s1?
I think my problem is not limited to the actual basic auth thing. I did managed to kinda solve it by replying on a specific value sent as argument in in one of the labels of the upstream container. I am using that in an expression matcher whch is used by basicauth.
I think the actual issue is (for me at the moment) that attempting to import a non-existent file kicks out the whole server block from the configuration.
Just for the next one stublimg around here in search for answers, using expression matcher on basicauth is really neat.
(auth) {
@check_auth {
expression "\"{args.0}\"" == "\"auth_enabled\""
}
basicauth @check_auth {
# if a file is missing, the whole vhost wont work, UNLESS you have a wildcard in the file name!
# in that case, missing files wont result in error
# the file should just contain the space separated user and password
import /etc/caddy/htpasswd/{args.1}*
}
}
If a named matcher only has a single matcher, it can be a one-liner and skip the { } block.
There’s two different string delimiters in the Caddyfile, i.e. backticks and double quotes. Since double quotes have its own meaning in CEL expressions, you can instead use backticks to wrap the tokens in the Caddyfile, and avoid escaping your double quotes.
But actually, in Caddy v2.5.0, you’ll be able to omit the backticks altogether, because I made a patch to make the expression matcher a bit smarter about how it handles tokens, so it will preserve double quotes as-is instead of consuming them before adapting the config to JSON.