Локальный .NET-админ snolla на HTTPS: pilorama98.snolla.com/admin 404 (не в hosts → VDS) → ERR_CONNECTION_CLOSED (HSTS upgrade, нет 443). Fix: IIS-native self-signed wildcard *.snolla.com на :443 + Trusted Root (без traefik — acme.json пуст, лишний слой). Рабочий entry-point /admin/account/login (голый /admin → canonical на public — предсуществующее поведение CMS). +index.md (2 строки, design-док ранее не индексирован) + log. Co-Authored-By: Claude <noreply@anthropic.com>
6.5 KiB
Локальный .NET-админ snolla — HTTPS на IIS :443 (self-signed wildcard)
Реализация 2026-07-29 поверх design-дока snolla-local-admin-and-on-snolla-migration-design (Task A). Design предполагал http-only локальную админку (нет traefik → без URL Rewrite → ходим по http). На практике браузер апгрейдил http→https (HSTS, закешированный с прошлых заходов на VDS, или Chrome/Edge «Always use secure connections») → локальный IIS без 443 → ERR_CONNECTION_CLOSED. Постановка wildcard self-signed прямо на IIS-сайт snolla :443 решает это без traefik.
Решение: IIS-native HTTPS, НЕ traefik
Рассматривали оживление локального traefik (traefik-on-windows-docker-desktop). Отклонено:
- Локальный
acme.jsonпуст — LE-сертификата наsnolla.comнет → traefik ради self-signed не нужен (IIS умеет сам). - Traefik как TLS-терминатор перед локальным IIS = лишний слой со всеми готчами: NAT-loopback (docker-host-loopback-detect), сломанный docker.sock provider, file-provider не watch'ит,
SERVER_PORTleak → нужен URL Rewrite, acme.json perms 0777. - Бэкенд теперь на том же хосте (локальный IIS), не в VBox-VM — reverse-proxy не несёт смысла.
IIS сам терминирует TLS → SERVER_PORT=443 чисто, X-Forwarded не нужен, port-leak'ов нет.
Что сделано
1. hosts — добавлен pilorama98.snolla.com
Symptom: https://pilorama98.snolla.com/admin → 404. Корень: pilorama98.snolla.com не был в hosts-override → реальный DNS → VDS 89.253.255.94 → traefik без роута → 404 (404 прилетал с VDS, не с локального). Системный прокси 127.0.0.1:10808 (xray) маскировал «server 127.0.0.1» в curl, но реальный backend был VDS.
pilorama98 — реальный сайт в dbo.Sites (Alias=pilorama98, PrimaryDomain=pilorama98.ru, Live=True, Production=False, SiteId 37e67fc4-…), просто не входил в тираж-5 из design-дока. Catch-all обслужит любой сайт из DB при добавлении в hosts.
Строка hosts теперь:
127.0.0.1 tandemmebel.snolla.com labtools.snolla.com labtoolspro.snolla.com emspb.snolla.com kupimknigi.snolla.com internal.snolla.com pilorama98.snolla.com
(правка hosts требует elevation — через Start-Process -Verb RunAs; Set-Content из не-elevated шелла = UnauthorizedAccess; по памяти Get-Content -Raw мог опустошить файл → читаем по строкам).
2. Self-signed wildcard cert на IIS :443
Скрипт (elevated, UAC):
New-SelfSignedCertificate -Subject '*.snolla.com' -DnsName '*.snolla.com','snolla.com' -CertStoreLocation Cert:\LocalMachine\My -NotAfter +10y -TextExtension @('2.5.29.37={text}1.3.6.1.5.5.7.3.1')— гоча:-DnsNameконфликтует с ручным SAN TextExtension2.5.29.17(параметр противоречит SAN) → SAN генерится через-DnsName, оставляем только EKU serverAuth.- Копия в
Cert:\LocalMachine\Root(Trusted Root) черезX509Store('Root','LocalMachine')→ браузер доверяет, HSTS удовлетворён. New-WebBinding -Name snolla -Protocol https -Port 443 -IPAddress '*'+$bind.AddSslCertificate($thumb,'My')+ Stop/Start-Website (без restart binding не активируется).- Cert thumbprint:
6E2212B4C13BD28E2FF680322F11741193E8C619, SANDNS:*.snolla.com, DNS:snolla.com, 10 лет.
Wildcard покрывает все alias'ы сразу — pilorama98, kupimknigi, internal, tandemmebel, labtools, labtoolspro, emspb и любой будущий.
3. Доступ
https://<alias>.snolla.com/admin/account/login→ 200, форма входа SNOLLA (titleSNOLLA, password-поле,<form action="/admin/login">). Покрытие верифицировано: pilorama98, kupimknigi, internal, tandemmebel → 200.- Голый
/admin→ 302/login→ 301https://www.<PrimaryDomain>/(canonical на public-домен). Это предсуществующее поведение CMS (подтверждено оператором: «так и было» на RUVDS), не поломка миграции. Рабочий entry-point =/admin/account/loginнапрямую (закладка). on.snolla.com→ 404: в hosts стоитinternal.snolla.com(реальный alias сайтаonв DB =internal, Title="Internal Site"), неon. Design-док писалon— фактический aliasinternal.
Trade-off
Self-signed, не LE. Допустимо: админка локальная, FW inbound 80/443 закрыт, публично не торчит. Если позже нужен real-LE — traefik DNS-01 через REGRU (креды OpeItcLoc03 в compose-env, см. traefik-on-windows-docker-desktop § DNS-01), но это отдельная задача и весь traefik-стек.
Повторяемость
Cert в Trusted Root переживает перезагрузку. При регенерации (например, истёк/потерян) — тот же скрипт: почистить старые *.snolla.com в My/Root, создать заново, бинд. SslFlags=0 (без SNI) — один catch-all сайт, один wildcard cert на все Host-header'ы.
Связано
- snolla-local-admin-and-on-snolla-migration-design — исходный design (Task A http-only, Task B on.snolla.com→VDS).
- stostayer-admin-minio-config — родственный локальный .NET-админ (:8090), тот же движок MoreThenCms.
- traefik-on-windows-docker-desktop — почему traefik отклонён.