feat: 自动生成JWT_SECRET和ADMIN_PASSWORD并持久化到secrets.json

This commit is contained in:
2026-05-18 16:48:04 +08:00
parent 86d79e550b
commit c57af012b1
3 changed files with 77 additions and 13 deletions

View File

@@ -6,6 +6,8 @@
* Production MUST set COOKIE_ENCRYPTION_KEY!
*/
import * as crypto from 'crypto';
import * as fs from 'fs';
import * as path from 'path';
const ALGORITHM = 'aes-256-gcm';
const IV_LENGTH = 12; // 96-bit nonce for GCM
@@ -25,9 +27,30 @@ function getKey(): Buffer {
ENCRYPTION_KEY = crypto.createHash('sha256').update(envKey).digest();
console.log('[Crypto] Cookie encryption enabled (key from COOKIE_ENCRYPTION_KEY, SHA-256 derived)');
} else {
// Default stable key (not ephemeral) — data survives container restart
ENCRYPTION_KEY = crypto.createHash('sha256').update('cloudsearch-cookie-key-v1').digest();
console.log('[Crypto] Cookie encryption enabled (built-in default key — set COOKIE_ENCRYPTION_KEY in .env for extra security)');
// Auto-generate a random key and persist to file
const keyFile = path.join(process.env.DATA_DIR || '/app/data', 'encryption.key');
try {
if (fs.existsSync(keyFile)) {
const savedKey = fs.readFileSync(keyFile, 'utf8').trim();
if (savedKey.length >= 32) {
ENCRYPTION_KEY = crypto.createHash('sha256').update(savedKey).digest();
console.log('[Crypto] Cookie encryption enabled (loaded from encryption.key)');
return ENCRYPTION_KEY;
}
}
} catch (_) { /* file read failed, will generate new key */ }
const autoKey = crypto.randomBytes(32).toString('hex');
try {
const dir = path.dirname(keyFile);
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
fs.writeFileSync(keyFile, autoKey);
console.log('[Crypto] Auto-generated encryption key saved to encryption.key');
} catch (e: any) {
console.log('[Crypto] Could not persist key, using ephemeral:', e.message);
}
ENCRYPTION_KEY = crypto.createHash('sha256').update(autoKey).digest();
console.log('[Crypto] Cookie encryption enabled (auto-generated key)');
}
return ENCRYPTION_KEY;
}