fix(nexus-db): UTF8-Encoding zur Installationszeit erzwingen (#8) #9
@@ -101,6 +101,13 @@ systemctl restart postgresql
|
||||
# ── role + database + extension (idempotent, password kept on re-run) ─────────
|
||||
run_psql() { runuser -u postgres -- psql -v ON_ERROR_STOP=1 -qAt "$@"; }
|
||||
|
||||
# Re-run safety (issue #8): if the database already exists, verify its
|
||||
# encoding BEFORE touching roles/passwords. An old SQL_ASCII database must
|
||||
# abort the run with NO side effects — not after rotating credentials.
|
||||
if [[ "$(run_psql -c "SELECT 1 FROM pg_database WHERE datname='$DB_NAME'")" == "1" ]]; then
|
||||
assert_db_encoding_utf8 "$DB_NAME"
|
||||
fi
|
||||
|
||||
if [[ "$(run_psql -c "SELECT 1 FROM pg_roles WHERE rolname='$DB_USER'")" != "1" ]]; then
|
||||
msg_info "Creating role $DB_USER + database $DB_NAME..."
|
||||
DB_PASS="$(openssl rand -base64 32 | tr -d '/+=' | head -c 32)"
|
||||
@@ -126,16 +133,14 @@ if [[ "$(run_psql -c "SELECT 1 FROM pg_database WHERE datname='$DB_NAME'")" != "
|
||||
run_psql -c "CREATE DATABASE $DB_NAME OWNER $DB_USER ENCODING 'UTF8' LC_COLLATE 'en_US.UTF-8' LC_CTYPE 'en_US.UTF-8' TEMPLATE template0"
|
||||
# Only the owner may connect — no PUBLIC access.
|
||||
run_psql -c "REVOKE CONNECT ON DATABASE $DB_NAME FROM PUBLIC"
|
||||
# Verify what we just created (the pre-existing case was already checked
|
||||
# before the role block, issue #8).
|
||||
assert_db_encoding_utf8 "$DB_NAME"
|
||||
msg_ok "Database $DB_NAME created (UTF8, owner $DB_USER, PUBLIC revoked)"
|
||||
else
|
||||
msg_warn "Database $DB_NAME already exists, skipping creation"
|
||||
fi
|
||||
|
||||
# Encoding guard (issue #8): catch both a freshly mis-created DB and a
|
||||
# pre-existing SQL_ASCII database from an old provisioning. Abort before the
|
||||
# app ever connects — a wrong encoding is DB damage, not a warning.
|
||||
assert_db_encoding_utf8 "$DB_NAME"
|
||||
|
||||
# pgvector: CREATE EXTENSION needs superuser; installed now (per ADR-0002:
|
||||
# "Extension ab Tag 1 installiert, ungenutzt bis Phase 2").
|
||||
run_psql -d "$DB_NAME" -c "CREATE EXTENSION IF NOT EXISTS vector" >/dev/null
|
||||
|
||||
+16
-6
@@ -63,14 +63,21 @@ apt_cleanup() {
|
||||
# for THIS process before the server package runs its automatic initdb, then
|
||||
# fail loudly if it is not actually available (generating alone is not enough
|
||||
# — the locale must be active when initdb runs).
|
||||
# Generates+activates a UTF-8 locale (default en_US.UTF-8); the argument
|
||||
# honours other UTF-8 locales consistently (match, locale.gen line and the
|
||||
# exported value all derive from it). Matching normalises case and dashes so
|
||||
# the canonical `en_US.UTF-8` matches `locale -a`'s `en_US.utf8`.
|
||||
ensure_utf8_locale_active() {
|
||||
local loc="${1:-en_US.UTF-8}"
|
||||
local norm; norm="$(printf '%s' "$loc" | tr 'A-Z' 'a-z' | tr -d '-')"
|
||||
_locale_present() { locale -a 2>/dev/null | tr 'A-Z' 'a-z' | tr -d '-' | grep -qx "$norm"; }
|
||||
msg_info "Ensuring $loc is generated and active (DB encoding is frozen at initdb)..."
|
||||
if ! locale -a 2>/dev/null | tr 'A-Z' 'a-z' | grep -q '^en_us\.utf-\?8$'; then
|
||||
sed -i 's/^# *en_US\.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen
|
||||
if ! _locale_present; then
|
||||
# Uncomment the matching `# <loc> UTF-8` line, then generate.
|
||||
sed -i "s/^# *${loc} UTF-8/${loc} UTF-8/" /etc/locale.gen
|
||||
locale-gen >/dev/null
|
||||
fi
|
||||
if ! locale -a 2>/dev/null | tr 'A-Z' 'a-z' | grep -q '^en_us\.utf-\?8$'; then
|
||||
if ! _locale_present; then
|
||||
msg_err "Locale $loc not available after locale-gen — refusing to continue (initdb would create a SQL_ASCII cluster)"
|
||||
return 1
|
||||
fi
|
||||
@@ -82,11 +89,14 @@ ensure_utf8_locale_active() {
|
||||
|
||||
# Post-install guard: a database MUST be UTF8. Encoding is irreversible, so a
|
||||
# wrong value is database damage — abort with a clear, actionable message
|
||||
# instead of shipping a broken cluster. Reads via `su - postgres -c` (minimal
|
||||
# LXCs have no sudo).
|
||||
# instead of shipping a broken cluster. Uses argv-clean `runuser ... psql`
|
||||
# with a quoted :'db' literal binding (robust regardless of caller); the
|
||||
# credentials/README docs use `su - postgres -c` for hand maintenance (these
|
||||
# minimal LXCs have no sudo).
|
||||
assert_db_encoding_utf8() {
|
||||
local db="$1" enc
|
||||
enc="$(su - postgres -c "psql -X -qAt -c \"SELECT pg_encoding_to_char(encoding) FROM pg_database WHERE datname='$db'\"")"
|
||||
enc="$(runuser -u postgres -- psql -X -qAt -v db="$db" \
|
||||
-c "SELECT pg_encoding_to_char(encoding) FROM pg_database WHERE datname = :'db'")"
|
||||
if [[ "$enc" != "UTF8" ]]; then
|
||||
msg_err "Database '$db' has encoding '${enc:-<not found>}', expected UTF8."
|
||||
msg_err "Encoding is frozen at creation time — this is DB damage, not cosmetic."
|
||||
|
||||
Reference in New Issue
Block a user