Montar una web con Apache, PHP 8 y PostgreSQL en Linux (actualizado 2026)

Artículo original de abril de 2000. Actualizado en mayo de 2026 por David Carrero. Las versiones originales (Apache 1.3, PHP 3, PostgreSQL 6.5) están muy lejos de la realidad actual, pero el artículo conserva el procedimiento histórico de compilación desde fuente como referencia.

Lo que ha cambiado en 26 años

En el año 2000, instalar Apache+PHP+PostgreSQL en Linux significaba descargar los tarballs, compilar todo desde cero con ./configure && make && make install y editar ficheros de configuración a mano. Era la única opción. Hoy ese proceso lleva unos minutos con el gestor de paquetes de cualquier distribución, o segundos con Docker.

Las versiones han cambiado radicalmente:

Componente

Año 2000

Año 2026

Apache

1.3.x

2.4.x (o Nginx/Caddy)

PHP

3.0.x

8.3 / 8.4 (PHP 5 llegó a EOL en 2018)

PostgreSQL

6.5.x

16.x / 17.x

SO

Linux compilando desde fuente

Paquetes, Docker, contenedores

PHP 3 no es compatible con ninguna versión moderna. La extensión pg_pconnect()/pg_Exec() que usaba el artículo original sigue existiendo en PHP 8 pero hay que usar sentencias preparadas para evitar inyección SQL.

Opción recomendada en 2026: Docker Compose

Para desarrollo local, Docker Compose levanta Apache, PHP y PostgreSQL en dos minutos sin tocar el sistema operativo host. Este es el compose.yml de partida:

services:
  web:
    image: php:8.3-apache
    ports:
      - "8080:80"
    volumes:
      - ./src:/var/www/html
    depends_on:
      - db
    environment:
      - DB_HOST=db
      - DB_NAME=prueba
      - DB_USER=webuser
      - DB_PASS=secreto

  db:
    image: postgres:16
    environment:
      POSTGRES_DB: prueba
      POSTGRES_USER: webuser
      POSTGRES_PASSWORD: secreto
    volumes:
      - pgdata:/var/lib/postgresql/data

volumes:
  pgdata:
# Levantar el stack completo
docker compose up -d

# Ver logs
docker compose logs -f web

La imagen oficial php:8.3-apache incluye Apache 2.4 configurado como módulo de PHP. Solo necesitas Docker instalado, nada más.

Para habilitar la extensión de PostgreSQL en esa imagen, añade un Dockerfile:

FROM php:8.3-apache
RUN apt-get update && apt-get install -y libpq-dev 
    && docker-php-ext-install pgsql pdo_pgsql 
    && a2enmod rewrite

Y en compose.yml cambia image: php:8.3-apache por build: ..

Instalación tradicional en servidor VPS o dedicado

Si prefieres instalar directamente en el sistema operativo (Ubuntu 24.04 / Debian 12), el proceso que en 2000 llevaba horas ahora tarda minutos:

# Ubuntu 24.04 / Debian 12
sudo apt update
sudo apt install -y apache2 php8.3 php8.3-pgsql php8.3-pdo-pgsql libapache2-mod-php8.3 postgresql

# Habilitar mod_rewrite
sudo a2enmod rewrite
sudo systemctl restart apache2

# Verificar versiones
php -v
psql --version
apache2 -v

En Red Hat / AlmaLinux / Rocky Linux:

sudo dnf install -y epel-release
sudo dnf install -y httpd php php-pgsql php-pdo postgresql-server postgresql-contrib

sudo postgresql-setup --initdb
sudo systemctl enable --now postgresql httpd

Configuración básica de PostgreSQL

Ya no hace falta compilar ni crear usuarios a mano. PostgreSQL en distribuciones modernas crea automáticamente el usuario del sistema postgres. Para crear una base de datos y un usuario web:

sudo -u postgres psql <<'SQL'
CREATE USER webuser WITH PASSWORD 'secreto';
CREATE DATABASE prueba OWNER webuser;
GRANT ALL PRIVILEGES ON DATABASE prueba TO webuser;
SQL

Para acceso desde PHP (que corre como el usuario de Apache, no como postgres), edita /etc/postgresql/16/main/pg_hba.conf y asegúrate de que la línea de conexiones locales usa md5 o scram-sha-256:

host    all             all             127.0.0.1/32            scram-sha-256

Código PHP histórico (referencia, año 2000)

El artículo original usaba funciones de PHP 3 para conectar a PostgreSQL. Las reproducimos tal cual, pero no las uses en proyectos nuevos: no tienen protección contra SQL injection:

<?php
// Código histórico PHP 3/4/5 — NO usar en proyectos nuevos
$conexion = pg_pconnect("host=servidor.domain.es port=5432 dbname=prueba");
$resultado_set = pg_Exec($conexion, "SELECT * FROM direcciones ORDER BY pais");
$filas = pg_NumRows($resultado_set);

for ($j = 0; $j < $filas; $j++) {
    echo "Dirección: " . pg_result($resultado_set, $j, 0) . "<br>";
}

pg_close($conexion);
?>

Conexión moderna con PDO en PHP 8

La versión equivalente con PDO es más segura, más expresiva y funciona igual con MySQL o SQLite si algún día cambias de motor:

<?php
$pdo = new PDO(
    'pgsql:host=localhost;port=5432;dbname=prueba',
    'webuser',
    'secreto',
    [
        PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
        PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
        PDO::ATTR_EMULATE_PREPARES   => false,
    ]
);

// Consulta con sentencia preparada (sin SQL injection)
$stmt = $pdo->prepare("SELECT calle, ciudad, pais FROM direcciones WHERE pais = :pais ORDER BY ciudad");
$stmt->execute([':pais' => $_GET['pais'] ?? 'España']);

foreach ($stmt->fetchAll() as $fila) {
    echo htmlspecialchars($fila['calle']) . ' — ' . htmlspecialchars($fila['ciudad']) . '<br>';
}
?>

Verificar que PHP ve PostgreSQL

Crea un fichero info.php en el directorio web (y bórralo después, nunca lo dejes en producción):

<?php phpinfo(); ?>

En la sección «pdo_pgsql» debes ver «enabled». Si no aparece, el módulo no está instalado.

Para más información sobre cómo interactuar con bases de datos relacionales desde PHP con PDO, consulta Cómo interactuar con una base de datos MySQL usando PHP 8 y PDO. Si necesitas gestionar las contraseñas de tus usuarios de forma segura, revisa Contraseñas seguras en PHP: de MD5 a bcrypt y Argon2.

Imagen: Pexels / Brett Sayles

COMPARTE ESTE ARTÍCULO

COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN LINKEDIN
COMPARTIR EN WHATSAPP