Files
admin/.wiki/concepts/mssql-on-vds.md
vitya e17e8eb1c3 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>
2026-05-22 09:55:17 +03:00

100 lines
5.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
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).