7

I am using Let's Encrypt (certonly) to generate SSL certificates for several websites hosted on an Apache server. The file location of these certificates is determinate before they are created, so I am writing their paths into my virtual host configuration in advance. Once the site is running, I will use certbot to get the certificate files and then reload the Apache configuration.

I also have a global SSL certificate defined with valid files, so every SSL virtual host will be certain to have a certificate.

The problem I'm having is that Apache won't run without all the certificate files, despite having a global fallback. I tried to conditionally configure the Let's Encrypt certificate only when the file exists using IF, but Apache says SSLCertificateFile not allowed here.

How might I override the global SSLCertificateFile only when the new certificate files exist? I'm trying to do all of this without having to modify the configuration before and after the certificates have been generated.

Here is what I tried:

<If "-f '/etc/letsencrypt/live/domain/fullchain.pem'">
  SSLCertificateFile /etc/letsencrypt/live/domain/fullchain.pem
  SSLCertificateKeyFile /etc/letsencrypt/live/domain/privkey.pem
</If>

→ SSLCertificateFile not allowed here

1
  • Simply deploy a dummy file there that you can let certbot overwrite?
    – HBruijn
    Apr 26, 2017 at 6:25

5 Answers 5

2

In this case, I would create a directory of symlinks for each domain, and use the server's snakeoil cert (or your previously mentioned "global" certificate) for domains you don't have configured yet. For example:

$ ls -1 /etc/ssl/domains
example.com/fullchain.pem -> /etc/letsencrypt/live/example.com/fullchain.pem
example.com/privkey.pem -> /etc/letsencrypt/live/example.com/privkey.pem
second-example.com/fullchain.pem -> /etc/ssl/certs/ssl-cert-snakeoil.pem
second-example.com/privkey.pem -> /etc/ssl/private/ssl-cert-snakeoil.key

You can then set the Apache directives to use the symlink directory:

SSLCertificateFile /etc/ssl/domains/example.com/fullchain.pem
SSLCertificateKeyFile /etc/ssl/domains/example.com/privkey.pem

This has the advantage of only needing to replace the symlink when you generate a Let's Encrypt certificate for the domain, however users visiting the domain before a full certificate is installed will receive warnings as the snakeoil certificate is self-signed.

1
  • Brilliant and much appreciated.
    – Nathan
    Apr 26, 2017 at 10:47
8

You can use IfFile instead of If:

<IfFile "/etc/letsencrypt/live/www.example.com/fullchain.pem">
SSLEngine on     
...  
</IfFile>

This works because the IfFile condition is evaluated at startup:

Encloses directives that will be processed only if file exists at startup

Whereas If is evaluated at runtime:

Contains directives that apply only if a condition is satisfied by a request at runtime

Configuring the SSLEngine must be done at startup and cannot be done at runtime.

Quotes are from the Apache 2.4 Core Features docs.

1
  • 3
    This is excellent. You may also wish to check if "privkey.pem" in the same directory exists too. ("fullchain.pem" and "privkey.pem" are enough.) Just two <IfFile> directives, one nested in the other, works brillaintly.
    – Adambean
    Aug 18, 2021 at 20:12
0

Another idea: if I understood correctly, you have global virtualhost as a catchall and then other virtualhosts, one per website. If the website has not yet the associated SSL certificate, then it should not be configured at all. You can put each website configuration in its own file, and have 2 directories: sites-enabled and sites-waiting with an Apache configuration saying to include everything from sites-enabled. When your website is configured (meaning it has its SSL certificate) you just need to move its configuration from one directory to another, and reload Apache.

This kind of setup is done by various Linux distributions.

1
  • The non-SSL configuration has to be enabled to obtain the certificate. Typically I keep both the non-SSL and SSL configurations in the same file, but if I split them up this scheme could work. Thanks!
    – Nathan
    Apr 30, 2017 at 1:38
0

Actually I have the .well-known alias in the same directory for all virtualhosts. This way the challenge is reachable via the default virtualhost when the new virtualhost is not enabled.

0

Everything was solved with IfFile directive added in the https .conf file of apache:

<IfFile "/etc/dehydrated/certs/hss.yatebts.com/fullchain.pem">
  SSLEngine on
  SSLCertificateFile /etc/dehydrated/certs/hss.yatebts.com/fullchain.pem
  SSLCertificateKeyFile /etc/dehydrated/certs/hss.yatebts.com/privkey.pem
  SSLCertificateChainFile /etc/dehydrated/certs/hss.yatebts.com/chain.pem
</IfFile>

Also, to test that everything is alright, try : su - apache -c "/usr/sbin/httpd -t -D DUMP_MODULES"

If this command does not work, will show what is not alright and you can fix it right away.

PS: "file" in double quotes in IfFile directive are allowed in Apache > 2.4.35

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .