El método más simple que funciona
Antes de adoptar herramientas complejas, vale la pena conocer el enfoque clásico: un webhook que dispara un git pull en tu servidor. Es la forma más directa de automatizar despliegues en un VPS o servidor dedicado, y para proyectos pequeños y medianos basta perfectamente. No necesitas runners, ni pipelines, ni cuentas adicionales.
Cómo funciona el flujo
La idea es sencilla y elegante:
- Haces push a tu repositorio en GitHub, GitLab o Bitbucket.
- El proveedor dispara una petición HTTP a una URL que tú defines (el webhook).
- Tu servidor recibe la petición en un endpoint PHP.
- El script valida que la petición sea legítima.
- Si pasa la validación, ejecuta
git pullen el directorio del proyecto.
En cuestión de segundos, el servidor tiene la versión nueva sin que hayas tocado una sola terminal.
Script PHP básico con validación HMAC
La validación HMAC es crítica: sin ella, cualquiera que conozca tu URL podría forzar despliegues. GitHub firma cada webhook con un secreto que compartes al configurarlo. Tu script recalcula esa firma y compara:
<?php
$secret = 'tu_secreto_largo_y_aleatorio';
$payload = file_get_contents('php://input');
$headerSig = $_SERVER['HTTP_X_HUB_SIGNATURE_256'] ?? '';
$expected = 'sha256=' . hash_hmac('sha256', $payload, $secret);
if (!hash_equals($expected, $headerSig)) {
http_response_code(401);
exit('Firma invalida');
}
$data = json_decode($payload, true);
if (($data['ref'] ?? '') !== 'refs/heads/main') {
exit('Rama ignorada');
}
chdir('/var/www/mi-proyecto');
$output = shell_exec('git pull origin main 2>&1');
file_put_contents('/var/log/deploy.log', date('c') . ' ' . $output . "
", FILE_APPEND);
echo "Deploy OK";
Fíjate en hash_equals: compara cadenas en tiempo constante para evitar ataques de timing. Nunca uses == para firmas criptográficas.
Consideraciones de seguridad que no puedes ignorar
- Secreto robusto: genera 32+ caracteres aleatorios. No lo guardes en el repositorio.
- HTTPS obligatorio: un webhook por HTTP plano puede interceptarse.
- Filtro de rama: ignora pushes a ramas de desarrollo, solo despliega
mainoproduction. - Permisos del usuario: el proceso PHP (normalmente www-data) necesita permisos de escritura en el directorio del proyecto y acceso al remoto Git.
- Log de ejecuciones: registra cada despliegue con timestamp. Cuando algo falle, este log es tu primer punto de consulta.
- Whitelist de IPs: GitHub y GitLab publican los rangos desde los que envían sus webhooks. Filtrarlos en el firewall añade una capa extra.
Deploy keys: la alternativa para repos privados
Si el repositorio es privado, tu servidor necesita credenciales para hacer pull. La peor idea es guardar tu contraseña personal. La buena práctica es usar una deploy key: una clave SSH generada específicamente para ese servidor, añadida como clave de solo lectura en el repositorio. Si el servidor se ve comprometido, revocas esa clave sin tocar el resto de tu cuenta.
ssh-keygen -t ed25519 -f ~/.ssh/deploy_key -C "deploy@miservidor"
# Añades el contenido de deploy_key.pub en Settings -> Deploy keys del repo
git clone git@github.com:usuario/repo.git
Limitaciones que debes conocer
Este método es perfecto para proyectos que no necesitan build (sitios PHP planos, WordPress con temas, scripts simples). Si tu aplicación requiere compilar assets, correr migraciones de base de datos o reiniciar servicios, el script se complica rápido y conviene evolucionar hacia un pipeline real. Pero para empezar, esta fórmula lleva años funcionando y seguirá funcionando.