The API is a JSON API, so it’s not ideal to use if you’re writing your configuration with the Caddyfile. It complicates things.
So you’ll need to decide whether you want to continue using the Caddyfile, and update the Caddyfile before reloading Caddy with the new config, or switch to using JSON and the API.
You can adapt your Caddyfile to JSON, to see what it looks like, but you can’t go from JSON back to Caddyfile:
caddy adapt --pretty --config /path/to/Caddyfile
It entirely depends on why you want to dynamically add domains. What problem are you trying to solve? There are other solutions depending on what you’re trying to do.
Thank you, basically I’m building a web application and I want to add customers domain names dynamically and have the ability to easily remove them. Long story short its a web app to create a web store so dynamically adding domains, removing them and having SSL automatically is a must.
So correct me if I’m wrong but I’d need to convert to use JSON and my config would look something like this:
…
"host": [
“domain1.com”,
“domain2.com”
]
…
How would I then use the API to add a new domain and remove one?
If there’s a better solution for my needs then please let me know.
What you’ll want in that case is Caddy’s On-Demand TLS feature.
That way, you’ll not need to update the config at all when you want to support another customer’s domain. You just make sure the domain is added to your backend’s database, and write a backend API endpoint that Caddy can query to check if that domain should be allowed.
Automatic SSL seems to be set up and working perfectly, what I’m trying to do now is figure out how to add/remove domains using the API or whatever other solution is best.
The domains will be added from an external/remote server so I presume API will be best.
You misunderstand. With On-Demand TLS enabled, you don’t update your config at all, when you want to allow a new domain.
Instead, Caddy will reach out to an API endpoint that your write to find out whether a domain is in an allow list you manage on your backend. If your backend gives a , then Caddy will issue a certificate for that domain on-the-fly (during the TLS handshake).
If you want to no longer allow that domain, then remove it from your database, and Caddy will not renew the certificate for that domain.
If you’re proxying to an app, then the Host header will contain the domain of the original request, so you can check at that point as well whether the domain is still allowed, and route or set up tenancy on your app for that request.
Caddy only reaches out to your ask endpoint when it’s time to issue (i.e. for any request where Caddy doesn’t have a certificate for that domain) or renew a certificate (when it’s in the last 1/3 of its lifetime).
Caddy will never “remove” a non-expired certificate, it’ll keep it around as long as it’s still valid. If you need to deny access, then you’ll need to do it in your app when Caddy proxies to it.
Is this correct? I tried this config, added the DNS record for my domain and browsed to it but no SSL was issued. When I browse to the domain I cannot see anything when looking at my caddy run --watch.
My check script simply returns this in a PHP script:
Is that domain in your ask something you’re trying to proxy with the same Caddy instance? If so, that’s a bit of a chicken-and-egg problem, Caddy won’t have a certificate to allow the connection yet.
If that’s the case, then I recommend making another site block in your Caddyfile listening on a different port like 8080 or something, and using that to proxy to your app for the ask instead.
It was me being stupid, the ask was hosted on a development environment and I was using my local /etc/hosts to access the script. Just needed to deploy that check script to the production server.