How to dynamically point to custom domain SSL certificates

I am using RewriteMap in Apache which points to a text file containing hundreds of domains. This means that a user can point their custom domain to my site through A Records and my site can show them the relevant directory.

It also generates an SSL certificate for them.

SSLCertificateFile /etc/letsencrypt/live/domain.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/domain.com/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf

I have one VirtualHost in total with the * sign to represent all custom domains. Is there a way to replace domain.com with the current domain of the user automatically?

For example, if someone visits example.com in their browser, is there a way to automatically point to the certificate file held in the /etc/letsencrypt/live/example.com directory?

I have tried things like SSLCertificateFile /etc/letsencrypt/live/%{HTTP_HOST}/fullchain.pem but it just causes an error

If you only have one VirtualHost file, then you only have one certificate?
It sounds like your trying to consolidate all your vhost configs into just one (dynamicly defined) vhost config file. But I don’t think you can dynamically redefine any critical vhost configuration settings (ServerName/documentRoot/CertificateFile).
So, you would need to create one vhost config for each required unique ServerName/Certificate.
[and then restart/reload the web service]

The best that I know you can do, to come close to this, is to pass the new domain as a variable to a script that can create all the necessary files, certs, and restart the web service for you.

1 Like

You’d have to find a way to set an environment variable. Here’s additional documentation from Apache:

https://httpd.apache.org/docs/2.4/env.html
https://httpd.apache.org/docs/2.4/mod/mod_ssl.html

You should be able to call on HTTP_HOST as an environment variable somehow.

1 Like

@ZetaRevan, but how would he define a vhost config for that “newly” assigned name?

I’m pretty sure you can’t get all this to work (dynamically):

<virtualhost *:443>
ServerName %{HTTP_HOST}
DocumentRoot /var/www/%{HTTP_HOST}
SSLCertificateFile /etc/letsencrypt/live/%{HTTP_HOST}/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/%{HTTP_HOST}/privkey.pem
</virtualhost>
1 Like

You make a valid point. The rewrite map still has to route to a 443 block that accepts the domain. Possibly a default block to handle all traffic and use an if statement to present a Cert if it matches an existing domain directory or present a default. Might not be possible within the apache Environment. I haven’t tried to run a dynamic vhost. I just create vhost files for every domain/subdomain. Keep it simple.

2 Likes

You know, maybe apache isn’t the right tool for the job.

Probably Caddy or Traefik can do the job without making humans miserable too much. (Be careful, Caddy’s automatic https doesn’t do SAN certs, but on_demand issuing sounds interesting)

4 Likes

Technically, all of Caddy’s certs are SAN certs, meaning they use SubjectAlternateName extension – what you probably refer to is having more than one SAN per certificate. If by “careful” you refer to rate limits, note that it only applies to a registered domain name with lots of subdomains, where you are getting certificates for many individual subdomains – like, 50+ or hundreds, in a short period of time. This can be mitigated by obtaining a single wildcard certificate (which Caddy can be configured to do). In fact, we recommend this when there are a large number of subdomains.

But in the general case, issuing single-name SAN certificates is practically optimal.

And yes, I agree that using Caddy would greatly reduce the burden for you. You can either whitelist the domains by adding them to your config, or set up an internal API that Caddy can “ask” for on-demand issuance. It will manage the storage and serving and renewal of those certs for you as handshakes come in.

3 Likes

I wrongly assumed there was a rate limit on IPs as well. My bad. (It’s there, but on account creation)

So @ozzie, you should probably look into using Caddy as a reverse proxy (or making it serve content directly).

1 Like