Ventas

Logo Nicalia
Desplegar con Git en un hosting compartido, sin VPS
Volver al blog

Desplegar con Git en un hosting compartido, sin VPS

Fran Navoz

Por Fran Navoz en Hosting, Nicalia, Productos y servicios

21 de octubre de 2026

Desplegar con Git en un hosting compartido, sin VPS

Usas Git en local desde hace años y, cuando toca subir los cambios a la web, abres el cliente FTP y arrastras carpetas a mano. Git ya lo sabes usar. Lo que suele faltar es tener claro qué se puede montar en un hosting compartido, porque casi todas las guías de despliegue dan por hecho que tienes un VPS con root, Docker o una plataforma de CI/CD de pago.

Tres formas que funcionan en un compartido con cPanel, desde la que no pide abrir la terminal hasta la que despliega sola, y el fallo de seguridad que más se repite al montarlas.

Para quién es esto y para quién no

Si tocas tu web una vez al mes y eres el único que lo hace, el FTP te vale. Montar un flujo de despliegue para eso es matar moscas a cañonazos y vas a dedicarle más tiempo del que te ahorra.

Empieza a compensar cuando os pisáis cambios porque sois dos o más tocando el mismo código, cuando tienes una web de pruebas y quieres que a producción llegue justo lo que probaste, o cuando despliegas cada semana y alguna vez ya has subido el archivo que no era. A partir de ahí, el día que algo se rompe sabes qué cambió y quién lo cambió, y vuelves a la versión anterior con un comando.

Qué puedes y qué no puedes hacer en un compartido

Antes de elegir método conviene saber con qué cuentas, y esto es lo que te vas a encontrar en la mayoría de hostings compartidos con cPanel:

Lo que necesitas para desplegar con Git y si lo tienes en un compartido
Necesitas ¿Lo tienes en un compartido?
Acceso SSH A veces: depende del proveedor y del plan
Git Version Control de cPanel Sí, si tu proveedor lo deja activado
Tareas programadas (cron) Sí
root, systemd, Docker No
Compilar assets en el servidor (Node) Depende: muchos no traen Node

La última fila importa más de lo que parece. Aunque tu hosting tenga Node, compilar con Vite o Webpack en un compartido es mala idea, porque el proceso tira de CPU y memoria un buen rato y los límites de la cuenta lo cortan o lo eternizan. Compila en tu ordenador o en GitHub Actions y despliega el resultado ya compilado.

En Nicalia todos los planes compartidos incluyen SSH, cron y Git Version Control. Si en tu cPanel no aparece la Terminal, abre un tique y te la activamos. Tienes las formas de conectarte en cómo acceder mediante SSH a tu hosting.

Método 1: Git Version Control de cPanel, sin tocar la terminal

Es la ruta que puede seguir más gente porque todo se hace desde el navegador. cPanel guarda una copia del repositorio en tu cuenta, fuera de la carpeta pública, y al pulsar un botón copia a la web los archivos que tú le indiques.

Ojo con un detalle: sin acceso shell, cPanel solo te deja crear, clonar, ver y borrar repositorios. Para desplegar, tu cuenta necesita tener el shell activado aunque tú no abras la terminal nunca.

Clona el repositorio desde la interfaz

Ve a cPanel → Archivos → Git™ Version Control y pulsa Crear. Activa «Clonar un repositorio», pega la URL de clonación y, en la ruta, pon una carpeta fuera de public_html, por ejemplo repositorios/miweb. Si el repositorio es privado, antes tienes que darle al servidor una clave con permiso de lectura, y eso lo tienes paso a paso en cómo configurar el acceso SSH a repositorios privados.

Dile qué copiar con .cpanel.yml

cPanel no despliega nada si en la raíz del repositorio no hay un archivo .cpanel.yml, que es una lista de comandos que se ejecutan en orden. Para un tema de WordPress quedaría así:

---
deployment:
  tasks:
    - export DEPLOYPATH=/home/usuario/public_html/wp-content/themes/mi-tema/
    - /bin/mkdir -p $DEPLOYPATH
    - /bin/cp -R wp-content/themes/mi-tema/. $DEPLOYPATH

Cambia usuario y mi-tema por los tuyos. Usa rutas absolutas y comandos con su ruta completa (/bin/cp), y no copies la raíz del repositorio con un comodín, porque te llevarías la carpeta .git a la web. Además cp no borra: si eliminas un archivo del repositorio, en el servidor sigue ahí hasta que lo quites tú.

Sube el .cpanel.yml al repositorio de origen y no lo crees en la copia del servidor, porque si esa copia tiene cambios sin confirmar cPanel no despliega.

Despliega con un botón

Cada vez que quieras publicar, entra en Gestionar, abre la pestaña Extraer o desplegar y pulsa «Actualizar desde remoto» para traer los cambios. Después, «Desplegar commit HEAD» los copia a la web.

Sus límites

  • No despliega solo. Hacer push a GitHub no cambia nada en tu web hasta que alguien pulsa los dos botones.
  • Solo avanza en línea recta. «Actualizar desde remoto» usa --ff-only, así que tras un push forzado falla y toca resolverlo a mano.

Si tienes SSH, cPanel admite también el camino contrario: haces push directamente al repositorio de tu cuenta y despliega en el momento. Tienes los dos modos explicados en configurar el despliegue en cPanel, y todas las opciones de la herramienta en la guía de control de versiones Git en cPanel.

Método 2: repositorio bare con hook post-receive

El clásico, y el más elegante. Cuando lo tienes montado, publicar se reduce a esto:

git push produccion main

Necesitas SSH. Si no lo tienes, quédate con el método 1.

El repositorio va fuera de la carpeta pública

Un repositorio bare guarda solo el historial, sin archivos de trabajo. Lo creas en tu cuenta, fuera de public_html, para que nada de él se pueda pedir desde un navegador:

mkdir -p ~/repos/miweb.git
cd ~/repos/miweb.git
git init --bare

El hook que publica

Git ejecuta el archivo hooks/post-receive cada vez que recibe un push. Crea ~/repos/miweb.git/hooks/post-receive con este contenido:

#!/bin/sh
DESTINO="$HOME/public_html"
REPO="$HOME/repos/miweb.git"
RAMA="main"

while read antiguo nuevo ref; do
  if [ "$ref" = "refs/heads/$RAMA" ]; then
    git --work-tree="$DESTINO" --git-dir="$REPO" checkout -f "$RAMA"
    echo "Desplegado $RAMA en $DESTINO"
  fi
done

Dale permisos de ejecución con chmod +x ~/repos/miweb.git/hooks/post-receive. El checkout solo toca los archivos que controla Git, así que wp-config.php y las imágenes subidas se quedan como estaban, y si borras un archivo del repositorio también desaparece del servidor en el siguiente push.

En tu ordenador añades el servidor como remoto. El puerto SSH lo tienes en cPanel → Información general:

git remote add produccion ssh://usuario@tudominio.com:PUERTO/home/usuario/repos/miweb.git

Qué pasa cuando el despliegue falla a medias

El checkout no es atómico. Si se corta a mitad porque te quedas sin cuota de disco o hay un archivo con permisos raros, la web se queda con unos archivos nuevos y otros viejos, y el push aparece como completado porque el historial ya llegó al servidor. Por eso conviene leer lo que devuelve la terminal tras cada push, donde las líneas que empiezan por remote: son la salida del hook.

Si ves un error, corrige la causa y lanza a mano el mismo checkout del hook:

git --work-tree="$HOME/public_html" --git-dir="$HOME/repos/miweb.git" checkout -f main

Y si lo que falla es el código, haz git revert del commit en local y vuelve a hacer push. Es mucho más limpio que tocar archivos en el servidor.

 

Desplegar con Git en un hosting compartido, sin VPS

Método 3: GitHub Actions desplegando por SSH

Si el repositorio vive en GitHub y quieres que la web se actualice sola cada vez que se hace merge a main, deja que GitHub haga el trabajo. Arranca una máquina, compila si hace falta y copia el resultado a tu hosting por SSH.

Una clave solo para desplegar

Genera un par de claves nuevo para esto y no reutilices la tuya personal. Si un día se filtra, revocas esa y tu acceso sigue intacto.

ssh-keygen -t ed25519 -f deploy_github -N "" -C "github-actions"

La parte pública (deploy_github.pub) la importas en cPanel → Acceso SSH → Administrar claves SSH → Importar clave, y después la autorizas. La privada no se sube al repositorio nunca. Si además tu servidor tiene que leer repositorios privados, el proceso con claves dedicadas lo tienes en configurar el acceso a repositorios privados.

Dónde van los secretos

En GitHub, dentro del repositorio: Settings → Secrets and variables → Actions → New repository secret. Crea cinco:

  • SSH_KEY: el contenido completo de la clave privada.
  • SSH_HOST, SSH_PORT y SSH_USER: tu dominio o la IP del servidor, el puerto SSH y tu usuario de cPanel.
  • SSH_KNOWN_HOSTS: lo que devuelve ssh-keyscan -p PUERTO tudominio.com en tu ordenador, para que la conexión verifique el servidor.

Y el flujo de trabajo, en .github/workflows/desplegar.yml:

name: Desplegar
on:
  push:
    branches: [main]

jobs:
  desplegar:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      # Si compilas assets, este es el sitio:
      # - run: npm ci && npm run build

      - name: Preparar la clave SSH
        run: |
          mkdir -p ~/.ssh
          echo "${{ secrets.SSH_KEY }}" > ~/.ssh/deploy_key
          chmod 600 ~/.ssh/deploy_key
          echo "${{ secrets.SSH_KNOWN_HOSTS }}" > ~/.ssh/known_hosts

      - name: Copiar el tema al servidor
        run: |
          rsync -az --delete \
            -e "ssh -i ~/.ssh/deploy_key -p ${{ secrets.SSH_PORT }}" \
            wp-content/themes/mi-tema/ \
            ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }}:public_html/wp-content/themes/mi-tema/

rsync con –delete, y por qué esa bandera da miedo

--delete borra en el servidor todo lo que no esté en lo que envías. Es justo lo que quieres para que no se queden archivos huérfanos, y también la forma más rápida de cargarte una web. Si el destino fuera public_html y en el repositorio no está wp-content/uploads, rsync borraría la biblioteca de medios entera sin preguntar.

Apunta siempre a la carpeta más concreta que puedas (el tema, no la raíz) y la primera vez añade --dry-run, que lista lo que haría sin tocar nada.

El agujero de seguridad que casi nadie cierra

Si clonas un repositorio dentro de la carpeta pública y el servidor no bloquea el acceso, cualquiera puede abrir https://tudominio.com/.git/ y reconstruir tu repositorio con herramientas que circulan desde hace años. Con todo el historial, incluida la contraseña de la base de datos que alguien subió hace dos años y borró en el commit siguiente, porque borrar un archivo en un commit nuevo no lo quita de los anteriores.

cPanel protege los repositorios que creas desde Git Version Control. Los que clonas a mano por SSH dentro de public_html, que es lo que enseñan muchos tutoriales, no tienen por qué estar protegidos.

Compruébalo en treinta segundos

Abre en el navegador https://tudominio.com/.git/HEAD. Si ves una línea del tipo ref: refs/heads/main, tu repositorio está a la vista de todo el mundo. Si te devuelve un error 403 o 404, bien. Repite la prueba en cada subcarpeta donde hayas clonado algo.

La regla de .htaccess que lo bloquea

Añade esto al principio del .htaccess de public_html:

RewriteEngine On
RewriteRule (^|/)\.git - [F,L]

Devuelve un 403 a cualquier ruta que pase por .git, esté en la carpeta que esté, y funciona tanto en Apache como en LiteSpeed.

La solución buena es no clonar en la carpeta pública

La regla es un parche. Lo que de verdad lo arregla es que el repositorio viva fuera de public_html, como en los tres métodos de arriba, y que a la web solo lleguen los archivos que tienen que estar ahí. Y si alguna vez se subió una contraseña al repositorio, cámbiala, porque limpiar el historial no sirve de nada si alguien ya lo descargó.

El caso WordPress: qué se versiona y qué no

La regla es sencilla: al repositorio va lo que escribes tú. Lo que genera WordPress, lo que suben los usuarios y lo que actualizas desde el escritorio se queda fuera.

Qué va al repositorio en un proyecto WordPress
Va al repositorio No va
El tema y los plugins que desarrollas tú wp-config.php y las credenciales de la base de datos
composer.json y composer.lock, si usas Composer wp-content/uploads/, la biblioteca de medios
El .gitignore (y el .cpanel.yml si usas el método 1) El núcleo de WordPress y los plugins de terceros

Este .gitignore está pensado para un repositorio con la misma estructura que la instalación de WordPress. Ignora todo y deja pasar solo lo tuyo, así que cambia mi-tema y mi-plugin por tus carpetas:

# Todo fuera por defecto
/*

# Lo que sí entra
!.gitignore
!.cpanel.yml
!composer.json
!composer.lock

!wp-content/
wp-content/*

!wp-content/themes/
wp-content/themes/*
!wp-content/themes/mi-tema/

!wp-content/plugins/
wp-content/plugins/*
!wp-content/plugins/mi-plugin/

La base de datos no se despliega con Git. Entradas, páginas, menús, widgets y los ajustes de casi todos los plugins viven en la base de datos, y Git solo mueve archivos.

Es el error de concepto más común. Si cambias un menú en la web de pruebas, ese cambio no viaja con el push, y para llevarlo a producción tienes que exportar e importar la base de datos o repetir el cambio a mano. Ojo con importar encima de producción, porque te llevas por delante los pedidos, comentarios o registros que hayan entrado mientras tanto.

Si tu hosting no te da ni SSH ni Git

Si tu cPanel no tiene Git Version Control y tu proveedor no te da SSH ni pagando más, no hay truco que valga y te toca seguir con el FTP. Es una limitación real de algunos planes baratos, y si trabajas con más gente o despliegas a menudo, es motivo suficiente para cambiar.

Todos nuestros planes de hosting NVMe incluyen Git Version Control, SSH, cron y WP-CLI. Si vienes de otro proveedor con cPanel, la migración es gratuita si la pides en los 30 días siguientes a contratar, y nos encargamos de la web, el correo, las bases de datos y las tareas cron.

Preguntas rápidas

¿Necesito usar la terminal para desplegar con Git en cPanel?

No. Con Git Version Control clonas y despliegas desde el navegador, aunque tu cuenta necesita tener el acceso shell activado.

¿Se puede desplegar automáticamente al hacer push en un hosting compartido?

Sí, si tienes SSH: con un hook post-receive en tu cuenta o con GitHub Actions copiando por SSH.

¿Git despliega también la base de datos de WordPress?

No. Git solo mueve archivos, y entradas, menús y ajustes viven en la base de datos.

¿Es peligroso tener la carpeta .git dentro de public_html?

Sí, si el servidor no bloquea el acceso, porque cualquiera podría descargar el repositorio con todo su historial.

 

Fran Navoz | Especialista en marketing digital

👉🏻LinkedIn
👉🏻Hubspot
👉🏻Google
👌🏻 Compromiso y trabajo | ✉️ Contacto
Fran Navoz