How to Set Up Webhook-Based Deployments
Webhook-based deployments let you automatically deploy code to your Breeze instance whenever you push to your Git repository. Instead of manually SSH-ing in and pulling changes, a webhook triggers the deployment pipeline instantly.
How Webhook Deployments Work
- You push code to your Git repository (GitHub, GitLab, Gitea, etc.)
- The platform sends an HTTP POST request to your Breeze instance
- A webhook listener on your server validates the request and runs the deploy script
- Your application is updated with zero manual steps
Setting Up a Webhook Listener
Use the lightweight webhook tool to listen for incoming hooks:
# Install webhook
sudo apt-get install -y webhook
# Or download the latest binary
WEBHOOK_VERSION="2.8.1"
wget "https://github.com/adnanh/webhook/releases/download/${WEBHOOK_VERSION}/webhook-linux-amd64.tar.gz"
tar xzf webhook-linux-amd64.tar.gz
sudo cp webhook-linux-amd64/webhook /usr/local/bin/
Configuring Webhook Hooks
Create a hooks configuration file:
# /etc/webhook/hooks.json
[
{
"id": "deploy-app",
"execute-command": "/usr/local/bin/deploy.sh",
"command-working-directory": "/var/www/myapp",
"pass-arguments-to-command": [
{
"source": "payload",
"name": "ref"
},
{
"source": "payload",
"name": "head_commit.message"
}
],
"trigger-rule": {
"and": [
{
"match": {
"type": "payload-hmac-sha256",
"secret": "YourWebhookSecretHere",
"parameter": {
"source": "header",
"name": "X-Hub-Signature-256"
}
}
},
{
"match": {
"type": "value",
"value": "refs/heads/main",
"parameter": {
"source": "payload",
"name": "ref"
}
}
}
]
}
}
]
Writing the Deploy Script
Create a deployment script that the webhook executes:
#!/usr/bin/env bash
# /usr/local/bin/deploy.sh
set -euo pipefail
APP_DIR="/var/www/myapp"
LOG_FILE="/var/log/deploy.log"
LOCK_FILE="/tmp/deploy.lock"
log() {
echo "$(date '+%Y-%m-%d %H:%M:%S') - $*" | tee -a "$LOG_FILE"
}
# Prevent concurrent deployments
exec 200>"$LOCK_FILE"
if ! flock -n 200; then
log "Deploy already in progress, skipping"
exit 0
fi
REF="${1:-unknown}"
COMMIT_MSG="${2:-no message}"
log "=== Starting deployment ==="
log "Ref: $REF"
log "Commit: $COMMIT_MSG"
cd "$APP_DIR"
# Pull latest changes
log "Pulling latest code..."
git fetch origin main
git reset --hard origin/main
# Install dependencies
log "Installing dependencies..."
composer install --no-dev --optimize-autoloader 2>&1 | tail -5
npm ci --production 2>&1 | tail -5
# Build assets
log "Building assets..."
npm run build 2>&1 | tail -5
# Run database migrations
log "Running migrations..."
php artisan migrate --force 2>&1
# Clear and rebuild caches
log "Clearing caches..."
php artisan cache:clear
php artisan config:cache
php artisan route:cache
php artisan view:cache
# Reload services
log "Reloading services..."
sudo systemctl reload php8.2-fpm
sudo systemctl reload nginx
# Health check
sleep 2
HTTP_STATUS=$(curl -s -o /dev/null -w "%{http_code}" http://localhost)
if [[ "$HTTP_STATUS" == "200" ]]; then
log "Health check passed (HTTP $HTTP_STATUS)"
log "=== Deployment successful ==="
else
log "ERROR: Health check failed (HTTP $HTTP_STATUS)"
log "=== Deployment may have issues ==="
exit 1
fi
Running as a systemd Service
Create a systemd service so the webhook listener starts on boot:
# /etc/systemd/system/webhook.service
[Unit]
Description=Webhook Listener
After=network-online.target
Wants=network-online.target
[Service]
User=deploy
ExecStart=/usr/local/bin/webhook \
-hooks /etc/webhook/hooks.json \
-port 9000 \
-verbose \
-hotreload
Restart=always
RestartSec=5
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now webhook.service
Reverse Proxy Configuration
Place the webhook listener behind Nginx with HTTPS:
# /etc/nginx/sites-available/webhook
server {
listen 443 ssl;
server_name deploy.example.com;
ssl_certificate /etc/letsencrypt/live/deploy.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/deploy.example.com/privkey.pem;
location /hooks/ {
proxy_pass http://127.0.0.1:9000/hooks/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Hub-Signature-256 $http_x_hub_signature_256;
}
}
Configuring the GitHub Webhook
In your GitHub repository settings:
- Go to Settings > Webhooks > Add webhook
- Set Payload URL to
https://deploy.example.com/hooks/deploy-app - Set Content type to
application/json - Enter your webhook secret
- Select "Just the push event"
- Check "Active" and save
Security Best Practices
- Always validate signatures — use HMAC verification to ensure requests come from your Git platform
- Restrict to specific branches — only deploy from
mainorproductionbranches - Use HTTPS — encrypt webhook traffic with TLS
- Run as a limited user — the deploy user should only have access to the application directory
- Use file locking — prevent concurrent deployments with
flock - Add health checks — verify the application works after deployment
- Log everything — maintain a deployment log for auditing and debugging
- Add rollback capability — keep the previous version available for quick rollback
Webhook-based deployments give your Breeze instances a fast, automated deployment pipeline triggered directly from Git pushes.