Good question, I need to expand the docs about this.
This is on Linux I guess?
The basic idea is that it’s a network socket, so you don’t want untrusted code to have access to it. Generally this is not a problem in the first place because if your system is running malicious code, it’s game over anyways. So we assume that your system is secure to begin with.
By default, Caddy’s admin port is bound to
localhost:2019 (the significance of that port number is the year this feature was developed). That covers the majority of problems already. This means that remote code can’t access the port. To further increase security, you can restrict requests to come only from designated hosts / origins, with
enforce_origin in your admin config:
This is primarily useful against browser-based attacks, as it causes the admin API to emit CORS headers which browsers honor. (But since most people don’t deploy servers on the same machines that use web browsers, this is seldom a concern anyway and it’s why it’s not enforced by default.) As a nice bonus, enabling this also mitigates DNS rebinding attacks.
Another option on Linux is to use unix sockets. Simply permission the socket file so that only the Caddy process and any clients can access it. Then you don’t need to have Caddy enforce permissions itself, the OS does it for you.
So that’s basic local access protections in a nutshell.
You mentioned that you want to have permissions for users, etc. You can enable the remote admin endpoint, which is a different socket because it uses TLS (mandatory):
You’ll use the
access_control property to specify permissions for specific public keys. That’s how you can control what each user can do.
In order for the admin endpoint to function, however, the server needs an identity certificate for itself. As the docs mention, you can use the
identity property of the config to tell Caddy what its identity is so it can manage a certificate for itself. If your server isn’t being accessed with a public DNS name, then you should configure the
issuers to be an internal issuer or your own ACME CA if you’re rolling your own PKI.
I really intend to write a docs page about this now, but for a while I was thinking it should be reserved for sponsors because it’s a very powerful and advanced feature.
Does that help?