PostgreSQL es el sistema de base de datos relacional de código abierto más avanzado en uso productivo actualmente. Confiado por organizaciones que van desde startups hasta grandes empresas, impulsa todo desde pequeñas aplicaciones web hasta sistemas masivos de almacenamiento de datos que procesan miles de millones de filas. Esta guía te lleva paso a paso a través de la instalación de PostgreSQL en Ubuntu Server, su configuración para uso en producción, la configuración de autenticación y acceso remoto, la implementación de estrategias de respaldo y la optimización de parámetros de rendimiento para un rendimiento óptimo.
Requisitos Previos
Antes de comenzar, asegúrate de tener:
- Ubuntu Server 20.04, 22.04 o 24.04 LTS
- Acceso a terminal con privilegios sudo
- Al menos 1 GB de RAM (2 GB o más recomendado para producción)
- Familiaridad básica con SQL y operaciones de línea de comandos en Linux
- Un firewall configurado (consulta nuestra guía de UFW para la configuración)
¿Qué es PostgreSQL?
PostgreSQL (frecuentemente llamado “Postgres”) es un sistema de gestión de bases de datos objeto-relacional (ORDBMS) que ha estado en desarrollo activo durante más de 35 años. Originalmente desarrollado en la Universidad de California, Berkeley, ahora es mantenido por una comunidad global de contribuidores.
Características clave de PostgreSQL:
- Cumplimiento ACID — soporte completo para atomicidad, consistencia, aislamiento y durabilidad
- MVCC (Control de Concurrencia Multi-Versión) — los lectores nunca bloquean a los escritores y los escritores nunca bloquean a los lectores
- Extensible — tipos de datos personalizados, operadores, funciones y métodos de índice
- Cumplimiento de estándares — la implementación más cercana al estándar SQL entre todas las bases de datos
- Características avanzadas — JSON/JSONB, búsqueda de texto completo, particionamiento de tablas, replicación lógica, CTEs, funciones de ventana
- Seguridad robusta — seguridad a nivel de fila, SSL/TLS, múltiples métodos de autenticación
Instalación de PostgreSQL en Ubuntu
Opción 1: Instalar desde los Repositorios de Ubuntu
El enfoque más simple usa los paquetes predeterminados de Ubuntu:
sudo apt update
sudo apt install postgresql postgresql-contrib
Esto instala la versión incluida con tu versión de Ubuntu (PostgreSQL 14 en 22.04, PostgreSQL 16 en 24.04).
Opción 2: Instalar la Última Versión desde el Repositorio Oficial
Para obtener la última versión de PostgreSQL (versión 17 al momento de escribir), agrega el repositorio APT oficial de PostgreSQL:
sudo apt install -y gnupg2 wget
sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list'
wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo gpg --dearmor -o /usr/share/keyrings/postgresql-archive-keyring.gpg
Actualiza las referencias del repositorio en la lista de fuentes para usar el llavero firmado:
sudo sed -i 's|deb http://apt.postgresql.org|deb [signed-by=/usr/share/keyrings/postgresql-archive-keyring.gpg] http://apt.postgresql.org|' /etc/apt/sources.list.d/pgdg.list
sudo apt update
sudo apt install -y postgresql-17 postgresql-contrib-17
Verificar la Instalación
Después de la instalación, PostgreSQL se inicia automáticamente. Verifica que esté ejecutándose:
sudo systemctl status postgresql
Comprueba la versión instalada:
psql --version
Salida esperada:
psql (PostgreSQL) 17.x
Configuración Inicial
PostgreSQL almacena su configuración en dos archivos principales. En Ubuntu, estos se encuentran en /etc/postgresql/<versión>/main/.
postgresql.conf — Configuración del Servidor
Este archivo controla el comportamiento del servidor, configuraciones de rendimiento, registro y parámetros de conexión:
sudo nano /etc/postgresql/17/main/postgresql.conf
Configuraciones clave a revisar inmediatamente:
# Configuración de conexión
listen_addresses = 'localhost' # Cambiar a '*' o IP específica para acceso remoto
port = 5432 # Puerto predeterminado de PostgreSQL
max_connections = 100 # Conexiones simultáneas máximas
# Configuración de memoria (ajustar según la RAM de tu servidor)
shared_buffers = 256MB # Comenzar con 25% de la RAM total
work_mem = 4MB # Memoria de ordenamiento por operación
maintenance_work_mem = 128MB # Para VACUUM, CREATE INDEX
# Write-Ahead Logging
wal_level = replica # Habilita replicación y PITR
max_wal_size = 1GB
min_wal_size = 80MB
# Registro
logging_collector = on
log_directory = 'log'
log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log'
log_statement = 'ddl' # Registrar sentencias DDL
log_min_duration_statement = 1000 # Registrar consultas que tarden más de 1 segundo
pg_hba.conf — Autenticación de Clientes
Este archivo controla quién puede conectarse, desde dónde y cómo se autentican:
sudo nano /etc/postgresql/17/main/pg_hba.conf
La configuración predeterminada típicamente se ve así:
# TYPE DATABASE USER ADDRESS METHOD
local all postgres peer
local all all peer
host all all 127.0.0.1/32 scram-sha-256
host all all ::1/128 scram-sha-256
Después de hacer cambios en cualquiera de los archivos, reinicia PostgreSQL:
sudo systemctl restart postgresql
O recarga sin reiniciar (para la mayoría de cambios en pg_hba.conf):
sudo systemctl reload postgresql
Métodos de Autenticación
PostgreSQL soporta múltiples métodos de autenticación. Comprenderlos es esencial para asegurar tu base de datos.
Autenticación peer
Mapea el nombre de usuario del sistema operativo a un rol de PostgreSQL. Si estás conectado como el usuario del sistema postgres, puedes conectarte al rol de base de datos postgres sin contraseña:
sudo -u postgres psql
Este es el predeterminado para conexiones locales por socket Unix y es seguro porque depende de la autenticación del sistema operativo.
Autenticación md5
Usa contraseñas con hash MD5. Aunque todavía funcional, se considera legado:
host all all 192.168.1.0/24 md5
Autenticación scram-sha-256 (Recomendada)
El método basado en contraseña más seguro, usando el mecanismo de desafío-respuesta SCRAM-SHA-256:
host all all 192.168.1.0/24 scram-sha-256
Para asegurar que las nuevas contraseñas usen SCRAM-SHA-256, establece esto en postgresql.conf:
password_encryption = scram-sha-256
Importante: Si cambias de md5 a scram-sha-256, las contraseñas de usuarios existentes deben restablecerse porque el formato de hash almacenado es diferente.
Creación de Bases de Datos y Usuarios
Conéctate a PostgreSQL como el superusuario:
sudo -u postgres psql
Crear un Nuevo Rol (Usuario)
CREATE ROLE appuser WITH LOGIN PASSWORD 'StrongPassword123!';
Otorgar capacidades específicas:
ALTER ROLE appuser CREATEDB;
Crear una Base de Datos
CREATE DATABASE myappdb OWNER appuser;
O desde la línea de comandos:
sudo -u postgres createdb -O appuser myappdb
Otorgar Privilegios
GRANT ALL PRIVILEGES ON DATABASE myappdb TO appuser;
Para un control más granular en esquemas y tablas:
\c myappdb
GRANT USAGE ON SCHEMA public TO appuser;
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO appuser;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO appuser;
Conectar como el Nuevo Usuario
psql -U appuser -d myappdb -h localhost
Configuración de Acceso Remoto
Por defecto, PostgreSQL solo acepta conexiones desde localhost. Para habilitar el acceso remoto:
Paso 1: Actualizar listen_addresses
Edita postgresql.conf:
listen_addresses = '*'
O restringe a una interfaz específica:
listen_addresses = '192.168.1.10'
Paso 2: Agregar Entrada en pg_hba.conf
Permitir una subred específica:
host myappdb appuser 192.168.1.0/24 scram-sha-256
Permitir un host único:
host all all 10.0.0.50/32 scram-sha-256
Paso 3: Configurar el Firewall
Permite PostgreSQL a través de UFW:
sudo ufw allow from 192.168.1.0/24 to any port 5432
O permite desde cualquier lugar (no recomendado para producción):
sudo ufw allow 5432/tcp
Paso 4: Reiniciar y Probar
sudo systemctl restart postgresql
Prueba desde la máquina remota:
psql -h 192.168.1.10 -U appuser -d myappdb
Comandos Esenciales de psql
El terminal interactivo psql es la herramienta principal para trabajar con PostgreSQL. Aquí están los comandos que usarás diariamente:
Conectar
# Conectar como superusuario postgres
sudo -u postgres psql
# Conectar a una base de datos específica
psql -U appuser -d myappdb -h localhost
# Conectar con una cadena de conexión
psql "postgresql://appuser:password@localhost:5432/myappdb"
Navegación e Información
-- Listar todas las bases de datos
\l
-- Conectar a una base de datos diferente
\c myappdb
-- Listar todas las tablas en el esquema actual
\dt
-- Describir la estructura de una tabla
\d tablename
-- Listar todos los esquemas
\dn
-- Listar todos los roles/usuarios
\du
-- Mostrar información de conexión actual
\conninfo
Ejecución de Consultas
-- Ejecutar una consulta
SELECT * FROM users LIMIT 10;
-- Habilitar visualización expandida para tablas anchas
\x auto
-- Medir tiempo de ejecución de consultas
\timing on
-- Ejecutar un archivo SQL
\i /path/to/script.sql
-- Guardar salida de consulta en un archivo
\o /tmp/output.txt
SELECT * FROM users;
\o
Salir
-- Salir de psql
\q
Respaldo y Restauración
Una estrategia de respaldo sólida es innegociable para bases de datos en producción.
pg_dump — Respaldos Lógicos
Exportar una sola base de datos:
# Formato SQL (legible por humanos)
sudo -u postgres pg_dump myappdb > /backups/myappdb_$(date +%Y%m%d).sql
# Formato personalizado (comprimido, soporta restauración paralela)
sudo -u postgres pg_dump -Fc myappdb > /backups/myappdb_$(date +%Y%m%d).dump
# Solo tablas específicas
sudo -u postgres pg_dump -t users -t orders myappdb > /backups/tables_$(date +%Y%m%d).sql
Exportar todas las bases de datos:
sudo -u postgres pg_dumpall > /backups/all_databases_$(date +%Y%m%d).sql
pg_restore — Restaurar Respaldos
Restaurar desde formato personalizado:
sudo -u postgres pg_restore -d myappdb /backups/myappdb_20260128.dump
Restaurar con trabajos paralelos para recuperación más rápida:
sudo -u postgres pg_restore -j 4 -d myappdb /backups/myappdb_20260128.dump
Restaurar desde formato SQL:
sudo -u postgres psql myappdb < /backups/myappdb_20260128.sql
pg_basebackup — Respaldos Físicos
Para recuperación en un punto en el tiempo (PITR) y configuración de replicación:
sudo -u postgres pg_basebackup -D /backups/base -Ft -Xs -P
Opciones explicadas:
-D— directorio de destino-Ft— formato tar-Xs— transmitir archivos WAL durante el respaldo-P— mostrar progreso
Script de Respaldo Automatizado
Crea un trabajo cron para respaldos diarios:
sudo nano /usr/local/bin/pg_backup.sh
#!/bin/bash
BACKUP_DIR="/backups/postgresql"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
RETENTION_DAYS=30
mkdir -p "$BACKUP_DIR"
# Volcar todas las bases de datos en formato personalizado
for DB in $(sudo -u postgres psql -At -c "SELECT datname FROM pg_database WHERE datistemplate = false AND datname != 'postgres';"); do
sudo -u postgres pg_dump -Fc "$DB" > "$BACKUP_DIR/${DB}_${TIMESTAMP}.dump"
done
# Eliminar respaldos más antiguos que el período de retención
find "$BACKUP_DIR" -name "*.dump" -mtime +$RETENTION_DAYS -delete
echo "Backup completed: $TIMESTAMP"
sudo chmod +x /usr/local/bin/pg_backup.sh
sudo crontab -e
Agrega la entrada de cron:
0 2 * * * /usr/local/bin/pg_backup.sh >> /var/log/pg_backup.log 2>&1
Optimización del Rendimiento
El rendimiento de PostgreSQL depende en gran medida de una configuración adecuada. Los valores predeterminados son conservadores y están diseñados para ejecutarse en hardware mínimo.
shared_buffers
El parámetro de memoria más importante. Establece cuánta memoria usa PostgreSQL para almacenar en caché bloques de datos:
# Recomendado: 25% de la RAM total del sistema
# Para un servidor con 16 GB de RAM:
shared_buffers = 4GB
work_mem
Memoria asignada para cada operación de ordenamiento, hash join u operación similar. Ten cuidado — esto es por operación, no por conexión:
# Para cargas OLTP con muchas conexiones:
work_mem = 4MB
# Para consultas analíticas con menos conexiones:
work_mem = 64MB
effective_cache_size
Indica al planificador de consultas cuánta memoria está disponible para caché (caché del SO + shared_buffers). No asigna memoria — solo influye en la planificación de consultas:
# Recomendado: 50-75% de la RAM total del sistema
# Para un servidor con 16 GB de RAM:
effective_cache_size = 12GB
Configuración WAL
Las configuraciones de Write-Ahead Logging impactan significativamente el rendimiento de escritura:
# Configuración de checkpoints
checkpoint_completion_target = 0.9
max_wal_size = 2GB
min_wal_size = 1GB
# Para cargas de escritura intensiva
wal_buffers = 64MB
synchronous_commit = on # Establecer a 'off' solo si puedes tolerar pérdida mínima de datos
Conexiones y Paralelismo
# Conexiones máximas (cada una consume ~10MB de RAM)
max_connections = 200
# Ejecución de consultas paralelas
max_parallel_workers_per_gather = 2
max_parallel_workers = 4
max_worker_processes = 8
Después de la Optimización
Aplica los cambios reiniciando PostgreSQL:
sudo systemctl restart postgresql
Verifica las configuraciones:
SHOW shared_buffers;
SHOW work_mem;
SHOW effective_cache_size;
Monitoreo con pg_stat_activity
La vista pg_stat_activity proporciona información en tiempo real sobre todas las conexiones y consultas activas.
Ver Consultas Activas
SELECT pid, usename, datname, state, query, query_start,
now() - query_start AS duration
FROM pg_stat_activity
WHERE state = 'active'
ORDER BY duration DESC;
Encontrar Consultas de Larga Duración
SELECT pid, usename, datname, query,
now() - query_start AS duration
FROM pg_stat_activity
WHERE state = 'active'
AND now() - query_start > interval '5 minutes';
Cancelar o Terminar una Consulta
-- Cancelación elegante (envía SIGINT)
SELECT pg_cancel_backend(12345);
-- Terminación forzada (envía SIGTERM)
SELECT pg_terminate_backend(12345);
Estadísticas de Base de Datos
-- Estadísticas a nivel de base de datos
SELECT datname, numbackends, xact_commit, xact_rollback,
blks_read, blks_hit,
round(blks_hit::numeric / (blks_read + blks_hit) * 100, 2) AS cache_hit_ratio
FROM pg_stat_database
WHERE datname = 'myappdb';
Estadísticas de Tablas
-- Estadísticas de acceso a tablas
SELECT relname, seq_scan, idx_scan, n_tup_ins, n_tup_upd, n_tup_del, n_live_tup
FROM pg_stat_user_tables
ORDER BY seq_scan DESC;
Monitoreo de Bloqueos
-- Ver bloqueos actuales
SELECT pid, locktype, relation::regclass, mode, granted
FROM pg_locks
WHERE NOT granted;
Tabla de Referencia de Comandos psql
| Comando | Descripción |
|---|---|
\l | Listar todas las bases de datos |
\c dbname | Conectar a una base de datos |
\dt | Listar tablas en el esquema actual |
\dt+ | Listar tablas con tamaños |
\d tablename | Describir una tabla |
\di | Listar índices |
\dv | Listar vistas |
\df | Listar funciones |
\du | Listar roles/usuarios |
\dn | Listar esquemas |
\dp | Listar privilegios de acceso a tablas |
\x | Alternar visualización expandida |
\timing | Alternar medición de tiempo de consultas |
\i file.sql | Ejecutar un archivo SQL |
\o file.txt | Enviar salida a un archivo |
\e | Abrir consulta en el editor |
\copy | Comando COPY del lado del cliente |
\password | Cambiar contraseña de usuario |
\conninfo | Mostrar información de conexión |
\q | Salir de psql |
Solución de Problemas
PostgreSQL No Inicia
Revisa los registros en busca de errores:
sudo journalctl -u postgresql -n 50
sudo cat /var/log/postgresql/postgresql-17-main.log
Causas comunes:
- El puerto 5432 ya está en uso por otra instancia
- Archivos de configuración corruptos (errores de sintaxis en postgresql.conf)
- Memoria compartida insuficiente — verifica el valor de
shared_buffers
Conexión Rechazada
Si obtienes psql: error: connection refused:
# Verificar que PostgreSQL esté ejecutándose
sudo systemctl status postgresql
# Verificar en qué dirección y puerto está escuchando
sudo ss -tlnp | grep 5432
# Verificar que pg_hba.conf permite tu conexión
sudo cat /etc/postgresql/17/main/pg_hba.conf
Autenticación Fallida
FATAL: password authentication failed for user "appuser"
Verifica la contraseña y el método de autenticación:
# Verificar el método de autenticación en pg_hba.conf
sudo grep -v '^#' /etc/postgresql/17/main/pg_hba.conf | grep -v '^$'
# Restablecer contraseña vía autenticación peer
sudo -u postgres psql -c "ALTER USER appuser PASSWORD 'NewPassword123!';"
Consultas Lentas
Habilita el registro de consultas lentas:
# En postgresql.conf
log_min_duration_statement = 500 # Registrar consultas que tarden más de 500ms
Usa EXPLAIN ANALYZE para diagnosticar:
EXPLAIN ANALYZE SELECT * FROM orders WHERE customer_id = 42;
Busca escaneos secuenciales en tablas grandes y agrega índices donde sea necesario:
CREATE INDEX idx_orders_customer_id ON orders(customer_id);
Problemas de Espacio en Disco
Verifica los tamaños de las bases de datos:
SELECT pg_database.datname,
pg_size_pretty(pg_database_size(pg_database.datname)) AS size
FROM pg_database
ORDER BY pg_database_size(pg_database.datname) DESC;
Encuentra las tablas más grandes:
SELECT relname, pg_size_pretty(pg_total_relation_size(relid)) AS total_size
FROM pg_catalog.pg_statio_user_tables
ORDER BY pg_total_relation_size(relid) DESC
LIMIT 10;
Ejecuta VACUUM para recuperar espacio:
sudo -u postgres vacuumdb --all --analyze
Resumen
PostgreSQL es una base de datos potente y lista para producción que recompensa la configuración adecuada. En esta guía, aprendiste cómo instalar PostgreSQL desde el repositorio oficial, configurar la autenticación con scram-sha-256, crear bases de datos y roles, habilitar el acceso remoto de forma segura, implementar estrategias de respaldo con pg_dump y pg_basebackup, optimizar parámetros de rendimiento para tu hardware y monitorear la actividad de la base de datos con pg_stat_activity.
Para un enfoque completo de endurecimiento del servidor, combina esta configuración con un firewall correctamente configurado — consulta nuestra guía de Firewall UFW para instrucciones detalladas. También deberías revisar nuestra Lista de Verificación de Seguridad para Servidores Linux para asegurar que toda tu pila de servidor siga las mejores prácticas de seguridad desde el nivel del sistema operativo.
Próximos pasos a considerar:
- Configurar replicación en streaming para alta disponibilidad
- Implementar pool de conexiones con PgBouncer para aplicaciones de alto tráfico
- Configurar conexiones SSL/TLS para comunicación cifrada entre cliente y servidor
- Explorar replicación lógica para migraciones sin tiempo de inactividad