openvibers/openvibe.coupons Commits

Coupons: nginx hardening from the pre-launch security review (#22)

OP OpenVibers committed 9 Oct 2026 · 3724257be2 · 1 file, +13 −2

- Pages get a per-address limit (10 a second); the sitemaps, feeds and llms-full.txt, which read every public row,
  30 a minute (the discovery routes ran before the app's page limiter).
- /metrics and /internal/ are refused case-insensitively and with any suffix (Express routes /METRICS and /metrics/ too).

Changes

ddiff --git a/deploy/nginx/openvibe.coupons.conf b/deploy/nginx/openvibe.coupons.conf
iindex 8f6cc82..08caf23 100644
---- a/deploy/nginx/openvibe.coupons.conf
++++ b/deploy/nginx/openvibe.coupons.conf
@@@ -15,6 +15,9 @@ limit_req_zone $binary_remote_addr zone=ovcoupons_lookup:10m rate=5r/s;
limit_req_zone $binary_remote_addr zone=ovcoupons_api:10m rate=5r/s;
limit_req_zone $binary_remote_addr zone=ovcoupons_auth:10m rate=10r/m;
limit_req_zone $binary_remote_addr zone=ovcoupons_forms:10m rate=2r/s;
++# Pages per address; the sitemaps, feeds and llms-full.txt (each reads every public row) slower.
++limit_req_zone $binary_remote_addr zone=ovcoupons_pages:10m rate=10r/s;
++limit_req_zone $binary_remote_addr zone=ovcoupons_index:10m rate=30r/m;
server {
listen 80;
@@@ -97,13 +100,21 @@ server {
}
# ── The Events webhook: OpenVibe.Events delivers over loopback, never through the public vhost ──
-- location /internal/ { return 404; }
++ location ~* ^/internal(/|$) { return 404; }
# ── Prometheus metrics: host-local scrapers only (http://127.0.0.1:4850/metrics) ──
-- location = /metrics { return 404; }
++ location ~* ^/metrics(/|$) { return 404; }
++
++ # ── Sitemaps, feeds and llms-full.txt: built from every public row on each request ──
++ location ~* ^/(sitemap[^/]*\.xml|sitemaps/|llms-full\.txt|feed\.|atom\.xml|.*/feed\.xml$) {
++ limit_req zone=ovcoupons_index burst=10 nodelay;
++ proxy_pass http://127.0.0.1:4850;
++ }
# ── Pages, feeds, sitemaps, robots.txt, llms.txt, static assets ──
++ # (No proxy_set_header here: one would drop every server-level header, Host and X-Forwarded-Proto included.)
location / {
++ limit_req zone=ovcoupons_pages burst=40 nodelay;
proxy_pass http://127.0.0.1:4850;
}