Basic shell script to generate certificates and crontabs

Hi!

Just trying to make a basic shell script to generate my certs and crontabs with acme-client(1) here on OpenBSD and was wondering what you guys think?

#!/usr/bin/env zsh
#
# Generate certificates and crontabs
# https://romanzolotarev.com/m/ow.html
#
 
list=(
  "foo.com"
  "bar.com"
  "baz.com"
)
 
for domain in $list; do
  if acme-client -v $domain; then
    echo "0 0 * * * acme-client $domain && rcctl reload relayd" | crontab -
 
    sleep 4
  else
    exit
  fi
done

Please don't set the crontab to run right at midnight--some other time, or better yet with a random delay, would be a better plan. Thousands, or millions, of clients hitting the CA right at midnight causes capacity issues.

8 Likes

I agree w/danb

here is one way for random starts
https://eff-certbot.readthedocs.io/en/stable/using.html#setting-up-automated-renewal

see the crontab entry this client uses

4 Likes

If I read your loop correctly, it would add the following lines into your crontab:

That would make all three (try to) run at the exact same time.
[in addition to all the other clients that incorrectly run at midnight]
Can your acme-client run multiple concurrently instances?
If not, then each line must ensure that it doesn't overlap [timewise] with any other running instance.

2 Likes

Hey, thanks a lot for the feedback!

It looks like this now:

for domain in $list; do
  if acme-client -v $domain; then
    # Random time intervals
    # https://unix.stackexchange.com/a/580493/68670
    echo "30~45 * * * acme-client $domain && rcctl reload relayd" | crontab -

    sleep 4
  else
    exit
  fi
done

What do you guys think?

An anti-overlap feature would indeed be nice. Please let me know if y'all find one :+1:

That seems to be missing a column.
And all entries would get the same timeframe.
So...

2 Likes

I think your premise is wrong

You should have one script that iterates thru your domains and issues / updates certs as needed. It should not create cron tasks for each domain.

Instead, have one crontab that runs that script at a random time.

As you have it, multiple cron entries (one for each domain) may create overlapped executions due to various timing lags and unlucky random times. It's not clear whether your acme client supports that but I think it will be easier to manage as a single crontab anyway.

3 Likes

@MikeMcQ, although I completely agree with you...
The question was more of:
"What do you think of this (mess I've made) thus far ..."
than
"How can this best be redesigned to ensure things go correctly ..."

But, as always, you go above and beyond the call of duty!!!
You get a star: :star2:

2 Likes

Hi! That sounds like a very good idea but first I need to get better organized.

For now I just did (OpenBSD):

for domain in $list; do
  acme-client -v $domain

  # Run sometime during the 1st of each month
  (crontab -l; echo "~ ~ 1 * * acme-client $domain && rcctl reload relayd") | crontab -

  sleep 8
done

Do share your own custom scripts if possible!

Is that to be run only on the first day of each month?

1 Like

Yup, that's safe right?

Checking monthly is not ideal.
Even checking weekly is only 4 (or 5) tries a month - not much room for error.
You really want to check it at least once a day.

2 Likes

Cool, thanks a lot :+1:

1 Like

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