feat(avatar): NMSR skin renderer at avatar.${BASE_DOMAIN}, Drasl-backed

Add NMSR-as-a-Service (NickAcPT/nmsr-rs) rendering players' skins/avatars,
sourced from Drasl instead of Mojang.

- docker/nmsr/Dockerfile     build from source, pinned to commit 948ba4bc027b
                             (ears feature, lavapipe software Vulkan)
- nmsr/config.toml.tmpl       [mojank] -> http://auth.${BASE_DOMAIN}; Drasl
                              serves the Mojang-compatible routes at its bare
                              BaseURL and embeds absolute skin URLs that NMSR
                              fetches directly. allow_offline_mode_uuids=true.
- docker-compose.nmsr.yml     nmsr service (build), host bind 127.0.0.1:9898
                              only, config mount; mounts the caddy avatar snippet
- caddy/conf.d/40-avatar.caddy avatar.${BASE_DOMAIN} -> reverse_proxy nmsr:8080
- nginx-front + LE_SUBDOMAINS  public TLS vhost (HSTS) + cert for avatar
- render-config.sh / .gitignore render + ignore nmsr/config.toml

Skin resolution stays internal over mcnet (caddy alias -> drasl), no public
round-trip.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-09 01:40:50 +02:00
parent a6155819b6
commit 6fac1647aa
9 changed files with 131 additions and 4 deletions

View File

@@ -32,7 +32,7 @@ upstream ulicraft_caddy {
server {
listen 80;
listen [::]:80;
server_name ${BASE_DOMAIN} www.${BASE_DOMAIN} auth.${BASE_DOMAIN} pack.${BASE_DOMAIN} distribution.${BASE_DOMAIN};
server_name ${BASE_DOMAIN} www.${BASE_DOMAIN} auth.${BASE_DOMAIN} pack.${BASE_DOMAIN} distribution.${BASE_DOMAIN} avatar.${BASE_DOMAIN};
return 301 https://$host$request_uri;
}
@@ -127,3 +127,21 @@ server {
proxy_set_header X-Forwarded-Proto $scheme;
}
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name avatar.${BASE_DOMAIN};
ssl_certificate ${APP_DIR}/certs/avatar.${BASE_DOMAIN}/cert.pem;
ssl_certificate_key ${APP_DIR}/certs/avatar.${BASE_DOMAIN}/key.pem;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
location / {
proxy_pass http://ulicraft_caddy;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}