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"
-- 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

ComandoDescripción
\lListar todas las bases de datos
\c dbnameConectar a una base de datos
\dtListar tablas en el esquema actual
\dt+Listar tablas con tamaños
\d tablenameDescribir una tabla
\diListar índices
\dvListar vistas
\dfListar funciones
\duListar roles/usuarios
\dnListar esquemas
\dpListar privilegios de acceso a tablas
\xAlternar visualización expandida
\timingAlternar medición de tiempo de consultas
\i file.sqlEjecutar un archivo SQL
\o file.txtEnviar salida a un archivo
\eAbrir consulta en el editor
\copyComando COPY del lado del cliente
\passwordCambiar contraseña de usuario
\conninfoMostrar información de conexión
\qSalir 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