Configuration SSL Apache2 [+ let's encrypt]

Hello,

I just moved into the NextCloud world:) The installation went well (on Debian 9) and everything was working fine until I set up my SSL certificates.

So I added these lines to my /etc/apache2/sites-available/nextcloud.conf

  SSLEngine On
  SSLCertificateFile /etc/apache2/ssl/next.domain.com.crt;
  SSLCertificateKeyFile /etc/apache2/ssl/next.domain.com.key;

and since then it has been impossible to restart my apache2 service.

root@NEXT:/etc/apache2/ssl# apachectl configtest
AH00526: Syntax error on line 23 of /etc/apache2/sites-enabled/nextcloud.conf:
SSLCertificateFile: file '/etc/apache2/ssl/next.domain.com.crt;' does not exist or is empty
Action 'configtest' failed.
The Apache error log may have more information.

root@NEXT:/etc/apache2/ssl# ls -l /etc/apache2/ssl/
total 8
-rw-r--r-- 1 root ssl-cert 3655 déc.   2 20:46 next.domain.com.crt
-r-------- 1 root root     1674 déc.   2 20:46 next.domain.com.key

root@NEXT:/etc/apache2# ls -l
total 84
-rw-r--r-- 1 root root  7224 nov.   3 19:46 apache2.conf
.......
drwxr-xr-x 2 root root  4096 déc.   2 21:27 sites-available
drwxr-xr-x 2 root root  4096 déc.   2 21:06 sites-enabled
drwx------ 2 root root  4096 déc.   2 20:52 ssl

Yet my certificates are in the right places and not corrupted

Do you have any idea ?

Thanks

next.domain.com.crt; is the file apache looks for, and next.domain.com.crt is the file in your folder. You see the semicolon?

1 Like

Thank you, that’s the problem… I thought I had looked closely but the proof that I didn’t:)

Thank you!!!

For automated SSL via Let’s Encrypt, use this script: https://github.com/nextcloud/vm/blob/master/lets-encrypt/activate-ssl.sh

It auto renews and everything. :smiley:

Thx but I use my certificat and no let’s encrypt :blush:

May I ask if you have any special reasons using a paid certificate? You can validate subdomains with Let’s Encrypt as well if that’s the case.

Let’s encrypt has some flaws… Opening of port 80…

but my reason is that my ssl certificate is offered with my domain name.

Well, if you don’t open port 80 everyone that goes to (http://)your.cloud.com won’t be redirected to https://your.cloud.com. So no one will ever be on port 80 as they are redirected. Also it’s a better user experience, because people are lazy, who types https:// these days except us nerds? :wink:

That’s best practice if you ask me.

Not sure if some browsers are perhaps checking https first when you just enter an address. We shouldn’t favour a specific certificate type or issuer as long as you use a https connection.

We shouldn’t favour a specific certificate type or issuer as long as you use a https connection.

Agreed.

Not sure if some browsers are perhaps checking https first when you just enter an address.

Probably not.

OnT: Putting a http → https redirect in your vhost conf is standard these days. Just trying to make life easier and cheaper here. :wink:

For automated SSL via Let’s Encrypt, use this script: https://github.com/nextcloud/vm/blob/master/lets-encrypt/activate-ssl.sh

It auto renews and everything. :smiley:

Does this script use the http validation or dns? If the former, what’s involved in using the dns method?

Thanks for asking!

It’s using 3 methods, where it tries DNS as a last resort: https://github.com/nextcloud/vm/blob/master/lets-encrypt/activate-ssl.sh#L211-L235

Ofc the Apache configuration is hardened and secured as well. “By the book” so to speak, including redirect from HTTP to HTTPS.

@enoch85

Thank you for your response. I’m quite new to nextcloud/letsencrypt, et al.

The line in question from the script appears below.

if eval "certbot certonly --manual --manual-public-ip-logging-ok --preferred-challenges dns --server https://acme-v02.api.letsencrypt.org/directory $default_le"

As I understand it, the dns method uses a TXT record for domain validation instead of a validation files accessible through standard web ports (80/443). As such, that means that for each letsencrypt renewal, a new TXT records must be generated at the registrar so the back end can validate it.

I just ran through it with another test subdomain. So during install of the VM it prompts you to add the TXT record w/key. The cert is successfully created.

The question then is what happens at renewal time? The corresponding command in the renew script is :

 certbot renew --quiet --no-self-upgrade 

This does not reference dns at all. In fact running it manualy with a --dry-run or --force-renew just results in a failure message.

Thanks for helping me understand this.

I would recommend you to read this: https://community.letsencrypt.org/t/renewing-with-dns-challenge/37184

The script isn’t designed to use DNS as primary, hence “last resort” so that you at least can get a cert during script run, and then fix a regular challenge which certbot renew can handle.

Afaik it’s not possible to script renewing a DNS challenge generated cert, without human interaction which makes it (almost) impossible to do it automatically in a script.

@enoch85,

I found a working solution here.

In essence it requires use of cloudflare nameservers. Using an api key to communicate with cloudflare and generate the validation TXT records.

I’ve adjusted the letsencryptrenew.sh script as follows. I’m sure this can be cleaned up by someone more knowledgeable. What do you think?

Also, I see the letsencryptrenew.sh is run as user root by cronjob. There’s also a systemd certbot process that runs. Can you help me understand the purpose of the systemd process?

/var/scripts/letsencryptrenew.sh

echo "Let's Encrypt started: " $(date +%Y-%m-%d_%H:%M:%S) >>  /var/log/letsencrypt/renew.log

#cleanup
/home/ncadmin/dehydrated/dehydrated -gc -d sub.domain.com -t dns-01 -k '/home/ncadmin/dehydrated/hooks/cloudflare/hook.py' >>  /var/log/letsencrypt/renew.log

#renew
/home/ncadmin/dehydrated/dehydrated -c -d sub.domain.com -t dns-01 -k '/home/ncadmin/dehydrated/hooks/cloudflare/hook.py'   >> /var/log/letsencrypt/renew.log

cp /etc/dehydrated/certs/sub.domain.com/chain.pem /etc/letsencrypt/archive/sub.domain.com/chain1.pem
cp /etc/dehydrated/certs/sub.domain.com/cert.pem /etc/letsencrypt/archive/sub.domain.com/cert1.pem
cp /etc/dehydrated/certs/sub.domain.com/privkey.pem /etc/letsencrypt/archive/sub.domain.com/privkey1.pem

echo "Let's Encrypt ended: " $(date +%Y-%m-%d_%H:%M:%S)'\n\n' >>  /var/log/letsencrypt/renew.log


# Check if service is running
#if ! pgrep apache2 > /dev/null
#then
#    service apache2 start
#fi

#restart apache2
service apache2 reload

Your question was if you could use SSL with DNS validation. Now you’re linking to something else?

I wrote about exactly that some time ago: https://www.techandme.se/setup-multiple-accounts-with-ddclient-and-cloudflare/

What is your end goal here? It’s hard to help if you’re not specific.

OK, so I found some info about it. Seems neat indeed. But then again, not possible without human interaction.

I’d prefer everything as easy as possible, automatic and easy to use.

Sure, we could create another flow, like; if ports are closed and use DNS if you have Cloudflare then ask user for credentials and make it variables else ask user to create an account on Cloudflare and then restart the script.

You’re welcome with a PR here: https://github.com/nextcloud/vm :smiley:

^^My end goal (like yours), is for full automation. I don’t want to think about certs every 90 days.

Once configured, the code above automates everything. I believe your cronjob executes the renew script once a day. Same script, different code. Similar to the http validation, this will skip certs until 30 days are left, then renews.

No human interaction needed. I suppose it is possible to even configure it to place the new certs in the same place your existing script does. Instead, I just copy them over there.

Perhaps a way of implementing this is to ask these questions during the initial run of the activate-ssl.sh script to build a dns compatible renew script instead of http (or the same script could contain code for both, chosen by the value of a single variable in a config file).

You are right, a cloudflare account is required to make this work. On the other hand, a number of registrar’s support API access too. Challenge is to interface properly between the hydrate script and them. I would love to code this properly, but that is way beyond my abilities.

PS. In your activate-ssl.sh script, why is there a systemd scheduled certbot process in addition to the cronjob?

Yeah, sure, the script itself renews the certs by removing them and generate new ones.

The are reasons for everything. certbot renew doesn’t renew if the script isn’t outdated, hence it can be run everyday -which also is best practice due to the fact that there is nothing 100% certain with renewing a cert.

So in short, what a few lines of bash does (like in your example) certbot renew does automagically. :slight_smile:

instead of http

I already have an idea regarding that. If the DNS method is used then set a varable called whateveryoulike-dns and generate a renew script for DNS. If that variable is not set, then run http renew script.

No human interaction needed.

Once it’s setup no, but how much “human interaction” did you do to come to the stage where it’s working by itself? That’s what i mean.

PS. In your activate-ssl.sh script, why is there a systemd scheduled certbot process in addition to the cronjob?

The cronjob always existed, that way I can decide which commands are being run. The service is not enabled, so it’s not run.

OK, so I opened an issue here: https://github.com/nextcloud/vm/issues/734

Anyone with some spare time are free to dig in and send a PR! :slight_smile: