mssql+minio vds migration done — IIS snolla cutover live
- mssql-vds-migration 🟢: Express 2022 Linux на mssql.kzntsv.site:1433, 5 DBs restored (schema 2019→2022 auto-upgrade), 8 prod hosts 200 OK - minio-imgproxy-vds-migration 🟡: stack live, 3 GiB / 19324 obj mirrored (2020→2025 upgrade via S3 API), DNS swap imgproxy.kzntsv.site pending - iis-cutover-to-vds-services 🟡: 1 web.config edit catch-all для 11 hosts; MinIO leg pending DNS swap (URLs уже через imgproxy.kzntsv.site domain) - 3 wiki concepts: mssql-on-vds, minio-imgproxy-on-vds, index updated Findings: (1) server logins НЕ переезжают в .bak — orphan fix manual, (2) traefik recreate-not-restart для port mapping change, (3) PowerShell не вызывает pass bash-script (NULL pw → misleading auth fail), (4) mc 2025 не auto-creates target buckets, (5) non-ASCII filename silent skip в mc mirror — verify по count+size обязательно. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
99
.wiki/concepts/mssql-on-vds.md
Normal file
99
.wiki/concepts/mssql-on-vds.md
Normal file
@@ -0,0 +1,99 @@
|
||||
---
|
||||
title: MSSQL on vds-kzntsv (Express 2022 Linux)
|
||||
status: live
|
||||
tags: [vds, mssql, migration, ops]
|
||||
related: [[vds-kzntsv]], [[recovery-architecture-snapshot]], [[traefik-tcp-passthrough-vs-starttls]], [[db-tls-self-signed-via-traefik-raw-tcp]]
|
||||
---
|
||||
|
||||
# MSSQL on vds-kzntsv
|
||||
|
||||
Запущен 2026-05-22 как часть `mssql-vds-migration`. SPOF с windows-recovery-host снят для CMS DB park.
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
IIS snolla site (web.config)
|
||||
→ mssql.kzntsv.site:1433 (LE/DNS A → 89.253.255.94)
|
||||
→ VDS traefik :1433 (TCP entrypoint, HostSNI(*))
|
||||
→ mssql container :1433 (self-signed TLS terminated по TDS)
|
||||
→ /var/opt/mssql/data/{5 prod DBs}
|
||||
```
|
||||
|
||||
Stack: `/opt/stacks/databases/mssql/{docker-compose.yml,.env,data,backups}`. Networks `proxy` only.
|
||||
|
||||
**Image:** `mcr.microsoft.com/mssql/server:2022-latest` (RTM-CU25, build 16.0.4255.1, on Ubuntu 22.04.5 LTS).
|
||||
**Edition:** Express (`MSSQL_PID=Express`) — production licensing OK, 10 GB/DB cap (max .mdf сейчас `stostayer` 968 MB → 10× запас).
|
||||
**Memory:** `MSSQL_MEMORY_LIMIT_MB=2048` env (Express auto-caps на 1410 в любом случае).
|
||||
**TLS:** self-signed cert, mssql generates automatically. Client connects with `TrustServerCertificate=True`. Traefik forwards raw TCP — TLS terminates at mssql.
|
||||
|
||||
## Migration recipe (one-shot, executed 2026-05-22)
|
||||
|
||||
Источник: `mcr.microsoft.com/mssql/server:2019-latest` Developer на windows-recovery-host (volume `mssql_mssql_data` 26.6 GB; real data ~2.4 GB; .ldf logs 12 GB inflated).
|
||||
|
||||
```sql
|
||||
-- 1. Source: BACKUP DATABASE for each prod DB (5 total)
|
||||
BACKUP DATABASE [<db>] TO DISK='/var/opt/mssql/backups/<db>.bak'
|
||||
WITH COMPRESSION, COPY_ONLY, INIT, STATS=50;
|
||||
-- Compressed total: 486 MB (10× от .mdf size — built-in compression на UTF-16/varchar pads)
|
||||
```
|
||||
|
||||
```bash
|
||||
# 2. Extract from container → scp → VDS bind
|
||||
docker cp mssql:/var/opt/mssql/backups/. C:/tmp/mssql-backups/
|
||||
scp C:/tmp/mssql-backups/*.bak vitya@vds.kzntsv.site:/tmp/mssql-bak-staging/
|
||||
ssh vitya@vds.kzntsv.site 'sudo mv /tmp/mssql-bak-staging/*.bak /opt/stacks/databases/mssql/backups/
|
||||
sudo chown 10001:0 /opt/stacks/databases/mssql/backups/*.bak'
|
||||
```
|
||||
|
||||
```yaml
|
||||
# 3. compose + .env (см. /opt/stacks/databases/mssql/)
|
||||
# MSSQL_SA_PASSWORD из pass show mssql-vds/sa-password (32-char alnum, no special chars)
|
||||
```
|
||||
|
||||
```yaml
|
||||
# 4. Traefik: добавить TCP entrypoint в /opt/stacks/traefik/data/traefik.yml
|
||||
entryPoints:
|
||||
mssql:
|
||||
address: ":1433"
|
||||
# + port 1433 в /opt/stacks/traefik/docker-compose.yml ports list
|
||||
# + ufw allow 1433/tcp
|
||||
# + sudo docker compose up -d (RECREATE, не restart — port mapping)
|
||||
```
|
||||
|
||||
```sql
|
||||
-- 5. RESTORE per DB
|
||||
RESTORE DATABASE [<db>] FROM DISK='/var/opt/mssql/backups/<db>.bak' WITH REPLACE, STATS=50;
|
||||
-- 2019 → 2022 schema upgrade автоматический (versions 953→957). DBCC CHECKDB PHYSICAL_ONLY clean.
|
||||
```
|
||||
|
||||
```sql
|
||||
-- 6. CRITICAL: server-level logins НЕ переезжают в .bak (sysadmin/master DB only).
|
||||
-- Создать manually + fix orphan users в каждой DB:
|
||||
CREATE LOGIN snolla WITH PASSWORD = '<from-source-web.config>', CHECK_POLICY = OFF;
|
||||
USE MoreThenCms;
|
||||
ALTER USER snolla WITH LOGIN = snolla;
|
||||
-- Repeat for каждой DB где web.config упоминает данного user'а.
|
||||
```
|
||||
|
||||
## Gotchas
|
||||
|
||||
1. **Logins vs users**: .bak восстанавливает DB-level users (с их role memberships + permissions), но НЕ server logins. Sites с `User Id=X` в conn-string ловят `Login failed for user 'X'` после restore, пока не выполнить `CREATE LOGIN` + `ALTER USER ... WITH LOGIN`.
|
||||
2. **Traefik recreate, не restart**: добавление port mapping в `docker-compose.yml` требует **recreate** контейнера (`docker compose up -d`), не `restart`. `restart` оставит старые published ports.
|
||||
3. **PowerShell + `pass` (bash script)**: `pass show` в PowerShell возвращает NULL (PS не запускает bash-скрипты напрямую). Нужно `bash -c "pass show ..."` или literal. Симптом: `Login failed for user 'sa'` несмотря на правильный пароль на VDS.
|
||||
4. **`MSSQL_SA_PASSWORD` спец-символы**: rotation password generator должен excludeавать `+/=` (Base64) и shell-meta (`$`, `` ` ``, `"`, `'`, `\`). Иначе env-var passing через ssh heredoc или sed конструкторы ломаются. Пример безопасного: `[Convert]::ToBase64String($bytes) -replace '[+/=]','x'`.
|
||||
5. **MSSQL Linux user uid**: `mssql` user = uid 10001. Bind-mount должен быть `chown 10001:0` чтобы контейнер read/write. Parent dir owns `vitya:vitya` чтобы можно было редактировать compose без sudo.
|
||||
|
||||
## Backup integration (TODO)
|
||||
|
||||
Расширить `/opt/stacks/backup/scripts/run.sh` (см. [[vds-backup-rsync-kreknin]]):
|
||||
- `mssql_dump_full` daily — `BACKUP DATABASE [<db>] TO DISK='...' WITH COMPRESSION, COPY_ONLY` через `docker exec mssql sqlcmd ...`
|
||||
- `mssql_tx_log_backup` hourly — `BACKUP LOG [<db>] TO DISK='...'` для FULL-recovery DBs (только `MoreThenCms` — остальные SIMPLE).
|
||||
- Достигает target RPO 1ч (vs current daily snapshot).
|
||||
- ntfy push на `vds-backup` topic.
|
||||
|
||||
## Rollback recipe
|
||||
|
||||
1. Revert IIS web.config'ы (см. `.bak-pre-vds-cutover-20260522` файлы).
|
||||
2. `iisreset /restart` (или ждать auto-recycle ~30 sec).
|
||||
3. Убедиться windows-host MSSQL контейнер всё ещё running (acceptance 48ч uptime до decommission).
|
||||
4. Если уже decommissioned: `docker start mssql` (volume сохранён ещё неделю по acceptance).
|
||||
Reference in New Issue
Block a user