@push.rocks/smartproxy 18.2.0 → 19.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/dist_ts/00_commitinfo_data.js +1 -1
  2. package/dist_ts/common/eventUtils.d.ts +1 -2
  3. package/dist_ts/common/eventUtils.js +2 -1
  4. package/dist_ts/core/models/common-types.d.ts +1 -1
  5. package/dist_ts/core/models/common-types.js +1 -1
  6. package/dist_ts/core/utils/event-utils.d.ts +9 -9
  7. package/dist_ts/core/utils/event-utils.js +6 -14
  8. package/dist_ts/http/models/http-types.d.ts +13 -1
  9. package/dist_ts/http/models/http-types.js +1 -1
  10. package/dist_ts/index.d.ts +4 -6
  11. package/dist_ts/index.js +4 -10
  12. package/dist_ts/proxies/index.d.ts +3 -2
  13. package/dist_ts/proxies/index.js +4 -5
  14. package/dist_ts/proxies/network-proxy/certificate-manager.d.ts +31 -49
  15. package/dist_ts/proxies/network-proxy/certificate-manager.js +77 -374
  16. package/dist_ts/proxies/network-proxy/models/types.d.ts +12 -1
  17. package/dist_ts/proxies/network-proxy/models/types.js +1 -1
  18. package/dist_ts/proxies/network-proxy/network-proxy.d.ts +2 -7
  19. package/dist_ts/proxies/network-proxy/network-proxy.js +10 -19
  20. package/dist_ts/proxies/smart-proxy/models/index.d.ts +1 -1
  21. package/dist_ts/proxies/smart-proxy/models/index.js +1 -5
  22. package/dist_ts/proxies/smart-proxy/models/interfaces.d.ts +13 -1
  23. package/dist_ts/proxies/smart-proxy/smart-proxy.js +2 -3
  24. package/package.json +1 -1
  25. package/readme.md +13 -5
  26. package/readme.plan.md +37 -20
  27. package/ts/00_commitinfo_data.ts +1 -1
  28. package/ts/common/eventUtils.ts +2 -2
  29. package/ts/core/models/common-types.ts +1 -1
  30. package/ts/core/utils/event-utils.ts +12 -21
  31. package/ts/http/models/http-types.ts +8 -4
  32. package/ts/index.ts +11 -14
  33. package/ts/proxies/index.ts +7 -4
  34. package/ts/proxies/network-proxy/certificate-manager.ts +92 -417
  35. package/ts/proxies/network-proxy/models/types.ts +14 -2
  36. package/ts/proxies/network-proxy/network-proxy.ts +10 -19
  37. package/ts/proxies/smart-proxy/models/index.ts +2 -1
  38. package/ts/proxies/smart-proxy/models/interfaces.ts +14 -1
  39. package/ts/proxies/smart-proxy/models/route-types.ts +1 -1
  40. package/ts/proxies/smart-proxy/smart-proxy.ts +1 -2
  41. package/ts/certificate/acme/acme-factory.ts +0 -48
  42. package/ts/certificate/acme/challenge-handler.ts +0 -110
  43. package/ts/certificate/acme/index.ts +0 -3
  44. package/ts/certificate/events/certificate-events.ts +0 -36
  45. package/ts/certificate/index.ts +0 -75
  46. package/ts/certificate/models/certificate-types.ts +0 -109
  47. package/ts/certificate/providers/cert-provisioner.ts +0 -519
  48. package/ts/certificate/providers/index.ts +0 -3
  49. package/ts/certificate/storage/file-storage.ts +0 -234
  50. package/ts/certificate/storage/index.ts +0 -3
  51. package/ts/certificate/utils/certificate-helpers.ts +0 -50
  52. package/ts/http/port80/acme-interfaces.ts +0 -169
  53. package/ts/http/port80/challenge-responder.ts +0 -246
  54. package/ts/http/port80/index.ts +0 -13
  55. package/ts/http/port80/port80-handler.ts +0 -728
@@ -1,5 +1,17 @@
1
1
  import * as plugins from '../../../plugins.js';
2
- import type { IAcmeOptions } from '../../../certificate/models/certificate-types.js';
2
+ // Certificate types removed - define IAcmeOptions locally
3
+ export interface IAcmeOptions {
4
+ enabled: boolean;
5
+ email?: string;
6
+ accountEmail?: string;
7
+ port?: number;
8
+ certificateStore?: string;
9
+ environment?: 'production' | 'staging';
10
+ useProduction?: boolean;
11
+ renewThresholdDays?: number;
12
+ autoRenew?: boolean;
13
+ skipConfiguredCerts?: boolean;
14
+ }
3
15
  import type { IRouteConfig } from '../../smart-proxy/models/route-types.js';
4
16
  import type { IRouteContext } from '../../../core/models/route-context.js';
5
17
 
@@ -22,7 +34,7 @@ export interface INetworkProxyOptions {
22
34
  // Settings for SmartProxy integration
23
35
  connectionPoolSize?: number; // Maximum connections to maintain in the pool to each backend
24
36
  portProxyIntegration?: boolean; // Flag to indicate this proxy is used by SmartProxy
25
- useExternalPort80Handler?: boolean; // Flag to indicate using external Port80Handler
37
+ useExternalPort80Handler?: boolean; // @deprecated - use SmartCertManager instead
26
38
  // Protocol to use when proxying to backends: HTTP/1.x or HTTP/2
27
39
  backendProtocol?: 'http1' | 'http2';
28
40
 
@@ -18,7 +18,6 @@ import { RequestHandler, type IMetricsTracker } from './request-handler.js';
18
18
  import { WebSocketHandler } from './websocket-handler.js';
19
19
  import { ProxyRouter } from '../../http/router/index.js';
20
20
  import { RouteRouter } from '../../http/router/route-router.js';
21
- import { Port80Handler } from '../../http/port80/port80-handler.js';
22
21
  import { FunctionCache } from './function-cache.js';
23
22
 
24
23
  /**
@@ -221,15 +220,10 @@ export class NetworkProxy implements IMetricsTracker {
221
220
  }
222
221
 
223
222
  /**
224
- * Sets an external Port80Handler for certificate management
225
- * This allows the NetworkProxy to use a centrally managed Port80Handler
226
- * instead of creating its own
227
- *
228
- * @param handler The Port80Handler instance to use
223
+ * @deprecated Use SmartCertManager instead
229
224
  */
230
- public setExternalPort80Handler(handler: Port80Handler): void {
231
- // Connect it to the certificate manager
232
- this.certificateManager.setExternalPort80Handler(handler);
225
+ public setExternalPort80Handler(handler: any): void {
226
+ this.logger.warn('Port80Handler is deprecated - use SmartCertManager instead');
233
227
  }
234
228
 
235
229
  /**
@@ -238,10 +232,7 @@ export class NetworkProxy implements IMetricsTracker {
238
232
  public async start(): Promise<void> {
239
233
  this.startTime = Date.now();
240
234
 
241
- // Initialize Port80Handler if enabled and not using external handler
242
- if (this.options.acme?.enabled && !this.options.useExternalPort80Handler) {
243
- await this.certificateManager.initializePort80Handler();
244
- }
235
+ // Certificate management is now handled by SmartCertManager
245
236
 
246
237
  // Create HTTP/2 server with HTTP/1 fallback
247
238
  this.httpsServer = plugins.http2.createSecureServer(
@@ -385,7 +376,7 @@ export class NetworkProxy implements IMetricsTracker {
385
376
 
386
377
  // Directly update the certificate manager with the new routes
387
378
  // This will extract domains and handle certificate provisioning
388
- this.certificateManager.updateRouteConfigs(routes);
379
+ this.certificateManager.updateRoutes(routes);
389
380
 
390
381
  // Collect all domains and certificates for configuration
391
382
  const currentHostnames = new Set<string>();
@@ -425,7 +416,7 @@ export class NetworkProxy implements IMetricsTracker {
425
416
  // Update certificate cache with any static certificates
426
417
  for (const [domain, certData] of certificateUpdates.entries()) {
427
418
  try {
428
- this.certificateManager.updateCertificateCache(
419
+ this.certificateManager.updateCertificate(
429
420
  domain,
430
421
  certData.cert,
431
422
  certData.key
@@ -547,8 +538,7 @@ export class NetworkProxy implements IMetricsTracker {
547
538
  // Close all connection pool connections
548
539
  this.connectionPool.closeAllConnections();
549
540
 
550
- // Stop Port80Handler if internally managed
551
- await this.certificateManager.stopPort80Handler();
541
+ // Certificate management cleanup is handled by SmartCertManager
552
542
 
553
543
  // Close the HTTPS server
554
544
  return new Promise((resolve) => {
@@ -566,7 +556,8 @@ export class NetworkProxy implements IMetricsTracker {
566
556
  * @returns A promise that resolves when the request is submitted (not when the certificate is issued)
567
557
  */
568
558
  public async requestCertificate(domain: string): Promise<boolean> {
569
- return this.certificateManager.requestCertificate(domain);
559
+ this.logger.warn('requestCertificate is deprecated - use SmartCertManager instead');
560
+ return false;
570
561
  }
571
562
 
572
563
  /**
@@ -587,7 +578,7 @@ export class NetworkProxy implements IMetricsTracker {
587
578
  expiryDate?: Date
588
579
  ): void {
589
580
  this.logger.info(`Updating certificate for ${domain}`);
590
- this.certificateManager.updateCertificateCache(domain, certificate, privateKey, expiryDate);
581
+ this.certificateManager.updateCertificate(domain, certificate, privateKey);
591
582
  }
592
583
 
593
584
  /**
@@ -1,5 +1,6 @@
1
1
  /**
2
2
  * SmartProxy models
3
3
  */
4
- export * from './interfaces.js';
4
+ // Export everything except IAcmeOptions from interfaces
5
+ export type { ISmartProxyOptions, IConnectionRecord, TSmartProxyCertProvisionObject } from './interfaces.js';
5
6
  export * from './route-types.js';
@@ -1,5 +1,18 @@
1
1
  import * as plugins from '../../../plugins.js';
2
- import type { IAcmeOptions } from '../../../certificate/models/certificate-types.js';
2
+ // Certificate types removed - define IAcmeOptions locally
3
+ export interface IAcmeOptions {
4
+ enabled?: boolean;
5
+ email?: string;
6
+ environment?: 'production' | 'staging';
7
+ port?: number;
8
+ useProduction?: boolean;
9
+ renewThresholdDays?: number;
10
+ autoRenew?: boolean;
11
+ certificateStore?: string;
12
+ skipConfiguredCerts?: boolean;
13
+ renewCheckIntervalHours?: number;
14
+ routeForwards?: any[];
15
+ }
3
16
  import type { IRouteConfig } from './route-types.js';
4
17
  import type { TForwardingType } from '../../../forwarding/config/forwarding-types.js';
5
18
 
@@ -1,5 +1,5 @@
1
1
  import * as plugins from '../../../plugins.js';
2
- import type { IAcmeOptions } from '../../../certificate/models/certificate-types.js';
2
+ // Certificate types removed - use local definition
3
3
  import type { TForwardingType } from '../../../forwarding/config/forwarding-types.js';
4
4
  import type { PortRange } from '../../../proxies/nftables-proxy/models/interfaces.js';
5
5
 
@@ -121,13 +121,12 @@ export class SmartProxy extends plugins.EventEmitter {
121
121
  this.settings.acme = {
122
122
  enabled: false,
123
123
  port: 80,
124
- accountEmail: 'admin@example.com',
124
+ email: 'admin@example.com',
125
125
  useProduction: false,
126
126
  renewThresholdDays: 30,
127
127
  autoRenew: true,
128
128
  certificateStore: './certs',
129
129
  skipConfiguredCerts: false,
130
- httpsRedirectPort: 443,
131
130
  renewCheckIntervalHours: 24,
132
131
  routeForwards: []
133
132
  };
@@ -1,48 +0,0 @@
1
- import * as fs from 'fs';
2
- import * as path from 'path';
3
- import type { IAcmeOptions } from '../models/certificate-types.js';
4
- import { ensureCertificateDirectory } from '../utils/certificate-helpers.js';
5
- // We'll need to update this import when we move the Port80Handler
6
- import { Port80Handler } from '../../http/port80/port80-handler.js';
7
-
8
- /**
9
- * Factory to create a Port80Handler with common setup.
10
- * Ensures the certificate store directory exists and instantiates the handler.
11
- * @param options Port80Handler configuration options
12
- * @returns A new Port80Handler instance
13
- */
14
- export function buildPort80Handler(
15
- options: IAcmeOptions
16
- ): Port80Handler {
17
- if (options.certificateStore) {
18
- ensureCertificateDirectory(options.certificateStore);
19
- console.log(`Ensured certificate store directory: ${options.certificateStore}`);
20
- }
21
- return new Port80Handler(options);
22
- }
23
-
24
- /**
25
- * Creates default ACME options with sensible defaults
26
- * @param email Account email for ACME provider
27
- * @param certificateStore Path to store certificates
28
- * @param useProduction Whether to use production ACME servers
29
- * @returns Configured ACME options
30
- */
31
- export function createDefaultAcmeOptions(
32
- email: string,
33
- certificateStore: string,
34
- useProduction: boolean = false
35
- ): IAcmeOptions {
36
- return {
37
- accountEmail: email,
38
- enabled: true,
39
- port: 80,
40
- useProduction,
41
- httpsRedirectPort: 443,
42
- renewThresholdDays: 30,
43
- renewCheckIntervalHours: 24,
44
- autoRenew: true,
45
- certificateStore,
46
- skipConfiguredCerts: false
47
- };
48
- }
@@ -1,110 +0,0 @@
1
- import * as plugins from '../../plugins.js';
2
- import type { IAcmeOptions, ICertificateData } from '../models/certificate-types.js';
3
- import { CertificateEvents } from '../events/certificate-events.js';
4
-
5
- /**
6
- * Manages ACME challenges and certificate validation
7
- */
8
- export class AcmeChallengeHandler extends plugins.EventEmitter {
9
- private options: IAcmeOptions;
10
- private client: any; // ACME client from plugins
11
- private pendingChallenges: Map<string, any>;
12
-
13
- /**
14
- * Creates a new ACME challenge handler
15
- * @param options ACME configuration options
16
- */
17
- constructor(options: IAcmeOptions) {
18
- super();
19
- this.options = options;
20
- this.pendingChallenges = new Map();
21
-
22
- // Initialize ACME client if needed
23
- // This is just a placeholder implementation since we don't use the actual
24
- // client directly in this implementation - it's handled by Port80Handler
25
- this.client = null;
26
- console.log('Created challenge handler with options:',
27
- options.accountEmail,
28
- options.useProduction ? 'production' : 'staging'
29
- );
30
- }
31
-
32
- /**
33
- * Gets or creates the ACME account key
34
- */
35
- private getAccountKey(): Buffer {
36
- // Implementation details would depend on plugin requirements
37
- // This is a simplified version
38
- if (!this.options.certificateStore) {
39
- throw new Error('Certificate store is required for ACME challenges');
40
- }
41
-
42
- // This is just a placeholder - actual implementation would check for
43
- // existing account key and create one if needed
44
- return Buffer.from('account-key-placeholder');
45
- }
46
-
47
- /**
48
- * Validates a domain using HTTP-01 challenge
49
- * @param domain Domain to validate
50
- * @param challengeToken ACME challenge token
51
- * @param keyAuthorization Key authorization for the challenge
52
- */
53
- public async handleHttpChallenge(
54
- domain: string,
55
- challengeToken: string,
56
- keyAuthorization: string
57
- ): Promise<void> {
58
- // Store challenge for response
59
- this.pendingChallenges.set(challengeToken, keyAuthorization);
60
-
61
- try {
62
- // Wait for challenge validation - this would normally be handled by the ACME client
63
- await new Promise(resolve => setTimeout(resolve, 1000));
64
- this.emit(CertificateEvents.CERTIFICATE_ISSUED, {
65
- domain,
66
- success: true
67
- });
68
- } catch (error) {
69
- this.emit(CertificateEvents.CERTIFICATE_FAILED, {
70
- domain,
71
- error: error instanceof Error ? error.message : String(error),
72
- isRenewal: false
73
- });
74
- throw error;
75
- } finally {
76
- // Clean up the challenge
77
- this.pendingChallenges.delete(challengeToken);
78
- }
79
- }
80
-
81
- /**
82
- * Responds to an HTTP-01 challenge request
83
- * @param token Challenge token from the request path
84
- * @returns The key authorization if found
85
- */
86
- public getChallengeResponse(token: string): string | null {
87
- return this.pendingChallenges.get(token) || null;
88
- }
89
-
90
- /**
91
- * Checks if a request path is an ACME challenge
92
- * @param path Request path
93
- * @returns True if this is an ACME challenge request
94
- */
95
- public isAcmeChallenge(path: string): boolean {
96
- return path.startsWith('/.well-known/acme-challenge/');
97
- }
98
-
99
- /**
100
- * Extracts the challenge token from an ACME challenge path
101
- * @param path Request path
102
- * @returns The challenge token if valid
103
- */
104
- public extractChallengeToken(path: string): string | null {
105
- if (!this.isAcmeChallenge(path)) return null;
106
-
107
- const parts = path.split('/');
108
- return parts[parts.length - 1] || null;
109
- }
110
- }
@@ -1,3 +0,0 @@
1
- /**
2
- * ACME certificate provisioning
3
- */
@@ -1,36 +0,0 @@
1
- /**
2
- * Certificate-related events emitted by certificate management components
3
- */
4
- export enum CertificateEvents {
5
- CERTIFICATE_ISSUED = 'certificate-issued',
6
- CERTIFICATE_RENEWED = 'certificate-renewed',
7
- CERTIFICATE_FAILED = 'certificate-failed',
8
- CERTIFICATE_EXPIRING = 'certificate-expiring',
9
- CERTIFICATE_APPLIED = 'certificate-applied',
10
- // Events moved from Port80Handler for compatibility
11
- MANAGER_STARTED = 'manager-started',
12
- MANAGER_STOPPED = 'manager-stopped',
13
- }
14
-
15
- /**
16
- * Port80Handler-specific events including certificate-related ones
17
- * @deprecated Use CertificateEvents and HttpEvents instead
18
- */
19
- export enum Port80HandlerEvents {
20
- CERTIFICATE_ISSUED = 'certificate-issued',
21
- CERTIFICATE_RENEWED = 'certificate-renewed',
22
- CERTIFICATE_FAILED = 'certificate-failed',
23
- CERTIFICATE_EXPIRING = 'certificate-expiring',
24
- MANAGER_STARTED = 'manager-started',
25
- MANAGER_STOPPED = 'manager-stopped',
26
- REQUEST_FORWARDED = 'request-forwarded',
27
- }
28
-
29
- /**
30
- * Certificate provider events
31
- */
32
- export enum CertProvisionerEvents {
33
- CERTIFICATE_ISSUED = 'certificate',
34
- CERTIFICATE_RENEWED = 'certificate',
35
- CERTIFICATE_FAILED = 'certificate-failed'
36
- }
@@ -1,75 +0,0 @@
1
- /**
2
- * Certificate management module for SmartProxy
3
- * Provides certificate provisioning, storage, and management capabilities
4
- */
5
-
6
- // Certificate types and models
7
- export * from './models/certificate-types.js';
8
-
9
- // Certificate events
10
- export * from './events/certificate-events.js';
11
-
12
- // Certificate providers
13
- export * from './providers/cert-provisioner.js';
14
-
15
- // ACME related exports
16
- export * from './acme/acme-factory.js';
17
- export * from './acme/challenge-handler.js';
18
-
19
- // Certificate utilities
20
- export * from './utils/certificate-helpers.js';
21
-
22
- // Certificate storage
23
- export * from './storage/file-storage.js';
24
-
25
- // Convenience function to create a certificate provisioner with common settings
26
- import { CertProvisioner } from './providers/cert-provisioner.js';
27
- import type { TCertProvisionObject } from './providers/cert-provisioner.js';
28
- import { buildPort80Handler } from './acme/acme-factory.js';
29
- import type { IAcmeOptions, IRouteForwardConfig } from './models/certificate-types.js';
30
- import type { IRouteConfig } from '../proxies/smart-proxy/models/route-types.js';
31
-
32
- /**
33
- * Interface for NetworkProxyBridge used by CertProvisioner
34
- */
35
- interface ICertNetworkProxyBridge {
36
- applyExternalCertificate(certData: any): void;
37
- }
38
-
39
- /**
40
- * Creates a complete certificate provisioning system with default settings
41
- * @param routeConfigs Route configurations that may need certificates
42
- * @param acmeOptions ACME options for certificate provisioning
43
- * @param networkProxyBridge Bridge to apply certificates to network proxy
44
- * @param certProvider Optional custom certificate provider
45
- * @returns Configured CertProvisioner
46
- */
47
- export function createCertificateProvisioner(
48
- routeConfigs: IRouteConfig[],
49
- acmeOptions: IAcmeOptions,
50
- networkProxyBridge: ICertNetworkProxyBridge,
51
- certProvider?: (domain: string) => Promise<TCertProvisionObject>
52
- ): CertProvisioner {
53
- // Build the Port80Handler for ACME challenges
54
- const port80Handler = buildPort80Handler(acmeOptions);
55
-
56
- // Extract ACME-specific configuration
57
- const {
58
- renewThresholdDays = 30,
59
- renewCheckIntervalHours = 24,
60
- autoRenew = true,
61
- routeForwards = []
62
- } = acmeOptions;
63
-
64
- // Create and return the certificate provisioner
65
- return new CertProvisioner(
66
- routeConfigs,
67
- port80Handler,
68
- networkProxyBridge,
69
- certProvider,
70
- renewThresholdDays,
71
- renewCheckIntervalHours,
72
- autoRenew,
73
- routeForwards
74
- );
75
- }
@@ -1,109 +0,0 @@
1
- import * as plugins from '../../plugins.js';
2
- import type { IRouteConfig } from '../../proxies/smart-proxy/models/route-types.js';
3
-
4
- /**
5
- * Certificate data structure containing all necessary information
6
- * about a certificate
7
- */
8
- export interface ICertificateData {
9
- domain: string;
10
- certificate: string;
11
- privateKey: string;
12
- expiryDate: Date;
13
- // Optional source and renewal information for event emissions
14
- source?: 'static' | 'http01' | 'dns01';
15
- isRenewal?: boolean;
16
- // Reference to the route that requested this certificate (if available)
17
- routeReference?: {
18
- routeId?: string;
19
- routeName?: string;
20
- };
21
- }
22
-
23
- /**
24
- * Certificates pair (private and public keys)
25
- */
26
- export interface ICertificates {
27
- privateKey: string;
28
- publicKey: string;
29
- }
30
-
31
- /**
32
- * Certificate failure payload type
33
- */
34
- export interface ICertificateFailure {
35
- domain: string;
36
- error: string;
37
- isRenewal: boolean;
38
- routeReference?: {
39
- routeId?: string;
40
- routeName?: string;
41
- };
42
- }
43
-
44
- /**
45
- * Certificate expiry payload type
46
- */
47
- export interface ICertificateExpiring {
48
- domain: string;
49
- expiryDate: Date;
50
- daysRemaining: number;
51
- routeReference?: {
52
- routeId?: string;
53
- routeName?: string;
54
- };
55
- }
56
-
57
- /**
58
- * Route-specific forwarding configuration for ACME challenges
59
- */
60
- export interface IRouteForwardConfig {
61
- domain: string;
62
- target: {
63
- host: string;
64
- port: number;
65
- };
66
- sslRedirect?: boolean;
67
- }
68
-
69
- /**
70
- * Domain configuration options for Port80Handler
71
- *
72
- * This is used internally by the Port80Handler to manage domains
73
- * but will eventually be replaced with route-based options.
74
- */
75
- export interface IDomainOptions {
76
- domainName: string;
77
- sslRedirect: boolean; // if true redirects the request to port 443
78
- acmeMaintenance: boolean; // tries to always have a valid cert for this domain
79
- forward?: {
80
- ip: string;
81
- port: number;
82
- }; // forwards all http requests to that target
83
- acmeForward?: {
84
- ip: string;
85
- port: number;
86
- }; // forwards letsencrypt requests to this config
87
- routeReference?: {
88
- routeId?: string;
89
- routeName?: string;
90
- };
91
- }
92
-
93
- /**
94
- * Unified ACME configuration options used across proxies and handlers
95
- */
96
- export interface IAcmeOptions {
97
- accountEmail?: string; // Email for Let's Encrypt account
98
- enabled?: boolean; // Whether ACME is enabled
99
- port?: number; // Port to listen on for ACME challenges (default: 80)
100
- useProduction?: boolean; // Use production environment (default: staging)
101
- httpsRedirectPort?: number; // Port to redirect HTTP requests to HTTPS (default: 443)
102
- renewThresholdDays?: number; // Days before expiry to renew certificates
103
- renewCheckIntervalHours?: number; // How often to check for renewals (in hours)
104
- autoRenew?: boolean; // Whether to automatically renew certificates
105
- certificateStore?: string; // Directory to store certificates
106
- skipConfiguredCerts?: boolean; // Skip domains with existing certificates
107
- routeForwards?: IRouteForwardConfig[]; // Route-specific forwarding configs
108
- }
109
-