chore(ops): harden deployment and runtime setup
This commit is contained in:
parent
1d7e7c41c9
commit
c35bd5877e
30 changed files with 534 additions and 61 deletions
13
scripts/backup.sh
Executable file
13
scripts/backup.sh
Executable file
|
|
@ -0,0 +1,13 @@
|
|||
#!/usr/bin/env sh
|
||||
set -eu
|
||||
|
||||
BACKUP_DIR="${BACKUP_DIR:-backups}"
|
||||
STAMP="$(date +%Y%m%d-%H%M%S)"
|
||||
TARGET="${BACKUP_DIR}/funktechnik-data-${STAMP}.tar.gz"
|
||||
|
||||
mkdir -p "$BACKUP_DIR"
|
||||
tar -czf "$TARGET" data public/uploads
|
||||
|
||||
echo "Backup erstellt: $TARGET"
|
||||
echo "Hinweis: .env wird aus Sicherheitsgruenden nicht automatisch gesichert."
|
||||
echo "Bitte .env separat und sicher ausserhalb des Repositories sichern."
|
||||
19
scripts/deploy.sh
Executable file
19
scripts/deploy.sh
Executable file
|
|
@ -0,0 +1,19 @@
|
|||
#!/usr/bin/env sh
|
||||
set -eu
|
||||
|
||||
COMPOSE="${COMPOSE:-docker compose}"
|
||||
BASE_URL="${BASE_URL:-http://localhost:3010}"
|
||||
|
||||
echo "Pruefe Docker Compose Konfiguration..."
|
||||
$COMPOSE config >/dev/null
|
||||
|
||||
echo "Baue Container..."
|
||||
$COMPOSE build
|
||||
|
||||
echo "Starte Container..."
|
||||
$COMPOSE up -d
|
||||
|
||||
echo "Fuehre Healthcheck aus..."
|
||||
BASE_URL="$BASE_URL" scripts/healthcheck.sh
|
||||
|
||||
echo "Deployment abgeschlossen."
|
||||
14
scripts/healthcheck.sh
Executable file
14
scripts/healthcheck.sh
Executable file
|
|
@ -0,0 +1,14 @@
|
|||
#!/usr/bin/env sh
|
||||
set -eu
|
||||
|
||||
BASE_URL="${BASE_URL:-http://localhost:3010}"
|
||||
HEALTH_URL="${BASE_URL%/}/api/health"
|
||||
|
||||
echo "Checking ${HEALTH_URL}"
|
||||
response="$(curl -fsS "$HEALTH_URL")"
|
||||
echo "$response"
|
||||
|
||||
case "$response" in
|
||||
*'"status":"ok"'*) exit 0 ;;
|
||||
*) echo "Healthcheck failed" >&2; exit 1 ;;
|
||||
esac
|
||||
17
scripts/restore.sh
Executable file
17
scripts/restore.sh
Executable file
|
|
@ -0,0 +1,17 @@
|
|||
#!/usr/bin/env sh
|
||||
set -eu
|
||||
|
||||
if [ "${1:-}" = "" ]; then
|
||||
echo "Usage: scripts/restore.sh <backup.tar.gz>" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
BACKUP_FILE="$1"
|
||||
|
||||
if [ ! -f "$BACKUP_FILE" ]; then
|
||||
echo "Backup nicht gefunden: $BACKUP_FILE" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
tar -xzf "$BACKUP_FILE"
|
||||
echo "Restore abgeschlossen: $BACKUP_FILE"
|
||||
36
scripts/runtime-start.js
Normal file
36
scripts/runtime-start.js
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
/* eslint-disable @typescript-eslint/no-require-imports */
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
|
||||
const requiredEnv = ["ADMIN_EMAIL", "ADMIN_PASSWORD", "ADMIN_SESSION_SECRET"];
|
||||
const requiredDirs = [
|
||||
path.join(process.cwd(), "data"),
|
||||
path.join(process.cwd(), "public", "uploads", "images"),
|
||||
path.join(process.cwd(), ".next", "cache"),
|
||||
];
|
||||
|
||||
function fail(message) {
|
||||
process.stderr.write(`[funktechnik-website] ${message}\n`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
function ensureWritableDirectory(directory) {
|
||||
fs.mkdirSync(directory, { recursive: true });
|
||||
const probe = path.join(directory, `.write-check-${Date.now()}`);
|
||||
fs.writeFileSync(probe, "ok", "utf8");
|
||||
fs.rmSync(probe, { force: true });
|
||||
}
|
||||
|
||||
const missingEnv = requiredEnv.filter((name) => !process.env[name]);
|
||||
if (missingEnv.length > 0) {
|
||||
fail(`Start abgebrochen: fehlende Umgebungsvariablen: ${missingEnv.join(", ")}. Bitte .env anhand von .env.example konfigurieren.`);
|
||||
}
|
||||
|
||||
try {
|
||||
for (const directory of requiredDirs) ensureWritableDirectory(directory);
|
||||
} catch (error) {
|
||||
fail(`Start abgebrochen: Runtime-Verzeichnis ist nicht beschreibbar. Details: ${error instanceof Error ? error.message : "unbekannter Fehler"}`);
|
||||
}
|
||||
|
||||
process.stdout.write(`[funktechnik-website] Runtime checks ok. Starting version ${process.env.NEXT_PUBLIC_APP_VERSION ?? "0.2.2"}.\n`);
|
||||
require("./server.js");
|
||||
Loading…
Add table
Add a link
Reference in a new issue