How to renew lets encrypt ssl after 3 months in digital ocean

Sure!

What might be a little confusing is:

  1. acme.sh can be installed in different places.
  2. You might or might not login to your server as the user root.

First, you should figure out where acme.sh is installed on your system/server/computer. Connect to a shell on your server from a terminal program – probably (and hopefully) via ssh. I thought you should be able to run whereis acme.sh but that doesn’t work for me. On my server, acme.sh is installed under /etc/letsencrypt/ but I noticed someone else in an earlier comment mentioned that for them (and presumably their server), it’s installed in /root/.acme.sh. You should be able to confirm that the file acme.sh exists via ls; from my server:

kenny@some-server:~$ sudo ls /etc/letsencrypt/
account.conf  acme.sh  acme.sh.env  ca	deploy	dnsapi	http.header  notify  renewal-hooks  example.com

example.com above is a directory for a dummy example domain name. (I edited the output to strip my site’s name from it.)

I’m going to assume acme.sh is installed under /etc/letsencrypt/.

Next, let’s upgrade acme.sh.

I ran this and it seemed to work fine for me:

$ sudo /etc/letsencrypt/acme.sh --upgrade --home "/etc/letsencrypt"

But acme.sh apparently doesn’t like being run via sudo, so – if you login to your server as a user OTHER than root, you could run these three commands:

$ sudo su
$ /etc/letsencrypt/acme.sh --upgrade --home "/etc/letsencrypt"
$ exit

The first command will effectively ‘log you in’ as root.

(Note that you could skip the last command until later; see below. But if you do skip running exit, make sure to run it after renewing your certs or sometime soon thereafter.)

Then, upgrade your site’s acme.sh config file. Assuming your site’s domain name is example.com, the config file should be at /etc/letsencrypt/example.com/example.com.conf.

You need to change the host for three URLs in three config variable values in this file; the config variables:

  • Le_API
  • Le_LinkCert
  • Le_LinkIssuer

Example line for the first value:

Le_API='https://acme-v01.api.letsencrypt.org/directory'

Change the URL so the line looks like this (i.e. replace the 1 with a 2):

Le_API='https://acme-v02.api.letsencrypt.org/directory'

Make the same change for the other two values.

Now you could either wait for the existing cron job to run or you could manually renew your site’s certificates now. The rest of this comment will cover the latter, i.e. manually renewing the certs.

If you do NOT login to your server as the root user (which, generally, you shouldn’t), you should first run:

$ sudo su

(Even if you do NOT login as root, you can skip this if you ran it in the step above.)

Then renew the certs:

$ /etc/letsencrypt/acme.sh --cron --home "/etc/letsencrypt"

If you ran sudo su before, run exit now to ‘logout’ as root.

That should be it. But of course computers are (often) pretty complicated and any of the above might not work for you for one of many reasons.

1 Like

This works like a Charm - Thanks @kenny-evitt !

1 Question - Will it auto renew next time or do I have to do this post everytime?

1 Like

You’re welcome!

I’m pretty sure that Ghost creates a cron job to automatically renew the certificates. There should be an entry defining the job in the crontab file for the user root (i.e. the cron schedule file for that user).

If you login to your server as root, you should be able to view the crontab file by running crontab -l. If you login as another user, you can run sudo crontab -u root -l.

You should see an entry – a line – like this:

23 0 * * * "/etc/letsencrypt"/acme.sh --cron --home "/etc/letsencrypt" > /dev/null

If you don’t see an entry like that, you can add one. Just run crontab -e or sudo crontab -u root -e to edit the file.

I know Let’s Encrypt has email notifications, e.g. if your certificates are about to expire, but I’m not sure whether Ghost and/or acme.sh configure that. Otherwise, there are lots of ways you could monitor the cron job, but that’s a whole 'nother topic and I’m not sure what would make sense for you, or Ghost administrators generally. I think my site has email notifications somehow – I didn’t set it up initially.

Kenny,

I’ve followed your (amazing) instructions to a T and when I check my certs at
/etc/letsencrypt/example.com/example.com.conf the certs are renewed and not out of date.

Then, frustratingly, when I reload the site in various browsers (cache cleared, new machines) they still seem to be pulling the old cert. Is it possible that there is an old cert somewhere in my nginx that is taking precedence and mucking things up? If so, how would I (a) find and delete it or (b) just ensure that the correct domain is the one being read?

Any and all help (from anyone) is beyond appreciated.

— Geoff

1 Like

I apologize in advance if I cover anything obvious to you! Remote (‘telepathic’) debuggin/troubleshooting is difficult and I’ve found it overall helpful to assume (basically) nothing!

Did you check your certs at /etc/letsencrypt/example.com/example.com.conf literally, or did you, like me in my earlier comments, replace your site’s name with example.com? (I’m guessing you’re just eliding/redacting your actual site’s name, which is fine.)

Would you check your crontab file for the root user and look for a job entry (line in the file) for running the auto-certificate-renewal? That should serve, at least, as a double-check on it being setup in the same way my instructions above assume.

Unfortunately, I’m not super familiar with Ghost itself – the TLS/SSL certificate issue was the first time I’d really done any administration/maintenance on it. (Which is good – it mostly just works!) But I am more familiar with the other components Ghost uses, e.g. the Let’s Encrypt ACME clients, Nginx, cron, Linux stuff, etc., so I’ll try to help more as I can.

@kenny-evitt : thanks for your earlier comment, it does auto renew on its own.

Beer on me.

1 Like

Or maybe some whiskey? :slight_smile:

Kenny,

Thanks so much for getting back so zippily and thoroughly. I assure you, nothing involving computers is obvious to me. Very much appreciated.

Ah, yes I did check my certs at my domain but just swap out example.com for my boring ol’ domain. (Tho that’s the level of mistake I’d be likely to make.)

Somehow, even using sudo -s or sudo su, when trying to access that example.com.conf file I get a permission bash: /etc…/example.com.conf permission denied notice. When accessing crontab in /etc, I get the following:

SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

m h dom mon dow user command

17 * * * * root cd / && run-parts --report /etc/cron.hourly
25 6 * * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )
47 6 * * 7 root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )
52 6 1 * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )

~

Elsewhere tho, I have seen that the Let’s Encrypt certificate has been renewed (either by --force or otherwise, I can’t be certain).

— G.

1 Like

To view/edit the root crontab file, run this:

$ sudo crontab -u root -e

I like vi (or Vim) instead of whatever the default text editor is:

$ sudo EDITOR=vi crontab -u root -e

I don’t remember seeing run-parts before, but apparently that will “run scripts or programs in a directory” so you’d need to view/edit the /etc/cron.x files, or the files in those directories, that are referenced in your crontab file.

The reason why I was curious about your crontab files is that I’m looking for some evidence that the acme.sh Let’s Encrypt client is/was setup, e.g. by Ghost. There are other Let’s Encrypt client programs/packages besides acme.sh and it’s possible that Nginx is setup to use another one. (That’s what I was going to ask about next.)


FYI – you can format ‘code’ or shell commands/output/history with ‘code fence blocks’ on this site (via the Markdown syntax it supports):

```
#m h dom mon dow user command
17 * * * * root cd / && run-parts --report /etc/cron.hourly
25 6 * * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )
47 6 * * 7 root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )
52 6 1 * * root test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )
```

That’s generally much easier to read than regular quoting, especially for files like the crontab files, which use # for comments, as # is interpreted in Markdown syntaxes as a h1 HTML header (e.g. the page title); hence the ‘funny’ formatting in the crontab file you quoted.

Kenny,

Continued thanks — and I genuinely appreciate the FYI. This is also the first forum I’ve ever participated in and am still learning the ropes. Sorry for sending over gobbledygook.

Running
sudo crontab -u root -e
(and choosing vim.basic) says it’s installing a new crontab and outputs:

9 0 * * * "/etc/letsencrypt"/acme.sh --cron --home "/etc/letsencrypt" > /dev/null```

Am I wrong in thinking this means none was setup by acme.sh? Acme.sh does exist in that directory tho will hold on re-hitting --renew-all in the event you advise differently and that pushes me over the weekly renewal limit.

— G.

1 Like

You’re doing great, even if it wasn’t your first forum :slight_smile:

Running sudo crontab -u root -e (and choosing vim.basic) says it’s installing a new crontab …

That’s weird!

I’m not sure why it installed a new crontab file, apparently for root.

Can you briefly outline how your server was created/setup initially? Maybe briefly outline how you installed Ghost on it too and any major setup/configuration you (or anyone else) has done to it since as well?

Your server seems pretty different from mine – I’m mostly curious as to how different they are, so I can, for one, adjust my expectations about what might be different between the two.

… and outputs:

9 0 * * * "/etc/letsencrypt"/acme.sh --cron --home "/etc/letsencrypt" > /dev/null

I think that’s fine. I like this site for quickly interpreting a cron schedule (e.g. 9 0 * * *):

I find it hard to remember exactly which schedule fields are which without a nice header comment.

I usually format my crontab files like a table and heavily comment (for the ease of my future selves that read these files):

#   minute   hour   day of month   month   day of week
         9      0              *       *             *   "/etc/letsencrypt"/acme.sh --cron --home "/etc/letsencrypt" > /dev/null # Renew TLS/SSL certificates

The job in your output should run once per day at 12:09a (per the time on the server, e.g. maybe UTC or GMT).

I think it’s fine that it runs daily, even if Let’s Encrypt only renews your certificates every 60 (?) days or so. That’s how my own Ghost server is setup.

Am I wrong in thinking this means none was setup by acme.sh ?

Technically, I don’t think acme.sh would, itself, create a cron job when it’s installed. I would think that Ghost would create the cron job. But if you (or someone else) installed acme.sh, then maybe it would prompt you to setup a cron job.

I have no idea why the job wasn’t created before. Any info you have about your server’s history might shed some light on this.

acme.sh does exist in that directory …

That’s good.

… tho will hold on re-hitting --renew-all in the event you advise differently and that pushes me over the weekly renewal limit.

I’m not sure what you mean. What’s ‘holding’ and what does that mean? Can you reply with some console output demonstrating whatever “will hold”?

Maybe you need to update the acme.sh config file for your site(s)? My earlier comment covered what we all need(ed) to do because Let’s Encrypt stopped supporting an old version of their ‘protocol’.

It’s also possible that acme.sh was installed and setup on your server to run as another user than root. (That might explain why you trying to edit the crontab file for root apparently created a new one.)

But my understanding of how Let’s Encrypt and the various clients (e.g. programs) for their ACME protocol (of which acme.sh is just one such client) is that a client sending a renewal request ‘early’
just results in a ‘no-op’ (i.e. nothing happens).

Any limit Let’s Encrypt has for making/submitting/sending renewal requests, e.g. using an ACME client, doesn’t apply to what acme.sh should be doing when run via your cron job.

And I’m pretty sure acme.sh, and other ACME clients, are smart enough to handle any limits they
might otherwise run into. I don’t think you’re hitting any kind of rate limit.

If you would, run the cron job command yourself on the server (as root, via sudo):

$ sudo "/etc/letsencrypt"/acme.sh --cron --home "/etc/letsencrypt"

Copy-paste any output in your next reply please.

Kenny,

Thanks again again for the kind words and great advice.

I setup Ghost 2.x as a Google Compute VM a while back (e2-micro if interested). Ubuntu 18.04.5 LTS, NGINX, standard Ghost-CLI install and then upgraded throughout time to the present, fully functioning till the security certificate expired (still functioning, just, you know…)

My only theory as to why it might have installed a new crontab file for root is the Ghost installer requires you to be logged in as a standard user and I might have run it as sudo. I believe I did this because the SSL stage of my install initially failed. I cannot remember this definitively.

(In the act of troubleshooting I did try and get certbot to install a new certificate, but I can’t see how that would lead to this.)

I didn’t install Acme separately and believe it is setup as one of the clients (?) run by the Ghost-CLI.

Ah, sorry for being so confusing with ‘will hold’: I meant, given that one has a 48 or 72 hour limit as to how many certificates he can ask Let’s Encrypt for, that I didn’t want to force a —renew-all if it meant having to wait 72 hours. Sounds like that would only result in a ‘no-op’ tho.

When I run the cron job command at the end of your last message as root, the output is the following (domain changed to example.com):

[Mon Oct 25 15:06:29 UTC 2021] ===Starting cron===
[Mon Oct 25 15:06:29 UTC 2021] Renew: 'example.com'
[Mon Oct 25 15:06:30 UTC 2021] Skip, Next renewal time is: Sat Dec 18 08:56:46 UTC 2021
[Mon Oct 25 15:06:30 UTC 2021] Add '--force' to force to renew.
[Mon Oct 25 15:06:30 UTC 2021] Skipped example.com
[Mon Oct 25 15:06:30 UTC 2021] ===End cron===

— G.