Migración del clúster PostgreSQL de SIU-Guaraní: guía y cuidados con los permisos¶
Mover una base de datos de Guaraní a otro host no es solo «copiar y restaurar». El error clásico que aparece después de la restauración
es Undefined table o permiso denegado, incluso cuando los datos están intactos. La causa casi siempre está en los roles, los search_path
y la jerarquía de permisos de PostgreSQL, que no viajan automáticamente con los datos.
Esta guía resume el flujo recomendado y los puntos críticos que debes verificar para que Guaraní funcione en el nuevo servidor.
Estrategia de volcado: no uses solo pg_dumpall¶
La documentación oficial de SIU-Guaraní para migrar a un nuevo servidor propone un flujo controlado: generar una instalación limpia de Guaraní en el host nuevo, hacer el dump de la base de datos vieja, restaurarla con el nombre que tenía la instalación nueva, y luego regenerar la instancia y migrar la base.
Recomendación práctica: separar los objetos globales (roles y tablespaces) de los datos de negocio.
Exportar solo roles y tablespaces (globales)¶
pg_dumpall --globals-only -U postgres -f globales.sql
Exportar la base de datos de Guaraní por separado (formato custom, comprimido)¶
pg_dump -U postgres -Fc -b -v -f BD-GUARANI.dump BD-GUARANI
Esto evita el problema más común: restaurar el dump completo antes de que los roles existan, lo que hace que los ALTER … OWNER TO fallen o se omitan.
El orden de restauración importa (y mucho)¶
El orden correcto en el host destino es:
Crear los roles primero
psql -f globales.sql
Crear la base de datos vacía (con createdb, usando template0 para evitar dependencias de template1).
Restaurar el dump de la base con
pg_restore -d BD-GUARANI-NUEVA BD-GUARANI.dump
Si restauras el dump completo con pg_dumpall sin haber creado los roles antes, PostgreSQL puede abortar la carga de datos o dejar las tablas sin dueño.
El síntoma típico es que pg_tables devuelve 0 filas en la base recién restaurada.
El problema del search_path: la tabla existe pero «no existe»¶
Guaraní y Toba consultan tablas sin calificar el esquema (FROM app_versiones_base, no FROM negocio.app_versiones_base). PostgreSQL resuelve ese nombre usando el search_path de la sesión.
Cuando recreas un rol a mano, este hereda el search_path predeterminado: «$user», public. Si el esquema negocio no está ahí, la tabla es invisible para la aplicación, aunque exista
y el usuario tenga permisos sobre ella.
Solución persistente: fijar el search_path en el rol que usa Guaraní.
ALTER ROLE usuario-guarani SET search_path TO negocio, public;
Verificar con:
SHOW search_path;
Debe mostrar: negocio, public
Si además la aplicación usa el esquema desarrollo para metadatos de Toba, puedes incluir ambos:
ALTER ROLE usuario-guarani SET search_path TO negocio, desarrollo, public;
Nota: Toba también lee el campo schema del bases.ini. Si la configuración original decía schema = «negocio», Toba debería establecer el contexto, pero fijarlo a nivel de rol es más robusto y sobrevive a reconexiones y pools de conexión.
Jerarquía de permisos: USAGE sobre el esquema + SELECT sobre la tabla¶
En PostgreSQL los permisos son jerárquicos. Para leer una tabla necesitas dos cosas:
Nivel |
Permiso |
Qué controla |
|---|---|---|
Esquema |
USAGE |
Permite «entrar» al esquema y resolver nombres de objetos |
Tabla |
SELECT |
Permite leer los datos de la tabla |
Si falta USAGE, el error es permiso denegado al esquema. Si falta SELECT, el error es permiso denegado a la tabla.
Comandos para asignar ambos niveles (ejecutar como superusuario, por cada esquema que use Guaraní):
-- Para el esquema de negocio
GRANT USAGE ON SCHEMA negocio TO usuario-guarani;
GRANT SELECT ON ALL TABLES IN SCHEMA negocio TO usuario-guarani;
-- Para el esquema de metadatos de Toba (si aplica)
GRANT USAGE ON SCHEMA desarrollo TO usuario-guarani;
GRANT SELECT ON ALL TABLES IN SCHEMA desarrollo TO usuario-guarani;
El futuro: tablas que se crearán después¶
GRANT ... ON ALL TABLES IN SCHEMA solo afecta a las tablas que ya existen. Si Guaraní o Toba crean nuevas tablas durante una migración o actualización,
el usuario nuevo no tendrá permisos automáticamente.
Para evitarlo, configurar privilegios predeterminados ejecutando el comando como el propietario de las tablas (normalmente el usuario que ejecuta las migraciones de Guaraní, o postgres si es el dueño original):
ALTER DEFAULT PRIVILEGES IN SCHEMA negocio GRANT SELECT ON TABLES TO usuario-guarani;
ALTER DEFAULT PRIVILEGES IN SCHEMA desarrollo GRANT SELECT ON TABLES TO usuario-guarani;
Esto garantiza que las tablas creadas en el futuro hereden el SELECT para el usuario .
Verificación final¶
Conectar con el usuario nuevo y ejecutar estas pruebas:
-- 1. El search_path es correcto
SHOW search_path;
-- 2. La tabla de negocio es visible sin prefijo
SELECT trim(version_app) FROM app_versiones_base ORDER BY id_conversion DESC LIMIT 1;
-- 3. La tabla de metadatos de Toba es visible
SELECT * FROM apex_proyecto LIMIT 1;
Si las tres consultas funcionan sin errores, la aplicación web debería cargar sin los Undefined table ni permiso denegado.
Chequeo rápido de migración¶
[ ] ¿Exportaste los roles con
pg_dumpall --globals-onlyantes de tocar la base de datos?[ ] ¿Creaste los roles en el destino antes de restaurar el dump de negocio?
[ ] ¿Fijaste
ALTER ROLE … SET search_pathcon los esquemas negocio (y desarrollo si aplica)?[ ] ¿Otorgaste
USAGEsobre cada esquema ySELECTsobre cada tabla?[ ] ¿Configuraste
ALTER DEFAULT PRIVILEGESpara tablas futuras?[ ] ¿Actualizaste el
bases.inicon el nuevo usuario y contraseña en todos los bloques que apuntan aBD-GUARANI?[ ] ¿Reiniciaste el servicio web o PHP-FPM después de cambiar
bases.ini?
Con estos pasos, la migración se convierte en un procedimiento reproducible.