- mssql-vds-migration ⚪: Express edition, BACKUP/RESTORE method, mssql.kzntsv.site:1433 - minio-imgproxy-vds-migration ⚪: MinIO upgrade 2020→latest, mc mirror, includes imgproxy+nginx - iis-cutover-to-vds-services 🔵: atomic web.config repoint (1 file → 11 hosts), blocked on both migrations - umbrella mssql-minio-migration-to-vds 🟢: decomposed (kept for history) Discovery: 5 prod DBs ≤ 968 MB (Express OK), .ldf logs 12 GB → SHRINKFILE pre-cutover. VDS: 79 GB free, 5.8 GB RAM avail. ownCloud capped 1G. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
78 lines
8.2 KiB
Markdown
78 lines
8.2 KiB
Markdown
# mssql-vds-migration
|
||
|
||
## Goal
|
||
Перенести MSSQL контейнер с [[../entities/windows-recovery-host]] на [[../entities/vds-kzntsv]] (`/opt/stacks/databases/mssql/`), Express Edition для прода, доступ снаружи через `mssql.kzntsv.site:1433` (traefik TCP passthrough), интеграция в существующий `vds-backup-rsync-kreknin` pipeline.
|
||
|
||
Это **MSSQL-only половина** umbrella'ы `mssql-minio-migration-to-vds` (декомпозирована 2026-05-22). Вторая половина — `minio-imgproxy-vds-migration`.
|
||
|
||
## Key files / refs
|
||
- **Source:** docker container `mssql` на windows-recovery-host, image `mcr.microsoft.com/mssql/server:2019-latest`, volume `mssql_mssql_data` (26.6 GB total, real data ~2.4 GB, остальное .ldf logs).
|
||
- **Source DBs** (verified via `docker exec mssql ls /var/opt/mssql/data/`, 2026-05-22):
|
||
- `MoreThenCms.mdf` 867 MB + log 9.9 GB
|
||
- `StayerCalculator.mdf` 504 MB + log 1.2 GB
|
||
- `StayerPrice.mdf` 38 MB + log 215 MB
|
||
- `TireService.mdf` 8 MB + log 8 MB
|
||
- `stostayer.mdf` 968 MB + log 264 MB
|
||
- **Max .mdf 968 MB < 10 GB Express limit ✓ all fit**
|
||
- **Target:** `/opt/stacks/databases/mssql/{data,docker-compose.yml,.env}` на VDS, паттерн как у postgres (`/opt/stacks/databases/postgres/data` bind, network `proxy` + `shared-dbs`).
|
||
- **Image:** `mcr.microsoft.com/mssql/server:2022-latest` Express Edition (`MSSQL_PID=Express`).
|
||
- **CMS connection strings:** `Data Source=localhost,1433` → `Data Source=mssql.kzntsv.site,1433` в IIS web.config / appsettings.
|
||
- **TLS:** self-signed, traefik raw-TCP passthrough — pattern [[../.wiki/concepts/db-tls-self-signed-via-traefik-raw-tcp]] + [[../.wiki/concepts/traefik-tcp-passthrough-vs-starttls]].
|
||
- **Backup pipeline:** `/opt/stacks/backup/scripts/run.sh` на VDS — добавить новые ноги (см. acceptance 6).
|
||
|
||
## Decisions
|
||
- **Edition: Express** (user 2026-05-22). Max DB size 10 GB соблюдён всеми текущими базами. RAM cap Express = 1.4 GB built-in. Дополнительно `MSSQL_MEMORY_LIMIT_MB=2048` (user-confirmed), но Express всё равно сам зажмёт до 1410.
|
||
- **Method: BACKUP DATABASE … WITH COMPRESSION, COPY_ONLY** → scp `.bak` → RESTORE на VDS. Не detach/attach — кросс-edition (Developer → Express) supported только через backup/restore. Compression ≈ 80% reduction, ожидаемый transfer ~500 MB.
|
||
- **Pre-cutover SHRINKFILE на .ldf** — срежет 12 GB logs до минимума (не для transfer — для cleanup source перед миграцией; transfer идёт через .bak, который и так не включает inactive log space).
|
||
- **Hostname: `mssql.kzntsv.site`** (не `mssql.vds.kzntsv.site` — user decision 2026-05-22). DNS A-record указать на VDS IP.
|
||
|
||
## Acceptance
|
||
1. **Pre-cutover на source** (windows-host):
|
||
- `BACKUP LOG <db> WITH TRUNCATE_ONLY` + `CHECKPOINT` + `DBCC SHRINKFILE` для .ldf всех 5 prod DBs.
|
||
- Verify `du -sh /var/opt/mssql/data/*_log.ldf` → каждый < 100 MB.
|
||
- **WARNING:** SHRINKFILE с TRUNCATE_ONLY ломает log-chain → no point-in-time restore до следующего FULL backup. Делается **только** в migration window, новый FULL снимается сразу после RESTORE на VDS.
|
||
2. **MSSQL container на VDS** запущен:
|
||
- `mcr.microsoft.com/mssql/server:2022-latest`, `ACCEPT_EULA=Y`, `MSSQL_PID=Express`, `MSSQL_MEMORY_LIMIT_MB=2048`, `SA_PASSWORD` из `pass show mssql-vds/sa-password` (новый pass entry).
|
||
- Volume bind `/opt/stacks/databases/mssql/data:/var/opt/mssql:rw`.
|
||
- Networks `proxy` + `shared-dbs`. Traefik labels TCP entrypoint `mssql` :1433 → HostSNI(`*`).
|
||
3. **Traefik static config** (`/opt/stacks/proxy/traefik/traefik.yml`):
|
||
```yaml
|
||
entryPoints:
|
||
mssql:
|
||
address: ":1433"
|
||
```
|
||
+ ufw allow 1433/tcp.
|
||
4. **5 prod DBs restored** на VDS:
|
||
- `BACKUP DATABASE … WITH COMPRESSION, COPY_ONLY` на source → 5 `.bak` файлов.
|
||
- scp → `/opt/stacks/databases/mssql/data/backups/` на VDS.
|
||
- `RESTORE DATABASE … FROM DISK='/var/opt/mssql/backups/<db>.bak' WITH MOVE`.
|
||
- Verify `SELECT name, state_desc FROM sys.databases` → все 5 ONLINE, `DBCC CHECKDB('<db>')` → 0 errors на каждой.
|
||
5. **CMS connection strings updated** в web.config (или эквиваленте), 8 sites smoke:
|
||
- 200 OK + asset loading + admin/assets/getList (известный hot-path).
|
||
- **Pre-cutover benchmark обязателен** — admin assets UI / search / catalogs latency измерены до и после, **degradation <2x** target. Если worse — discuss перед commit'ом cutover (10-30ms WAN vs localhost).
|
||
6. **Backup pipeline на VDS расширен** (`/opt/stacks/backup/scripts/run.sh`):
|
||
- `mssql_dump_full` ежедневно (BACKUP DATABASE WITH COMPRESSION для каждой DB → tar.gz → rsync nightly).
|
||
- `mssql_tx_log_backup` ежечасно (BACKUP LOG для каждой DB через `docker exec mssql /opt/mssql-tools/bin/sqlcmd …`) → rsync hourly. **Достигает target RPO 1ч.**
|
||
7. **ntfy push verified** для расширенного pipeline (включает MSSQL dump size/duration).
|
||
8. **Source windows-host MSSQL** — после 48ч uptime на VDS: stop container (read-only fallback пропустить — pass), через неделю — `docker rm + docker volume rm mssql_mssql_data`.
|
||
9. **Documented** в [[../.wiki/concepts/mssql-on-vds]] (создать): architecture, rollback recipe (revert connection strings + start windows-host MSSQL container), migration runbook.
|
||
|
||
## Open questions
|
||
- [ ] **DNS A-record `mssql.kzntsv.site` → VDS IP** (89.253.255.94) — сделать через REGRU API или manual?
|
||
- [ ] **Hermes service на windows-host** — зависит от local MSSQL? Если да — мигрируется заодно или ломается. См. [[../.wiki/entities/vds-kzntsv]] Open issues.
|
||
- [ ] **CMS connection-string location** — web.config? appsettings? hardcoded в DLL? Если hardcoded — нужен rebuild (build env вопрос). См. note в [[../.wiki/concepts/cms-admin-assets-root-folder-seed]] §"Долгосрочный TODO".
|
||
|
||
## Risks
|
||
- **WAN latency IIS→MSSQL:** 10-30ms vs localhost. Большинство CMS-операций batchey, не latency-sensitive. **Pre-cutover benchmark обязателен** (acceptance 5).
|
||
- **Express Edition limits:** 10 GB/DB, 1.4 GB RAM, 1 socket / 4 cores. Max .mdf сейчас 968 MB — запас 10x. Если `stostayer` начнёт расти — early warning через monitoring (separate task).
|
||
- **MSSQL Linux compat:** некоторые edge-case T-SQL отличаются (CLR, FileStream, full-text). Smoke обязателен — `EXEC sp_helpdb` + проверить нет ли CLR assemblies / FileStream filegroups в prod DBs.
|
||
- **TLS overhead:** raw-TCP через traefik adds <1ms — negligible.
|
||
- **VDS RAM tight:** owncloud `anon` 282 MB + gitea 834 MB + verdaccio 226 MB + DBs 285 MB + traefik 52 MB + redis 6 MB = ~1.7 GB реально используется (page-cache reclaimable). MSSQL 2 GB влезает с запасом 4 GB до OOM.
|
||
- **Disk free на VDS не проверен** (ops-mcp read-only docker). Нужно ~3 GB MSSQL restored + ~5 GB free для backup'ов. **Проверить `df -h /opt/stacks` ssh'ем перед стартом.**
|
||
- **Cutover rollback:** revert возможен только если windows-host MSSQL container оставлен running (read-only желательно но не критично) 48ч после cutover. Acceptance 8 это закладывает.
|
||
|
||
## Notes
|
||
- **Зависит от:** `minio-imgproxy-vds-migration` (нет — независимы).
|
||
- **Зависимая follow-up:** списать `cms-stopgap-backup-daily` cron после успешного first VDS backup-pipeline run.
|
||
- **Atomic revert (full):** revert CMS web.config → windows-host MSSQL; восстановить cms-stopgap-backup-daily cron; на VDS — `docker compose down -v` для mssql stack; удалить mssql ноги из `run.sh`; remove traefik mssql entrypoint; ufw deny 1433/tcp.
|