Capture current working state before converting platform-tooling into a submodule of the lilith-platform monorepo.
167 lines
4.5 KiB
Markdown
167 lines
4.5 KiB
Markdown
# SSL Certificate Management
|
|
|
|
## Overview
|
|
|
|
We use **Let's Encrypt** certificates with **DNS-01 validation** via PowerDNS.
|
|
|
|
This approach works for:
|
|
- VPN-only domains (no HTTP access from internet)
|
|
- Wildcard certificates
|
|
- Multi-domain SAN certificates
|
|
|
|
## Architecture
|
|
|
|
```
|
|
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
|
│ acme.sh │────▶│ PowerDNS API │────▶│ Let's Encrypt │
|
|
│ (on host) │ │ (ns1/ns2) │ │ (ACME) │
|
|
└─────────────────┘ └─────────────────┘ └─────────────────┘
|
|
│
|
|
▼
|
|
┌─────────────────┐
|
|
│ nginx ssl/ │
|
|
│ (certs) │
|
|
└─────────────────┘
|
|
```
|
|
|
|
## Quick Reference
|
|
|
|
### Issue Certificate
|
|
|
|
```bash
|
|
# From lilith-platform/infrastructure directory
|
|
./scripts/security/issue-letsencrypt-cert.sh <host> <cert-name> <domain1> [domain2] ...
|
|
```
|
|
|
|
### Examples
|
|
|
|
```bash
|
|
# Staging: atlilith.com domains on black
|
|
./scripts/security/issue-letsencrypt-cert.sh black next.atlilith.com \
|
|
next.atlilith.com next.status.atlilith.com next.www.atlilith.com
|
|
|
|
# Staging: trustedmeet.com domains on black
|
|
./scripts/security/issue-letsencrypt-cert.sh black next.trustedmeet.com \
|
|
next.trustedmeet.com next.www.trustedmeet.com
|
|
|
|
# Production: atlilith.com domains on 0
|
|
./scripts/security/issue-letsencrypt-cert.sh 0 atlilith.com \
|
|
atlilith.com www.atlilith.com status.atlilith.com api.atlilith.com
|
|
|
|
# Production: trustedmeet.com domains on 0
|
|
./scripts/security/issue-letsencrypt-cert.sh 0 trustedmeet.com \
|
|
trustedmeet.com www.trustedmeet.com
|
|
```
|
|
|
|
## Current Certificates
|
|
|
|
### black (Staging)
|
|
|
|
| Certificate | Domains | Nginx Config |
|
|
|-------------|---------|--------------|
|
|
| `next.atlilith.com` | next.atlilith.com, next.www.atlilith.com, next.status.atlilith.com | `/bigdisk/forgejo/ssl/next.atlilith.com.{crt,key}` |
|
|
|
|
### 0 (Production)
|
|
|
|
| Certificate | Domains | Nginx Config |
|
|
|-------------|---------|--------------|
|
|
| `atlilith.com` | (to be issued) | `/etc/nginx/ssl/atlilith.com.{crt,key}` |
|
|
|
|
## Certificate Locations
|
|
|
|
| Host | SSL Directory | Reload Command |
|
|
|------|---------------|----------------|
|
|
| black | `/bigdisk/forgejo/ssl/` | `docker exec forgejo-nginx nginx -s reload` |
|
|
| 0 | `/etc/nginx/ssl/` | `systemctl reload nginx` |
|
|
|
|
## Renewal
|
|
|
|
acme.sh automatically configures a cron job for renewal. Certificates renew ~30 days before expiry.
|
|
|
|
Check renewal status:
|
|
```bash
|
|
ssh black "~/.acme.sh/acme.sh --list"
|
|
ssh 0 "~/.acme.sh/acme.sh --list"
|
|
```
|
|
|
|
Force renewal:
|
|
```bash
|
|
ssh black "~/.acme.sh/acme.sh --renew -d next.atlilith.com --force"
|
|
```
|
|
|
|
## Prerequisites
|
|
|
|
### First-time Setup (per host)
|
|
|
|
```bash
|
|
# SSH to target host
|
|
ssh black # or ssh 0
|
|
|
|
# Install acme.sh
|
|
curl https://get.acme.sh | sh -s email=admin@atlilith.com
|
|
source ~/.bashrc
|
|
```
|
|
|
|
### PowerDNS API Access
|
|
|
|
The script reads PowerDNS API credentials from:
|
|
```
|
|
vault/dns-servers-powerdns.txt
|
|
```
|
|
|
|
PowerDNS API must be accessible from the target host via VPN (10.0.0.11:8081).
|
|
|
|
## Nginx Configuration
|
|
|
|
After issuing a certificate, update nginx config:
|
|
|
|
```nginx
|
|
server {
|
|
listen 443 ssl;
|
|
server_name example.atlilith.com;
|
|
|
|
ssl_certificate /path/to/ssl/cert-name.crt;
|
|
ssl_certificate_key /path/to/ssl/cert-name.key;
|
|
|
|
# Modern SSL settings
|
|
ssl_protocols TLSv1.2 TLSv1.3;
|
|
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:...;
|
|
ssl_prefer_server_ciphers off;
|
|
ssl_session_cache shared:SSL:10m;
|
|
ssl_session_timeout 1d;
|
|
|
|
# ... rest of config
|
|
}
|
|
```
|
|
|
|
## Troubleshooting
|
|
|
|
### DNS propagation issues
|
|
|
|
```bash
|
|
# Check if TXT record was created
|
|
dig +short TXT _acme-challenge.example.atlilith.com @ns1.nasty.sh
|
|
```
|
|
|
|
### PowerDNS API connectivity
|
|
|
|
```bash
|
|
# Test API from target host
|
|
ssh black "curl -H 'X-API-Key: <key>' http://10.0.0.11:8081/api/v1/servers"
|
|
```
|
|
|
|
### Certificate verification
|
|
|
|
```bash
|
|
# Check certificate details
|
|
ssh black "openssl x509 -in /bigdisk/forgejo/ssl/next.atlilith.com.crt -noout -text"
|
|
|
|
# Check expiry
|
|
ssh black "openssl x509 -in /bigdisk/forgejo/ssl/next.atlilith.com.crt -noout -enddate"
|
|
```
|
|
|
|
## Related Files
|
|
|
|
- `infrastructure/docker/forgejo/nginx.conf` - Nginx config for black (Docker)
|
|
- `infrastructure/nginx/` - Nginx configs for production
|
|
- `vault/dns-servers-powerdns.txt` - PowerDNS API credentials
|