openvibers/openvibe.mediahub Commits

MediaHub vhost: form writes only on the strict zone (GET /files is a page), /internal/ 404, security.txt, and openvibe.pics / openvibe.video server blocks with their own certificates

OP OpenVibers committed 8 Oct 2026 · cfd01bf0b2 · 1 file, +108 −2


Changes

ddiff --git a/deploy/nginx/openvibe.download.conf b/deploy/nginx/openvibe.download.conf
iindex 30b10f8..470b18e 100644
---- a/deploy/nginx/openvibe.download.conf
++++ b/deploy/nginx/openvibe.download.conf
@@@ -12,6 +12,14 @@
limit_req_zone $binary_remote_addr zone=media-hub_auth:10m rate=10r/m;
limit_req_zone $binary_remote_addr zone=media-hub_api:10m rate=5r/s;
limit_req_zone $binary_remote_addr zone=media-hub_forms:10m rate=1r/s;
++# Form writes only: reading /files is a page like any other (an empty key is not counted; limit_req is not allowed
++# inside limit_except).
++map $request_method $media_hub_write_key {
++ GET "";
++ HEAD "";
++ default $binary_remote_addr;
++}
++limit_req_zone $media_hub_write_key zone=media-hub_writes:10m rate=1r/s;
server {
listen 80;
@@@ -41,6 +49,7 @@ server {
http2 on;
server_name openvibe.download;
++ include snippets/security-txt.conf; # /.well-known/security.txt (host file; SECURITY.md in every repo)
ssl_certificate /etc/letsencrypt/live/openvibe.download/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/openvibe.download/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
@@@ -125,12 +134,13 @@ server {
# ── Form writes (the upload form is the exact match above) ──
location ~ ^/(files|folders|shares|staff)(/|$) {
-- limit_req zone=media-hub_forms burst=10 nodelay;
++ limit_req zone=media-hub_writes burst=10 nodelay;
limit_req_status 429;
proxy_pass http://127.0.0.1:4990;
}
-- # ── Prometheus metrics: host-local scrapers only (http://127.0.0.1:4990/metrics) ──
++ # ── Loopback only: OpenVibe.Events' deliveries (account export and deletion) and Prometheus ──
++ location /internal/ { return 404; }
location = /metrics { return 404; }
# ── Pages, docs, robots.txt, sitemap, static assets ─────
@@@ -142,3 +152,99 @@ server {
deny all;
}
}
++
++# ── openvibe.pics and openvibe.video: the same process answers by Host with "coming" pages (no uploads there) ──
++server {
++ listen 80;
++ listen [::]:80;
++ server_name openvibe.pics www.openvibe.pics openvibe.video www.openvibe.video;
++
++ location /.well-known/acme-challenge/ { root /var/www/certbot; }
++ location / { return 301 https://$host$request_uri; }
++}
++
++server {
++ listen 443 ssl;
++ listen [::]:443 ssl;
++ http2 on;
++ server_name www.openvibe.pics;
++ ssl_certificate /etc/letsencrypt/live/openvibe.pics/fullchain.pem;
++ ssl_certificate_key /etc/letsencrypt/live/openvibe.pics/privkey.pem;
++ return 301 https://openvibe.pics$request_uri;
++}
++
++server {
++ listen 443 ssl;
++ listen [::]:443 ssl;
++ http2 on;
++ server_name www.openvibe.video;
++ ssl_certificate /etc/letsencrypt/live/openvibe.video/fullchain.pem;
++ ssl_certificate_key /etc/letsencrypt/live/openvibe.video/privkey.pem;
++ return 301 https://openvibe.video$request_uri;
++}
++
++server {
++ listen 443 ssl;
++ listen [::]:443 ssl;
++ http2 on;
++ server_name openvibe.pics;
++ include snippets/security-txt.conf;
++ ssl_certificate /etc/letsencrypt/live/openvibe.pics/fullchain.pem;
++ ssl_certificate_key /etc/letsencrypt/live/openvibe.pics/privkey.pem;
++ ssl_protocols TLSv1.2 TLSv1.3;
++ access_log /var/log/nginx/openvibe.pics.access.log;
++ error_log /var/log/nginx/openvibe.pics.error.log;
++ client_max_body_size 128k;
++ add_header X-Content-Type-Options nosniff always;
++ add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
++ gzip on;
++ gzip_types text/css application/javascript application/json text/plain application/xml;
++ proxy_http_version 1.1;
++ proxy_set_header Host $host;
++ proxy_set_header X-Real-IP $remote_addr;
++ proxy_set_header X-Forwarded-For $remote_addr;
++ proxy_set_header CF-Connecting-IP $remote_addr;
++ proxy_set_header X-Forwarded-Proto $scheme;
++ location /auth/ {
++ limit_req zone=media-hub_auth burst=10 nodelay;
++ limit_req_status 429;
++ proxy_pass http://127.0.0.1:4990;
++ }
++ location /internal/ { return 404; }
++ location = /metrics { return 404; }
++ location / { proxy_pass http://127.0.0.1:4990; }
++ location ~ /\.(?!well-known) { deny all; }
++}
++
++server {
++ listen 443 ssl;
++ listen [::]:443 ssl;
++ http2 on;
++ server_name openvibe.video;
++ include snippets/security-txt.conf;
++ ssl_certificate /etc/letsencrypt/live/openvibe.video/fullchain.pem;
++ ssl_certificate_key /etc/letsencrypt/live/openvibe.video/privkey.pem;
++ ssl_protocols TLSv1.2 TLSv1.3;
++ access_log /var/log/nginx/openvibe.video.access.log;
++ error_log /var/log/nginx/openvibe.video.error.log;
++ client_max_body_size 128k;
++ add_header X-Content-Type-Options nosniff always;
++ add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
++ gzip on;
++ gzip_types text/css application/javascript application/json text/plain application/xml;
++ proxy_http_version 1.1;
++ proxy_set_header Host $host;
++ proxy_set_header X-Real-IP $remote_addr;
++ proxy_set_header X-Forwarded-For $remote_addr;
++ proxy_set_header CF-Connecting-IP $remote_addr;
++ proxy_set_header X-Forwarded-Proto $scheme;
++ location /auth/ {
++ limit_req zone=media-hub_auth burst=10 nodelay;
++ limit_req_status 429;
++ proxy_pass http://127.0.0.1:4990;
++ }
++ location /internal/ { return 404; }
++ location = /metrics { return 404; }
++ location / { proxy_pass http://127.0.0.1:4990; }
++ location ~ /\.(?!well-known) { deny all; }
++}