Container aus dem Proxmox-Template (neueste passende Version aus aplinfo), unprivilegiert, nesting automatisch für docker. Weil Proxmox keine Exec-API für Container hat, läuft die Provisionierung per SSH: bevorzugt pct exec über den Node, sonst direkt in den Container mit einem Bereitstellungsschlüssel, der am Ende wieder entfernt wird. Auf pve-demo beide Wege geprüft: Debian 13 mit docker per pct exec (hello-world läuft mit nesting allein) und Ubuntu 24.04 per SSH in den Container. Dabei gefunden: chrony scheitert ohne CAP_SYS_TIME (jetzt if: vm), sshd -t auf Ubuntu 24.04 ohne /run/sshd. Closes #009 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
31 lines
1.5 KiB
TypeScript
31 lines
1.5 KiB
TypeScript
import ssh2 from "ssh2";
|
|
import type { Bereitstellungsschluessel } from "@/engine/ablaeufe/lxc-ausrollen";
|
|
import { prisma } from "@/lib/db";
|
|
import { entschluesseln, verschluesseln } from "@/lib/geheimnisse";
|
|
|
|
/**
|
|
* Der Bereitstellungsschlüssel: damit meldet sich ProxDeploy als root in frisch angelegten
|
|
* Containern an, wenn es keinen SSH-Zugang zum Node hat. Er steht nur während der
|
|
* Provisionierung in /root/.ssh/authorized_keys und wird am Ende des Skripts entfernt (am
|
|
* Kommentar `proxdeploy-bereitstellung` erkennbar). Einmal erzeugt, privat nur verschlüsselt.
|
|
*/
|
|
const SCHLUESSEL = "bereitstellungsschluessel";
|
|
export const KOMMENTAR = "proxdeploy-bereitstellung";
|
|
|
|
export async function bereitstellungsschluessel(): Promise<Bereitstellungsschluessel> {
|
|
const vorhanden = await prisma.einstellung.findUnique({ where: { schluessel: SCHLUESSEL } });
|
|
if (vorhanden) {
|
|
const wert = vorhanden.wert as { privat: string; oeffentlich: string };
|
|
return { privat: entschluesseln(wert.privat), oeffentlich: wert.oeffentlich };
|
|
}
|
|
const paar = ssh2.utils.generateKeyPairSync("ed25519", { comment: KOMMENTAR });
|
|
const neu = { privat: verschluesseln(paar.private), oeffentlich: paar.public.trim() };
|
|
// Zwei gleichzeitige Aufträge: der erste gewinnt, der zweite liest dessen Schlüssel.
|
|
await prisma.einstellung.upsert({
|
|
where: { schluessel: SCHLUESSEL },
|
|
create: { schluessel: SCHLUESSEL, wert: neu },
|
|
update: {},
|
|
});
|
|
return await bereitstellungsschluessel();
|
|
}
|