Cómo publicar varias webs y apps en un solo VPS con Coolify y Hostinger

Si estás creando aplicaciones con IA o vendiendo webs, no necesitas contratar un servidor distinto para cada proyecto. Puedes reunir una aplicación con su base de datos y varias páginas de clientes en un mismo VPS, cada una con su dirección, su código y su configuración.

A mí lo que me gusta de esta combinación es tener un proceso que pueda repetir. Preparo el servidor, conecto los repositorios y después publico y mantengo los proyectos desde Coolify. Cuando llega otro trabajo, ya tengo una base sobre la que avanzar.

Vamos a hacerlo con dos proyectos: Solicitudes, una aplicación con Next.js y PostgreSQL para registrar clientes y cambiar el estado de sus proyectos, y Signal, una landing con un gorila animado. Las dos van a funcionar en el mismo VPS de Hostinger.

Pero publicar es solo el comienzo. También vamos a comprobar qué ocurre con los datos cuando actualizamos, cómo volver a una versión anterior y cómo recuperar una copia de PostgreSQL sin tocar la base que está utilizando la aplicación.

Tabla de contenido

🧩 Qué aporta el VPS y qué hace Coolify

Un VPS es un servidor virtual que alquilas, con su sistema operativo, procesador, memoria y almacenamiento. Allí se ejecutan tus aplicaciones, aunque cierres el navegador o apagues tu computador. Hostinger proporciona esa infraestructura.

Coolify es el panel que instalamos dentro del servidor para organizar las piezas. Es una herramienta de código abierto que permite administrar aplicaciones, bases de datos, dominios y despliegues desde una interfaz.

La diferencia es sencilla: el VPS aporta la capacidad para ejecutar los proyectos y Coolify facilita su administración. Le conectas el código de una aplicación, configuras lo que necesita y desde el panel puedes desplegarla, revisar sus registros y asignarle un dominio.

Esquema de una web, una aplicación y una base de datos en un VPS con Coolify

Usaremos la modalidad autoalojada. Coolify no cobra una licencia por esta modalidad, pero seguimos pagando el servidor y los servicios adicionales que contratemos, como dominios o almacenamiento para copias.

Eso no convierte al VPS en la mejor opción para cualquier caso. Si solo necesitas una web de presentación o un WordPress habitual, un alojamiento compatible puede ser suficiente y más sencillo de administrar.

El VPS tiene sentido cuando necesitas decidir qué software ejecutar y cómo conectar tus servicios. También permite repartir el coste entre varios proyectos. Eso sí, todos comparten recursos y tú sigues a cargo del servidor, sus accesos y sus respaldos.

📍 Elegir el VPS y preparar la instalación

Para esta prueba utilizo un Hostinger KVM 2 con dos procesadores virtuales y 8 GB de memoria. Es la configuración con la que ejecuto las dos webs y PostgreSQL de este ejemplo, no una promesa de capacidad para cualquier combinación de aplicaciones.

El procesador ejecuta las tareas y la memoria permite mantener los procesos funcionando. Al añadir proyectos tendrás que revisar su consumo, porque compartir servidor no significa disponer de recursos ilimitados.

También importa la ubicación. Yo vivo en Brasil y elegí São Paulo. En tu caso, piensa dónde estarán las personas que utilizarán las aplicaciones y selecciona la región teniendo eso en cuenta.

Si decides contratarlo, puedes entrar desde mi enlace de VPS de Hostinger. Utilizarlo es una forma de apoyar mi trabajo. Después comprueba que aparezca el cupón RODRIGO en el carrito y revisa tanto el total como las condiciones de renovación.

Instalar Ubuntu con Coolify

Dentro del panel de Hostinger, entra en VPS y abre la administración del servidor. En el apartado del sistema operativo y el panel encontrarás las plantillas disponibles. La opción que utilizo es Ubuntu con Coolify.

Ubuntu es el sistema operativo. La plantilla deja preparado el sistema junto con Coolify y evita hacer esa instalación manual por terminal. Cuando termina, utiliza la dirección de acceso que proporciona Hostinger para abrir el panel.

La primera vez tendrás que crear la cuenta administradora con tu nombre, correo y una contraseña propia. Esta cuenta no es lo mismo que root, el usuario con control administrativo del servidor. Una sirve para entrar a Coolify; la otra pertenece a la administración del sistema.

Durante la configuración inicial, elige desplegar en este mismo servidor. Si aparece Localhost o This Machine, se refiere al VPS donde está instalado Coolify, no a tu computador. Valida la conexión y comprueba que quede listo.

🗂️ Organizar proyectos y asegurar el panel con HTTPS

Antes de añadir aplicaciones conviene entender cómo organiza Coolify el trabajo:

  • Recurso: cada elemento que ponemos en marcha, como una aplicación o una base de datos.
  • Proyecto: la agrupación de esos recursos.
  • Entorno: la separación entre versiones de producción o de pruebas dentro de un proyecto.

Creamos el proyecto Solicitudes y entramos en su entorno de producción. Ahí vamos a incorporar la aplicación y PostgreSQL. Producción es la versión que queremos tener publicada para sus usuarios.

Diagrama del proyecto Solicitudes con un entorno de producción, una aplicación y PostgreSQL

Antes de conectar GitHub, dejamos el panel accesible mediante HTTPS, que cifra la conexión entre el navegador y el servidor. En los ajustes de Coolify configura una dirección pública válida para la instalación, guarda y vuelve a entrar utilizando esa dirección. Comprueba también el certificado.

Hay dos tipos de direcciones que no debemos confundir. La dirección del panel sirve para administrar Coolify; las direcciones de las webs sirven para acceder a las aplicaciones. Más adelante asignaremos esas otras direcciones a cada recurso.

Además de proteger la conexión, disponer de una dirección pública estable nos permite preparar la integración con GitHub y recibir sus avisos de actualización.

🔗 Conectar GitHub y dar acceso a los repositorios

GitHub guarda los archivos del proyecto y el historial de sus cambios. Cada proyecto de código se organiza en un repositorio. Yo mantengo Solicitudes y Signal en repositorios separados para actualizar cada uno por su lado.

Antes de continuar, necesitas tener el código de tu aplicación en GitHub. En este ejemplo, los archivos están en la raíz del repositorio, incluido el archivo que describe las dependencias y las instrucciones de construcción y arranque.

No subas contraseñas ni archivos de variables con secretos al repositorio. Esos valores los configuraremos dentro de Coolify, separados del código.

Crear la integración mediante GitHub App

La GitHub App dará permiso a Coolify para leer los repositorios elegidos y recibir notificaciones cuando cambien. El recorrido es el siguiente:

  1. Entra en Sources y crea una fuente de tipo GitHub App.
  2. Asigna un nombre reconocible. Si utilizas una cuenta personal, deja vacío el campo de organización.
  3. Para este recorrido, mantén desactivadas las opciones adicionales de vistas previas y ejecutores de GitHub Actions.
  4. Continúa con el registro automático utilizando la dirección pública del panel.
  5. Pulsa Register with GitHub y asigna un nombre único a la aplicación de GitHub.
  6. Al instalarla, selecciona Only select repositories y autoriza únicamente los proyectos que vas a publicar.

Yo doy acceso a las dos demos. Si solo vas a desplegar una aplicación, basta con autorizar ese repositorio. No hace falta abrir el acceso a todos tus proyectos.

Al terminar, vuelve a Coolify y comprueba que la fuente esté conectada. Ya tenemos el puente entre el código y el servidor.

🚀 Desplegar la aplicación Next.js con Railpack

Dentro del entorno de producción añade una aplicación desde un repositorio privado conectado mediante GitHub App. Selecciona la fuente que acabas de crear, el repositorio de Solicitudes y la rama main.

Una rama es una línea de trabajo dentro del repositorio. En esta demo, main contiene el código que queremos publicar, así que Coolify tomará las versiones desde ahí.

Solicitudes no es únicamente una interfaz. Tiene una parte que funciona en el navegador y otra en el servidor. Cuando guardamos una solicitud, el navegador envía la operación al servidor y este se comunica con PostgreSQL. Next.js reúne esas partes dentro del proyecto.

Imagen, contenedor y puerto interno

Para construir esta aplicación utilizo Railpack, que prepara la imagen a partir del código y sus dependencias, es decir, los paquetes de software que necesita el proyecto.

  • Imagen: el paquete preparado con la aplicación y lo necesario para ejecutarla.
  • Contenedor: la aplicación ejecutándose dentro del entorno creado por Docker a partir de esa imagen.

Coolify organiza ese proceso desde el panel. Como el proyecto está en la raíz del repositorio, dejamos esa ubicación como carpeta base.

También configuramos el puerto interno 3000, que es donde esta demo está preparada para recibir conexiones dentro del contenedor. No copies ese número sin revisar tu aplicación: debe coincidir con el puerto en el que realmente escucha.

Después accederemos mediante un dominio con HTTPS. Quien entre en la web no tendrá que escribir ese puerto en el navegador.

Guarda y pulsa Deploy. Coolify obtiene el código, instala las dependencias, construye la imagen y arranca el contenedor. Los registros, o logs, permiten seguir las etapas y comprobar qué versión está utilizando.

Con eso tenemos una primera puesta en marcha, pero todavía falta conectar la base de datos. Que la interfaz cargue no demuestra que la aplicación pueda guardar información.

🗄️ Crear PostgreSQL y conservar los datos

Desde el mismo proyecto añade otro recurso, entra en la categoría de bases de datos y selecciona PostgreSQL. Para esta demo utilizo la versión 18.

Al recurso le doy el nombre Solicitudes-db para distinguirlo de la aplicación y a la base inicial la llamo solicitudes. El usuario y la contraseña forman parte de sus credenciales, así que hay que conservarlos de forma privada.

La aplicación necesita encontrar una estructura concreta. En este caso utilizamos una tabla donde cada fila representa una solicitud y las columnas contienen datos como el cliente, el servicio y el estado.

Antes de arrancar la base vacía, añadimos el SQL correspondiente al proyecto en Initialization Scripts. SQL es el lenguaje con el que definimos esa estructura y trabajamos con la información.

Aquí hay una diferencia importante: inicializar una base vacía no es lo mismo que actualizar una base que ya contiene datos. Si después necesitas modificar su estructura, tendrás que utilizar un procedimiento de actualización adecuado, como las migraciones. No basta con editar el campo de inicialización y esperar que lo rehaga todo.

Acceso privado y volumen persistente

Mantén PostgreSQL como un recurso privado. La aplicación se conectará por la red interna de Coolify, por lo que no necesitamos abrir la base de datos a Internet.

Arranca el recurso y revisa su estado y sus registros. Comprueba que termine la inicialización y quede listo para aceptar conexiones.

En el apartado de almacenamiento también encontrarás un volumen persistente: un espacio del servidor conectado al contenedor para guardar los archivos de PostgreSQL por separado de la parte reemplazable.

Así podemos reiniciar o sustituir el contenedor conservando los archivos en el mismo volumen. Revisa la ruta que muestra tu instalación, especialmente la correspondiente a la versión utilizada. Más adelante comprobaremos la persistencia con datos guardados.

⚙️ Variables de entorno, dirección temporal y comprobación de salud

Ahora debemos indicarle a la aplicación dónde está PostgreSQL y con qué credenciales conectarse. Lo hacemos mediante una variable de entorno, un dato de configuración que entregamos desde fuera del código.

Esto permite utilizar conexiones distintas en el computador y en producción sin reescribir el proyecto.

Configurar DATABASE_URL y APP_URL

Copia la URL interna de PostgreSQL y vuelve a Environment Variables dentro de Solicitudes. Añade DATABASE_URL con esa conexión como valor. El código de esta demo busca exactamente ese nombre.

La URL incluye credenciales. No debe aparecer en el repositorio ni compartirse como si fuera una dirección pública.

Coolify distingue dos momentos:

  • Build: la etapa en la que se prepara y construye la aplicación.
  • Runtime: cuando la aplicación ya está ejecutándose y atendiendo peticiones.

En esta demo, la conexión a PostgreSQL se utiliza durante la ejecución. Por eso dejamos la variable no disponible durante la construcción y disponible dentro del contenedor en runtime. Esta configuración responde a las necesidades de este proyecto; no significa que todas las aplicaciones funcionen igual.

Añade también APP_URL con la dirección pública exacta de Solicitudes. Es una variable propia del código de esta demo y se utiliza para comprobar desde qué dirección llegan las operaciones de guardado.

Para la primera prueba utilizamos la dirección temporal generada por el panel. En Domains, configúrala con HTTPS y comprueba que dirija al puerto interno 3000.

Después configura el health check, la comprobación con la que Coolify verifica si la aplicación responde. Utiliza la ruta de comprobación que tenga implementada tu proyecto y el puerto correspondiente. Guarda las variables y aplica los cambios con un nuevo despliegue.

🔄 Guardar solicitudes y actualizar desde GitHub

Con la aplicación y PostgreSQL conectados, hacemos una prueba completa: crear una solicitud, elegir el servicio, guardar, modificar su estado y recargar.

Yo añado tres clientes ficticios: Café Aurora, Estudio Norte y Casa Olivia. Representan una web, una aplicación y una tienda online. Después de recargar, las tres solicitudes siguen en la bandeja.

Eso es lo que queríamos comprobar: la aplicación guarda la información en PostgreSQL y puede volver a consultarla.

Esta demo no tiene autenticación de usuarios. Por eso utilizamos datos ficticios. Antes de convertirla en una herramienta para clientes, hay que añadir control de acceso y preparar esa versión para su uso real. Tener dominio y HTTPS no sustituye esa parte.

Del cambio local al despliegue automático

Ahora modificamos el titular de la aplicación. El recorrido de actualización queda así:

  1. Cambiamos el código en el computador.
  2. Registramos el conjunto de cambios mediante un commit.
  3. Lo enviamos a GitHub con un push.
  4. Con el despliegue automático activado, GitHub notifica a Coolify mediante un webhook.
  5. Coolify construye y publica una nueva versión desde la rama configurada.
Diagrama del recorrido del código local a GitHub, Coolify y la web

En el historial podemos comprobar el despliegue iniciado por webhook y la versión de código utilizada. Después abrimos la página: el titular cambió y las solicitudes siguen ahí.

La aplicación se actualizó, pero los datos permanecen en su base separada. Esa separación es una de las piezas más útiles de este montaje.

↩️ Volver a una versión anterior sin confundir código y datos

El rollback permite volver a una imagen anterior de la aplicación. Dentro del recurso, abre esa sección y elige una de las versiones que todavía estén disponibles en el servidor.

En nuestra prueba el cambio era visual, así que la imagen anterior seguía siendo compatible con la misma base. Aplicamos esa versión, esperamos y volvemos a abrir la web.

Regresa el titular anterior y permanecen las tres solicitudes. Hemos recuperado una versión de la aplicación, no un estado anterior de PostgreSQL.

Esta distinción importa: un rollback no recupera por sí solo datos borrados ni deshace cambios en la estructura de la base. Si una versión modificó esa estructura, también hay que considerar la compatibilidad del código al retroceder.

Para comprobar el almacenamiento, reiniciamos PostgreSQL y recargamos la aplicación. Las tres filas siguen guardadas. El volumen persistente funciona, pero todavía no hemos demostrado que podamos recuperarnos si perdemos ese almacenamiento.

💾 Crear una copia de PostgreSQL y probar su restauración

Persistencia y copia de seguridad resuelven problemas distintos. El volumen mantiene los datos al reiniciar o reemplazar el contenedor. Un respaldo permite recuperar información desde una copia.

En el apartado de backups de PostgreSQL creamos una copia de la base solicitudes. Para esta prueba dejo una programación diaria y ejecuto otra inmediatamente con Backup Now.

Espera a que aparezca el resultado Success y comprueba que exista el archivo. Después conserva una copia fuera del VPS. Yo guardo una en el computador para esta demostración.

Si el único respaldo está en el mismo servidor que los datos originales, perder ese servidor puede afectar a ambos. Por eso hay que decidir tanto cada cuánto se copia como dónde se conserva.

Restaurar en otra base, sin reemplazar producción

Para verificar el respaldo creamos otra base de PostgreSQL, separada de la que utiliza la aplicación. Así podemos probar la recuperación sin sobrescribir la información que está funcionando.

Desde la terminal del servidor utilizamos pg_restore, la herramienta de PostgreSQL adecuada para el formato de copia empleado. Hay que indicar el contenedor de destino, la base vacía y la ruta del archivo.

Esos nombres y rutas deben corresponder a tu instalación. No conviene copiar identificadores de otro servidor ni ejecutar una restauración sin comprobar el destino.

Una vez restaurada, consultamos la tabla requests. Aparecen las tres solicitudes con sus nombres, servicios y estados. La aplicación sigue conectada a la base original: no hemos cambiado su conexión por la de pruebas.

Ahora sí hemos comprobado algo más que la creación de un archivo. Hemos recuperado su contenido en otra base.

🌐 Publicar una segunda web con Dockerfile y Nginx

La segunda web es Signal, la landing del gorila animado. Es una web estática: el servidor entrega archivos y el navegador los utiliza para mostrar la página.

Estática no significa sin movimiento. Puede incluir HTML, estilos, JavaScript, imágenes y vídeo, y tener animaciones e interacción. La diferencia está en cómo se sirve el proyecto, no en lo llamativa que sea su apariencia.

Añadimos un nuevo recurso desde la conexión de GitHub, pero seleccionamos el repositorio de Signal. El VPS sigue siendo el mismo.

Este proyecto incluye un Dockerfile, un archivo con las instrucciones para construir su imagen. Utiliza Nginx para entregar los archivos de la web.

  • En Solicitudes utilizamos Railpack y el puerto interno 3000.
  • En Signal seleccionamos Dockerfile y el puerto interno 80.

Guardamos, preparamos su dirección HTTPS y desplegamos. Ya tenemos la aplicación con PostgreSQL y una segunda web sin contratar otro VPS. Cada una conserva su repositorio y configuración, aunque las gestionemos desde el mismo panel.

Página de Signal con fondo verde, titular y un gorila con auriculares rojos

Si haces webs para clientes y quieres partir de una base visual más trabajada, en Dínamo Sites tengo secciones animadas con demos, prompts, código y recursos para adaptarlas. Y si estás en la etapa de crear una aplicación, puedes explorar los prompts profesionales de Primera App.

🔒 Conectar dominios propios, DNS y HTTPS

El servidor tiene una dirección IP que permite localizarlo en la red. Un dominio nos deja utilizar un nombre, y el DNS relaciona ese nombre con la dirección del servidor.

Para esta prueba utilizo un dominio que tenía libre:

  • vortexclips.com: la landing Signal.
  • app.vortexclips.com: la aplicación Solicitudes.

La parte app es un subdominio. Permite dar otra dirección a la aplicación utilizando el mismo dominio principal.

Crear los registros DNS

No necesitas transferir el dominio a Hostinger para apuntarlo al VPS. Entra donde administras su DNS y crea los registros de tipo A, que relacionan un nombre con una dirección IPv4:

  • Un registro para la raíz del dominio, que en el panel utilizado aparece como @, con la IP pública del VPS.
  • Otro registro para app, con esa misma IP pública.

Utiliza la IP de tu servidor. Antes de reemplazar registros existentes, comprueba qué servicios utilizan el dominio, incluido el correo.

Si la web principal ya está en otro alojamiento, puedes mantenerla allí y apuntar únicamente un subdominio al VPS. No hace falta moverlo todo para publicar una aplicación nueva.

Asignar cada dirección a su aplicación

De vuelta en Coolify, añade el nuevo dominio de Solicitudes con HTTPS y el puerto interno 3000. Actualiza también APP_URL para que coincida con la nueva dirección y vuelve a desplegar.

En Signal configura el dominio principal con HTTPS, esta vez hacia el puerto interno 80, y aplica los cambios.

El DNS lleva la petición al servidor. Después, el proxy reconoce el dominio solicitado y la dirige a la aplicación correspondiente. Por eso ambas webs pueden compartir IP y tener direcciones distintas.

Para emitir el certificado, el dominio debe resolver al servidor correcto y el tráfico web tiene que llegar al proxy. Los cambios de DNS pueden tardar en estar disponibles; en mi prueba dejé pasar unas horas antes de comprobar ambas direcciones.

✅ Comprobar el resultado y mantener lo publicado

La comprobación final no consiste solo en abrir las portadas. En Solicitudes entramos mediante el dominio con HTTPS, verificamos las solicitudes anteriores, añadimos otra, cambiamos su estado y recargamos. La información permanece.

Después comprobamos Signal con su propia dirección, sus animaciones y sus pestañas. Los dos proyectos funcionan en el mismo VPS, cada uno con su configuración.

Antes de dar por terminado un montaje así, me interesa confirmar estos puntos:

  • Las aplicaciones responden desde sus dominios con HTTPS.
  • Los cambios enviados a GitHub llegan al despliegue esperado.
  • Actualizar la aplicación conserva los datos.
  • El rollback probado es compatible con la base.
  • PostgreSQL conserva la información al reiniciarse.
  • Existe una copia fuera del VPS y se ha probado su restauración.

Después de publicar queda trabajo: revisar el consumo, mantener el sistema y Coolify actualizados, cuidar los accesos y comprobar las copias. El panel facilita muchas tareas, pero seguimos administrando un servidor.

Si quieres compartir tus avances y conversar conmigo sobre webs, aplicaciones y proyectos para clientes, puedes unirte a Círculo Builders. Como miembro también tienes acceso a Dínamo Sites.

Eso es lo que busco con esta combinación: control sobre mis aplicaciones y sus datos, y un proceso repetible para publicarlas y mantenerlas. No se trata de acumular proyectos sin revisar la capacidad, sino de aprovechar una misma infraestructura con cada pieza bien configurada y una recuperación comprobada.

Ver planes y ofertas de Hostinger

Aviso: este artículo puede incluir enlaces promocionales. Si realizas una compra, puedo recibir una comisión sin costo adicional para ti.

Hazte más capaz con IA

Ideas, herramientas y aprendizajes prácticos para crear, automatizar y detectar nuevas oportunidades.

Al suscribirte, aceptas recibir mis emails. Puedes darte de baja cuando quieras.