Can’t Seem to Renew Cert on MacOS Sierra

I am trying to renew a certificate on MacOS Sierra on a MacMini Server. I set it up, just fine, however can’t renew.

Here is what I see when I run sudo ls -l /etc/letsencrypt/live/spartn.xyz

lrwxr-xr-x  1 root  wheel    34 Jul  8 15:07 cert.pem -> ../../archive/spartn.xyz/cert3.pem
lrwxr-xr-x  1 root  wheel    35 Jul  8 15:07 chain.pem -> ../../archive/spartn.xyz/chain3.pem
lrwxr-xr-x  1 root  wheel    39 Jul  8 15:07 fullchain.pem -> ../../archive/spartn.xyz/fullchain3.pem
-rw-r--r--  1 root  wheel  5453 Apr  8 07:19 letsencrypt_sslcert.p12
lrwxr-xr-x  1 root  wheel    37 Jul  8 15:07 privkey.pem -> ../../archive/spartn.xyz/privkey3.pem

However, the browser still says it is expired. Not sure how to fix this or what the issue even is…

Thanks for any help.

Dennis

How are you going about attempting to renew?

The letsencrypt_sslcert.p12 file is a PKCS12 format file, which Certbot wouldn’t create automatically for you, but which must have been created by using some kind of script or command to convert from PEM format.

It looks like the PEM-format certificates were renewed successfully, but that nothing has been done to update the .p12 file. If your web server software is using it, then you probably need to repeat the step that generates it.

I used:

spartn: sudo letsencrypt certonly --webroot -w /Library/Server/Web/Data/Sites/spartn.xyz -d spartn.xyz -d www.spartn.xyz

I think the .pem file came from me trying to use the server.app to renew the cert. I was trying just about anything since I have multiple cert’s on the server for the multiple domains it hosts.

All of the cert’s renewed using the same method as above, but none of them are recognized :frowning:

What web server do you use and how did you configure it to know which certificates to use? Did you restart or reload the web server after renewing the certificates? (Most don’t notice that certificates have changed unless they’re restarted or told to reload their configuration.)

macOS Server comes with Apache built-in.

How did you configure it to know which certificates to use? Did you restart or reload the web server after renewing the certificates?

I did restart the server since macOS has the server app, it can be done in the GUI. I rebooted the machine to see if that would help, it did not.

I followed the steps here on the discussion boards to get the server to find the initial cert’s. Compatibility certbot-OSX Server

What configuration steps did you take to tell your web server to use particular certificate files? Where are those files located on your system?

With macOS Server 5.1 and later, you must perform a few additional steps when renewing the certs.

  1. Terminal: Renew the certs using Certbot
  2. Server.app: Make sure you have a self-signed certificate available
  3. Server.app: For each site you have a renewed certificate for, change the SSL cert to the self-signed cert
  4. Server.app: Delete the old certs from Certificates
  5. Server.app: Quite the app
  6. Terminal: Convert & Import the renewed certs to Keychain
  7. Server.app: For each site you have a renewed certificate for, change the SSL cert to the new cert
  8. Server.app: You may need to toggle “Websites” on and off for this to take effect

Hi @MacSupport, do you know why the self-signed certificate steps that you gave are necessary? Why won’t Keychain allow importing the renewed certificates directly?

It’s not so much an issue with the importing, but rather having two certificates with the same FQDN. For some reason, if you don’t remove the old certificate first, the Server.app has a tendency to corrupt the website config file. The self-signed cert trick is just a workaround. I would love to do this all via command line, but I haven’t found the api to do steps 2-5 & 7,8. Right now I have a script that checks for renewals and then imports them into Keychain.

Thanks @MacSupport, will give those steps a go.

How do I go about completing step #6 above

Fingers crossed…

Here is the Bash script I use for step 6:

#!/bin/bash
RED='\033[0;31m'
YELLOW='\033[0;33m'
NC='\033[0m' # No Color

if [[ $UID != 0 ]]; then
    echo "Please run this script with sudo:"
    echo "sudo $0 $*"
    exit 1
fi

read -r -p "Type the domain name you would like to import (example.com), followed by [ENTER]: " thedomain

# bash generate random 32 character alphanumeric string (upper and lowercase)
TEMP_PASS=$(cat /dev/urandom | env LC_CTYPE=C tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1)

echo "\n\n${YELLOW}Temp password created for import to Keychain Access: ${RED}"$TEMP_PASS"${NC}\n\n"

read -p "Export the $thedomain LetsEncrypt Cert to Keychain Access Format (.p12) [Y or N]: " -n 1 -r
echo    # (optional) move to a new line
if [[ ! $REPLY =~ ^[Yy]$ ]]
then
    exit 1
fi

eval openssl pkcs12 -export -inkey /etc/letsencrypt/live/$thedomain/privkey.pem -in /etc/letsencrypt/live/$thedomain/cert.pem -certfile /etc/letsencrypt/live/$thedomain/fullchain.pem -out /etc/letsencrypt/live/$thedomain/letsencrypt_sslcert.p12 -passout pass:$TEMP_PASS

read -p "Import the $thedomain LetsEncrypt Cert to Keychain Access [Y or N]: " -n 1 -r
echo    # (optional) move to a new line
if [[ ! $REPLY =~ ^[Yy]$ ]]
then
    exit 1
fi

eval security import /etc/letsencrypt/live/$thedomain/letsencrypt_sslcert.p12 -f pkcs12 -k /Library/Keychains/System.keychain -P $TEMP_PASS -T /Applications/Server.app/Contents/ServerRoot/System/Library/CoreServices/ServerManagerDaemon.bundle/Contents/MacOS/servermgrd

I did it manually, what a pain in the neck! Thanks for the script and the help, it worked! I have my websites back…

I’m glad you figured it out! When I kept asking

I guess part of the answer that I was looking for was “by importing them into Keychain”. I’m afraid I didn’t know about Keychain because I don’t use macOS.

If @MacSupport’s script or something like it does work properly for you, there’s a way that you could combine it with Certbot’s autorenewal feature so that it runs automatically when certificates get renewed. The supported way to do this is to add a --renew-hook option to the cron job that called certbot renew, with an additional argument indicating the location of the script. Then that script will be run whenever certificates get renewed by certbot renew.

I guess the script wouldn’t work properly that way in its exact current form because it tries to read the domain name interactively from the user with read, but we could create a non-interactive version that can be used with --renew-hook so that unattended renewals from cron result in getting an import into Keychain.

1 Like

@MacSupport, would you be willing to work on a non-interactive version of this? The --renew-hook invocation method should be able to tell your script via environment variables which certificate was renewed.

Does the security import command require the user to interact with a dialog box or anything, or can it run totally unattended? (I think the eval is superfluous there.)

Absolutely!!! I would enjoy making the necessary changes.

Great, let's use this new thread.

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