bunker-admin 2fa50b001c Merge changemaker-control-panel into v2 monorepo
Absorbs the separate control-panel git repo as a subdirectory.
Instances and backups directories excluded via .gitignore.

Bunker Admin
2026-02-21 11:51:45 -07:00

74 lines
2.2 KiB
TypeScript

import crypto from 'crypto';
function randomHex(bytes = 32): string {
return crypto.randomBytes(bytes).toString('hex');
}
function randomPassword(length = 16): string {
// Generate password meeting CML policy: 12+ chars, uppercase, lowercase, digit
const upper = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
const lower = 'abcdefghijklmnopqrstuvwxyz';
const digits = '0123456789';
// Avoid $, #, !, % — they break Docker Compose .env files
// ($=var expansion, #=comment, !=bash history, %=printf)
const special = '@&*_-+=';
const all = upper + lower + digits + special;
// Ensure at least one of each required class
const required = [
upper[crypto.randomInt(upper.length)],
lower[crypto.randomInt(lower.length)],
digits[crypto.randomInt(digits.length)],
special[crypto.randomInt(special.length)],
];
// Fill remaining with random chars
const remaining = Array.from({ length: length - required.length }, () =>
all[crypto.randomInt(all.length)]
);
// Shuffle
const chars = [...required, ...remaining];
for (let i = chars.length - 1; i > 0; i--) {
const j = crypto.randomInt(i + 1);
[chars[i], chars[j]] = [chars[j], chars[i]];
}
return chars.join('');
}
export interface InstanceSecrets {
postgresPassword: string;
redisPassword: string;
jwtAccessSecret: string;
jwtRefreshSecret: string;
encryptionKey: string;
initialAdminPassword: string;
nocodbAdminPassword: string;
grafanaAdminPassword: string;
listmonkAdminPassword: string;
listmonkApiToken: string;
giteaAdminPassword: string;
n8nEncryptionKey: string;
gancioAdminPassword: string;
}
export function generateSecrets(adminEmail: string): InstanceSecrets & { adminEmail: string } {
return {
adminEmail,
postgresPassword: randomHex(16),
redisPassword: randomHex(16),
jwtAccessSecret: randomHex(32),
jwtRefreshSecret: randomHex(32),
encryptionKey: randomHex(32),
initialAdminPassword: randomPassword(16),
nocodbAdminPassword: randomPassword(16),
grafanaAdminPassword: randomPassword(16),
listmonkAdminPassword: randomPassword(16),
listmonkApiToken: randomHex(16),
giteaAdminPassword: randomPassword(16),
n8nEncryptionKey: randomHex(32),
gancioAdminPassword: randomPassword(16),
};
}