# Deploy webhook receiver (push-to-deploy, hardened) Every push to the `production` branch triggers a rebuild on the VPS through this receiver (host port 9000). The receiver must **verify the Gitea webhook signature** — an open deploy endpoint is effectively remote code execution on the production server. ## VPS setup (one time) ```bash # 1) Files live here: sudo mkdir -p /srv/erp && sudo chown $USER /srv/erp # copy the repo to /srv/erp (the receiver runs docker compose in this dir) # 2) Secrets — add to /srv/erp/.env (git-ignored): # GITEA_WEBHOOK_SECRET= # 3) Install as a systemd service: sudo cp infra/deploy-webhook/erp-deploy-webhook.service /etc/systemd/system/ # adjust User= and paths inside, then: sudo systemctl daemon-reload sudo systemctl enable --now erp-deploy-webhook curl http://127.0.0.1:9000/ping # → {"status":"ok"} ``` ## Gitea webhook Repo → Settings → Webhooks → Add webhook → Gitea: - Target URL: `http://:9000/deploy` - Method: `POST` — Secret: same value as `GITEA_WEBHOOK_SECRET` - Trigger: Push Events, Branch filter: `production` ## Behavior - Verifies `X-Gitea-Signature` (HMAC-SHA256) — rejects everything else with 401. - Only pushes to `refs/heads/production` deploy; other branches are acknowledged and ignored. - Deploys are serialized with a lock (concurrent pushes don't race). - Runs `docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d --build` in `/srv/erp`. - After a successful build, polls the API `/health/ready` endpoint and logs a failed post-deploy check (surfaced by the monitoring stack). - Logs to journald (`journalctl -u erp-deploy-webhook -f`).