acme: avoid overlapping manual and automatic certificate generation
Massimo Melina committed
Sep 22, 2023 at 15:28 UTC
e8f1444839d62d2b37e8bd90b84457253176f1be
1 file changed
+9
-31
src/api.net.ts
+9
-31
@@ -245,7 +245,7 @@ const apis: ApiHandlers = {
245
export const acme_domain = defineConfig<string>('acme_domain', '')
246
export const acme_email = defineConfig<string>('acme_email', '')
247
248
-export async function makeCert(domain: string, email?: string) {
248
+export const makeCert = debounceAsync(async (domain: string, email?: string) => {
249
if (!domain) return new ApiError(HTTP_BAD_REQUEST, 'bad params')
250
const res = await generateSSLCert(domain, email)
251
const CERT_FILE = 'acme.cert'
@@ -254,33 +254,13 @@ export async function makeCert(domain: string, email?: string) {
254
await fs.writeFile(KEY_FILE, res.key)
255
cert.set(CERT_FILE) // update config
256
privateKey.set(KEY_FILE)
257
-}
258
-
259
-export const renewAcme = {
260
- timer: null,
261
- reset() {
262
- if (this.timer !== null)
263
- clearTimeout(this.timer)
264
- this.timer = null
265
- },
266
- set() {
267
- if (this.timer !== null) {
268
- setTimeout(this.set.bind(this), 5_000);
269
- } else {
270
- this.reset()
271
- setImmediate(() => repeat(DAY, renewCert)
272
- .then(v => ((this.timer as any) = v)))
273
- }
274
- }
275
-}
257
+}, 0)
258
259
defineConfig('acme_renew', false) // handle config changes
278
-events.once('https ready', () => renewAcme.set())
279
-/**
280
- * checks if the cert is near expiration date.
281
- * if so renews it
282
- */
283
-async function renewCert() {
260
+events.once('https ready', () => repeat(HOUR, renewCert))
261
+
262
+// checks if the cert is near expiration date, and if so renews it
263
+const renewCert = debounceAsync(async () => {
264
const acmeLog = (...args: any[]) => console.log('[acme-renew]:', ...args)
265
const now = new Date()
266
const cert = getCertObject()
@@ -288,11 +268,9 @@ async function renewCert() {
268
const validTo = new Date(cert.validTo)
269
const isValid = now > new Date(cert.validFrom) && now < validTo &&
270
validTo.getTime() - now.getTime() >= 30 * DAY // it's not expiring in a month
291
- if (isValid) return acmeLog("cert is valid")
271
+ if (isValid) return acmeLog("certificate is good")
272
await makeCert(acme_domain.get(), acme_email.get())
293
- .catch(e => {
294
- acmeLog("error renewing cert:", e.toString())
295
- })
296
-}
273
+ .catch(e => acmeLog("error: ", e.toString()))
274
+}, 0, { retain: DAY, retainFailure: HOUR })
275
276
export default apis
\ No newline at end of file