Files
netrunner-data/scripts/migrate-vaultwarden.md
T
nineap 9ca6df3dfc Postgres переезжает сюда физически — backend теперь на отдельном VPS
Раньше предполагалось, что backend и БД живут на одном хосте и делят
Docker-сеть — на деле backend будет на отдельном, ещё не арендованном
VPS, а Postgres стоит здесь же, рядом с Vaultwarden. Возвращает свой
контейнер `db` (общий для обеих баз — vaultwarden создаётся через
POSTGRES_USER/POSTGRES_DB, вторая, для backend, через новый
postgres/init-backend-db.sh), публикует 5432 наружу с hostssl+TLS
(postgres/pg_hba.conf, самоподписанный сертификат генерируется один раз
прямо в deploy.yml). Backup-джоба (pg_dump обеих баз) тоже переехала
сюда из netrunner-backend — дампить логичнее там, где физически лежат
данные.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-09 17:17:05 +07:00

8.5 KiB
Raw Blame History

Перенос Vaultwarden со старого VPS на новый (136.244.78.208), SQLite → Postgres

Все команды — ручные, выполняются вами на серверах (у меня нет SSH-доступа ни к старому, ни к новому VPS). Ниже — точная последовательность без потери данных. Не удалять старый сервер/старые файлы, пока не пройден пункт "Проверка" в самом конце.

Старый инстанс живёт на SQLite в WAL-режиме (видно по файлам db.sqlite3-wal и db.sqlite3-shm рядом с db.sqlite3 — это значит часть последних изменений может ещё не быть слита в основной файл). Поэтому нельзя просто скопировать db.sqlite3 в одиночку — копируем директорию data/ целиком и только после чистой остановки контейнера.

Фаза 0 — предварительно, на новом VPS (136.244.78.208)

Postgres теперь физически стоит прямо здесь, в этом репозитории (docker-compose.yml, сервис db) — не в netrunner-backend. Задеплоить этот репозиторий (через CI или руками docker compose up -d) — обе базы (vaultwarden и netrunner-backend) создаются автоматически при первой инициализации кластера: vaultwarden через POSTGRES_USER/POSTGRES_DB, вторая — через postgres/init-backend-db.sh (BACKEND_DB_USER/ BACKEND_DB_NAME). Ручных CREATE ROLE/CREATE DATABASE не требуется.

netrunner-backend сам ещё не задеплоен (живёт на отдельном, пока не арендованном VPS) — это не мешает: Vaultwarden обращается к db внутри локальной Docker-сети этого же compose, backend подключится позже по сети, когда появится.

Фаза 1 — на СТАРОМ сервере (текущий Vaultwarden)

cd ~/vaultwarden-data

# Останавливаем контейнер — чистое закрытие sqlite-соединения (checkpoint
# WAL в основной файл на выходе). НЕ удалять после — только stop.
docker compose stop vaultwarden

# На всякий случай форсируем checkpoint+truncate WAL явно, а не полагаемся
# только на чистое закрытие процессом:
docker run --rm -v "$PWD/data:/data" alpine:3.20 sh -c \
  "apk add --no-cache sqlite >/dev/null && sqlite3 /data/db.sqlite3 'PRAGMA wal_checkpoint(TRUNCATE);'"

# Теперь весь ./data — самодостаточный снимок. Архивируем целиком одним
# куском (attachments, rsa_key.pem, db.sqlite3 — всё вместе, не выборочно).
tar czf ~/vaultwarden-data-backup-$(date +%Y%m%d-%H%M%S).tar.gz -C ~/vaultwarden-data data

ls -la ~/vaultwarden-data-backup-*.tar.gz

Скопировать архив на новый VPS (с любой машины, у которой есть доступ к обоим — например, с вашего ноутбука):

scp root@<СТАРЫЙ_VPS_IP>:~/vaultwarden-data-backup-*.tar.gz .
scp vaultwarden-data-backup-*.tar.gz root@136.244.78.208:~/

Старый Vaultwarden пока НЕ запускать обратно — он останется единственным живым источником правды до подтверждённого успеха миграции (Фаза 4).

Фаза 2 — распаковка на НОВОМ сервере

# На новом VPS (136.244.78.208)
mkdir -p ~/netrunner-data
cd ~/netrunner-data
git clone <URL_РЕПО_netrunner-data> . 2>/dev/null || true   # если ещё не клонирован
tar xzf ~/vaultwarden-data-backup-*.tar.gz -C ~/netrunner-data
# теперь ~/netrunner-data/data/db.sqlite3 (+ -wal/-shm, rsa_key.pem, ...) на месте

ls -la ~/netrunner-data/data

Фаза 3 — конвертация SQLite → Postgres через pgloader

Сначала дать Vaultwarden создать пустую Postgres-схему (diesel-миграции идут из самого бинаря при первом старте с DATABASE_URL=postgresql://...) — НЕ через pgloader: типы колонок в postgres-схеме vaultwarden подогнаны под его собственный Rust/diesel-код, автосоздание схемы pgloader'ом из sqlite-типов даст несовместимую структуру.

# .env уже должен быть заполнен (VW_DB_USER/VW_DB_PASSWORD/VW_DB_NAME и т.д.)
cd ~/netrunner-data
docker compose up -d vaultwarden
sleep 5
docker compose logs vaultwarden | tail -30   # убедиться что миграции прошли, схема создана
docker compose stop vaultwarden              # снова стоп — дальше пишет только pgloader

Теперь перелить данные (не схему) из sqlite-файла в уже созданную схему:

docker run --rm \
  --network host \
  -v ~/netrunner-data/data:/data \
  dimitri/pgloader:latest \
  pgloader \
    --with "data only" \
    --with "disable triggers" \
    --with "quote identifiers" \
    sqlite:///data/db.sqlite3 \
    postgresql://vaultwarden:СЮДА_VW_DB_PASSWORD@localhost:5432/vaultwarden

(--network host + localhost:5432 — Postgres на этом же VPS уже публикует порт наружу, так что localhost работает без разбора имени Docker-сети.)

Проверить, что pgloader завершился без ошибок ("... rows" summary без Errors) — если есть ошибки по конкретным таблицам, здесь и надо разбираться, ДО того как запускать vaultwarden поверх.

Фаза 4 — запуск и проверка

cd ~/netrunner-data
docker compose up -d vaultwarden
docker compose logs -f vaultwarden   # ждём "Rocket has launched" без ошибок БД

Затем, ДО переключения DNS на новый IP:

  • Зайти по прежнему домену через /etc/hosts-подмену (временно указать vault.netrunner-vpn.com на 136.244.78.208 только на своей машине) и залогиниться существующим аккаунтом — проверить, что все записи/сейфы на месте, вложения открываются.
  • Проверить 2FA/WebAuthn там, где он был настроен — привязан к домену, не к IP, так что при простой смене DNS (см. ниже) ломаться не должен.

Только после успешного логина и видимых данных:

  1. Переключить DNS A-запись vault.netrunner-vpn.com на 136.244.78.208.
  2. Подождать TTL, ещё раз проверить логин уже по-настоящему через домен.
  3. Только теперь можно выключить (не обязательно сразу удалять) старый Vaultwarden — оставить его на пару дней выключенным как холодный откат, прежде чем сносить директорию ~/vaultwarden-data на старом сервере.

Если pgloader ругается на конкретную таблицу

Обычно это twofactor/ciphers из-за BLOB/бинарных полей — можно догнать их руками через INSERT INTO ... SELECT в отдельном скрипте или повторным прогоном pgloader с --with "batch rows = 1" для этой таблицы (медленнее, но проще диагностировать построчно). Не обязательно решать это заранее — сначала просто прогнать команду выше и смотреть на реальный лог ошибок.