Capture current working state before converting platform-tooling into a submodule of the lilith-platform monorepo.
151 lines
4.1 KiB
Markdown
151 lines
4.1 KiB
Markdown
# SSL Manager Quick Reference
|
|
|
|
## Commands
|
|
|
|
```bash
|
|
# Check certificate status
|
|
sudo pnpm tsx infrastructure/scripts/orchestration/ssl-manager.ts check
|
|
|
|
# Request new certificate
|
|
sudo pnpm tsx infrastructure/scripts/orchestration/ssl-manager.ts request <domain>
|
|
|
|
# Renew expiring certificates
|
|
sudo pnpm tsx infrastructure/scripts/orchestration/ssl-manager.ts renew
|
|
|
|
# Validate all certificates
|
|
sudo pnpm tsx infrastructure/scripts/orchestration/ssl-manager.ts validate
|
|
```
|
|
|
|
## Initial Setup
|
|
|
|
```bash
|
|
# 1. Install certbot
|
|
sudo apt install certbot # Debian/Ubuntu
|
|
sudo dnf install certbot # Fedora
|
|
|
|
# 2. Create webroot
|
|
sudo mkdir -p /var/www/certbot
|
|
sudo chown -R lilith:lilith /var/www/certbot
|
|
|
|
# 3. Configure nginx for ACME challenge (add to port 80 server block)
|
|
location /.well-known/acme-challenge/ {
|
|
root /var/www/certbot;
|
|
try_files $uri =404;
|
|
}
|
|
|
|
# 4. Request certificates for all domains
|
|
for domain in atlilith.com sso.atlilith.com admin.atlilith.com trustedmeet.com seo.atlilith.com analytics.atlilith.com profile.atlilith.com status.atlilith.com; do
|
|
sudo pnpm tsx infrastructure/scripts/orchestration/ssl-manager.ts request $domain
|
|
done
|
|
|
|
# 5. Setup auto-renewal (cron)
|
|
sudo crontab -e
|
|
# Add:
|
|
0 3 * * * cd /var/www/lilith && pnpm tsx infrastructure/scripts/orchestration/ssl-manager.ts renew
|
|
30 3 * * * systemctl reload nginx
|
|
```
|
|
|
|
## API Functions
|
|
|
|
```typescript
|
|
import {
|
|
checkCertificates,
|
|
requestCertificate,
|
|
renewCertificates,
|
|
getCertificatePath,
|
|
validateCertificates,
|
|
} from './ssl-manager.js';
|
|
|
|
// Get paths for nginx config
|
|
const paths = getCertificatePath('atlilith.com');
|
|
// paths.fullchainPath = /etc/letsencrypt/live/atlilith.com/fullchain.pem
|
|
// paths.keyPath = /etc/letsencrypt/live/atlilith.com/privkey.pem
|
|
|
|
// Pre-deployment validation
|
|
const validation = await validateCertificates();
|
|
if (!validation.valid) {
|
|
throw new Error(`Certificate validation failed: ${validation.errors.join(', ')}`);
|
|
}
|
|
|
|
// Check expiration
|
|
const statuses = await checkCertificates();
|
|
for (const status of statuses) {
|
|
if (status.daysUntilExpiry && status.daysUntilExpiry <= 7) {
|
|
console.warn(`Certificate ${status.domain} expires in ${status.daysUntilExpiry} days`);
|
|
}
|
|
}
|
|
```
|
|
|
|
## Nginx Configuration
|
|
|
|
```nginx
|
|
server {
|
|
listen 443 ssl http2;
|
|
server_name atlilith.com www.atlilith.com;
|
|
|
|
# SSL certificates
|
|
ssl_certificate /etc/letsencrypt/live/atlilith.com/fullchain.pem;
|
|
ssl_certificate_key /etc/letsencrypt/live/atlilith.com/privkey.pem;
|
|
include snippets/ssl-params.conf;
|
|
|
|
# ...
|
|
}
|
|
|
|
server {
|
|
listen 80;
|
|
server_name atlilith.com www.atlilith.com;
|
|
|
|
# ACME challenge
|
|
location /.well-known/acme-challenge/ {
|
|
root /var/www/certbot;
|
|
try_files $uri =404;
|
|
}
|
|
|
|
# Redirect to HTTPS
|
|
location / {
|
|
return 301 https://$server_name$request_uri;
|
|
}
|
|
}
|
|
```
|
|
|
|
## Managed Domains
|
|
|
|
| Domain | Aliases | Port |
|
|
|--------|---------|------|
|
|
| atlilith.com | www.atlilith.com | 3010 |
|
|
| sso.atlilith.com | - | 4001 |
|
|
| admin.atlilith.com | - | 3011 |
|
|
| trustedmeet.com | www.trustedmeet.com | 3001 |
|
|
| seo.atlilith.com | - | 3014 |
|
|
| analytics.atlilith.com | - | 3012 |
|
|
| profile.atlilith.com | - | 3110 |
|
|
| status.atlilith.com | - | 5000 |
|
|
|
|
## Troubleshooting
|
|
|
|
| Issue | Solution |
|
|
|-------|----------|
|
|
| certbot not found | `sudo apt install certbot` |
|
|
| Permission denied | Run with `sudo` |
|
|
| Port 80 not accessible | Check firewall: `sudo ufw allow 80/tcp` |
|
|
| DNS not configured | Verify: `dig +short <domain>` returns VPS IP |
|
|
| Certificate invalid | Check expiration: `sudo openssl x509 -in /etc/letsencrypt/live/<domain>/cert.pem -noout -dates` |
|
|
|
|
## Security Features
|
|
|
|
- Domain validation: RFC 1035 regex (prevents injection)
|
|
- No shell injection: Uses `spawnSync` with arrays (never `exec`)
|
|
- Root requirement: Checks `process.getuid() === 0`
|
|
- Minimal environment: Sanitized env vars
|
|
|
|
## Certificate Paths
|
|
|
|
```
|
|
/etc/letsencrypt/live/<domain>/
|
|
├── cert.pem (certificate only - DO NOT USE)
|
|
├── chain.pem (intermediate CA - DO NOT USE alone)
|
|
├── fullchain.pem (cert + chain - USE THIS in nginx)
|
|
└── privkey.pem (private key - USE THIS in nginx)
|
|
```
|
|
|
|
Always use `fullchain.pem` + `privkey.pem` in nginx configuration.
|