The lock added alongside compare-and-set removed its map entry inside the critical section. A queued waiter still held that mutex, so the next arrival found no entry, created a fresh one, and the two then ran concurrently -- defeating the lock exactly when there was contention, which is the only time it does anything. I previously reported this fix as working on the strength of ten clean release-mode runs. That was wrong: in debug, where the timing differs, the guarding test fails 3 times in 12. Retiring the entry only after dropping our own reference, under the same shard lock `entry` takes, gives 0 failures in 25 -- and restoring the old behaviour reproduces 3 in 12, so the test really does catch it. The consequence was the one the test names: a file served to a client but never recorded, and so invisible the moment the instance is sealed. Real against the local filesystem store, which has no conditional put and relies on the verify-after-write retry; MinIO's compare-and-set covers the same race, which is why the deployed path never showed it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XZG2i4AmfSqE97EJGBVb64
93 lines
3.5 KiB
Plaintext
93 lines
3.5 KiB
Plaintext
# rustingface.com — the public face.
|
|
#
|
|
# A shop window for operators evaluating whether to run their own instance:
|
|
# the catalogue, the model cards, and the app are readable by anyone. Weights
|
|
# are not. That split is enforced by the service (`auth.mode = "bearer"` with
|
|
# `auth.anonymous = "catalog"`), not by this file — nginx here is defence in
|
|
# depth, and the two must not be allowed to disagree.
|
|
#
|
|
# Installed on hanzalova, whose WAN address is nh.thgttg.com. TCP :443 belongs
|
|
# to the stream SNI router, so this listens on the https tier behind it.
|
|
#
|
|
# Public name => Let's Encrypt (external-tls.md). The mesh name rf.internal is
|
|
# a separate vhost with an internal-CA cert, sharing this webroot and upstream
|
|
# (reverse-proxies.md §2).
|
|
|
|
server {
|
|
listen 127.0.0.1:14443 ssl proxy_protocol;
|
|
http2 on;
|
|
server_name rustingface.com www.rustingface.com;
|
|
|
|
ssl_certificate /etc/letsencrypt/live/rustingface.com/fullchain.pem;
|
|
ssl_certificate_key /etc/letsencrypt/live/rustingface.com/privkey.pem;
|
|
ssl_protocols TLSv1.2 TLSv1.3;
|
|
|
|
root /var/www/rustingface;
|
|
index index.html;
|
|
|
|
absolute_redirect off;
|
|
|
|
access_log /var/log/nginx/rustingface.com.access.log;
|
|
error_log /var/log/nginx/rustingface.com.error.log;
|
|
|
|
# A public origin gets the headers a public origin needs. The app loads
|
|
# nothing cross-origin, so the policy can be tight.
|
|
add_header X-Content-Type-Options "nosniff" always;
|
|
add_header X-Frame-Options "DENY" always;
|
|
add_header Referrer-Policy "no-referrer" always;
|
|
add_header Strict-Transport-Security "max-age=31536000" always;
|
|
|
|
proxy_http_version 1.1;
|
|
proxy_set_header Host $host;
|
|
proxy_set_header Connection "";
|
|
proxy_set_header X-Real-IP $proxy_protocol_addr;
|
|
proxy_set_header X-Forwarded-For $proxy_protocol_addr;
|
|
proxy_set_header X-Forwarded-Proto https;
|
|
proxy_set_header Accept-Encoding $http_accept_encoding;
|
|
|
|
proxy_buffering off;
|
|
proxy_request_buffering off;
|
|
client_max_body_size 0;
|
|
proxy_connect_timeout 15s;
|
|
proxy_read_timeout 300s;
|
|
proxy_send_timeout 300s;
|
|
|
|
# --- never public ------------------------------------------------------
|
|
|
|
# /metrics is exempt from the service's own auth so a mesh Prometheus can
|
|
# scrape it without a credential. That exemption is fine on rf.internal
|
|
# and unacceptable here, so the public vhost closes it explicitly rather
|
|
# than relying on the service to.
|
|
location = /metrics { return 404; }
|
|
|
|
# --- the service -------------------------------------------------------
|
|
|
|
# Reachable, but the service answers 401 without a token. Published so a
|
|
# token holder can pull from anywhere, and so an anonymous client gets a
|
|
# 401 it can act on rather than a 404 that reads as "no such model".
|
|
location ^~ /api/ { proxy_pass http://rustingface; }
|
|
location ^~ /v1/ { proxy_pass http://rustingface; }
|
|
location ~ /resolve/ { proxy_pass http://rustingface; }
|
|
|
|
location = /healthz { proxy_pass http://rustingface; }
|
|
|
|
# --- the app -----------------------------------------------------------
|
|
|
|
location /assets/ {
|
|
gzip_static on;
|
|
add_header Cache-Control "public, max-age=31536000, immutable";
|
|
}
|
|
|
|
location = /index.html {
|
|
add_header Cache-Control "no-cache";
|
|
}
|
|
|
|
location / {
|
|
try_files $uri $uri/ /index.html;
|
|
}
|
|
|
|
gzip on;
|
|
gzip_types text/css application/javascript application/json image/svg+xml;
|
|
gzip_min_length 1024;
|
|
}
|