snolla galleries 404 (imgproxy "Source unreachable"): legacy storageClient "galleries" = MoreThenCms Local storage class (App_Data\galleries\<siteId>), never in S3 — products were migrated, galleries weren't. Path A (user pick): new bucket `galleries`, 301 pilorama98 originals (77 MiB) rclone'd from RUVDS IIS → s3://galleries/37e6…/<guid>.jpg verbatim. snolla code unchanged (storageClient=bucket is the working convention). imgproxy smoke from books-vds: real obj 200 image/webp, fake guid 404. Other sites unmigrated (scope). Inbox sent to victor/snolla. - close [migrate-gallery-originals-to-s3] (scope pilorama98) - NEW .wiki concept galleries-storage-class-local-not-s3 - fix stale minio-imgproxy-on-vds (pipeline on books-vds since 2026-06-08) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
4.6 KiB
Galleries storage class = Local (disk), not S3
Root cause
В MoreThenCms <fileStorageClients> (Web.config) каждый storageClient — это алиас конфига, не имя бакета. Алиас galleries маппится на тип MoreThenCms.FileStorage.Local.GalleriesStorage → файлы на локальном диске IIS:
C:\sites\snolla\App_Data\galleries\<siteId:N>\<storageFilename-guid>.<ext>
То же у assets, images, scripts, stylesheets, watermarks — все Local. Продукты (e-commerce) — другой механизм, реально в S3 (bucket pilorama98, prefix products/, шард по hex, без siteId).
Переписка snolla (Node) наивно строит источник как s3://${image.storageClient}/${siteId}/${storageFilename} (packages/snolla/middleware/galleries.js:47, lib/viewModels/index.js:289) — т.е. ждёт галереи в S3 в бакете с именем galleries. Но их там никогда не было → imgproxy «Source image is unreachable» (404). Это НЕ баг билдера URL и НЕ поломка ресайза — просто данные не мигрированы из Local-диска в S3.
Симптом-близнец на legacy-prod (pilorama98.ru/galleries/<id>/images/<size>/<seq>.jpg): original/* = 200 (читает диск), любой ресайз = 404 — отдельная мёртвая ветка legacy-ресайзера (System.Drawing/image-cache). Целевая архитектура = imgproxy, legacy-ресайз не чинится.
Fix recipe (путь A — выбран)
storageClient как имя бакета = рабочая конвенция snolla. Заливаем Local-диск в одноимённый bucket, ключи verbatim — код snolla не меняется:
# на RUVDS IIS (rclone v1.74.2 уже стоит). env-var remote, без записи cred в rclone.conf
$env:RCLONE_CONFIG_MIN_TYPE='s3'; $env:RCLONE_CONFIG_MIN_PROVIDER='Minio'
$env:RCLONE_CONFIG_MIN_ACCESS_KEY_ID='<minio-access>'; $env:RCLONE_CONFIG_MIN_SECRET_ACCESS_KEY='<minio-secret>'
$env:RCLONE_CONFIG_MIN_ENDPOINT='https://minio.kzntsv.site' # books-vds S3 API за traefik
& rclone mkdir min:galleries
& rclone copy "C:\sites\snolla\App_Data\galleries\<siteId>" min:galleries/<siteId> --transfers 8
& rclone size min:galleries/<siteId> # сверить count+size с источником
<siteId>папки на диске уже lowercase 32-hex ==ownerIdsnolla (String(site.id).replace(-).toLowerCase()) → ключи совпадают 1:1, трансформаций не надо.- Креды MinIO:
pass books-vds/full-env(контейнерminio, envMINIO_ACCESS_KEY/MINIO_SECRET_KEY). imgproxy key/salt — env контейнераimgproxy.
Smoke (важно: мимо LAN-DNS воркстейшна)
imgproxy.kzntsv.site с воркстейшна резолвится в 127.0.0.1 (LAN-перехват CMS-доменов) — смоук гнать с самого books-vds или --resolve …:89.253.255.133:
curl -sk --resolve imgproxy.kzntsv.site:443:127.0.0.1 'https://imgproxy.kzntsv.site/<sig>/fill/W/H/ce/0/<b64url(s3://galleries/<siteId>/<guid>.jpg)>.webp'
# подпись: base64url( HMAC_SHA256(KEY_bin, SALT_bin + path) ), KEY/SALT = hex из env imgproxy
Реальный объект → 200 image/webp; несуществующий guid → 404 (негативный контроль).
Status / scope
- pilorama98 (siteId
37e67fc44b9e4c06a522a26a73bac9b0): мигрирован 2026-06-12 — 301 файл / 77 MiB, imgproxy 200 verified. - Остальные ~40 siteId-папок в
App_Data\galleries— НЕ мигрированы (часть пустые). Bucketgalleriesshared; заполнен только префикс pilorama98. Другие сайты в snolla → 404 пока не зальёшь (регрессии нет). - Если поднимаются другие Local-классы (
assets/images/…) в snolla через imgproxy — их ждёт та же дыра, тот же рецепт.
См. задачу .tasks/STATUS.md → [migrate-gallery-originals-to-s3].