---
title: "De GitHub a producción: despliega Next.js, PostgreSQL y un dominio personalizado"
description: "Despliega una aplicación Next.js junto con PostgreSQL en tu propio servidor con Zenavo, configura la conexión por red privada, las variables de compilación y de ejecución, las migraciones de Prisma, el dominio HTTPS y el despliegue automático."
date: 2026-11-10
language: es-ES
url: https://zenavo.app/es-ES/blog/deploy-nextjs-postgresql
---

# De GitHub a producción: despliega Next.js, PostgreSQL y un dominio personalizado

Llevar una aplicación Next.js desde tu ordenador hasta producción suele reducirse a cinco pasos: el script de arranque, la conexión a la base de datos, las variables de entorno (distinguiendo las de compilación de las de ejecución), las migraciones de tablas y el dominio con HTTPS.

En esta guía tomamos un repositorio existente de Next.js y lo desplegamos junto con PostgreSQL en tu propio servidor. Antes de empezar, [conecta un servidor Linux](https://docs.zenavo.app/es-ES/servers/add-a-server) a Zenavo.

## 1. Revisa el `package.json` de tu repositorio

Si el repositorio no tiene un `Dockerfile` propio, Zenavo usa zbpack para detectar y compilar Next.js automáticamente. Asegúrate de haber subido el archivo de bloqueo (`package-lock.json`, `pnpm-lock.yaml`, `yarn.lock` o `bun.lockb`) y de que `package.json` incluye los scripts estándar de producción:

```json
{
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start"
  },
  "engines": {
    "node": ">=20"
  }
}
```

Ejecuta `npm run build` en local una vez antes de desplegar para detectar a tiempo errores de tipos de TypeScript o fallos durante la compilación.

## 2. Despliega PostgreSQL

Crea un proyecto en Zenavo, elige el servidor, haz clic en **Añadir servicio → Base de datos → PostgreSQL**, selecciona la versión y despliega.

La base de datos corre en la red privada del proyecto y no expone su puerto a internet por defecto. En cuanto está lista, comparte sus variables de conexión con el resto de servicios del proyecto; cuando el servicio se llama `postgresql`, la variable con la cadena de conexión completa es `POSTGRESQL_CONNECTION_STRING`.

## 3. Añade la aplicación Next.js desde GitHub

En el mismo proyecto, haz clic en **Añadir servicio → GitHub**, autoriza a la GitHub App de Zenavo a leer tu repositorio y elige el repositorio, la rama y el directorio raíz (si es un monorepo y la web está en `apps/web`, pon `apps/web` como directorio raíz).

En las variables de entorno, haz referencia a la base de datos:

```dotenv
DATABASE_URL=${POSTGRESQL_CONNECTION_STRING}
```

`${POSTGRESQL_CONNECTION_STRING}` es una referencia entre servicios de Zenavo que en tiempo de ejecución se sustituye por la cadena de conexión interna real (si le pusiste otro nombre al servicio de base de datos, usa el nombre de variable que muestra la consola).

Por defecto, `next start` toma automáticamente la variable `PORT` que le pasa la plataforma. Si usas tu propio `Dockerfile` o un `server.js` personalizado, asegúrate de que escuche en `0.0.0.0` y en el mismo puerto HTTP configurado en el servicio de Zenavo. Tienes más detalles en la [guía de Next.js](https://docs.zenavo.app/es-ES/frameworks/nextjs).

## 4. Diferencia entre `NEXT_PUBLIC_*` y las variables de servidor

Next.js trata estos dos tipos de variables de entorno de forma muy distinta:

- **Variables de servidor** (como `DATABASE_URL`, claves de pasarelas de pago o API keys de IA): solo se leen en código de servidor y nunca deben llevar el prefijo `NEXT_PUBLIC_`. Cuando las cambias en la pestaña **Variable** de Zenavo, basta con reiniciar el servicio para aplicar el nuevo valor.
- **Variables `NEXT_PUBLIC_*`**: se incrustan directamente en el paquete JavaScript del navegador durante `next build`. **Si cambias una variable `NEXT_PUBLIC_*`, tienes que volver a desplegar (recompilar)**; reiniciar el contenedor no cambia el valor que ya quedó empaquetado.

Además, **las máquinas de compilación de Zenavo no tienen acceso a la base de datos privada de tu servidor durante `next build`**. Por tanto:

- No ejecutes migraciones de la base de datos de producción dentro del script `build`;
- Las páginas que consulten la base de datos deben usar renderizado dinámico en cada petición en lugar de pregenerarse estáticamente durante la compilación.

## 5. Ejecuta las migraciones al arrancar (ejemplo con Prisma)

Como durante la compilación no se puede conectar a la base de datos interna, las migraciones de esquema deben ejecutarse **justo antes de arrancar el contenedor**, no en `build`.

Si compilas con zbpack, puedes añadir un script `predeploy` en `package.json`, que se ejecuta automáticamente antes de `start` en cada despliegue:

```json
{
  "scripts": {
    "build": "prisma generate && next build",
    "predeploy": "prisma migrate deploy",
    "start": "next start"
  }
}
```

Dos detalles importantes:

- En producción usa siempre `prisma migrate deploy` (que aplica las migraciones subidas al repositorio), nunca `prisma migrate dev` ni `db push --force-reset`.
- Si usas tu propio `Dockerfile`, el gancho `predeploy` de zbpack no interviene: pon `npx prisma migrate deploy && npm start` en el `CMD` o `ENTRYPOINT` de tu Dockerfile.

## 6. Asocia un dominio y activa el despliegue automático

Cuando arranque la aplicación, entra en la pestaña **Red** del servicio, asocia tu dominio (como `app.example.com`), apunta un registro A de DNS a la IP del servidor y espera a que se emita automáticamente el certificado HTTPS (ver [Dominios y HTTPS](https://docs.zenavo.app/es-ES/networking/domains)). Si usas NextAuth / Auth.js, Clerk u OAuth, acuérdate de actualizar también `NEXTAUTH_URL` y las URL de callback en los paneles de terceros.

Abre la web, inicia sesión y prueba a crear, leer, editar y borrar un registro para confirmar que la aplicación lee y escribe en PostgreSQL.

En los **Ajustes** del servicio, activa **Desplegar automáticamente al hacer push a esta rama** para que cada `git push` compile y despliegue sin corte de servicio. En un monorepo puedes configurar rutas vigiladas para que solo se despliegue cuando cambie esa carpeta (ver [Desplegar desde GitHub](https://docs.zenavo.app/es-ES/deploy/github)).

## Preguntas frecuentes

**¿El registro de compilación falla con `Can't reach database server at postgresql.zenavo.internal:5432`?**
Tu script `build` o alguna página generada estáticamente (SSG) está intentando conectarse a la base de datos interna durante la compilación. Pasa las migraciones a `predeploy` (o al comando de arranque) y añade `export const dynamic = 'force-dynamic'` a las páginas que consulten la base de datos.

**¿He cambiado `NEXT_PUBLIC_API_URL` y reiniciado, pero la web sigue usando la dirección antigua?**
Las variables `NEXT_PUBLIC_*` se incrustan al compilar. Haz clic en **Volver a desplegar (Redeploy)** para lanzar una compilación nueva.

**¿Cómo vuelvo atrás si un despliegue nuevo tiene un fallo?**
Desde el historial de despliegues puedes revertir la aplicación a la imagen anterior con un clic. Ten en cuenta que **revertir el servicio restaura la imagen y las variables de la aplicación, pero no la base de datos**. Antes de aplicar migraciones destructivas (como borrar una columna), haz una copia de seguridad en la pestaña **Copias de seguridad y restauración** del servicio PostgreSQL.

Cuando tengas listo el repositorio, crea un proyecto en la [consola de Zenavo](https://zenavo.app): levanta PostgreSQL, conecta tu repositorio de GitHub, configura `DATABASE_URL` y asocia tu dominio para pasar de `git push` a producción en pocos minutos.
