Pretty easy (if I understand what you're asking for):
@needsAuth not remote_ip private_ranges
basicauth @needsAuth {
user pass
}
This uses a named matcher[0] `@needsAuth` with the `not` and `remote_ip` matchers, to match all public IP ranges (change `private_ranges` to a list of CIDRs if you prefer), then applies that request matcher to the `basicauth` handler[1], and pass in user/pass pairs to it (passwords are bcrypt hashed).
If the user fails authentication, then they won't be able to get in, as you'd expect. But users inside your allowed IP ranges will get through without basicauth.
If the user fails authentication, then they won't be able to get in, as you'd expect. But users inside your allowed IP ranges will get through without basicauth.
[0]: https://caddyserver.com/docs/caddyfile/matchers
[1]: https://caddyserver.com/docs/caddyfile/directives/basicauth