feat: enhance deployment documentation and nginx configuration for Gitea webhook handling

This commit is contained in:
Sascha 2026-07-29 18:20:39 +02:00
parent 960943bd60
commit aaa9a9f567
2 changed files with 57 additions and 13 deletions

View File

@ -222,18 +222,25 @@ Without this, updating means SSHing in and running the commands under
"Updating later" by hand every time. This section makes a `git push` to
your own Gitea/Forgejo trigger a pull + restart automatically.
Since Git already runs on this same VPS, the webhook listener never needs to
be reachable from the internet - it binds to `127.0.0.1` only, and Gitea
calls it over loopback. Nothing new is exposed publicly.
**Check this first:** run `docker ps` to see whether Gitea/Forgejo runs in a
Docker container. This decides which of the two setups below applies.
**Check this first:** if Gitea/Forgejo runs inside Docker, `127.0.0.1` inside
its container is the container's own loopback, not the host's - the webhook
target below would not connect. Run `docker ps` to check. If Gitea is
containerized, either add the webhook service to the same Docker network and
call it by container name, or expose the webhook through the nginx vhost
(same pattern as `/api/audit-request` in step 7) with an `allow`/`deny` block
restricting it to the container network's subnet, instead of the loopback
target used below.
**Gitea runs natively on this machine (not in Docker):** the webhook listener
never needs to be reachable from the internet - it binds to `127.0.0.1`
only, and Gitea calls it over loopback. Use `http://127.0.0.1:3002/deploy-webhook`
as the Target URL in step 11.4 and skip the nginx part of step 11.3.
**Gitea runs in Docker:** inside that container, `127.0.0.1` is the
container's own loopback, not this host - a target of `127.0.0.1:3002` would
never connect, regardless of Docker's networking mode. Rather than depending
on that container's specific network setup (bridge vs. host, custom networks,
`host.docker.internal` availability - all of which vary by how it was set
up), route the webhook through the same nginx vhost as the audit endpoint
instead: the request just goes out over HTTPS to `api.sascha-bach.de` and
back in, exactly like any other webhook call, independent of how Gitea's
container is networked. `backend/deploy/nginx-api.sascha-bach.de.conf`
already has the `/deploy-webhook` location for this - see step 11.3. Use
`https://api.sascha-bach.de/deploy-webhook` as the Target URL in step 11.4.
### 11.1 Generate a secret and configure it
@ -274,6 +281,17 @@ sudo systemctl enable --now audit-webhook
systemctl status audit-webhook --no-pager
```
**Only if Gitea runs in Docker**, additionally expose it through nginx (the
config was already updated when you copied it in step 7 - if that was before
this section existed, re-copy it):
```bash
sudo cp /opt/audit-endpoint/backend/deploy/nginx-api.sascha-bach.de.conf \
/etc/nginx/sites-available/api.sascha-bach.de
sudo nginx -t
sudo systemctl reload nginx
```
### 11.4 Register the webhook in Gitea/Forgejo
In the repository on `git.sascha-bach.de`: **Settings → Webhooks → Add
@ -282,7 +300,7 @@ Gitea fork and uses the same webhook format).
| Field | Value |
| --- | --- |
| Target URL | `http://127.0.0.1:3002/deploy-webhook` |
| Target URL | `http://127.0.0.1:3002/deploy-webhook` (native Gitea) **or** `https://api.sascha-bach.de/deploy-webhook` (Gitea in Docker) |
| HTTP Method | `POST` |
| POST Content Type | `application/json` |
| Secret | the value generated in 11.1 |

View File

@ -22,6 +22,13 @@ server {
}
}
# Rate-limits /deploy-webhook specifically. It is now reachable over the
# public hostname (see the location block below), so unlike
# /api/audit-request it has no per-request Node-side limiter of its own -
# the HMAC signature check is the real gate, this is just a cheap first
# filter against noise.
limit_req_zone $binary_remote_addr zone=deploy_webhook:1m rate=10r/m;
server {
listen 443 ssl;
listen [::]:443 ssl;
@ -34,7 +41,7 @@ server {
# so they never reach it.
client_max_body_size 16k;
# Only these two paths exist. Everything else is refused rather than
# Only these paths exist. Everything else is refused rather than
# forwarded, which keeps the attack surface to what the form needs.
location = /api/audit-request {
proxy_pass http://127.0.0.1:3001;
@ -57,6 +64,25 @@ server {
access_log off;
}
# Only needed if Gitea/Forgejo runs in a Docker container: 127.0.0.1
# inside that container is the container's own loopback, not this host,
# so the webhook target can't be http://127.0.0.1:3002 in that case.
# Routing it here instead works regardless of the container network
# setup - the request simply goes out over HTTPS to this hostname and
# back in, the same way any other webhook call would.
#
# If Gitea runs natively on this same machine (not in Docker), this
# block is not needed - point the Gitea webhook straight at
# http://127.0.0.1:3002/deploy-webhook instead and skip this location.
location = /deploy-webhook {
limit_req zone=deploy_webhook burst=5 nodelay;
proxy_pass http://127.0.0.1:3002;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 30s;
}
location / {
return 404;
}