fix(nexus-db): enforce UTF8 encoding at install time (issue #8)
CI / Shell-Lint (bash -n, source-check, Validierungs-Tests) (pull_request) Successful in 1s
CI / Shell-Lint (bash -n, source-check, Validierungs-Tests) (pull_request) Successful in 1s
A PostgreSQL cluster/database freezes its encoding at initdb / CREATE DATABASE time; a C (non-UTF-8) locale yields a SQL_ASCII cluster, which makes psycopg3 return bytes and crashes SQLAlchemy. Harden the installer and add a reusable pattern for future DB installers: - ensure_utf8_locale_active: generate AND activate en_US.UTF-8 for the install process before the server package runs initdb; abort if the locale is not actually available - create the database explicitly with TEMPLATE template0 ENCODING 'UTF8' LC_COLLATE/LC_CTYPE 'en_US.UTF-8' instead of inheriting the cluster default - assert_db_encoding_utf8: post-install guard, abort with an actionable message if pg_encoding_to_char is not UTF8 (catches old SQL_ASCII DBs on re-run too) - credentials/README docs use su - postgres -c (minimal LXCs have no sudo)
This commit is contained in:
@@ -54,6 +54,50 @@ apt_cleanup() {
|
||||
apt-get autoclean -qq >/dev/null || true
|
||||
}
|
||||
|
||||
# ── database installers: UTF-8 locale before initdb ──────────────────────────
|
||||
# Pattern for every DB installer. A PostgreSQL cluster/database freezes its
|
||||
# encoding at initdb / CREATE DATABASE time and it cannot be changed later —
|
||||
# a C (non-UTF-8) locale yields a SQL_ASCII cluster. psycopg3 then returns
|
||||
# text as bytes and SQLAlchemy crashes on server-version detection; the app
|
||||
# reports "db: unreachable". So: GENERATE the UTF-8 locale AND make it active
|
||||
# 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).
|
||||
ensure_utf8_locale_active() {
|
||||
local loc="${1:-en_US.UTF-8}"
|
||||
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
|
||||
locale-gen >/dev/null
|
||||
fi
|
||||
if ! locale -a 2>/dev/null | tr 'A-Z' 'a-z' | grep -q '^en_us\.utf-\?8$'; then
|
||||
msg_err "Locale $loc not available after locale-gen — refusing to continue (initdb would create a SQL_ASCII cluster)"
|
||||
return 1
|
||||
fi
|
||||
# Activate for the current process so any automatic initdb during the
|
||||
# server package install inherits a UTF-8 locale, not the bare-template C.
|
||||
export LANG="$loc" LC_ALL="$loc"
|
||||
msg_ok "Locale active for initdb: LANG=$LANG"
|
||||
}
|
||||
|
||||
# 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).
|
||||
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'\"")"
|
||||
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."
|
||||
msg_err "Fix: regenerate the locale (locale-gen en_US.UTF-8) and recreate the DB"
|
||||
msg_err " with: CREATE DATABASE $db ... TEMPLATE template0 ENCODING 'UTF8'"
|
||||
msg_err " LC_COLLATE 'en_US.UTF-8' LC_CTYPE 'en_US.UTF-8';"
|
||||
return 1
|
||||
fi
|
||||
msg_ok "Encoding check: database '$db' is UTF8"
|
||||
}
|
||||
|
||||
# ── ssh ──────────────────────────────────────────────────────────────────────
|
||||
# SSH-Root-Login gemäß Host-Prompt (prompt_lxc_config setzt SSH_ROOT_LOGIN,
|
||||
# bootstrap_install_script reicht es als Env durch; Default: yes).
|
||||
|
||||
Reference in New Issue
Block a user