Локальный .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>
58 lines
6.5 KiB
Markdown
58 lines
6.5 KiB
Markdown
---
|
||
title: Локальный .NET-админ snolla — HTTPS на IIS :443 (self-signed wildcard)
|
||
type: concept
|
||
tags: [snolla, morethencms, iis, admin, https, self-signed, certificate, local, pilorama98]
|
||
related: [[snolla-local-admin-and-on-snolla-migration-design]], [[traefik-on-windows-docker-desktop]], [[docker-host-loopback-detect]], [[stostayer-admin-minio-config]]
|
||
updated: 2026-07-29
|
||
---
|
||
|
||
# Локальный .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_PORT` leak → нужен 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 TextExtension `2.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`, SAN `DNS:*.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 (title `SNOLLA`, password-поле, `<form action="/admin/login">`). Покрытие верифицировано: pilorama98, kupimknigi, internal, tandemmebel → 200.
|
||
- **Голый `/admin` → 302 `/login` → 301 `https://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` — фактический alias `internal`.
|
||
|
||
## 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 отклонён. |