119 lines
3.6 KiB
TypeScript
119 lines
3.6 KiB
TypeScript
/**
|
|
* 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); |