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
Notasi necesitas una versión más reciente, el proyecto PostgreSQL mantiene su propio repositorio (PGDG). Instala
postgresql-commony ejecutasudo /usr/share/postgresql-common/pgdg/apt.postgresql.org.shpara añadirlo; después instala la versión concreta, por ejemplosudo apt install postgresql-18. En el resto de la guía, sustituye16por tu versión en las rutas.
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:
| Ruta | Contenido |
|---|---|
/etc/postgresql/16/main/postgresql.conf | Configuración del servidor |
/etc/postgresql/16/main/pg_hba.conf | Reglas de autenticación de clientes |
/etc/postgresql/16/main/conf.d/ | Archivos de configuración adicionales |
/var/lib/postgresql/16/main | Datos |
/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
Importanteguarda también una copia fuera del servidor, por ejemplo sincronizando
/var/backups/postgresqlconrsyncorclonea un almacenamiento de objetos. Si necesitas recuperar datos a un momento concreto, y no solo a la última copia diaria, estudia el archivado continuo de WAL con herramientas como pgBackRest.
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_statementspara 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.
