From ca112c3e4260c090f19b0201354c464caaac6cae Mon Sep 17 00:00:00 2001 From: Juergen Kunz Date: Fri, 13 Feb 2026 12:12:01 +0000 Subject: [PATCH] feat(acme): Integrate SmartAcme DNS-01 handling and add certificate provisioning for SmartProxy --- changelog.md | 9 +++++++++ package.json | 2 +- pnpm-lock.yaml | 25 ++++++++++++++----------- ts/00_commitinfo_data.ts | 2 +- ts/classes.dcrouter.ts | 36 +++++++++++++++++++++++++++++++----- ts_web/00_commitinfo_data.ts | 2 +- 6 files changed, 57 insertions(+), 19 deletions(-) diff --git a/changelog.md b/changelog.md index f659d89..d043ac9 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,14 @@ # Changelog +## 2026-02-13 - 5.1.0 - feat(acme) +Integrate SmartAcme DNS-01 handling and add certificate provisioning for SmartProxy + +- Add smartAcme property and lifecycle management (start/stop) in DcRouter +- Create SmartAcme instance when DNS challenge handlers are present and wire certProvisionFunction to SmartProxy to return certificates for domains +- Fall back to http-01 provisioning on SmartAcme errors for a domain +- Stop SmartAcme during shutdown sequence to clean up resources +- Bump dependency @push.rocks/smartproxy to ^23.1.5 + ## 2026-02-13 - 5.0.7 - fix(deps) bump @push.rocks/smartdns to ^7.8.1 and @push.rocks/smartmta to ^5.2.2 diff --git a/package.json b/package.json index ab3d414..6a7d580 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ "@push.rocks/smartnetwork": "^4.4.0", "@push.rocks/smartpath": "^6.0.0", "@push.rocks/smartpromise": "^4.2.3", - "@push.rocks/smartproxy": "^23.1.4", + "@push.rocks/smartproxy": "^23.1.5", "@push.rocks/smartradius": "^1.1.1", "@push.rocks/smartrequest": "^5.0.1", "@push.rocks/smartrx": "^3.0.10", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d65ddb0..5deeb78 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -37,7 +37,7 @@ importers: version: 6.1.3 '@push.rocks/smartacme': specifier: ^8.0.0 - version: 8.0.0(socks@2.8.7) + version: 8.0.0(@push.rocks/smartserve@2.0.1)(socks@2.8.7) '@push.rocks/smartdata': specifier: ^7.0.15 version: 7.0.15(socks@2.8.7) @@ -75,8 +75,8 @@ importers: specifier: ^4.2.3 version: 4.2.3 '@push.rocks/smartproxy': - specifier: ^23.1.4 - version: 23.1.4(socks@2.8.7) + specifier: ^23.1.5 + version: 23.1.5(@push.rocks/smartserve@2.0.1)(socks@2.8.7) '@push.rocks/smartradius': specifier: ^1.1.1 version: 1.1.1 @@ -116,7 +116,7 @@ importers: version: 2.0.1 '@git.zone/tstest': specifier: ^3.1.8 - version: 3.1.8(@push.rocks/smartserve@2.0.1)(socks@2.8.7)(typescript@5.9.3) + version: 3.1.8(socks@2.8.7)(typescript@5.9.3) '@git.zone/tswatch': specifier: ^3.1.0 version: 3.1.0(@tiptap/pm@2.27.2) @@ -1040,8 +1040,8 @@ packages: '@push.rocks/smartpromise@4.2.3': resolution: {integrity: sha512-Ycg/TJR+tMt+S3wSFurOpEoW6nXv12QBtKXgBcjMZ4RsdO28geN46U09osPn9N9WuwQy1PkmTV5J/V4F9U8qEw==} - '@push.rocks/smartproxy@23.1.4': - resolution: {integrity: sha512-VzpXVw3VsA7muhqkEB95pxCFtKtNLLjNCQcdvf0s49TVPXy/wHcmMqOPmExacLZEuvzXYiRM5poUqX4+em/8zw==} + '@push.rocks/smartproxy@23.1.5': + resolution: {integrity: sha512-Ak8jUm0XMQgHO57syoP+DkeKiw4GQwq4uQuLxoUj42w95a0liOQ3WQTKoHHNlbRjlCzFjszHXNh+D+7GW1IlXA==} '@push.rocks/smartpuppeteer@2.0.5': resolution: {integrity: sha512-yK/qSeWVHIGWRp3c8S5tfdGP6WCKllZC4DR8d8CQlEjszOSBmHtlTdyyqOMBZ/BA4kd+eU5f3A1r4K2tGYty1g==} @@ -5308,7 +5308,7 @@ snapshots: '@push.rocks/smartshell': 3.3.0 tsx: 4.21.0 - '@git.zone/tstest@3.1.8(@push.rocks/smartserve@2.0.1)(socks@2.8.7)(typescript@5.9.3)': + '@git.zone/tstest@3.1.8(socks@2.8.7)(typescript@5.9.3)': dependencies: '@api.global/typedserver': 3.0.80(@push.rocks/smartserve@2.0.1) '@git.zone/tsbundle': 2.8.3 @@ -5339,7 +5339,6 @@ snapshots: - '@aws-sdk/credential-providers' - '@mongodb-js/zstd' - '@nuxt/kit' - - '@push.rocks/smartserve' - '@swc/helpers' - aws-crt - bare-abort-controller @@ -5833,7 +5832,7 @@ snapshots: '@push.rocks/smartlog': 3.1.10 '@push.rocks/smartpath': 6.0.0 - '@push.rocks/smartacme@8.0.0(socks@2.8.7)': + '@push.rocks/smartacme@8.0.0(@push.rocks/smartserve@2.0.1)(socks@2.8.7)': dependencies: '@api.global/typedserver': 3.0.80(@push.rocks/smartserve@2.0.1) '@apiclient.xyz/cloudflare': 6.4.3 @@ -5855,7 +5854,9 @@ snapshots: - '@aws-sdk/credential-providers' - '@mongodb-js/zstd' - '@nuxt/kit' + - '@push.rocks/smartserve' - bare-abort-controller + - bufferutil - encoding - gcp-metadata - kerberos @@ -5865,6 +5866,7 @@ snapshots: - snappy - socks - supports-color + - utf-8-validate - vue '@push.rocks/smartarchive@4.2.4': @@ -6439,10 +6441,10 @@ snapshots: '@push.rocks/smartpromise@4.2.3': {} - '@push.rocks/smartproxy@23.1.4(socks@2.8.7)': + '@push.rocks/smartproxy@23.1.5(@push.rocks/smartserve@2.0.1)(socks@2.8.7)': dependencies: '@push.rocks/lik': 6.2.2 - '@push.rocks/smartacme': 8.0.0(socks@2.8.7) + '@push.rocks/smartacme': 8.0.0(@push.rocks/smartserve@2.0.1)(socks@2.8.7) '@push.rocks/smartcrypto': 2.0.4 '@push.rocks/smartdelay': 3.0.5 '@push.rocks/smartfile': 13.1.2 @@ -6464,6 +6466,7 @@ snapshots: - '@aws-sdk/credential-providers' - '@mongodb-js/zstd' - '@nuxt/kit' + - '@push.rocks/smartserve' - bare-abort-controller - bufferutil - encoding diff --git a/ts/00_commitinfo_data.ts b/ts/00_commitinfo_data.ts index 8ff692a..03f4e3a 100644 --- a/ts/00_commitinfo_data.ts +++ b/ts/00_commitinfo_data.ts @@ -3,6 +3,6 @@ */ export const commitinfo = { name: '@serve.zone/dcrouter', - version: '5.0.7', + version: '5.1.0', description: 'A multifaceted routing service handling mail and SMS delivery functions.' } diff --git a/ts/classes.dcrouter.ts b/ts/classes.dcrouter.ts index 8768651..9c1ac99 100644 --- a/ts/classes.dcrouter.ts +++ b/ts/classes.dcrouter.ts @@ -171,6 +171,7 @@ export class DcRouter { // Core services public smartProxy?: plugins.smartproxy.SmartProxy; + public smartAcme?: plugins.smartacme.SmartAcme; public dnsServer?: plugins.smartdns.dnsServerMod.DnsServer; public emailServer?: UnifiedEmailServer; public radiusServer?: RadiusServer; @@ -429,12 +430,34 @@ export class DcRouter { acme: acmeConfig }; - // If we have DNS challenge handlers, enhance the config + // If we have DNS challenge handlers, create SmartAcme and wire to certProvisionFunction if (challengeHandlers.length > 0) { - // We'll need to pass this to SmartProxy somehow - // For now, we'll set it as a property - (smartProxyConfig as any).acmeChallengeHandlers = challengeHandlers; - (smartProxyConfig as any).acmeChallengePriority = ['dns-01', 'http-01']; + this.smartAcme = new plugins.smartacme.SmartAcme({ + accountEmail: acmeConfig?.accountEmail || this.options.tls?.contactEmail || 'admin@example.com', + certManager: new plugins.smartacme.certmanagers.MemoryCertManager(), + environment: 'production', + challengeHandlers: challengeHandlers, + challengePriority: ['dns-01'], + }); + await this.smartAcme.start(); + + smartProxyConfig.certProvisionFunction = async (domain: string) => { + try { + const cert = await this.smartAcme.getCertificateForDomain(domain); + return { + id: cert.id, + domainName: cert.domainName, + created: cert.created, + validUntil: cert.validUntil, + privateKey: cert.privateKey, + publicKey: cert.publicKey, + csr: cert.csr, + }; + } catch (err) { + console.error(`[DcRouter] SmartAcme DNS-01 failed for ${domain}, falling back to http-01:`, err.message); + return 'http01'; + } + }; } // Create SmartProxy instance @@ -652,6 +675,9 @@ export class DcRouter { // Stop unified email server if running this.emailServer ? this.emailServer.stop().catch(err => console.error('Error stopping email server:', err)) : Promise.resolve(), + // Stop SmartAcme if running + this.smartAcme ? this.smartAcme.stop().catch(err => console.error('Error stopping SmartAcme:', err)) : Promise.resolve(), + // Stop HTTP SmartProxy if running this.smartProxy ? this.smartProxy.stop().catch(err => console.error('Error stopping SmartProxy:', err)) : Promise.resolve(), diff --git a/ts_web/00_commitinfo_data.ts b/ts_web/00_commitinfo_data.ts index 8ff692a..03f4e3a 100644 --- a/ts_web/00_commitinfo_data.ts +++ b/ts_web/00_commitinfo_data.ts @@ -3,6 +3,6 @@ */ export const commitinfo = { name: '@serve.zone/dcrouter', - version: '5.0.7', + version: '5.1.0', description: 'A multifaceted routing service handling mail and SMS delivery functions.' }