Репозитории
Репозиторий - это LUKS-зашифрованный образ диска на удалённом сервере. После монтирования он предоставляет:
- Изолированную файловую систему для данных приложения
- Отдельный демон Docker (отдельно от Docker хоста)
- Уникальные адреса loopback для каждого сервиса в подсети /26
Создание репозитория
rdc repo create --name my-app -m server-1 --size 10G
| Параметр | Обязателен | Описание |
|---|---|---|
-m, --machine <name> | Да | Целевая машина, на которой будет создан репозиторий |
--size <size> | Да | Размер зашифрованного образа диска (например, 5G, 10G, 50G) |
--skip-router-restart | Нет | Пропустить перезагрузку маршрутизатора после операции |
Результат содержит три автоматически сгенерированных значения:
- Repository GUID - UUID, который идентифицирует зашифрованный образ диска на сервере.
- Credential - случайная парольная фраза для шифрования/расшифровки LUKS-тома.
- Network ID - целое число (начиная с 2816, увеличиваясь на 64), определяющее подсеть IP для сервисов этого репозитория.
Храните учётные данные в безопасности. Это ключ шифрования вашего репозитория. В случае потери данные не могут быть восстановлены. Учётные данные хранятся в локальном файле
config.json, но НЕ хранятся на сервере.
Монтирование и отмонтирование
Монтирование расшифровывает и делает файловую систему репозитория доступной. Отмонтирование закрывает зашифрованный том.
rdc repo mount --name my-app -m server-1 # Расшифровать и смонтировать
rdc repo unmount --name my-app -m server-1 # Отмонтировать и переш...кать
| Параметр | Описание |
|---|---|
--checkpoint | Создать контрольную точку CRIU перед монтированием/отмонтированием (для контейнеров с меткой rediacc.checkpoint=true) |
--skip-router-restart | Пропустить перезагрузку маршрутизатора после операции |
Проверка статуса
rdc repo status --name my-app -m server-1
Список репозиториев
rdc repo list -m server-1
Колонка Type и зеркало состояния
Таблица вывода содержит колонку Type с тремя значениями:
grand. Репозиторий верхнего уровня, зарегистрированный в локальной конфигурации CLI без родителя. Базовый случай.fork. Форк copy-on-write другого репозитория. Идентифицируется либо черезgrandGuidв локальной конфигурации, либо через зеркало.interim/stateв renet на машине. Оба источника авторитетны; оба должны совпадать после заполнения зеркала.unknown. Ни один сигнал не может классифицировать репозиторий. Чаще всего это форк, созданный до кода зеркала и никогда не переустанавливаемый после, или устаревшийgrand, запись которого в локальной конфигурации была случайно удалена. CLI отказывается угадывать; оператор должен запустить заполнение зеркала или удалить директорию, если она действительно orphaned.
Зеркало .interim/state/<guid>/.rediacc.json - это небольшой файл-сопровождение, написанный вне LUKS-зашифрованного тома, так что инструменты резервного копирования и repo list могут читать родословную форков без разблокировки каждого образа. Он имеет ту же структуру, что и файл .rediacc.json внутри тома (is_fork, grand_guid, name и т.д.), и обновляется при каждом вызове Repository.SaveState. То есть при каждом монтировании и при каждой мутации состояния. Это источник истины для обнаружения форков в запланированных резервных копиях: немонтированный форк с зеркалом, в котором написано is_fork: true, правильно пропускается из загрузок cold и hot.
Для регулярной очистки неизвестных записей смотрите rdc machine prune --prune-unknown.
Изменение размера
Установите репозиторий на точный размер или расширьте его на заданное количество:
rdc repo resize --name my-app -m server-1 --size 20G # Установить точный размер
rdc repo expand --name my-app -m server-1 --size 5G # Добавить 5G к текущему размеру
Репозиторий должен быть отмонтирован перед изменением размера.
repo expandработает в режиме онлайн. Изменение размера меняет максимальный размер репозитория; чтобы вернуть освободившиеся блоки в пул без изменения максимума, используйте вместо этогоrepo trim.
Освобождение пространства (trim)
Удаление файлов внутри репозитория освобождает пространство для этого репозитория, а repo trim возвращает освободившиеся блоки в общий пул хранилища. Команда работает в режиме онлайн без каких-либо простоев:
rdc repo trim -m server-1 # Trim every mounted repository plus the datastore
rdc repo trim -m server-1 --name my-app # Trim one repository
rdc repo trim -m server-1 --report-only # Show reclaimable space without trimming
rdc repo trim -m server-1 --docker # Also clear stopped containers, dangling images, and build cache first
Принцип работы: образы репозиториев являются разреженными файлами, и зашифрованный том пропускает discards насквозь. Trim сообщает файловой системе внутри репозитория освободить все неиспользуемые блоки, что пробивает дыры в исходном образе и немедленно сокращает использование пула.
Примечания:
- Для репозиториев с активным резервным копированием операция trim файловой системы пропускается и об этом сообщается: снимок резервной копии по-прежнему ссылается на блоки, поэтому пробивать дыры бессмысленно с точки зрения пула. Операция
--dockerэтим не затрагивается и выполняется в штатном режиме (см. ниже). - Двойной запуск trim подряд сообщает 0 байт при втором запуске. Файловая система запоминает, какие группы блоков уже были обработаны; это ожидаемое поведение, а не сбой.
--dockerникогда не удаляет помеченные тегами образы, только зависшие образы, остановленные контейнеры и кэш сборки. Добавьте--docker-volumesдля удаления также неиспользуемых томов (это удаляет данные; только CLI). В отличие от trim файловой системы,--dockerработает даже во время резервного копирования, так что вы можете очистить зависший кэш сборки, не дожидаясь окончания окна резервного копирования.
Политика автоматического размера
Вместо того чтобы изменять размер вручную, позвольте машине управлять размерами репозиториев. Политика включает автоматическое увеличение онлайн (максимальный размер репозитория увеличивается при заполнении) и запланированные операции trim. Машина применяет политики каждые несколько минут с помощью таймера systemd rediacc-storage-maintain.
# Machine-wide default: trim every repository daily
rdc repo policy set -m server-1 --auto-trim true
# Per-repository: grow my-app automatically, up to a hard ceiling
rdc repo policy set -m server-1 --name my-app --auto-grow true --max-quota 50G
# Inspect the stored and effective policy
rdc repo policy get -m server-1 --name my-app
Поля политики:
| Поле | Значение | По умолчанию |
|---|---|---|
--auto-grow | Увеличивать репозиторий онлайн при превышении файловой системой порогового значения | выключено |
--max-quota | Жёсткий потолок для автоувеличения. Обязателен: его установка является явным согласием на сверхпроизводительность пула | нет |
--grow-threshold | Процент использования файловой системы, при котором запускается увеличение | 85 |
--grow-step | Сколько добавлять за одно увеличение: абсолютное значение (10G) или процент от текущего размера (20%) | 20% |
--auto-trim | Выполнять плановые операции trim | выключено |
--trim-interval | Минимальный интервал в часах между автоматическими операциями trim | 24 |
Ограничения безопасности: автоувеличение не выполняется, когда свободное пространство в пуле ниже резерва (10 ГБ или 5% пула, в зависимости от того, что больше), ожидает не менее 30 минут между увеличениями одного репозитория и никогда не превышает --max-quota. Автоматического уменьшения нет: снижение максимального размера репозитория остаётся ручной офлайн-операцией repo resize.
Настройки на уровне репозитория переопределяют общий машинный параметр по умолчанию. Повторные вызовы policy set изменяют только переданные флаги.
Форк
Создайте копию существующего репозитория в его текущем состоянии:
rdc repo fork --parent my-app --tag staging -m server-1
Форки используют модель name:tag: полученный форк называется my-app:staging. Это создаёт новую зашифрованную копию с её собственным GUID и network ID, при этом делясь именем родителя. Форк использует тот же LUKS-credential, что и родитель.
Форки разделяют данные родителя через BTRFS reflink, включая любые учётные данные, хранящиеся на диске. Смотрите Что Rediacc не изолирует для обсуждения последствий, когда эти учётные данные авторизуют внешние сервисы, такие как Stripe, AWS или Railway. Чтобы защитить учётные данные развёртывания от доступа форка, используйте secrets для каждого репозитория вместо прямого внедрения значений в
.envфайлы внутри репозитория.
При создании форка repo fork записывает файл-сопровождение зеркала состояния по адресу <datastore>/.interim/state/<fork-guid>/.rediacc.json немедленно. Без разблокировки тома. Поэтому новый форк правильно идентифицируется как is_fork: true с момента создания. Это позволяет запланированным резервным копиям пропускать его (форки исключены из pipeline загрузок по умолчанию) даже если он никогда не был смонтирован. При форкировании форка grand_guid цепочка работает правильно: зеркало нового форка указывает на GUID оригинального родителя grand, а не на промежуточный форк.
Форк и запуск за один шаг
--up создаёт форк, монтирует репозиторий и запускает сервисы в рамках одной удалённой операции. Флаг --detach возвращает управление терминалом сразу после старта контейнеров; проверки готовности завершаются в фоновом режиме, а прокси повторяет попытки подключения, пока каждый сервис не будет доступен:
rdc repo fork --parent my-app --tag staging -m server-1 --up
rdc repo fork --parent my-app --tag scratch -m server-1 --up --detach
В наших тестах репозиторий объёмом 128 ГБ форкировался и выходил на работающие сервисы примерно за 57 секунд, а с --detach это занимает около 31 секунды. Отсоединённый запуск выводит подсказку для отслеживания прогресса: rdc machine query --containers --name <machine>.
Куда уходит время
Операции длительностью несколько секунд и более завершаются сводкой по времени: пошаговая разбивка, вотерфол с параллельными шагами и строка атрибуции, разделяющая конвейер Rediacc и время старта ваших сервисов:
Rediacc pipeline 19.2s (61%) · service startup 12.3s (39%)
Время запуска сервисов означает загрузку контейнеров: образы, инициализация, проверки готовности, определённые в Rediaccfile репозитория, поэтому оно зависит от приложения. Диаграммы отображаются в интерактивных терминалах; задайте RDC_TIMING_CHART=1, чтобы принудительно вывести их при работе в конвейере.
Версионирование в стиле Git
Форки могут выступать как git-коммиты. rdc repo commit замораживает рабочий форк в неизменяемый, байт-стабильный коммит; rdc repo branch называет линию истории; rdc repo checkout клонирует коммит через reflink в новый записываемый форк; rdc repo log обходит цепочку родителей; rdc repo merge объединяет две линии без мутации живого репозитория на месте. rdc repo fork --immutable создаёт коммит-эквивалентную базу в один шаг.
rdc repo commit --name my-app:work --message "schema migration applied" -m server-1
rdc repo branch --branch staging --name my-app:work
rdc repo checkout --ref staging --from my-app:work --tag staging-copy -m server-1
Смотрите справочник по версионированию в стиле Git для полного набора команд, параметров и примеров.
Secrets
Secrets для каждого репозитория - это учётные данные развёртывания, вводимые в контейнеры без записи в зашифрованный образ репозитория. Они хранятся в отдельной плоскости от данных репозитория, поэтому rdc repo fork не распространяет их. Форк начинает с пустой карты secrets, и его контейнеры загружаются, идентифицируя себя как другой внешний principal, чем родитель.
Хотите пошаговое руководство? Смотрите учебник Управление Secrets для полного цикла set/list/deploy/verify/rotate.
Модель write-only (в стиле GitHub): get возвращает только SHA-256 digest. Значение в открытом виде никогда не возвращается никому, ни человеку, ни агенту. Если вы забыли значение, посмотрите его в менеджере паролей и произведите ротацию; вы не можете прочитать его обратно из Rediacc по дизайну. Это исключает целый класс утечек: записи терминала, историю shell, случайное перенаправление, подглядывание через плечо.
Два режима доставки:
env. Secret экспортируется какREDIACC_SECRET_<KEY>в оболочке renet на целевой машине. Ссылайтесь на него изdocker-compose.ymlчерез интерполяцию${REDIACC_SECRET_<KEY>}. Видимо внутри окружения контейнера, поэтому используйте это для значений, похожих на строки подключения, которые приложение уже ожидает в env.file. Secret записывается в/var/run/rediacc/secrets/<networkID>/<KEY>на хосте (tmpfs, никогда не сохраняется). Ссылайтесь на него из файла compose через декларациюsecrets:верхнего уровня с источникомfile:, плюс списокsecrets:для каждого сервиса. Контейнеры читают из/run/secrets/<key>. Предпочитайте этот режим для всего, что чувствительно. Он никогда не появляется вdocker inspectили/proc/<pid>/environ.
# Set, list, get (digest only), unset
rdc repo secret set --name my-app --key STRIPE_LIVE_KEY --value sk_live_xxx --mode file --current ""
rdc repo secret set --name my-app --key DB_HOST --value postgres.internal --mode env --current ""
rdc repo secret list --name my-app
rdc repo secret get --name my-app --key DB_HOST # → { key, mode, digest } — no value
rdc repo secret unset --name my-app --key STRIPE_LIVE_KEY --current sk_live_xxx
Симметричный mutation gate. И люди, и агенты нуждаются в --current <previous-value> для перезаписи или отмены secret (предусловие в стиле passwd). Для первой записи нового ключа передайте --current "" (пусто). Чтобы произвести ротацию без проверки предыдущего значения, передайте --rotate-secret. Это громко логируется как ротация. --current и --rotate-secret являются взаимоисключающими.
Передайте --value - для чтения из stdin вместо argv (избегает exposure истории shell для одноразовых записей).
В вашем docker-compose.yml:
services:
api:
image: myapp
environment:
DATABASE_HOST: ${REDIACC_SECRET_DB_HOST}
secrets:
- stripe_live_key
secrets:
stripe_live_key:
file: /var/run/rediacc/secrets/${REDIACC_NETWORK_ID}/STRIPE_LIVE_KEY
Ссылка на сервис в нижнем регистре (stripe_live_key) - это имя файла /run/secrets/<name> внутри контейнера; последний part хостовой пути в верхнем регистре (STRIPE_LIVE_KEY) совпадает с тем, что вы установили с помощью --key. ${REDIACC_NETWORK_ID} автоматически интерполируется renet compose.
Кросс-репозиторная изоляция обеспечена: validator compose renet отклоняет пути
secrets: file:(иconfigs: file:, иenv_file:), которые ссылаются на network ID любого другого репозитория. Литеральный токен${REDIACC_NETWORK_ID}(или целое число вашей собственной сети) - это единственно допустимая форма для ссылок/var/run/rediacc/secrets/.... И--unsafeНЕ переопределяет эту проверку. Песочница Landlock вокруг subprocess bash Rediaccfile также ограничивает доступ к файловой системе только к директории secrets вашей собственной сети, поэтому злонамеренныйcat /var/run/rediacc/secrets/<other>/Xиз Rediaccfile не работает с EACCES на уровне ядра.
Форки:
rdc repo forkне копирует secrets. Чтобы использовать secrets в форке, запуститеrdc repo secret set --name <fork>на форке явно. Это load-bearing свойство безопасности. Контейнеры форка не должны иметь возможность действовать как production principal против внешних сервисов.
Агенты (Claude Code, Cursor и т.д.):
repo secret listиrepo secret getпредоставляются как MCP-инструменты (read-safe. Только имена и digests, никогда значения).setиunsetдоступны только в CLI, потому что церемония--current/--rotate-secretтребует человеческого надзора; агенты, вызывающие их через shell, получают тот же gate, что и люди. Когда предусловие не выполняется, JSON-оболочка содержит структурированное полеerrors[].next.options[].run. Агенты должны передавать эти команды пользователю verbatim. Смотрите безопасность AI-агентов для полной модели.
Проверка
Проверить целостность файловой системы репозитория:
rdc repo validate --name my-app -m server-1
Владение
Установите владение файлами в репозитории для универсального пользователя (UID 7111). Это обычно требуется после загрузки файлов с вашей рабочей станции, которые приходят с вашим локальным UID.
rdc repo ownership --name my-app -m server-1
Команда автоматически обнаруживает директории данных Docker-контейнеров (монтируемые bind-мауты с правом записи) и исключает их. Это предотвращает разрушение контейнеров, которые управляют файлами со своими собственными UID (например, MariaDB=999, www-data=33).
| Параметр | Описание |
|---|---|
--uid <uid> | Установить пользовательский UID вместо 7111 |
--skip-router-restart | Пропустить перезагрузку маршрутизатора после операции |
Чтобы принудительно установить владение всеми файлами, включая данные контейнеров:
rdc repo ownership --name my-app -m server-1
Смотрите Руководство по миграции для полного пошагового объяснения того, когда и как использовать владение во время миграции проекта.
Шаблон
Применить шаблон для инициализации репозитория файлами:
rdc repo template apply --name my-template -m server-1 -r my-app --file ./my-template.tar.gz
Удаление
Постоянно уничтожить репозиторий и все данные внутри него:
rdc repo delete --name my-app -m server-1
Это постоянно уничтожает зашифрованный образ диска. Это действие нельзя отменить.
Миграция репозитория
Live-миграция репозитория с одной машины на другую. Единственный downtime - это финальная фаза delta-sync: обычно секунды до низких минут в зависимости от скорости записи в момент перехода.
rdc repo migrate --name my-app --from server-1 --to server-2
| Параметр | Описание |
|---|---|
--provision | Подготовить репозиторий на целевой машине перед миграцией (создаёт LUKS-образ и регистрирует конфиг) |
--checkpoint | Создать контрольную точку CRIU запущенных контейнеров перед переходом |
--bwlimit <kbps> | Ограничить пропускную способность rsync в килобайтах в секунду |
--skip-dns | Пропустить обновление DNS-записей после перехода |
Трёхфазный процесс:
- Hot pre-copy - rsync передаёт данные, пока репозиторий остаётся запущенным на источнике. Большие файлы передаются до любого downtime.
- Cutover - репозиторий остановлен на источнике, финальный проход rsync синхронизирует оставшиеся изменения, и репозиторий запускается на целевой машине.
- Start on target - renet монтирует и запускает репозиторий на целевой машине. DNS обновляется, если не передан
--skip-dns.
Push vs migrate:
repo push | repo migrate | |
|---|---|---|
| Операция | Копировать | Переместить |
| Источник после | Без изменений | Остановлен |
| Downtime | Нет (только копирование) | Краткое окно перехода |
| DNS update | Нет | Да (если не --skip-dns) |
| Use case | Резервная копия, клон staging | Замена машины, перемещение сервера |
Очистка
После удаления репозиториев или восстановления после неудачных операций могут оставаться orphaned директории монтирования, файлы блокировки и неподвижные маркеры. Очистка удаляет их безопасно:
# Просмотрите, что будет удалено
rdc machine prune --name server-1 --dry-run
# Удалить orphaned ресурсы
rdc machine prune --name server-1
Затрагиваются только ресурсы без соответствующего образа репозитория. Непустые директории монтирования никогда не удаляются.