fix(lxc): resolver 500 propagando permisos PostgreSQL universales y logging en journald

This commit is contained in:
Carlos Tello
2026-09-04 23:15:02 -03:00
parent b367b106bf
commit 4e49311208
3 changed files with 107 additions and 24 deletions
+82 -23
View File
@@ -131,6 +131,14 @@ for i in {1..15}; do
done
if [ "$PG_READY" = true ]; then
# Configurar pg_hba.conf para permitir conexiones locales (socket y 127.0.0.1) sin fallos de autenticación
PG_HBA=$(find /etc/postgresql/ -name pg_hba.conf 2>/dev/null | sort -V | tail -n1)
if [[ -n "$PG_HBA" && -f "$PG_HBA" ]]; then
sed -i -E 's/^(local\s+all\s+all\s+)peer/\1trust/' "$PG_HBA" 2>/dev/null || true
sed -i -E 's/^(host\s+all\s+all\s+127\.0\.0\.1\/32\s+)(scram-sha-256|md5)/\1trust/' "$PG_HBA" 2>/dev/null || true
sed -i -E 's/^(host\s+all\s+all\s+::1\/128\s+)(scram-sha-256|md5)/\1trust/' "$PG_HBA" 2>/dev/null || true
systemctl reload postgresql 2>/dev/null || true
fi
systemctl enable postgresql > /dev/null 2>&1 || true
ok "PostgreSQL activo y aceptando conexiones"
else
@@ -140,7 +148,7 @@ fi
# ─── 5. Configurar Variables de Entorno (.env) ─────────────────────────────────
hdr "5. Configurando variables de entorno (.env)"
# Configuración idéntica al entorno del sistema activo (100% automático sin interacción)
# Valores predeterminados (paridad con sistema activo)
DB_NAME="classrooms_db"
DB_USER="postgres"
DB_PASSWORD="password"
@@ -151,9 +159,26 @@ if [[ -f "$APP_ENV" ]]; then
# shellcheck disable=SC1090
source <(grep -v '^#' "$APP_ENV" | grep '=')
set +a
DB_USER="${DB_USERNAME:-$DB_USER}"
# Extraer credenciales desde DATABASE_URL si está presente
if [[ -n "${DATABASE_URL:-}" ]]; then
URL_USER=$(echo "$DATABASE_URL" | sed -E 's|^.*://([^:@]+).*|\1|')
URL_PASS=$(echo "$DATABASE_URL" | sed -E 's|^.*://[^:]+:([^@]+)@.*|\1|')
URL_NAME=$(echo "$DATABASE_URL" | sed -E 's|^.*/([^?]+).*|\1|')
if [[ "$URL_USER" != "$DATABASE_URL" && -n "$URL_USER" ]]; then
DB_USER="$URL_USER"
fi
if [[ "$URL_PASS" != "$DATABASE_URL" && -n "$URL_PASS" ]]; then
DB_PASSWORD="$URL_PASS"
fi
if [[ "$URL_NAME" != "$DATABASE_URL" && -n "$URL_NAME" ]]; then
DB_NAME="$URL_NAME"
fi
fi
DB_USER="${DB_USER:-${DB_USERNAME:-postgres}}"
DB_PASSWORD="${DB_PASSWORD:-password}"
DB_NAME=$(echo "${DATABASE_URL:-}" | sed -E 's|.*/([^?]+).*|\1|')
DB_NAME="${DB_NAME:-classrooms_db}"
else
SECRET_KEY=$(python3 -c 'import secrets; print(secrets.token_hex(32))')
@@ -182,20 +207,29 @@ fi
# ─── 6. Configurar Usuario y Base de Datos en PostgreSQL ───────────────────────
hdr "6. Configurando motor PostgreSQL y credenciales de base de datos"
# Asignar contraseña al usuario postgres
sudo -u postgres psql -c "ALTER USER postgres WITH PASSWORD '${DB_PASSWORD}';" >/dev/null 2>&1 || true
# Configurar usuarios en PostgreSQL con privilegios completos
for u in "${DB_USER}" "${DB_USERNAME:-}" eduspace_user; do
if [[ -n "$u" && "$u" != "postgres" ]]; then
sudo -u postgres psql -c "CREATE USER \"${u}\" WITH PASSWORD '${DB_PASSWORD}';" >/dev/null 2>&1 \
|| sudo -u postgres psql -c "ALTER USER \"${u}\" WITH PASSWORD '${DB_PASSWORD}';" >/dev/null 2>&1 \
|| true
sudo -u postgres psql -c "ALTER USER \"${u}\" WITH SUPERUSER CREATEDB;" >/dev/null 2>&1 || true
fi
done
# Crear usuario eduspace_user con la misma contraseña como alternativa
sudo -u postgres psql -c "CREATE USER eduspace_user WITH PASSWORD '${DB_PASSWORD}';" >/dev/null 2>&1 \
|| sudo -u postgres psql -c "ALTER USER eduspace_user WITH PASSWORD '${DB_PASSWORD}';" >/dev/null 2>&1 \
|| true
sudo -u postgres psql -c "ALTER USER postgres WITH PASSWORD '${DB_PASSWORD}';" >/dev/null 2>&1 || true
sudo -u postgres psql -c "ALTER USER postgres WITH SUPERUSER CREATEDB;" >/dev/null 2>&1 || true
# Crear base de datos
sudo -u postgres psql -c "CREATE DATABASE ${DB_NAME} OWNER postgres;" >/dev/null 2>&1 \
sudo -u postgres psql -c "CREATE DATABASE \"${DB_NAME}\" OWNER postgres;" >/dev/null 2>&1 \
|| info "La base de datos '${DB_NAME}' ya existía."
sudo -u postgres psql -d "${DB_NAME}" -c "GRANT ALL PRIVILEGES ON DATABASE ${DB_NAME} TO postgres, eduspace_user;" >/dev/null 2>&1 || true
sudo -u postgres psql -d "${DB_NAME}" -c "GRANT ALL ON SCHEMA public TO postgres, eduspace_user;" >/dev/null 2>&1 || true
for u in "${DB_USER}" "${DB_USERNAME:-}" postgres eduspace_user; do
if [[ -n "$u" ]]; then
sudo -u postgres psql -c "GRANT ALL PRIVILEGES ON DATABASE \"${DB_NAME}\" TO \"${u}\";" >/dev/null 2>&1 || true
sudo -u postgres psql -d "${DB_NAME}" -c "GRANT ALL ON SCHEMA public TO \"${u}\";" >/dev/null 2>&1 || true
fi
done
ok "Motor PostgreSQL configurado (usuario: ${DB_USER}, base: ${DB_NAME})"
@@ -229,8 +263,8 @@ if [[ -f "$SQL_BACKUP_FILE" ]]; then
info "Restaurando volcado integral de aulas, comisiones, materias, reservas y usuarios..."
# Recrear base de datos limpia para carga sin colisiones
sudo -u postgres psql -c "DROP DATABASE IF EXISTS ${DB_NAME};" > /dev/null 2>&1 || true
sudo -u postgres psql -c "CREATE DATABASE ${DB_NAME} OWNER postgres;" > /dev/null 2>&1
sudo -u postgres psql -c "DROP DATABASE IF EXISTS \"${DB_NAME}\";" > /dev/null 2>&1 || true
sudo -u postgres psql -c "CREATE DATABASE \"${DB_NAME}\" OWNER postgres;" > /dev/null 2>&1
# Restaurar backup filtrando directivas específicas de PG18 si existiesen
if sed '/^\\restrict/d' "$SQL_BACKUP_FILE" | sudo -u postgres psql -d "${DB_NAME}" > /dev/null 2>&1; then
@@ -240,17 +274,28 @@ if [[ -f "$SQL_BACKUP_FILE" ]]; then
fi
# Otorgar propiedad y permisos absolutos sobre todas las tablas y secuencias al usuario de la app
info "Garantizando permisos y secuencias para ${DB_USER} y eduspace_user..."
sudo -u postgres psql -d "${DB_NAME}" -c "GRANT ALL ON SCHEMA public TO postgres, eduspace_user;" > /dev/null 2>&1 || true
sudo -u postgres psql -d "${DB_NAME}" -c "GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO postgres, eduspace_user;" > /dev/null 2>&1 || true
sudo -u postgres psql -d "${DB_NAME}" -c "GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO postgres, eduspace_user;" > /dev/null 2>&1 || true
sudo -u postgres psql -d "${DB_NAME}" -c "ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON TABLES TO postgres, eduspace_user;" > /dev/null 2>&1 || true
sudo -u postgres psql -d "${DB_NAME}" -c "ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON SEQUENCES TO postgres, eduspace_user;" > /dev/null 2>&1 || true
info "Garantizando permisos y secuencias para ${DB_USER}..."
for u in "${DB_USER}" "${DB_USERNAME:-}" postgres eduspace_user; do
if [[ -n "$u" ]]; then
sudo -u postgres psql -d "${DB_NAME}" -c "GRANT ALL PRIVILEGES ON DATABASE \"${DB_NAME}\" TO \"${u}\";" > /dev/null 2>&1 || true
sudo -u postgres psql -d "${DB_NAME}" -c "GRANT ALL ON SCHEMA public TO \"${u}\";" > /dev/null 2>&1 || true
sudo -u postgres psql -d "${DB_NAME}" -c "GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO \"${u}\";" > /dev/null 2>&1 || true
sudo -u postgres psql -d "${DB_NAME}" -c "GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO \"${u}\";" > /dev/null 2>&1 || true
sudo -u postgres psql -d "${DB_NAME}" -c "GRANT ALL PRIVILEGES ON ALL FUNCTIONS IN SCHEMA public TO \"${u}\";" > /dev/null 2>&1 || true
sudo -u postgres psql -d "${DB_NAME}" -c "ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON TABLES TO \"${u}\";" > /dev/null 2>&1 || true
sudo -u postgres psql -d "${DB_NAME}" -c "ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON SEQUENCES TO \"${u}\";" > /dev/null 2>&1 || true
sudo -u postgres psql -d "${DB_NAME}" -c "ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON FUNCTIONS TO \"${u}\";" > /dev/null 2>&1 || true
fi
done
if [[ "${DB_USER}" != "postgres" ]]; then
sudo -u postgres psql -d "${DB_NAME}" -c "ALTER SCHEMA public OWNER TO \"${DB_USER}\";" > /dev/null 2>&1 || true
fi
# Ejecutar init_db.py de forma idempotente para verificar roles y migraciones incrementales
info "Validando coherencia de modelos con init_db.py..."
LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8 PYTHONUTF8=1 PYTHONIOENCODING=utf-8 \
FLASK_APP=wsgi.py "${VENV_DIR}/bin/python" -X utf8 init_db.py > /dev/null 2>&1 || true
FLASK_APP=wsgi.py "${VENV_DIR}/bin/python" -X utf8 init_db.py
ok "Base de datos sincronizada y verificada"
else
info "No se encontró classrooms_db.sql. Creando esquema desde cero con init_db.py..."
@@ -269,13 +314,15 @@ else
ok "Usuario de sistema '${APP_USER}' creado (sin shell)"
fi
mkdir -p "${APP_DIR}/app/static/uploads"
chown -R "${APP_USER}:${APP_USER}" "$APP_DIR"
chmod -R 755 "$APP_DIR"
chmod -R 775 "${APP_DIR}/app/static/uploads"
chmod 640 "$APP_ENV"
mkdir -p "$LOG_DIR"
chown -R "${APP_USER}:${APP_USER}" "$LOG_DIR"
chmod 750 "$LOG_DIR"
chmod 755 "$LOG_DIR"
ok "Permisos de seguridad aplicados en ${APP_DIR} y ${LOG_DIR}"
# ─── 10. Servicio Systemd (Gunicorn de Producción) ─────────────────────────────
@@ -307,7 +354,9 @@ ExecStart=${GUNICORN_BIN} \
--bind 0.0.0.0:5000 \
--timeout 120 \
--access-logfile ${LOG_DIR}/access.log \
--error-logfile ${LOG_DIR}/error.log \
--error-logfile - \
--capture-output \
--enable-stdio-inheritance \
--log-level info \
wsgi:app
Restart=always
@@ -329,6 +378,16 @@ sleep 3
if systemctl is-active --quiet "$SERVICE_NAME"; then
ok "Servicio '${SERVICE_NAME}' activo y en ejecución"
# Validar respuesta HTTP local
info "Verificando respuesta del servidor web..."
sleep 2
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" http://127.0.0.1:5000/ || echo "000")
if [[ "$HTTP_CODE" == "200" || "$HTTP_CODE" == "302" ]]; then
ok "Servidor web respondiendo correctamente (HTTP ${HTTP_CODE})"
else
warn "El servidor web devolvió código HTTP ${HTTP_CODE}. Podés revisar los logs con: journalctl -u ${SERVICE_NAME} -n 30 --no-pager"
fi
else
warn "El servicio tardó en arrancar. Podés revisar los logs con:"
warn " journalctl -u ${SERVICE_NAME} -n 50 --no-pager"