Add new domain via API?

Hello, currently I am using the below Caddyfile:

domain1.com {
        root * /var/www/html
        file_server
}

I wan’t to be able to use the API to add domains to this so it’d be something like this:

domain1.com, domain2.com {
        root * /var/www/html
        file_server
}

Is this possible, and if so, how would I do this please?

Sorry if this is a dumb question.

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.

2 Likes

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 :+1:, 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.

Just read through something Matt wrong.

So would I add this to the config and then the ‘ask’ part is what checks my database to see the domains in there and then Caddy adds/removes those?

on_demand_tls {
        ask      http://localhost:5555/check
        interval 2m
        burst    5
    }

Would I just be ok to list those domains on that check like this:
{
domain1.com”,
domain2.com
}

1 Like

Yes, essentially.

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.

1 Like

So from what I’ve ready, is this correct?

Caddy will send request to the ‘ask’ part in the config. For example, application.com/check

That will be sent as ?domain= and if a 200 is returned it’ll issue an SSL?

{
    on_demand_tls {
        ask      https://my.application.com/check
        interval 2m
        burst    5
    }
}

https:// {
    tls {
        on_demand
    }
    root * /var/www/html
    file_server
    php_fastcgi unix//run/php/php7.4-fpm.sock
}

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:

http_response_code(200);

What am I doing wrong?

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.

The ask is hosted on an external server. I’ve done some playing around and managed to get it working.

I’ve never been so hapy to see a website load with SSL, haha!

Thank you so much for you help @francislavoie, it’s much appreciated.

1 Like

What was the problem?

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.

1 Like

This topic was automatically closed after 30 days. New replies are no longer allowed.