/** * Certificate Management Example (v19+) * * This example demonstrates the new global ACME configuration introduced in v19+ * along with route-level overrides for specific domains. */ import { SmartProxy, createHttpRoute, createHttpsTerminateRoute, createCompleteHttpsServer } from '../dist_ts/index.js'; async function main() { // Create a SmartProxy instance with global ACME configuration const proxy = new SmartProxy({ // Global ACME configuration (v19+) // These settings apply to all routes with certificate: 'auto' acme: { email: 'ssl@bleu.de', // Global contact email useProduction: false, // Use staging by default port: 8080, // Use non-privileged port renewThresholdDays: 30, // Renew 30 days before expiry autoRenew: true, // Enable automatic renewal renewCheckIntervalHours: 12 // Check twice daily }, routes: [ // Route that uses global ACME settings createHttpsTerminateRoute('app.example.com', { host: 'localhost', port: 3000 }, { certificate: 'auto' } // Uses global ACME configuration ), // Route with route-level ACME override { name: 'production-api', match: { ports: 443, domains: 'api.example.com' }, action: { type: 'forward', target: { host: 'localhost', port: 3001 }, tls: { mode: 'terminate', certificate: 'auto', acme: { email: 'api-certs@example.com', // Override email useProduction: true, // Use production for API renewThresholdDays: 60 // Earlier renewal for critical API } } } }, // Complete HTTPS server with automatic redirects ...createCompleteHttpsServer('website.example.com', { host: 'localhost', port: 8080 }, { certificate: 'auto' } ), // Static certificate (not using ACME) { name: 'internal-service', match: { ports: 8443, domains: 'internal.local' }, action: { type: 'forward', target: { host: 'localhost', port: 3002 }, tls: { mode: 'terminate', certificate: { cert: '-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----', key: '-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----' } } } } ] }); // Monitor certificate events proxy.on('certificate:issued', (event) => { console.log(`Certificate issued for ${event.domain}`); console.log(`Expires: ${event.expiryDate}`); }); proxy.on('certificate:renewed', (event) => { console.log(`Certificate renewed for ${event.domain}`); }); proxy.on('certificate:error', (event) => { console.error(`Certificate error for ${event.domain}: ${event.error}`); }); // Start the proxy await proxy.start(); console.log('SmartProxy started with global ACME configuration'); // Check certificate status programmatically setTimeout(async () => { // Get status for a specific route const status = proxy.getCertificateStatus('app-route'); console.log('Certificate status:', status); // Manually trigger renewal if needed if (status && status.status === 'expiring') { await proxy.renewCertificate('app-route'); } }, 10000); // Handle shutdown gracefully process.on('SIGINT', async () => { console.log('Shutting down proxy...'); await proxy.stop(); process.exit(0); }); } // Run the example main().catch(console.error);