Files
rustingface/asset/nginx/rustingface.com.conf
T
grenadeandClaude Opus 5 3790f2589c
deploy / build (push) Waiting to run
deploy / build-web (push) Failing after 55s
deploy / deploy (push) Has been cancelled
deploy / deploy-web (push) Has been cancelled
fix(core): the per-key manifest lock did not actually exclude
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
2026-08-31 13:03:55 +03:00

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;
}