# Руководство по миграции

Перенесите существующий проект, файлы, Docker-сервисы, базы данных, с традиционного сервера или локальной среды разработки в зашифрованный репозиторий Rediacc.

## Предварительные требования

- Установленный CLI `rdc` ([Установка](/ru/docs/installation))
- Добавленная и подготовленная машина ([Настройка](/ru/docs/setup))
- Достаточно дискового пространства на сервере для вашего проекта (проверьте с помощью `rdc machine status`)

## Шаг 1: Создание репозитория

Создайте зашифрованный репозиторий достаточного размера для вашего проекта. Выделите дополнительное пространство для Docker-образов и данных контейнеров.

```bash
rdc repo create --name my-project -m server-1 --size 20G
```

> **Совет:** Вы можете изменить размер позже с помощью `rdc repo resize`, но репозиторий сначала необходимо отмонтировать. Проще начать с достаточного объёма.

## Шаг 2: Загрузка файлов

Используйте `rdc repo sync upload` для передачи файлов проекта в репозиторий.

```bash
# Предварительный просмотр того, что будет передано (без изменений)
rdc repo sync upload -m server-1 -r my-project --local ./my-project --dry-run

# Загрузка файлов
rdc repo sync upload -m server-1 -r my-project --local ./my-project
```

Перед загрузкой репозиторий должен быть смонтирован. Если он ещё не смонтирован:

```bash
rdc repo mount --name my-project -m server-1
```

Для последующих синхронизаций, когда удалённая копия должна точно соответствовать локальному каталогу:

```bash
rdc repo sync upload -m server-1 -r my-project --local ./my-project --mirror
```

> Флаг `--mirror` удаляет файлы на удалённом сервере, которые не существуют локально. Сначала используйте `--dry-run` для проверки.

## Шаг 3: Исправление владения файлами

Загруженные файлы приходят с UID вашего локального пользователя (например, 1000). Rediacc использует универсального пользователя (UID 7111), чтобы VS Code, терминальные сессии и инструменты имели единообразный доступ. Выполните команду изменения владельца:

```bash
rdc repo ownership --name my-project -m server-1
```

### Исключения с учётом Docker

Если Docker-контейнеры запущены (или были запущены), команда владения автоматически обнаруживает их записываемые каталоги данных и **пропускает их**. Это предотвращает повреждение контейнеров, которые управляют своими файлами с другими UID (например, MariaDB использует UID 999, Nextcloud, UID 33).

Команда выводит отчёт:

```
Excluding Docker volume: database/data
Excluding Docker volume: redis/data
Ownership set to UID 7111 (245 changed, 4 skipped, 0 errors)
```

### Когда запускать

- **После загрузки файлов**, для преобразования вашего локального UID в 7111
- **После запуска контейнеров**, если вы хотите, чтобы каталоги Docker-томов были автоматически исключены. Если контейнеры ещё не были запущены, томов для исключения нет, и все каталоги будут изменены (это нормально, контейнеры пересоздадут свои данные при первом запуске)

### Принудительный режим

Чтобы пропустить обнаружение Docker-томов и изменить владельца всего, включая каталоги данных контейнеров:

```bash
rdc repo ownership --name my-project -m server-1
```

> **Предупреждение:** Это может повредить работающие контейнеры. Сначала остановите их с помощью `rdc repo down`, если необходимо.

### Пользовательский UID

Чтобы установить UID, отличный от стандартного 7111:

```bash
rdc repo ownership --name my-project -m server-1 --uid 1000
```

## Шаг 4: Настройка Rediaccfile

Создайте `Rediaccfile` в корне вашего проекта. Этот Bash-скрипт определяет, как ваши сервисы запускаются и останавливаются.

```bash
#!/bin/bash

up() {
    renet compose -- up -d
}

down() {
    renet compose -- down
}
```

Три функции жизненного цикла:

| Функция | Назначение | Поведение при ошибке |
|---------|------------|---------------------|
| `up()` | Запуск сервисов | Ошибка в корне критична; ошибки в подкаталогах логируются и продолжаются |
| `down()` | Остановка сервисов | Максимальное усилие: всегда пытается выполнить всё |

> **Важно:** Всегда используйте `renet compose --` вместо `docker compose` в вашем Rediaccfile. Обёртка `renet compose` обеспечивает host-сеть, возможности CRIU checkpoint/restore, назначение IP и обнаружение сервисов, необходимые для renet-proxy. Прямое использование `docker compose` обходит всё это и будет отклонено при валидации.
>
> Также никогда не используйте `sudo docker`, `sudo` сбрасывает переменные окружения, включая `DOCKER_HOST`, из-за чего контейнеры создаются в системном Docker-демоне, а не в изолированном демоне репозитория. Функции Rediaccfile уже выполняются с достаточными привилегиями.

Подробнее о Rediaccfile, многосервисных конфигурациях и порядке выполнения см. [Сервисы](/ru/docs/services).

## Шаг 5: Настройка сети сервисов

Rediacc запускает изолированный Docker-демон для каждого репозитория. Сервисы используют `network_mode: host` и привязываются к уникальным loopback-IP, чтобы использовать стандартные порты без конфликтов между репозиториями.

### Адаптация docker-compose.yml

**До (традиционный подход):**

```yaml
services:
  postgres:
    image: postgres:16
    ports:
      - "5432:5432"
    volumes:
      - ./data/postgres:/var/lib/postgresql/data
    environment:
      POSTGRES_PASSWORD: secret

  redis:
    image: redis:7-alpine
    ports:
      - "6379:6379"

  app:
    image: my-app:latest
    ports:
      - "8080:8080"
    environment:
      DATABASE_URL: postgresql://postgres:secret@postgres:5432/mydb
      REDIS_URL: redis://redis:6379
```

**После (Rediacc):**

```yaml
services:
  postgres:
    image: postgres:16
    volumes:
      - ./data/postgres:/var/lib/postgresql/data
    environment:
      POSTGRES_PASSWORD: secret
    command: -c listen_addresses=${POSTGRES_IP} -c port=5432

  redis:
    image: redis:7-alpine
    command: redis-server --bind ${REDIS_IP} --port 6379

  app:
    image: my-app:latest
    environment:
      DATABASE_URL: postgresql://postgres:secret@${POSTGRES_IP}:5432/mydb
      REDIS_URL: redis://${REDIS_IP}:6379
      LISTEN_ADDR: ${APP_IP}:8080
```

Основные изменения:

1. **Удалить маппинги `ports:`**, `renet compose` использует host-сеть и автоматически удаляет маппинги портов
2. **Удалить `network_mode: host`**, `renet compose` добавляет это автоматически
3. **Удалить `restart: always` или `restart: unless-stopped`**, они конфликтуют с CRIU checkpoint/restore (Docker автоматически запускает контейнеры до того, как checkpoint restore сможет выполниться). Используйте `restart: on-failure`, если вам нужно поведение перезапуска, или полностью опустите, Rediaccfile `up()`/`down()` управляет жизненным циклом контейнеров
4. **Привязать сервисы к переменным окружения `${SERVICE_IP}`** (автоматически внедряются Rediacc)
5. **Ссылаться на другие сервисы по их IP** вместо Docker DNS-имён (например, `${POSTGRES_IP}` вместо `postgres`)

Переменные `{SERVICE}_IP` автоматически генерируются из имён сервисов вашего compose-файла. Соглашение об именовании: верхний регистр, дефисы заменяются подчёркиваниями, суффикс `_IP`. Например, `listmonk-app` становится `LISTMONK_APP_IP`.

Подробнее о назначении IP и `.rediacc.json` см. [Сетевое взаимодействие сервисов](/ru/docs/services#service-networking-rediaccjson).

## Шаг 6: Запуск сервисов

Смонтируйте репозиторий (если ещё не смонтирован) и запустите все сервисы:

```bash
rdc repo up --name my-project -m server-1 --mount
```

Это выполнит:
1. Монтирование зашифрованного репозитория
2. Запуск изолированного Docker-демона
3. Автоматическую генерацию `.rediacc.json` с назначением IP сервисов
4. Выполнение `up()` из всех Rediaccfile

Убедитесь, что ваши контейнеры запущены:

```bash
rdc machine containers server-1
```

## Шаг 7: Включение автозапуска (необязательно)

По умолчанию репозитории необходимо монтировать и запускать вручную после перезагрузки сервера. Включите автозапуск, чтобы ваши сервисы запускались автоматически:

```bash
rdc repo autostart enable --name my-project -m server-1
```

Вам будет предложено ввести парольную фразу репозитория.

> **Примечание о безопасности:** Автозапуск сохраняет ключевой файл LUKS на сервере. Любой пользователь с root-доступом может смонтировать репозиторий без парольной фразы. Подробнее см. [Автозапуск](/ru/docs/services#autostart-on-boot).

## Типичные сценарии миграции

### WordPress / PHP с базой данных

```
my-wordpress/
├── Rediaccfile
├── docker-compose.yml
├── app/                    # Файлы WordPress (UID 33 при работе)
├── database/data/          # Данные MariaDB (UID 999 при работе)
└── wp-content/uploads/     # Загрузки пользователей
```

1. Загрузите файлы проекта
2. Сначала запустите сервисы (`rdc repo up`), чтобы контейнеры создали свои каталоги данных
3. Выполните исправление владения, каталоги данных MariaDB и приложения автоматически исключаются

### Node.js / Python с Redis

```
my-api/
├── Rediaccfile
├── docker-compose.yml
├── src/                    # Исходный код приложения
├── node_modules/           # Зависимости
└── redis-data/             # Персистентность Redis (UID 999 при работе)
```

1. Загрузите проект (рассмотрите исключение `node_modules` и получение их в `up()`)
2. Выполните исправление владения после запуска контейнеров

### Пользовательский Docker-проект

Для любого проекта с Docker-сервисами:

1. Загрузить файлы проекта
2. Адаптировать `docker-compose.yml` (см. Шаг 5)
3. Создать `Rediaccfile` с функциями жизненного цикла
4. Выполнить исправление владения
5. Запустить сервисы

## Устранение неполадок

### Отказ в доступе после загрузки

Файлы всё ещё имеют ваш локальный UID. Выполните команду изменения владельца:

```bash
rdc repo ownership --name my-project -m server-1
```

### Контейнер не запускается

Убедитесь, что сервисы привязаны к назначенному IP, а не к `0.0.0.0` или `localhost`:

```bash
# Проверить назначенные IP
rdc term connect -m server-1 -r my-project -c "cat .rediacc.json"

# Проверить логи контейнера
rdc term connect -m server-1 -r my-project -c "docker logs <container-name>"
```

### Конфликт портов между репозиториями

Каждый репозиторий получает уникальные loopback-IP. Если вы видите конфликты портов, убедитесь, что ваш `docker-compose.yml` использует `${SERVICE_IP}` для привязки вместо `0.0.0.0`. Сервисы, привязанные к `0.0.0.0`, слушают на всех интерфейсах и будут конфликтовать с другими репозиториями.

### Исправление владения повредило контейнеры

Если вы выполнили `rdc repo ownership` и контейнер перестал работать, файлы данных контейнера были изменены. Остановите контейнер, удалите его каталог данных и перезапустите, контейнер пересоздаст его:

```bash
rdc repo down --name my-project -m server-1
# Удалить каталог данных контейнера (например, database/data)
rdc repo up --name my-project -m server-1
```