PostgreSQL es una base de datos relacional de código abierto conocida por su fiabilidad, su cumplimiento estricto de SQL y funciones como JSONB, búsqueda de texto completo y extensiones como PostGIS. En este tutorial instalarás PostgreSQL en Ubuntu 24.04, crearás un rol y una base de datos para tu aplicación, habilitarás conexiones remotas de forma segura, ajustarás la memoria y programarás copias de seguridad diarias.

Requisitos previos

  • Un servidor con Ubuntu 24.04 LTS, por ejemplo un VPS de CubePath.
  • Un usuario no root con privilegios sudo.
  • Al menos 1 GB de RAM; 2 GB o más para cargas reales.

Paso 1: Instalar PostgreSQL

Ubuntu 24.04 incluye PostgreSQL 16 en sus repositorios, con actualizaciones de seguridad durante toda la vida de la distribución. Es la opción más sencilla:

sudo apt update
sudo apt install postgresql

El paquete crea y arranca automáticamente un clúster llamado main. Compruébalo con pg_lsclusters, la herramienta de Ubuntu para gestionar clústeres:

pg_lsclusters
Ver Cluster Port Status Owner    Data directory              Log file
16  main    5432 online postgres /var/lib/postgresql/16/main /var/log/postgresql/postgresql-16-main.log

El estado debe ser online. Las rutas más importantes son:

RutaContenido
/etc/postgresql/16/main/postgresql.confConfiguración del servidor
/etc/postgresql/16/main/pg_hba.confReglas de autenticación de clientes
/etc/postgresql/16/main/conf.d/Archivos de configuración adicionales
/var/lib/postgresql/16/mainDatos
/var/log/postgresql/Logs

Paso 2: Conectarse como el usuario postgres

La instalación crea el usuario del sistema postgres y un rol de base de datos con el mismo nombre, que es el superusuario. Por defecto usa la autenticación peer: el sistema comprueba que el usuario de Linux coincide con el rol de PostgreSQL, sin contraseña. Por eso se entra así:

sudo -u postgres psql
psql (16.10 (Ubuntu 16.10-0ubuntu0.24.04.1))
Type "help" for help.

postgres=#

Algunos comandos útiles dentro de psql: \l lista las bases de datos, \du los roles, \dt las tablas de la base actual y \q sale. No hace falta asignar contraseña al rol postgres: mientras solo se use localmente con sudo, la autenticación peer es más segura. Sal con:

\q

Paso 3: Crear un rol y una base de datos

Cada aplicación debe tener su propio rol, sin privilegios de superusuario, y ser propietaria de su base de datos. Crea el rol; el parámetro --pwprompt pide la contraseña de forma interactiva, sin que quede en el historial de la shell:

sudo -u postgres createuser --pwprompt app_user

Introduce una contraseña larga y aleatoria (puedes generarla con openssl rand -base64 24). Crea la base de datos con app_user como propietario:

sudo -u postgres createdb --owner=app_user app_db

Como propietario, app_user puede crear tablas en el esquema public de app_db. Desde PostgreSQL 15, el resto de roles ya no pueden crear objetos en ese esquema por defecto.

Comprueba la conexión con contraseña a través de TCP. Usar -h 127.0.0.1 es importante: sin él, psql usaría el socket local y la autenticación peer, que falla porque no existe un usuario de Linux llamado app_user:

psql -h 127.0.0.1 -U app_user -d app_db -c "SELECT current_user, current_database();"
 current_user | current_database
--------------+------------------
 app_user     | app_db
(1 row)

La cadena de conexión para tu aplicación será postgresql://app_user:[email protected]:5432/app_db.

Paso 4: Ajustar la memoria y el registro

Los valores por defecto de PostgreSQL son muy conservadores (por ejemplo, shared_buffers de 128 MB). En Ubuntu, postgresql.conf incluye todos los archivos del directorio conf.d/, así que puedes poner tus ajustes en un archivo aparte y dejar intacto el original:

sudo nano /etc/postgresql/16/main/conf.d/tuning.conf

Estos valores son un punto de partida para un servidor con 4 GB de RAM dedicado a PostgreSQL:

# Caché propia de PostgreSQL: alrededor del 25 % de la RAM
shared_buffers = 1GB

# Estimación de la caché total (PostgreSQL + sistema de archivos): 50-75 % de la RAM.
# No reserva memoria, solo orienta al planificador de consultas.
effective_cache_size = 3GB

# Memoria por operación de ordenación o hash. Una consulta puede usar varias,
# y se multiplica por el número de conexiones activas.
work_mem = 16MB

# Memoria para VACUUM, CREATE INDEX y similares
maintenance_work_mem = 256MB

# Conexiones simultáneas máximas
max_connections = 100

# Registrar consultas que tardan más de 500 ms
log_min_duration_statement = 500ms

Si el servidor comparte RAM con la aplicación, reduce shared_buffers y effective_cache_size en proporción. Si necesitas cientos de conexiones, no subas max_connections sin más: usa un pooler como PgBouncer.

shared_buffers y max_connections solo cambian al reiniciar el servidor:

sudo systemctl restart postgresql@16-main

Verifica los valores:

sudo -u postgres psql -c "SHOW shared_buffers;" -c "SHOW work_mem;"
 shared_buffers
----------------
 1GB
(1 row)

 work_mem
----------
 16MB
(1 row)

Si el servicio no arranca, revisa el log con sudo tail -n 20 /var/log/postgresql/postgresql-16-main.log; indicará el parámetro erróneo.

Paso 5: Permitir conexiones remotas (opcional)

Por defecto PostgreSQL solo escucha en localhost. Si la aplicación está en el mismo servidor, sáltate este paso. Si está en otra máquina, necesitas tres cambios: la dirección de escucha, una regla en pg_hba.conf y el firewall.

Añade la dirección de escucha en tu archivo de ajustes:

sudo nano /etc/postgresql/16/main/conf.d/tuning.conf
listen_addresses = 'localhost,your_server_ip'

Usa la IP privada del servidor si la aplicación está en la misma red privada, o '*' para escuchar en todas las interfaces. A continuación, permite al rol conectarse desde la IP de la aplicación, representada aquí como 203.0.113.10:

sudo nano /etc/postgresql/16/main/pg_hba.conf

Añade esta línea al final del archivo:

hostssl  app_db  app_user  203.0.113.10/32  scram-sha-256

Cada columna indica tipo de conexión, base de datos, rol, origen y método de autenticación. hostssl solo acepta conexiones cifradas con TLS: el paquete de Ubuntu activa ssl = on por defecto con un certificado autofirmado, suficiente para cifrar el tráfico. scram-sha-256 es el método de contraseña recomendado.

Reinicia PostgreSQL para aplicar listen_addresses y abre el puerto solo para la IP de la aplicación:

sudo systemctl restart postgresql@16-main
sudo ufw allow from 203.0.113.10 to any port 5432 proto tcp

Nunca abras el puerto 5432 a todo Internet. Comprueba que escucha en la nueva dirección:

sudo ss -tlnp | grep 5432
LISTEN 0      200     203.0.113.50:5432      0.0.0.0:*    users:(("postgres",pid=5210,fd=7))
LISTEN 0      200        127.0.0.1:5432      0.0.0.0:*    users:(("postgres",pid=5210,fd=6))

Desde el servidor de la aplicación, prueba la conexión forzando TLS:

psql "host=your_server_ip dbname=app_db user=app_user sslmode=require"

Para cambios posteriores solo en pg_hba.conf basta con recargar: sudo systemctl reload postgresql@16-main.

Paso 6: Programar copias de seguridad

pg_dump genera una copia coherente de una base de datos sin detener el servicio. El formato personalizado (-Fc) va comprimido y permite restaurar tablas concretas con pg_restore. Los roles y sus contraseñas no se guardan en pg_dump, así que el script también ejecuta pg_dumpall --globals-only.

Crea el directorio de copias, propiedad de postgres:

sudo install -d -m 700 -o postgres -g postgres /var/backups/postgresql

Crea el script:

sudo nano /usr/local/bin/pg-backup.sh
#!/usr/bin/env bash
set -euo pipefail

BACKUP_DIR="/var/backups/postgresql"
RETENTION_DAYS=7
STAMP="$(date +%F_%H%M)"
cd "$BACKUP_DIR"

# Roles y configuración global
pg_dumpall --globals-only > "${BACKUP_DIR}/globals_${STAMP}.sql"

# Una copia por cada base de datos que admite conexiones
psql -AtX -c "SELECT datname FROM pg_database WHERE datallowconn AND NOT datistemplate" |
while read -r db; do
    pg_dump -Fc -f "${BACKUP_DIR}/${db}_${STAMP}.dump" "$db"
done

# Borrar copias más antiguas que la retención
find "$BACKUP_DIR" -type f \( -name '*.dump' -o -name '*.sql' \) -mtime +"$RETENTION_DAYS" -delete

El script se ejecuta como el usuario del sistema postgres, que se autentica por peer, así que no necesita guardar contraseñas. Hazlo ejecutable y pruébalo:

sudo chmod 755 /usr/local/bin/pg-backup.sh
sudo -u postgres /usr/local/bin/pg-backup.sh
sudo ls -lh /var/backups/postgresql
-rw-r--r-- 1 postgres postgres 3.4K Sep 25 11:20 app_db_2026-09-25_1120.dump
-rw-r--r-- 1 postgres postgres  512 Sep 25 11:20 globals_2026-09-25_1120.sql
-rw-r--r-- 1 postgres postgres 1.1K Sep 25 11:20 postgres_2026-09-25_1120.dump

Prográmalo a diario a las 3:15 con cron, ejecutándose como postgres:

echo '15 3 * * * postgres /usr/local/bin/pg-backup.sh' | sudo tee /etc/cron.d/pg-backup

Para restaurar una copia, crea una base de datos vacía con el mismo propietario y usa pg_restore:

sudo -u postgres createdb --owner=app_user app_db_restored
sudo -u postgres pg_restore -d app_db_restored /var/backups/postgresql/app_db_2026-09-25_1120.dump

Solución de problemas

FATAL: Peer authentication failed for user "app_user". Te estás conectando por el socket local, que usa peer. Añade -h 127.0.0.1 para conectar por TCP con contraseña.

FATAL: no pg_hba.conf entry for host "203.0.113.10", user "app_user", database "app_db", no encryption. No hay una regla que coincida con esa combinación, o el cliente no usa TLS y la regla es hostssl. Revisa la línea de pg_hba.conf, conecta con sslmode=require y recarga el servicio.

Connection refused desde otra máquina. PostgreSQL no escucha en esa interfaz o el firewall bloquea el puerto. Comprueba listen_addresses con sudo -u postgres psql -c "SHOW listen_addresses;", la salida de ss -tlnp y sudo ufw status.

ERROR: permission denied for schema public. El rol no es propietario de la base de datos. Desde PostgreSQL 15, los roles que no son propietarios necesitan permiso explícito: GRANT CREATE ON SCHEMA public TO app_user; ejecutado en esa base de datos, o cambia el propietario con ALTER DATABASE app_db OWNER TO app_user;.

El clúster aparece como down. Revisa pg_lsclusters y el log de /var/log/postgresql/. Un error en un archivo de conf.d/ o en pg_hba.conf impide el arranque; corrígelo y ejecuta sudo systemctl start postgresql@16-main.

Conclusión

Tienes PostgreSQL funcionando en Ubuntu 24.04 con un rol y una base de datos dedicados a tu aplicación, memoria ajustada al servidor, registro de consultas lentas, acceso remoto limitado a una IP y cifrado, y copias de seguridad diarias con rotación.

Como siguientes pasos puedes:

  • Activar la extensión pg_stat_statements para ver qué consultas consumen más tiempo.
  • Instalar PgBouncer si tu aplicación abre muchas conexiones cortas.
  • Configurar una réplica en streaming para alta disponibilidad.