# Перенос 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) Задеплоить (или обновить) прод `netrunner-backend` **первым** — Vaultwarden теперь не поднимает свой Postgres, а подключается к тому же контейнеру `netrunner-db` и сети `netrunner_grid`, которые создаёт `netrunner-backend/docker-compose.prod.yml`. Пока backend не поднят на этом VPS — `docker compose up` для vaultwarden ниже упадёт с "network netrunner_grid not found". Затем создать отдельную базу и роль для Vaultwarden в этом общем Postgres (не переиспользовать логин backend'а): ```bash # На новом VPS, после того как netrunner-backend/docker-compose.prod.yml поднят docker exec -it netrunner-db psql -U "$DB_USER" -d postgres -c \ "CREATE ROLE vaultwarden WITH LOGIN PASSWORD 'СЮДА_ТОТ_ЖЕ_ПАРОЛЬ_ЧТО_В_VW_DB_PASSWORD';" docker exec -it netrunner-db psql -U "$DB_USER" -d postgres -c \ "CREATE DATABASE vaultwarden OWNER vaultwarden;" ``` (`$DB_USER` — существующий админ-юзер backend-Postgres, из его `.env`.) ## Фаза 1 — на СТАРОМ сервере (текущий Vaultwarden) ```bash 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 (с любой машины, у которой есть доступ к обоим — например, с вашего ноутбука): ```bash scp root@<СТАРЫЙ_VPS_IP>:~/vaultwarden-data-backup-*.tar.gz . scp vaultwarden-data-backup-*.tar.gz root@136.244.78.208:~/ ``` Старый Vaultwarden пока НЕ запускать обратно — он останется единственным живым источником правды до подтверждённого успеха миграции (Фаза 4). ## Фаза 2 — распаковка на НОВОМ сервере ```bash # На новом VPS (136.244.78.208) mkdir -p ~/netrunner-data cd ~/netrunner-data git clone . 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-типов даст несовместимую структуру. ```bash # .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-файла в уже созданную схему: ```bash docker run --rm \ --network netrunner_grid \ -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@netrunner-db:5432/vaultwarden ``` Проверить, что pgloader завершился без ошибок ("... rows" summary без Errors) — если есть ошибки по конкретным таблицам, здесь и надо разбираться, ДО того как запускать vaultwarden поверх. ## Фаза 4 — запуск и проверка ```bash 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"` для этой таблицы (медленнее, но проще диагностировать построчно). Не обязательно решать это заранее — сначала просто прогнать команду выше и смотреть на реальный лог ошибок.