smartproxy/docs/certificate-management.md

5.3 KiB

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:

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:

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

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

// 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:

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)

// 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+)

// 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:

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