981ca81f64
Stack-Skelett ist drin (compose, Dockerfile, kong.yml, nginx.conf, sync- Script, generate-keys-Skript), aber End-to-End noch nicht lauffähig. Beim ersten lokalen Bring-up sind aufgefallen: - auth.users-Schema fehlt beim Init (Migration 0001 referenziert FK) - Healthcheck-User: supabase/postgres default ist supabase_admin - auth.uid()/auth.role() müssen vor Migrations existieren - Standard-Init-SQL (roles, _supabase, realtime, jwt, …) aus supabase/supabase docker fehlt Punkte sind in separater Iteration zu adressieren — Self-Host-Init in Production-Qualität ist nicht in einem Rutsch zu bauen. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
54 lines
2.0 KiB
JavaScript
Executable File
54 lines
2.0 KiB
JavaScript
Executable File
#!/usr/bin/env node
|
|
// Generiert ANON_KEY und SERVICE_ROLE_KEY (JWTs, HS256 signiert) aus dem
|
|
// JWT_SECRET in der .env. Ohne diese Keys können GoTrue, PostgREST, Storage
|
|
// und Realtime nicht miteinander reden.
|
|
//
|
|
// Aufruf:
|
|
// node scripts/generate-keys.mjs # liest JWT_SECRET aus .env
|
|
// node scripts/generate-keys.mjs <secret> # explizit übergeben
|
|
//
|
|
// Output: zwei JWTs auf stdout, die du in .env als ANON_KEY und
|
|
// SERVICE_ROLE_KEY einsetzen kannst.
|
|
|
|
import crypto from "node:crypto";
|
|
import fs from "node:fs";
|
|
|
|
function base64url(input) {
|
|
return Buffer.from(input).toString("base64")
|
|
.replace(/=+$/, "").replace(/\+/g, "-").replace(/\//g, "_");
|
|
}
|
|
|
|
function signJwt(payload, secret) {
|
|
const header = base64url(JSON.stringify({ alg: "HS256", typ: "JWT" }));
|
|
const body = base64url(JSON.stringify(payload));
|
|
const sig = base64url(crypto.createHmac("sha256", secret).update(`${header}.${body}`).digest());
|
|
return `${header}.${body}.${sig}`;
|
|
}
|
|
|
|
let secret = process.argv[2];
|
|
if (!secret) {
|
|
try {
|
|
const env = fs.readFileSync(".env", "utf8");
|
|
const m = env.match(/^JWT_SECRET=(.+)$/m);
|
|
if (m) secret = m[1].trim().replace(/^["']|["']$/g, "");
|
|
} catch {}
|
|
}
|
|
|
|
if (!secret || secret.length < 32 || secret.includes("CHANGE-ME")) {
|
|
console.error("✗ Kein gültiges JWT_SECRET gefunden (mind. 32 Zeichen, nicht der Placeholder).");
|
|
console.error(" Setze JWT_SECRET in .env oder gib es als Argument:");
|
|
console.error(" node scripts/generate-keys.mjs $(openssl rand -hex 32)");
|
|
process.exit(1);
|
|
}
|
|
|
|
const now = Math.floor(Date.now() / 1000);
|
|
const tenYears = now + 10 * 365 * 24 * 3600;
|
|
|
|
const anonKey = signJwt({ role: "anon", iss: "supabase", iat: now, exp: tenYears }, secret);
|
|
const serviceKey = signJwt({ role: "service_role", iss: "supabase", iat: now, exp: tenYears }, secret);
|
|
|
|
console.log("ANON_KEY=" + anonKey);
|
|
console.log("SERVICE_ROLE_KEY=" + serviceKey);
|
|
console.error("");
|
|
console.error("→ Werte in .env eintragen (überschreibt CHANGE-ME-Placeholder).");
|