217 lines
5.3 KiB
Markdown
217 lines
5.3 KiB
Markdown
|
# Certificate Management in SmartProxy v18+
|
||
|
|
||
|
## Overview
|
||
|
|
||
|
SmartProxy v18+ introduces a simplified certificate management system using the new `SmartCertManager` class. This replaces the previous `Port80Handler` and multiple certificate-related modules with a unified, route-based approach.
|
||
|
|
||
|
## Key Changes from Previous Versions
|
||
|
|
||
|
- **No backward compatibility**: This is a clean break from the legacy certificate system
|
||
|
- **No separate Port80Handler**: ACME challenges are now handled as regular SmartProxy routes
|
||
|
- **Unified route-based configuration**: Certificates are configured directly in route definitions
|
||
|
- **Direct integration with @push.rocks/smartacme**: Leverages SmartAcme's built-in capabilities
|
||
|
|
||
|
## Configuration
|
||
|
|
||
|
### Route-Level Certificate Configuration
|
||
|
|
||
|
Certificates are now configured at the route level using the `tls` property:
|
||
|
|
||
|
```typescript
|
||
|
const route: IRouteConfig = {
|
||
|
name: 'secure-website',
|
||
|
match: {
|
||
|
ports: 443,
|
||
|
domains: ['example.com', 'www.example.com']
|
||
|
},
|
||
|
action: {
|
||
|
type: 'forward',
|
||
|
target: { host: 'localhost', port: 8080 },
|
||
|
tls: {
|
||
|
mode: 'terminate',
|
||
|
certificate: 'auto', // Use ACME (Let's Encrypt)
|
||
|
acme: {
|
||
|
email: 'admin@example.com',
|
||
|
useProduction: true,
|
||
|
renewBeforeDays: 30
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
```
|
||
|
|
||
|
### Static Certificate Configuration
|
||
|
|
||
|
For manually managed certificates:
|
||
|
|
||
|
```typescript
|
||
|
const route: IRouteConfig = {
|
||
|
name: 'api-endpoint',
|
||
|
match: {
|
||
|
ports: 443,
|
||
|
domains: 'api.example.com'
|
||
|
},
|
||
|
action: {
|
||
|
type: 'forward',
|
||
|
target: { host: 'localhost', port: 9000 },
|
||
|
tls: {
|
||
|
mode: 'terminate',
|
||
|
certificate: {
|
||
|
certFile: './certs/api.crt',
|
||
|
keyFile: './certs/api.key',
|
||
|
ca: '...' // Optional CA chain
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
```
|
||
|
|
||
|
## TLS Modes
|
||
|
|
||
|
SmartProxy supports three TLS modes:
|
||
|
|
||
|
1. **terminate**: Decrypt TLS at the proxy and forward plain HTTP
|
||
|
2. **passthrough**: Pass encrypted TLS traffic directly to the backend
|
||
|
3. **terminate-and-reencrypt**: Decrypt at proxy, then re-encrypt to backend
|
||
|
|
||
|
## Certificate Storage
|
||
|
|
||
|
Certificates are stored in the `./certs` directory by default:
|
||
|
|
||
|
```
|
||
|
./certs/
|
||
|
├── route-name/
|
||
|
│ ├── cert.pem
|
||
|
│ ├── key.pem
|
||
|
│ ├── ca.pem (if available)
|
||
|
│ └── meta.json
|
||
|
```
|
||
|
|
||
|
## ACME Integration
|
||
|
|
||
|
### How It Works
|
||
|
|
||
|
1. SmartProxy creates a high-priority route for ACME challenges
|
||
|
2. When ACME server makes requests to `/.well-known/acme-challenge/*`, SmartProxy handles them automatically
|
||
|
3. Certificates are obtained and stored locally
|
||
|
4. Automatic renewal checks every 12 hours
|
||
|
|
||
|
### Configuration Options
|
||
|
|
||
|
```typescript
|
||
|
export interface IRouteAcme {
|
||
|
email: string; // Contact email for ACME account
|
||
|
useProduction?: boolean; // Use production servers (default: false)
|
||
|
challengePort?: number; // Port for HTTP-01 challenges (default: 80)
|
||
|
renewBeforeDays?: number; // Days before expiry to renew (default: 30)
|
||
|
}
|
||
|
```
|
||
|
|
||
|
## Advanced Usage
|
||
|
|
||
|
### Manual Certificate Operations
|
||
|
|
||
|
```typescript
|
||
|
// Get certificate status
|
||
|
const status = proxy.getCertificateStatus('route-name');
|
||
|
console.log(status);
|
||
|
// {
|
||
|
// domain: 'example.com',
|
||
|
// status: 'valid',
|
||
|
// source: 'acme',
|
||
|
// expiryDate: Date,
|
||
|
// issueDate: Date
|
||
|
// }
|
||
|
|
||
|
// Force certificate renewal
|
||
|
await proxy.renewCertificate('route-name');
|
||
|
|
||
|
// Manually provision a certificate
|
||
|
await proxy.provisionCertificate('route-name');
|
||
|
```
|
||
|
|
||
|
### Events
|
||
|
|
||
|
SmartProxy emits certificate-related events:
|
||
|
|
||
|
```typescript
|
||
|
proxy.on('certificate:issued', (event) => {
|
||
|
console.log(`New certificate for ${event.domain}`);
|
||
|
});
|
||
|
|
||
|
proxy.on('certificate:renewed', (event) => {
|
||
|
console.log(`Certificate renewed for ${event.domain}`);
|
||
|
});
|
||
|
|
||
|
proxy.on('certificate:expiring', (event) => {
|
||
|
console.log(`Certificate expiring soon for ${event.domain}`);
|
||
|
});
|
||
|
```
|
||
|
|
||
|
## Migration from Previous Versions
|
||
|
|
||
|
### Before (v17 and earlier)
|
||
|
|
||
|
```typescript
|
||
|
// Old approach with Port80Handler
|
||
|
const smartproxy = new SmartProxy({
|
||
|
port: 443,
|
||
|
acme: {
|
||
|
enabled: true,
|
||
|
accountEmail: 'admin@example.com',
|
||
|
// ... other ACME options
|
||
|
}
|
||
|
});
|
||
|
|
||
|
// Certificate provisioning was automatic or via certProvisionFunction
|
||
|
```
|
||
|
|
||
|
### After (v18+)
|
||
|
|
||
|
```typescript
|
||
|
// New approach with route-based configuration
|
||
|
const smartproxy = new SmartProxy({
|
||
|
routes: [{
|
||
|
match: { ports: 443, domains: 'example.com' },
|
||
|
action: {
|
||
|
type: 'forward',
|
||
|
target: { host: 'localhost', port: 8080 },
|
||
|
tls: {
|
||
|
mode: 'terminate',
|
||
|
certificate: 'auto',
|
||
|
acme: {
|
||
|
email: 'admin@example.com',
|
||
|
useProduction: true
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}]
|
||
|
});
|
||
|
```
|
||
|
|
||
|
## Troubleshooting
|
||
|
|
||
|
### Common Issues
|
||
|
|
||
|
1. **Certificate not provisioning**: Ensure port 80 is accessible for ACME challenges
|
||
|
2. **ACME rate limits**: Use staging environment for testing
|
||
|
3. **Permission errors**: Ensure the certificate directory is writable
|
||
|
|
||
|
### Debug Mode
|
||
|
|
||
|
Enable detailed logging to troubleshoot certificate issues:
|
||
|
|
||
|
```typescript
|
||
|
const proxy = new SmartProxy({
|
||
|
enableDetailedLogging: true,
|
||
|
// ... other options
|
||
|
});
|
||
|
```
|
||
|
|
||
|
## Best Practices
|
||
|
|
||
|
1. **Always test with staging ACME servers first**
|
||
|
2. **Set up monitoring for certificate expiration**
|
||
|
3. **Use meaningful route names for easier certificate management**
|
||
|
4. **Store static certificates securely with appropriate permissions**
|
||
|
5. **Implement certificate status monitoring in production**
|