feat(iis-migration): win-acme HTTP-01 auto-renewal on RUVDS IIS
Stood up a permanent self-renewing Let's Encrypt pipeline on the RUVDS IIS host, replacing the manual traefik acme.json -> PFX import and closing the 2026-07-22 cert-expiry deadline (new 25-SAN cert valid to 2026-09-03, SYSTEM scheduled task renews 55 days before expiry). Key obstacle: the MoreThenCms OWIN catch-all (owin:HandleAllRequests) swallowed /.well-known/acme-challenge/. Solved by carving the challenge path into a separate IIS application in a No-Managed-Code app pool, plus patching win-acme's Web_Config.xml template to remove the inherited Owin handler. Staging + prod validation green for all 25 hostnames; live TLS smoke confirms the new cert is served (incl degraded maljarka/rimiz). - scripts/iis-migration-to-ruvds/03-ruvds-winacme.ps1 (idempotent setup) - scripts/iis-migration-to-ruvds/winacme-Web_Config.xml (patched template) - .wiki/concepts/winacme-iis-owin-catchall-http01.md (recipe + gotchas) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,45 +1,51 @@
|
|||||||
---
|
---
|
||||||
_last_updated_: 2026-06-05T00:30:00+03:00
|
_last_updated_: 2026-06-05T02:00:00+03:00
|
||||||
session_id: 2026-06-05-iis-migration-full-cutover
|
session_id: 2026-06-05-iis-cutover-and-winacme-renewal
|
||||||
---
|
---
|
||||||
|
|
||||||
# Next session handoff
|
# Next session handoff
|
||||||
|
|
||||||
_Сессия: **FULL CUTOVER достигнут** — все 25 hostname (tandemmebel + вся зона snolla.com) authoritative
|
_Сессия: (1) full DNS cutover на RUVDS достигнут; (2) поднят постоянный win-acme HTTP-01 auto-renewal
|
||||||
на RUVDS `80.64.31.36`. Source НЕ заглушен (user-decision: 7-day soak warm rollback). Зафиксировано в
|
на RUVDS IIS — дедлайн cert-expiry 2026-07-22 СНЯТ. Source НЕ заглушен (warm rollback). Всё проверено,
|
||||||
`.tasks/iis-migration-to-ruvds.md`. Ничего не висит._
|
ничего не висит._
|
||||||
|
|
||||||
## Recent commits
|
## Recent commits
|
||||||
|
|
||||||
- `539f1a07` task(iis-migration): tandemmebel DNS cutover 2026-06-05
|
- `9cd6d4e2` task(iis-migration): full DNS cutover reached 2026-06-05
|
||||||
- (+ commit этой сессии с full-cutover записью)
|
- (+ commit этой сессии: win-acme renewal pipeline + wiki concept)
|
||||||
|
|
||||||
## Что сделано (iis-migration, 05.06)
|
## Что сделано (iis-migration, 05.06)
|
||||||
|
|
||||||
- ✅ **Full cutover:** все 25 hostname → RUVDS на authoritative ns1.reg.ru. На windows-source
|
- ✅ **Full cutover:** все 25 hostname authoritative на RUVDS `80.64.31.36`. На windows-source ничего authoritative.
|
||||||
(`94.19.247.14`) authoritative не осталось ничего. Вся зона `snolla.com` (apex + 10 субдоменов,
|
- ✅ **win-acme auto-renewal** на RUVDS: 25-SAN LE cert (до **2026-09-03**) во всех SNI-биндингах +
|
||||||
независимые A) переехала вслед за tandemmebel.
|
SYSTEM scheduled task `win-acme-renew-snolla` (renew 55д до expiry). RUVDS больше НЕ зависит от
|
||||||
- ✅ Хвост кэша: `on.snolla.com` + `tandemmebel.snolla.com` ещё `94.19.247.14` на Google 8.8.8.8
|
домашнего traefik по сертификатам.
|
||||||
(TTL 86400, дотекает; 1.1.1.1/Yandex уже RUVDS). Дренаж до ~24ч.
|
- Gotcha решён: OWIN-catch-all CMS жрал `/.well-known/acme-challenge/` → challenge вынесен в отдельное
|
||||||
- ✅ RUVDS smoke: `snolla.com` 200, `tandemmebel.snolla.com` 200. `maljarka` 502 (pre-existing CMS, не cutover).
|
IIS-приложение (пул «No Managed Code») + патч шаблона `C:\win-acme\Web_Config.xml`.
|
||||||
|
- Артефакты: `scripts/iis-migration-to-ruvds/03-ruvds-winacme.ps1` + `winacme-Web_Config.xml`;
|
||||||
|
recipe в `.wiki/concepts/winacme-iis-owin-catchall-http01.md`.
|
||||||
|
- Доступ к RUVDS: SSH `~/.ssh/ruvds-iis-migration` → `Administrator@80.64.31.36` (elevated сессия).
|
||||||
|
|
||||||
## Спроси user'а
|
## Спроси user'а
|
||||||
|
|
||||||
- **Decommission `snolla` site** — ждём soak (~2026-06-12) + drain кэша, или форсировать раньше?
|
- **Decommission `snolla` site** на windows-source — ждём soak (~2026-06-12) + drain кэша, или раньше?
|
||||||
Когда решит: elevated PS → `Stop-Website snolla` → архив `C:\sites\snolla` (8.66 ГБ) → kreknin →
|
Когда решит: elevated PS → `Stop-Website snolla` → архив `C:\sites\snolla` (8.66 ГБ) → kreknin +
|
||||||
cleanup temp SSH-ключей + FW-правил (`ssh-from-source`/`smb-from-source` на RUVDS).
|
cleanup temp SSH-ключей/FW-правил. (win-acme на RUVDS от этого не зависит — он самостоятелен.)
|
||||||
- **LE-renewal на RUVDS** — теперь DNS полностью на RUVDS → можно win-acme + HTTP-01. Дедлайн ~2026-07-15
|
- `maljarka.tandemmebel.ru` 502 — чинить CMS-тенант отдельно? (pre-existing, не блокер; HTTPS-cert у него валиден).
|
||||||
(certs expire 2026-07-22). Поднимать?
|
|
||||||
- `maljarka.tandemmebel.ru` 502 — чинить CMS-тенант отдельно? (pre-existing, не блокер).
|
|
||||||
|
|
||||||
## Не делать (preemptive guards)
|
## Не делать (preemptive guards)
|
||||||
|
|
||||||
- **Не `Stop-Website snolla` пока хвост кэша течёт** — `on.`/`tandemmebel.snolla.com` ещё резолвятся
|
- **Не `--test` в win-acme под SSH** — включает интерактив, виснет. Для staging — `--baseuri <staging>`.
|
||||||
на windows у части юзеров (Google). Остановка сейчас = частичный downtime до drain.
|
- **Не трогать `acme-challenge` IIS-приложение / пул «No Managed Code» / патченый `Web_Config.xml`** —
|
||||||
- **Не глушить до soak** без явного запроса — user выбрал 7-day warm rollback.
|
на них держится авто-renewal. Detail: `.wiki/concepts/winacme-iis-owin-catchall-http01.md`.
|
||||||
- IIS-правки требуют **elevated shell** (текущий `vitya` — не admin; W3SVC running).
|
- **Не `Stop-Website snolla` пока хвост кэша течёт / без явного запроса** (warm rollback).
|
||||||
- **branch ahead от origin** — push без явного grant'а (Rule 4). Этой сессии grant НЕ давали.
|
- IIS-правки — elevated shell. **branch ahead от origin** — push без явного grant'а (Rule 4); grant НЕ давали.
|
||||||
|
|
||||||
## Memory updates за сессию
|
## Memory updates за сессию
|
||||||
|
|
||||||
- (нет нового файла)
|
- (нет нового файла; знание — в wiki concept + task decisions log)
|
||||||
|
|
||||||
|
## ⚠️ Sensitive (НЕ в git)
|
||||||
|
|
||||||
|
- Корневой `C:\sites\snolla\web.config` содержит plaintext-креды (MSSQL/SMTP/Azure/API-ключи). Pre-existing,
|
||||||
|
не вводилось этой сессией. Если будешь декоммишить/архивировать — не плодить копии в трекаемых местах.
|
||||||
|
|||||||
@@ -62,6 +62,7 @@ Migrate IIS hosting from [[../entities/windows-recovery-host]] (DESKTOP-NSEF0UK)
|
|||||||
- **На windows source 94.19.247.14** (16): `labtools.ru` + `www.labtools.ru`, `snolla.com` + 12× *.snolla.com (incl `rimiz.snolla.com`), `maljarka.tandemmebel.ru`, `tandemmebel.ru` + `www.tandemmebel.ru` (scope exception). TTL 86400s — не lowered.
|
- **На windows source 94.19.247.14** (16): `labtools.ru` + `www.labtools.ru`, `snolla.com` + 12× *.snolla.com (incl `rimiz.snolla.com`), `maljarka.tandemmebel.ru`, `tandemmebel.ru` + `www.tandemmebel.ru` (scope exception). TTL 86400s — не lowered.
|
||||||
- **Live smoke** через real DNS: `kupimknigi.spb.ru`/`www.emspb.ru`/`www.pilorama98.ru`/`www.labtools.pro` → 200 OK + correct per-tenant title. Bare-domain 3 redirects работают (emspb/pilorama98/labtools.pro). `rimiz.ru` / `www.rimiz.ru` → 404 — pre-existing CMS-defect (тоже 404 на source), не migration regression.
|
- **Live smoke** через real DNS: `kupimknigi.spb.ru`/`www.emspb.ru`/`www.pilorama98.ru`/`www.labtools.pro` → 200 OK + correct per-tenant title. Bare-domain 3 redirects работают (emspb/pilorama98/labtools.pro). `rimiz.ru` / `www.rimiz.ru` → 404 — pre-existing CMS-defect (тоже 404 на source), не migration regression.
|
||||||
- **2026-06-05 (tandemmebel cutover — post-closure follow-up):** user (владелец tandemmebel) сам перенастроил DNS в reg.ru. Проверено `Resolve-DnsName`: `tandemmebel.ru` + `www.tandemmebel.ru` + `maljarka.tandemmebel.ru` → `80.64.31.36` (RUVDS) на authoritative ns1.reg.ru + 8.8.8.8 + 1.1.1.1 + Yandex. apex+CNAME сработал (www/maljarka follow apex автоматом). Smoke через real DNS: `tandemmebel.ru`/`www` → **200 OK** correct content; `maljarka.tandemmebel.ru` → **502** (pre-existing CMS-дефект, на source ровно так же — не регрессия cutover'а, см. Open questions). **Снимает прежнюю scope-exception 2026-05-24** (tandemmebel больше НЕ остаётся на windows). **Source НЕ заглушен** — user-decision держать как warm rollback: сайт `snolla` — общий catch-all, 11 `*.snolla.com` (incl `tandemmebel.snolla.com`) ещё резолвятся на `94.19.247.14`, полный `Stop-Website` невозможен; индивидуальное снятие 3 HTTPS-биндингов отложено до full-site decommission. Текущий баланс: **14 hostnames на RUVDS / 11 на windows-source**.
|
- **2026-06-05 (tandemmebel cutover — post-closure follow-up):** user (владелец tandemmebel) сам перенастроил DNS в reg.ru. Проверено `Resolve-DnsName`: `tandemmebel.ru` + `www.tandemmebel.ru` + `maljarka.tandemmebel.ru` → `80.64.31.36` (RUVDS) на authoritative ns1.reg.ru + 8.8.8.8 + 1.1.1.1 + Yandex. apex+CNAME сработал (www/maljarka follow apex автоматом). Smoke через real DNS: `tandemmebel.ru`/`www` → **200 OK** correct content; `maljarka.tandemmebel.ru` → **502** (pre-existing CMS-дефект, на source ровно так же — не регрессия cutover'а, см. Open questions). **Снимает прежнюю scope-exception 2026-05-24** (tandemmebel больше НЕ остаётся на windows). **Source НЕ заглушен** — user-decision держать как warm rollback: сайт `snolla` — общий catch-all, 11 `*.snolla.com` (incl `tandemmebel.snolla.com`) ещё резолвятся на `94.19.247.14`, полный `Stop-Website` невозможен; индивидуальное снятие 3 HTTPS-биндингов отложено до full-site decommission. Текущий баланс: **14 hostnames на RUVDS / 11 на windows-source**.
|
||||||
|
- **2026-06-05 (LE auto-renewal pipeline построен — win-acme):** на RUVDS поднят постоянный self-renewing HTTP-01 pipeline (win-acme v2.2.9). Один **25-SAN cert** (store WebHosting, Issuer LE YR2, valid до **2026-09-03**) установлен во все 25 SNI-биндинга; **scheduled task `win-acme-renew-snolla`** (SYSTEM, daily, renew 55д до expiry). **Закрывает дедлайн cert-expiry 2026-07-22** и снимает зависимость RUVDS от домашнего traefik по сертификатам. Главный gotcha: OWIN-catch-all CMS (`owin:HandleAllRequests=true`) перехватывал `/.well-known/acme-challenge/` → решено выносом challenge-пути в **отдельное IIS-приложение в пуле «No Managed Code»** + патч шаблона `C:\win-acme\Web_Config.xml` (`<remove name="Owin"/>`). Staging + prod валидация всех 25 хостов зелёная; живые HTTPS-эндпоинты отдают новый cert (проверено TLS-смоком, incl maljarka/rimiz). Скрипт `scripts/iis-migration-to-ruvds/03-ruvds-winacme.ps1` + шаблон `winacme-Web_Config.xml`. Полный recipe: [[../.wiki/concepts/winacme-iis-owin-catchall-http01]].
|
||||||
- **2026-06-05 (FULL CUTOVER достигнут):** проверка всех 25 hostname против authoritative ns1.reg.ru — **все → `80.64.31.36` (RUVDS), на windows-source authoritative не осталось ничего**. Вся зона `snolla.com` (apex + 10 субдоменов, независимые A-записи) переехала. Хвост кэша: `on.snolla.com` + `tandemmebel.snolla.com` ещё `94.19.247.14` на Google 8.8.8.8 (TTL 86400, дотекает; 1.1.1.1/Yandex уже RUVDS). RUVDS smoke: `snolla.com` 200 (default лендинг), `tandemmebel.snolla.com` 200 (tenant content). **Разблокирует decommission** `snolla` site + LE-renewal через win-acme+HTTP-01 (теперь challenge не отскочит на windows). **Source НЕ заглушен** — user-decision: 7-day soak warm rollback + ждём drain кэша. Целевой decommission ~2026-06-12; cert-renewal deadline ~2026-07-15 (certs expire 2026-07-22).
|
- **2026-06-05 (FULL CUTOVER достигнут):** проверка всех 25 hostname против authoritative ns1.reg.ru — **все → `80.64.31.36` (RUVDS), на windows-source authoritative не осталось ничего**. Вся зона `snolla.com` (apex + 10 субдоменов, независимые A-записи) переехала. Хвост кэша: `on.snolla.com` + `tandemmebel.snolla.com` ещё `94.19.247.14` на Google 8.8.8.8 (TTL 86400, дотекает; 1.1.1.1/Yandex уже RUVDS). RUVDS smoke: `snolla.com` 200 (default лендинг), `tandemmebel.snolla.com` 200 (tenant content). **Разблокирует decommission** `snolla` site + LE-renewal через win-acme+HTTP-01 (теперь challenge не отскочит на windows). **Source НЕ заглушен** — user-decision: 7-day soak warm rollback + ждём drain кэша. Целевой decommission ~2026-06-12; cert-renewal deadline ~2026-07-15 (certs expire 2026-07-22).
|
||||||
- **2026-05-25 (close decision):** user-decision close — несмотря на 16 hostnames pending DNS swap + source IIS:8089 still live + LE renewal pipeline pending + cleanup pending, **task закрывается** на этом этапе. Reason: Phase 1 (RUVDS infra + scp + IIS recreate + cert import + 9 DNS swaps) выполнен и live; остальное — coordination/wait/decommission character, не agent-work load. Future actions перечислены в Closure note ниже, не trackable как `iis-migration-to-ruvds` continuation.
|
- **2026-05-25 (close decision):** user-decision close — несмотря на 16 hostnames pending DNS swap + source IIS:8089 still live + LE renewal pipeline pending + cleanup pending, **task закрывается** на этом этапе. Reason: Phase 1 (RUVDS infra + scp + IIS recreate + cert import + 9 DNS swaps) выполнен и live; остальное — coordination/wait/decommission character, не agent-work load. Future actions перечислены в Closure note ниже, не trackable как `iis-migration-to-ruvds` continuation.
|
||||||
|
|
||||||
@@ -71,7 +72,7 @@ Migrate IIS hosting from [[../entities/windows-recovery-host]] (DESKTOP-NSEF0UK)
|
|||||||
- [ ] **Source IIS state backup НЕ снят** (skip'нули — appcmd требует elevated source-shell которого не было). Acceptable risk — source IIS всё ещё running как rollback. Если RUVDS proves stable за 1 неделю → можно decommission source без forensic snapshot'а.
|
- [ ] **Source IIS state backup НЕ снят** (skip'нули — appcmd требует elevated source-shell которого не было). Acceptable risk — source IIS всё ещё running как rollback. Если RUVDS proves stable за 1 неделю → можно decommission source без forensic snapshot'а.
|
||||||
- [ ] **CMS-side 502/404 на 4 hostnames** — `maljarka.tandemmebel.ru` / `rimiz.ru` / `www.rimiz.ru` / `rimiz.snolla.com`. На source тоже не работают (return default page). Pre-existing dead-routes от `[iis-traefik-dead-routes-cleanup]` 2026-05-21. Изоляция не блокер для migration; защититься от cutover-blame — отдельная investigation если нужно.
|
- [ ] **CMS-side 502/404 на 4 hostnames** — `maljarka.tandemmebel.ru` / `rimiz.ru` / `www.rimiz.ru` / `rimiz.snolla.com`. На source тоже не работают (return default page). Pre-existing dead-routes от `[iis-traefik-dead-routes-cleanup]` 2026-05-21. Изоляция не блокер для migration; защититься от cutover-blame — отдельная investigation если нужно.
|
||||||
- [ ] **Backup strategy для RUVDS** — расширить `vds-backup-rsync-kreknin` cron как третий source? Решение отложено до после full cutover.
|
- [ ] **Backup strategy для RUVDS** — расширить `vds-backup-rsync-kreknin` cron как третий source? Решение отложено до после full cutover.
|
||||||
- [ ] **LE renewal на RUVDS** — текущие certs valid до 2026-07-22 (~60 дней). До expiry нужен permanent renewal pipeline:
|
- [x] **LE renewal на RUVDS** — ✅ DONE 2026-06-05 (win-acme HTTP-01, см. Decisions log + [[../.wiki/concepts/winacme-iis-owin-catchall-http01]]). Выбран Option A (win-acme + HTTP-01 после full cutover). Новый 25-SAN cert до 2026-09-03, авто-renewal через SYSTEM scheduled task. Дедлайн 2026-07-22 снят. ~~Историческая формулировка ниже:~~ текущие certs valid до 2026-07-22 (~60 дней). До expiry нужен permanent renewal pipeline:
|
||||||
- Option A: win-acme (wacs.exe) standalone-на-RUVDS с DNS-01 (manual TXT на reg.ru — нет reg.ru-plugin) или HTTP-01 (но только после DNS swap'а — иначе LE challenge bounce'нется на home).
|
- Option A: win-acme (wacs.exe) standalone-на-RUVDS с DNS-01 (manual TXT на reg.ru — нет reg.ru-plugin) или HTTP-01 (но только после DNS swap'а — иначе LE challenge bounce'нется на home).
|
||||||
- Option B: cron-job который re-extract'ит из traefik acme.json + scp upload + Import-PfxCertificate на RUVDS. Pollute source's traefik lifecycle.
|
- Option B: cron-job который re-extract'ит из traefik acme.json + scp upload + Import-PfxCertificate на RUVDS. Pollute source's traefik lifecycle.
|
||||||
- Recommendation: Option A win-acme + HTTP-01 после full cutover (~95 days margin до cert expiry — 60 days minus DNS-stabilization window).
|
- Recommendation: Option A win-acme + HTTP-01 после full cutover (~95 days margin до cert expiry — 60 days minus DNS-stabilization window).
|
||||||
@@ -105,9 +106,7 @@ Task **closed 🟢** per user decision. Phase 1 — RUVDS infra + cert pipeline
|
|||||||
|
|
||||||
2. **Source IIS НЕ decommission'ен.** `localhost:8089` snolla site + port 80 catch-all still live на windows-recovery-host. Не трогать пока 16 hostnames на 94.19.247.14. После full cutover + 7-day soak — `Stop-Website snolla` + archive `C:\sites\snolla` (8.66GB) → kreknin.
|
2. **Source IIS НЕ decommission'ен.** `localhost:8089` snolla site + port 80 catch-all still live на windows-recovery-host. Не трогать пока 16 hostnames на 94.19.247.14. После full cutover + 7-day soak — `Stop-Website snolla` + archive `C:\sites\snolla` (8.66GB) → kreknin.
|
||||||
|
|
||||||
3. **LE renewal pipeline НЕ построен.** Текущие RUVDS PFX certs valid до 2026-07-22 (~57 days от 2026-05-25). До этой даты нужен renewal-mechanism:
|
3. ~~**LE renewal pipeline НЕ построен.**~~ → **DONE 2026-06-05** (win-acme HTTP-01 после full cutover, как и рекомендовалось). Новый 25-SAN LE cert до 2026-09-03 + SYSTEM auto-renew task. Recipe: [[../.wiki/concepts/winacme-iis-owin-catchall-http01]].
|
||||||
- Recommend: win-acme на RUVDS + HTTP-01 challenge — **возможно только после full DNS cutover** (HTTP-01 bounce'нется на windows source pre-cutover, LE не сможет verify owners).
|
|
||||||
- Soft deadline: ~2026-07-15 (week of margin до cert expiry).
|
|
||||||
|
|
||||||
4. **Temp SSH key cleanup не сделан.** Оставлены (могут понадобиться для будущих push'ей на RUVDS):
|
4. **Temp SSH key cleanup не сделан.** Оставлены (могут понадобиться для будущих push'ей на RUVDS):
|
||||||
- `~/.ssh/ruvds-iis-migration` + `.pub` на source workstation
|
- `~/.ssh/ruvds-iis-migration` + `.pub` на source workstation
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ updated: 2026-05-24
|
|||||||
|
|
||||||
Recipe для one-shot переноса Let's Encrypt certs из traefik `acme.json` (single-file ACME store) в IIS на Windows host с SNI multi-binding'ами. Использован при миграции [[../entities/ruvds-iis-host]] 2026-05-23 для 14 LE certs → 25 HTTPS hostnames bound via SNI. **Это не renewal pipeline**, а bootstrap-перенос — для long-term renewal recommend `win-acme` standalone на IIS host'е (см. footnote).
|
Recipe для one-shot переноса Let's Encrypt certs из traefik `acme.json` (single-file ACME store) в IIS на Windows host с SNI multi-binding'ами. Использован при миграции [[../entities/ruvds-iis-host]] 2026-05-23 для 14 LE certs → 25 HTTPS hostnames bound via SNI. **Это не renewal pipeline**, а bootstrap-перенос — для long-term renewal recommend `win-acme` standalone на IIS host'е (см. footnote).
|
||||||
|
|
||||||
|
> **Update 2026-06-05 — SUPERSEDED для renewal'а.** Этот ручной PFX-перенос больше не на критическом пути: на RUVDS поднят постоянный self-renewing win-acme HTTP-01 pipeline — см. [[winacme-iis-owin-catchall-http01]]. RUVDS больше не зависит от домашнего traefik по сертификатам. Этот recipe оставлен как reference для bootstrap-сценария / если HTTP-01 недоступен.
|
||||||
|
|
||||||
## Когда применять
|
## Когда применять
|
||||||
|
|
||||||
- Migration: traefik-on-A → IIS-on-B, certs нужны до того как ACME-validation с нового host'а станет возможной (DNS ещё указывает на старый host, HTTP-01 challenge bounce'нется).
|
- Migration: traefik-on-A → IIS-on-B, certs нужны до того как ACME-validation с нового host'а станет возможной (DNS ещё указывает на старый host, HTTP-01 challenge bounce'нется).
|
||||||
|
|||||||
94
.wiki/concepts/winacme-iis-owin-catchall-http01.md
Normal file
94
.wiki/concepts/winacme-iis-owin-catchall-http01.md
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
---
|
||||||
|
title: win-acme HTTP-01 авто-renewal на IIS под OWIN-catch-all CMS
|
||||||
|
status: live
|
||||||
|
tags: [windows, iis, ruvds, letsencrypt, win-acme, acme, http-01, owin, cms, ops]
|
||||||
|
related: [[ruvds-iis-host]], [[traefik-acme-json-to-iis-cert-import]], [[windows-server-2025-core-bootstrap]], [[iis-migration-2026-05-19-postmortem]]
|
||||||
|
---
|
||||||
|
|
||||||
|
# win-acme HTTP-01 авто-renewal на IIS под OWIN-catch-all CMS
|
||||||
|
|
||||||
|
Постоянный self-renewing LE-pipeline на RUVDS IIS-хосте ([[ruvds-iis-host]]) для сайта `snolla`
|
||||||
|
(25 hostname через SNI). **Заменяет** ручной метод [[traefik-acme-json-to-iis-cert-import]]
|
||||||
|
(экспорт PFX из домашнего traefik `acme.json` + ручной `Import-PfxCertificate`) — тот делал
|
||||||
|
RUVDS зависимым от домашней машины по сертификатам и требовал ручного продления.
|
||||||
|
|
||||||
|
Поднято 2026-06-05, после full DNS cutover на RUVDS (HTTP-01 challenge до cutover'а отскакивал
|
||||||
|
на windows-source — LE не мог достучаться).
|
||||||
|
|
||||||
|
## Что развёрнуто
|
||||||
|
|
||||||
|
- **win-acme v2.2.9** в `C:\win-acme\` (скачан с GitHub releases, `x64.pluggable`).
|
||||||
|
- Один **SAN-cert на 25 hostname** в store `WebHosting`, установлен во все 25 `*:443:<host>` SNI-биндинга.
|
||||||
|
- **Scheduled task `win-acme-renew-snolla`** — daily 09:00 + random delay 4h, runs as **SYSTEM**,
|
||||||
|
`wacs.exe --renew --baseuri https://acme-v02.api.letsencrypt.org/`. Renewal due 55 дней до expiry.
|
||||||
|
- Idempotent setup-скрипт: `scripts/iis-migration-to-ruvds/03-ruvds-winacme.ps1` (фазы `download`/`app`/`probe`/`task`/`verify`).
|
||||||
|
|
||||||
|
## Главный gotcha: OWIN-catch-all жрёт `/.well-known/acme-challenge/`
|
||||||
|
|
||||||
|
Сайт = **MoreThenCms** на OWIN. В корневом `web.config`: `owin:HandleAllRequests=true` +
|
||||||
|
handler `Owin path="*"` + `runAllManagedModulesForAllRequests="true"` → **весь** трафик уходит в
|
||||||
|
managed OWIN-pipeline. HTTP-01 токен (статический файл) отдаётся не статикой, а CMS → `404`/`500`/redirect.
|
||||||
|
LE-валидация падает (`Invalid response ...: 500`).
|
||||||
|
|
||||||
|
Снятие Owin-**handler**'а в дочернем `web.config` НЕ помогает — OWIN перехватывает на уровне
|
||||||
|
**модуля** (HandleAllRequests). Что НЕ сработало:
|
||||||
|
- web.config с `<rewrite><rules><clear/></rules>` — рерайта-то и нет, маршрутит managed-pipeline.
|
||||||
|
- web.config с `<handlers><remove name="Owin"/></handlers>` в обычном (managed) пуле — модуль всё равно жив.
|
||||||
|
|
||||||
|
### Рабочее решение: отдельное IIS-приложение в пуле «No Managed Code»
|
||||||
|
|
||||||
|
`.well-known/acme-challenge` вынесен в **отдельное IIS Application** под сайтом `snolla` с
|
||||||
|
app-pool'ом `acme-challenge`, у которого `managedRuntimeVersion=''` (**No Managed Code**). В таком
|
||||||
|
пуле .NET/OWIN не стартует вообще — токен отдаётся нативным `StaticFileModule`.
|
||||||
|
|
||||||
|
Нюанс: в дочернем web.config всё равно нужно **`<handlers><remove name="Owin"/></handlers>`** —
|
||||||
|
иначе унаследованный managed Owin-handler даёт `500` (managed handler в unmanaged пуле). Плюс
|
||||||
|
extensionless-mime (токены без расширения). Проверенный web.config:
|
||||||
|
|
||||||
|
```xml
|
||||||
|
<configuration>
|
||||||
|
<system.webServer>
|
||||||
|
<handlers><remove name="Owin" /></handlers>
|
||||||
|
<staticContent>
|
||||||
|
<remove fileExtension="." /><mimeMap fileExtension="." mimeType="text/plain" />
|
||||||
|
</staticContent>
|
||||||
|
<modules runAllManagedModulesForAllRequests="false" />
|
||||||
|
</system.webServer>
|
||||||
|
</configuration>
|
||||||
|
```
|
||||||
|
|
||||||
|
Результат: токен отдаётся `200` для **любого** Host — даже для деградировавших CMS-тенантов
|
||||||
|
(`maljarka.tandemmebel.ru`/`rimiz.ru`, которые на app-уровне отдают `502`/`404`), т.к. статика
|
||||||
|
обходит CMS-роутинг.
|
||||||
|
|
||||||
|
### Патч шаблона win-acme
|
||||||
|
|
||||||
|
win-acme при filesystem-валидации **перезаписывает** дочерний web.config своим шаблоном
|
||||||
|
`C:\win-acme\Web_Config.xml` (а при `CleanupFolders=true` потом удаляет токен+web.config). Дефолтный
|
||||||
|
шаблон делает `<staticContent><clear/>` + mime, но **не снимает Owin-handler** → снова `500`.
|
||||||
|
|
||||||
|
Durable-фикс = **пропатчить сам шаблон** `C:\win-acme\Web_Config.xml`, добавив `<remove name="Owin"/>`
|
||||||
|
+ `runAllManagedModulesForAllRequests="false"`. Трекаемая копия: `scripts/iis-migration-to-ruvds/winacme-Web_Config.xml`.
|
||||||
|
Тогда на каждом renewal win-acme сам кладёт рабочий web.config в (постоянное) unmanaged-приложение,
|
||||||
|
валидирует, чистит. Между renewal'ами папка пустая — трафика на неё нет.
|
||||||
|
|
||||||
|
## Процедура де-риска (повторяемо)
|
||||||
|
|
||||||
|
1. `--validationmode http-01 --validation filesystem` локальный probe токена через `localhost` + `Host:`-заголовок (обходит home-DPI middlebox).
|
||||||
|
2. **Staging** через `--baseuri https://acme-staging-v02.api.letsencrypt.org/` (НЕ `--test` — он включает интерактивные промпты, которые вешают non-interactive SSH). pemfiles store + `--installation none` — без правок IIS.
|
||||||
|
3. Прод: `--store certificatestore --installation iis --installationsiteid 1`.
|
||||||
|
|
||||||
|
## Грабли
|
||||||
|
|
||||||
|
- **`--test` ≠ staging-only.** `--test` тащит интерактив («Try in default browser?», «Quit?») → виснет под SSH. Для staging без интерактива — `--baseuri <staging>`.
|
||||||
|
- **pemfiles path должен существовать** заранее, иначе abort до валидации.
|
||||||
|
- **Scheduled task руками, не через win-acme.** `--notaskscheduler` при выпуске; таск создаётся отдельно как SYSTEM (win-acme-овский setup может спросить креды интерактивно). win-acme потом пишет «Scheduled task not configured yet» — косметика, ищет *свой* таск.
|
||||||
|
- win-acme renewal'ы раздельны по `--baseuri` (разные ConfigurationPath): staging-renewal не трогается прод-таском. Staging-renewal всё равно убран для чистоты.
|
||||||
|
|
||||||
|
## Команда боевого выпуска (reference)
|
||||||
|
|
||||||
|
```
|
||||||
|
C:\win-acme\wacs.exe --source iis --siteid 1 --validationmode http-01 --validation filesystem ^
|
||||||
|
--webroot C:\sites\snolla --store certificatestore --installation iis --installationsiteid 1 ^
|
||||||
|
--accepttos --emailaddress <ops-email> --force --notaskscheduler
|
||||||
|
```
|
||||||
@@ -48,6 +48,7 @@ Catalog of all wiki pages. One line per page, organized by type. Updated on ever
|
|||||||
- [vbox-windows-stability-tuning](concepts/vbox-windows-stability-tuning.md) — VirtualBox + Windows-гость — нюансы стабильности cross-hypervisor миграции
|
- [vbox-windows-stability-tuning](concepts/vbox-windows-stability-tuning.md) — VirtualBox + Windows-гость — нюансы стабильности cross-hypervisor миграции
|
||||||
- [vds-kzntsv-dhcp-outage-2026-05-28](concepts/vds-kzntsv-dhcp-outage-2026-05-28.md) — DHCP outage 2026-05-28 на vds-kzntsv — диагностика + recovery runbook (link UP но без IPv4 → статика + тикет хостеру)
|
- [vds-kzntsv-dhcp-outage-2026-05-28](concepts/vds-kzntsv-dhcp-outage-2026-05-28.md) — DHCP outage 2026-05-28 на vds-kzntsv — диагностика + recovery runbook (link UP но без IPv4 → статика + тикет хостеру)
|
||||||
- [verdaccio-prune-semantics](concepts/verdaccio-prune-semantics.md) — Verdaccio prune semantics — proxied vs locally-published
|
- [verdaccio-prune-semantics](concepts/verdaccio-prune-semantics.md) — Verdaccio prune semantics — proxied vs locally-published
|
||||||
|
- [winacme-iis-owin-catchall-http01](concepts/winacme-iis-owin-catchall-http01.md) — win-acme HTTP-01 авто-renewal LE на IIS под OWIN-catch-all CMS — challenge в отдельном No-Managed-Code приложении + патч шаблона; заменяет ручной PFX-импорт
|
||||||
- [wd40efax-smr-cascade](concepts/wd40efax-smr-cascade.md) — WD40EFAX SMR Cascade — root cause NAS failure 2026-05-18
|
- [wd40efax-smr-cascade](concepts/wd40efax-smr-cascade.md) — WD40EFAX SMR Cascade — root cause NAS failure 2026-05-18
|
||||||
- [windows-server-2025-core-bootstrap](concepts/windows-server-2025-core-bootstrap.md) — Win Server 2025 Core (RUVDS) — bootstrap для IIS-хоста: default-blockers + transfer-методов матрица
|
- [windows-server-2025-core-bootstrap](concepts/windows-server-2025-core-bootstrap.md) — Win Server 2025 Core (RUVDS) — bootstrap для IIS-хоста: default-blockers + transfer-методов матрица
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
Append-only log of wiki operations (ingests, promotions, lints, migrations).
|
Append-only log of wiki operations (ingests, promotions, lints, migrations).
|
||||||
|
|
||||||
|
## [2026-06-05] ingest | concepts/winacme-iis-owin-catchall-http01 — постоянный self-renewing LE pipeline на RUVDS IIS (win-acme v2.2.9, 25-SAN cert, SYSTEM scheduled task). Главное: OWIN-catch-all CMS жрёт `/.well-known/acme-challenge/` → решено отдельным IIS-приложением в пуле «No Managed Code» + патч шаблона `Web_Config.xml` (snять Owin-handler). Заменяет ручной [[traefik-acme-json-to-iis-cert-import]] для renewal'а; снимает зависимость RUVDS от домашнего traefik. Закрывает дедлайн cert-expiry 2026-07-22 (новый cert до 2026-09-03). Источник: `.tasks/iis-migration-to-ruvds.md` Decisions log 2026-06-05.
|
||||||
|
|
||||||
## [2026-05-28] ingest | concepts/es-destructive-delete-incident-2026-05-26 — RCA для удаления 3 user-индексов на canonical ES `elasticsearch.kzntsv.site` (books VDS stack 33) во время cutover-prep. Caller identity unrecoverable (audit log = X-Pack платный, traefik accessLog был выключен). 2 preventive controls applied + verified: ES env `action.destructive_requires_name=true` + traefik JSON accessLog. Источник: `.tasks/restore-elasticsearch-indices-books-vds.md` § Closure note.
|
## [2026-05-28] ingest | concepts/es-destructive-delete-incident-2026-05-26 — RCA для удаления 3 user-индексов на canonical ES `elasticsearch.kzntsv.site` (books VDS stack 33) во время cutover-prep. Caller identity unrecoverable (audit log = X-Pack платный, traefik accessLog был выключен). 2 preventive controls applied + verified: ES env `action.destructive_requires_name=true` + traefik JSON accessLog. Источник: `.tasks/restore-elasticsearch-indices-books-vds.md` § Closure note.
|
||||||
|
|
||||||
## 2026-05-21
|
## 2026-05-21
|
||||||
|
|||||||
159
scripts/iis-migration-to-ruvds/03-ruvds-winacme.ps1
Normal file
159
scripts/iis-migration-to-ruvds/03-ruvds-winacme.ps1
Normal file
@@ -0,0 +1,159 @@
|
|||||||
|
# 03-ruvds-winacme.ps1 — win-acme setup + HTTP-01 challenge-path probe on RUVDS IIS host.
|
||||||
|
# Idempotent. Run elevated on RUVDS (80.64.31.36) over SSH.
|
||||||
|
# Phase switch: -Phase download|probe|cleanprobe
|
||||||
|
param([string]$Phase = 'probe')
|
||||||
|
|
||||||
|
$ErrorActionPreference = 'Stop'
|
||||||
|
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
|
||||||
|
$dest = 'C:\win-acme'
|
||||||
|
$root = 'C:\sites\snolla'
|
||||||
|
$chDir = Join-Path $root '.well-known\acme-challenge'
|
||||||
|
|
||||||
|
function Download-WinAcme {
|
||||||
|
if (Test-Path (Join-Path $dest 'wacs.exe')) { Write-Output "wacs already present: $dest\wacs.exe"; return }
|
||||||
|
$api = 'https://api.github.com/repos/win-acme/win-acme/releases/latest'
|
||||||
|
$rel = Invoke-RestMethod -Uri $api -Headers @{ 'User-Agent' = 'ruvds-setup' }
|
||||||
|
$asset = $rel.assets | Where-Object { $_.name -match 'x64\.pluggable\.zip$' } | Select-Object -First 1
|
||||||
|
if (-not $asset) { throw "no x64.pluggable.zip asset in $($rel.tag_name)" }
|
||||||
|
$zip = Join-Path $env:TEMP $asset.name
|
||||||
|
Write-Output "downloading $($rel.tag_name): $($asset.name)"
|
||||||
|
Invoke-WebRequest -Uri $asset.browser_download_url -OutFile $zip -Headers @{ 'User-Agent' = 'ruvds-setup' }
|
||||||
|
New-Item -ItemType Directory -Force -Path $dest | Out-Null
|
||||||
|
Expand-Archive -Path $zip -DestinationPath $dest -Force
|
||||||
|
Remove-Item $zip -Force
|
||||||
|
Write-Output ("installed: " + (Get-Item (Join-Path $dest 'wacs.exe')).VersionInfo.ProductVersion)
|
||||||
|
}
|
||||||
|
|
||||||
|
function Test-ChallengePath {
|
||||||
|
New-Item -ItemType Directory -Force -Path $chDir | Out-Null
|
||||||
|
$token = 'acme-probe-' + (Get-Random)
|
||||||
|
$tokenFile = Join-Path $chDir $token
|
||||||
|
Set-Content -Path $tokenFile -Value $token -NoNewline -Encoding ascii
|
||||||
|
Write-Output "token file: $tokenFile (content='$token')"
|
||||||
|
|
||||||
|
$hosts = 'snolla.com','tandemmebel.ru','maljarka.tandemmebel.ru','rimiz.ru'
|
||||||
|
Write-Output "--- WITHOUT challenge web.config (baseline CMS behaviour) ---"
|
||||||
|
Probe-Hosts $hosts $token
|
||||||
|
|
||||||
|
# Mirror the proven /admin escape: remove the catch-all Owin handler so OWIN stops
|
||||||
|
# intercepting this path, add extensionless-token mime, drop managed-module overhead.
|
||||||
|
$webcfg = @'
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<configuration>
|
||||||
|
<system.webServer>
|
||||||
|
<handlers>
|
||||||
|
<remove name="Owin" />
|
||||||
|
</handlers>
|
||||||
|
<staticContent>
|
||||||
|
<remove fileExtension="." />
|
||||||
|
<mimeMap fileExtension="." mimeType="text/plain" />
|
||||||
|
</staticContent>
|
||||||
|
<modules runAllManagedModulesForAllRequests="false" />
|
||||||
|
</system.webServer>
|
||||||
|
</configuration>
|
||||||
|
'@
|
||||||
|
Set-Content -Path (Join-Path $chDir 'web.config') -Value $webcfg -Encoding utf8
|
||||||
|
Write-Output "--- WITH challenge web.config (win-acme style) ---"
|
||||||
|
Probe-Hosts $hosts $token
|
||||||
|
}
|
||||||
|
|
||||||
|
function Probe-Hosts($hosts, $token) {
|
||||||
|
foreach ($h in $hosts) {
|
||||||
|
try {
|
||||||
|
$r = Invoke-WebRequest "http://localhost/.well-known/acme-challenge/$token" -Headers @{ Host = $h } -UseBasicParsing -TimeoutSec 15 -MaximumRedirection 0
|
||||||
|
$ok = ($r.Content.Trim() -eq $token)
|
||||||
|
Write-Output (" [{0}] HTTP {1} match={2} body='{3}'" -f $h, $r.StatusCode, $ok, ($r.Content -replace '\s+',' ').Substring(0,[Math]::Min(40,$r.Content.Length)))
|
||||||
|
} catch {
|
||||||
|
$resp = $_.Exception.Response
|
||||||
|
if ($resp) { Write-Output (" [{0}] HTTP {1} loc={2}" -f $h, [int]$resp.StatusCode, $resp.Headers['Location']) }
|
||||||
|
else { Write-Output (" [{0}] ERR: {1}" -f $h, $_.Exception.Message) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Setup-ChallengeApp {
|
||||||
|
Import-Module WebAdministration
|
||||||
|
$pool = 'acme-challenge'
|
||||||
|
if (-not (Test-Path "IIS:\AppPools\$pool")) { New-WebAppPool -Name $pool | Out-Null; Write-Output "created app pool $pool" }
|
||||||
|
Set-ItemProperty "IIS:\AppPools\$pool" -Name managedRuntimeVersion -Value '' # No Managed Code
|
||||||
|
Set-ItemProperty "IIS:\AppPools\$pool" -Name autoStart -Value $true
|
||||||
|
New-Item -ItemType Directory -Force -Path $chDir | Out-Null
|
||||||
|
# No-Managed-Code pool + drop the inherited catch-all Owin handler (else it 500s in an
|
||||||
|
# unmanaged pool), serve extensionless ACME tokens as text/plain. Verified combo.
|
||||||
|
$appcfg = @'
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<configuration>
|
||||||
|
<system.webServer>
|
||||||
|
<handlers>
|
||||||
|
<remove name="Owin" />
|
||||||
|
</handlers>
|
||||||
|
<staticContent>
|
||||||
|
<remove fileExtension="." />
|
||||||
|
<mimeMap fileExtension="." mimeType="text/plain" />
|
||||||
|
</staticContent>
|
||||||
|
<modules runAllManagedModulesForAllRequests="false" />
|
||||||
|
<directoryBrowse enabled="false" />
|
||||||
|
</system.webServer>
|
||||||
|
</configuration>
|
||||||
|
'@
|
||||||
|
Set-Content -Path (Join-Path $chDir 'web.config') -Value $appcfg -Encoding utf8
|
||||||
|
$vpath = '/.well-known/acme-challenge'
|
||||||
|
$app = Get-WebApplication -Site 'snolla' | Where-Object { $_.path -eq $vpath }
|
||||||
|
if (-not $app) {
|
||||||
|
New-WebApplication -Site 'snolla' -Name '.well-known/acme-challenge' -PhysicalPath $chDir -ApplicationPool $pool -Force | Out-Null
|
||||||
|
Write-Output "created IIS application $vpath (pool=$pool, No Managed Code)"
|
||||||
|
} else {
|
||||||
|
Set-ItemProperty "IIS:\Sites\snolla$vpath" -Name applicationPool -Value $pool
|
||||||
|
Write-Output "IIS application $vpath exists (pool ensured=$pool)"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Probe-Once {
|
||||||
|
New-Item -ItemType Directory -Force -Path $chDir | Out-Null
|
||||||
|
$token = 'acme-probe-' + (Get-Random)
|
||||||
|
Set-Content -Path (Join-Path $chDir $token) -Value $token -NoNewline -Encoding ascii
|
||||||
|
Write-Output "probe token: $token"
|
||||||
|
Probe-Hosts ('snolla.com','tandemmebel.ru','www.tandemmebel.ru','maljarka.tandemmebel.ru','rimiz.ru','kupimknigi.spb.ru') $token
|
||||||
|
}
|
||||||
|
|
||||||
|
function Clean-Probe {
|
||||||
|
if (Test-Path $chDir) { Get-ChildItem $chDir -Filter 'acme-probe-*' | Remove-Item -Force -EA SilentlyContinue; Write-Output "removed probe tokens" }
|
||||||
|
}
|
||||||
|
|
||||||
|
function Setup-RenewTask {
|
||||||
|
$wacs = 'C:\win-acme\wacs.exe'
|
||||||
|
$taskName = 'win-acme-renew-snolla'
|
||||||
|
$action = New-ScheduledTaskAction -Execute $wacs -Argument '--renew --baseuri https://acme-v02.api.letsencrypt.org/'
|
||||||
|
$trigger = New-ScheduledTaskTrigger -Daily -At 9am
|
||||||
|
try { $trigger.RandomDelay = 'PT4H' } catch {}
|
||||||
|
$principal = New-ScheduledTaskPrincipal -UserId 'SYSTEM' -LogonType ServiceAccount -RunLevel Highest
|
||||||
|
$settings = New-ScheduledTaskSettingsSet -StartWhenAvailable -ExecutionTimeLimit (New-TimeSpan -Hours 2)
|
||||||
|
Register-ScheduledTask -TaskName $taskName -Action $action -Trigger $trigger -Principal $principal -Settings $settings -Description 'Auto-renew Let''s Encrypt cert for IIS site snolla (25 SNI bindings) via HTTP-01.' -Force | Out-Null
|
||||||
|
$t = Get-ScheduledTask -TaskName $taskName
|
||||||
|
$info = $t | Get-ScheduledTaskInfo
|
||||||
|
Write-Output ("task '{0}' state={1} nextRun={2}" -f $taskName, $t.State, $info.NextRunTime)
|
||||||
|
|
||||||
|
# remove the staging renewal so a stray --renew against staging does nothing
|
||||||
|
$stagingRenewals = 'C:\ProgramData\win-acme\acme-staging-v02.api.letsencrypt.org\Renewals'
|
||||||
|
if (Test-Path $stagingRenewals) { Remove-Item "$stagingRenewals\*" -Recurse -Force -EA SilentlyContinue; Write-Output "cleared staging renewals" }
|
||||||
|
if (Test-Path 'C:\win-acme\stagingtest') { Remove-Item 'C:\win-acme\stagingtest' -Recurse -Force -EA SilentlyContinue; Write-Output "removed stagingtest pemfiles" }
|
||||||
|
}
|
||||||
|
|
||||||
|
function Verify-Certs {
|
||||||
|
Import-Module WebAdministration
|
||||||
|
# show the cert now bound (thumbprint -> subject/expiry)
|
||||||
|
$b = Get-WebBinding -Port 443 | Select-Object -First 1
|
||||||
|
$hash = (Get-Item "IIS:\SslBindings\*!443!*" -EA SilentlyContinue | Select-Object -First 1).Thumbprint
|
||||||
|
Get-ChildItem Cert:\LocalMachine\WebHosting | Sort-Object NotAfter -Descending | Select-Object -First 3 |
|
||||||
|
ForEach-Object { Write-Output ("WebHosting cert: {0} | NotAfter={1} | Issuer={2} | SAN-count via DnsNameList={3}" -f $_.Thumbprint, $_.NotAfter, $_.Issuer, $_.DnsNameList.Count) }
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ($Phase) {
|
||||||
|
'download' { Download-WinAcme }
|
||||||
|
'probe' { Download-WinAcme; Test-ChallengePath }
|
||||||
|
'app' { Download-WinAcme; Setup-ChallengeApp; Probe-Once }
|
||||||
|
'task' { Setup-RenewTask; Verify-Certs }
|
||||||
|
'verify' { Verify-Certs }
|
||||||
|
'cleanprobe' { Clean-Probe }
|
||||||
|
default { throw "unknown phase $Phase" }
|
||||||
|
}
|
||||||
23
scripts/iis-migration-to-ruvds/winacme-Web_Config.xml
Normal file
23
scripts/iis-migration-to-ruvds/winacme-Web_Config.xml
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
win-acme HTTP-01 challenge web.config template (overwrites C:\win-acme\Web_Config.xml on RUVDS).
|
||||||
|
Patched for the MoreThenCms / OWIN catch-all: the .well-known/acme-challenge folder is a
|
||||||
|
separate IIS application in a "No Managed Code" app pool (acme-challenge). The inherited
|
||||||
|
catch-all Owin *managed* handler 500s in an unmanaged pool, so we <remove> it; tokens are
|
||||||
|
served by the native StaticFileModule with an extensionless mimeMap. See task decisions log.
|
||||||
|
-->
|
||||||
|
<configuration>
|
||||||
|
<system.webServer>
|
||||||
|
<httpRedirect enabled="false" />
|
||||||
|
<validation validateIntegratedModeConfiguration="false" />
|
||||||
|
<handlers>
|
||||||
|
<remove name="Owin" />
|
||||||
|
</handlers>
|
||||||
|
<modules runAllManagedModulesForAllRequests="false" />
|
||||||
|
<staticContent>
|
||||||
|
<clear />
|
||||||
|
<mimeMap fileExtension="." mimeType="text/json" />
|
||||||
|
<mimeMap fileExtension=".*" mimeType="text/json" />
|
||||||
|
</staticContent>
|
||||||
|
</system.webServer>
|
||||||
|
</configuration>
|
||||||
Reference in New Issue
Block a user