// DevOps
Как я усмирил Terraform: переезд со стейта в Git на Cloudflare R2
Опубликовано 10.04.2026
Когда я только начинал работать над инфраструктурой проекта, хранить terraform.tfstate локально (или, каюсь, подкидывать его в Git) казалось мне нормальным решением. Но как только к работе подключились коллеги, я быстро понял: локальный стейт — это пороховая бочка.
Один забыл сделать git pull, второй применил изменения со своей машины — и вот я уже трачу полдня на то, чтобы «разрулить» конфликты в инфраструктуре. В какой-то момент стало очевидно: мне нужен Remote State.
В качестве бэкенда я выбрал Cloudflare R2. Причина простая: это S3-совместимое хранилище без платы за исходящий трафик (zero egress fees), и на его настройку у меня ушло буквально несколько минут.
Почему я отказался от локального стейта
Главная проблема локального файла — отсутствие синхронизации и контроля.
Риск затереть чужие изменения
Если два человека запускают terraform apply одновременно, Terraform не предотвращает гонку без блокировок. В итоге побеждает тот, кто записал стейт последним.
Секреты в открытом виде
В terraform.tfstate могут лежать пароли, токены и ключи — зачастую в открытом виде. Держать это в Git — откровенно плохая идея.
Невозможность нормального CI/CD
Без удаленного состояния каждый запуск Terraform в CI видит «свой» мир, что делает автоматизацию бессмысленной.
Как я это настроил
Поскольку R2 поддерживает S3 API, я использовал стандартный backend s3. Но так как это не AWS, мне пришлось отключить ряд проверок Terraform.
Я вынес конфигурацию в отдельный файл backend.hcl, чтобы не захламлять основной код:
bucket = "my-infrastructure-state"
key = "prod/main.tfstate"
region = "auto"
# Важно для R2
use_path_style = true
# Отключаю AWS-специфичные проверки
skip_credentials_validation = true
skip_metadata_api_check = true
skip_region_validation = true
skip_requesting_account_id = true
# Иногда требуется в зависимости от версии Terraform
skip_s3_checksum = true
endpoints = {
s3 = "https://<YOUR_ACCOUNT_ID>.r2.cloudflarestorage.com"
}
В основном коде Terraform я оставил минимальный блок:
terraform {
backend "s3" {}
}
Как я решал проблему блокировок (State Locking)
Классическая схема для S3 backend — использовать DynamoDB для блокировок. Но в случае с Cloudflare R2 у меня такой опции нет, потому что это не AWS.
Я попробовал использовать:
use_lockfile = true
Этот параметр появился в новых версиях Terraform (начиная с 1.10) и позволяет использовать файл в бакете как механизм блокировки.
Но на практике я понял важную вещь:
это не полноценная замена DynamoDB-locking.
Что это значит на практике
- блокировка работает по принципу best-effort
- нет гарантии полной атомарности
- теоретически гонки всё ещё возможны
Как я с этим живу
Я не стал надеяться только на lockfile и ввёл для себя простые правила:
- я не запускаю
terraform applyпараллельно с другими - стараюсь выносить apply в CI/CD
- воспринимаю locking в R2 как дополнительную защиту, а не гарантию
Если бы у меня была критичная инфраструктура — я бы делал строгий CI-only pipeline с внешним механизмом блокировки.
Как я переезжал
Миграция заняла одну команду:
terraform init \
-backend-config=backend.hcl \
-migrate-state
Terraform сам:
- нашёл локальный
terraform.tfstate - запросил подтверждение
- перенёс его в R2
После этого я удалил локальный файл и добавил его в .gitignore.
Что я получил в итоге
Спокойствие
Теперь стейт не хранится на моей машине.
Я дополнительно включил versioning в R2-бакете, чтобы иметь возможность откатиться.
Командную работу
Даже без идеального locking-а:
- у меня один источник правды
- исчезли вопросы «у кого актуальный стейт»
Безопасность
- секреты больше не лежат в Git
- доступ регулируется через API-токены Cloudflare
- можно ограничивать права
Практические выводы
Если я снова буду настраивать Terraform backend на R2, я обязательно:
- включу versioning
- разделю окружения (prod/stage)
- не буду запускать apply с разных машин
- по возможности вынесу apply в CI/CD
Заключение
Если я продолжаю хранить стейт локально или в Git — я сознательно создаю себе проблему.
Cloudflare R2 дал мне быстрый способ перейти на Remote State без AWS. Да, у него есть ограничения, особенно в части блокировок, но это всё равно огромный шаг вперед.
Для меня это тот случай, когда небольшое инфраструктурное изменение реально сэкономило время, нервы и избавило от класса проблем, которые раньше казались «нормальными».
// Reviews
Отзывы по теме
Было несколько проблем касаясь как технической части так и понимания в целом. Михаил быстро ответил на запрос, помог разобраться и решил проблеммы технические и помог разобраться в понимании, за что отдельное спасибо. Результатом доволен.
Было несколько проблем касаясь как технической части так и понимания в целом. Михаил быстро ответил на запрос, помог разобраться и решил проблеммы технические и помог разобраться в понимании, за что отдельное спасибо. …
Настройка vps, настройка сервера
18.02.2026 · ★ 5/5
Все было сделано быстро и четко. Рекомендую
Все было сделано быстро и четко. Рекомендую
Настройка vps, настройка сервера
17.01.2026 · ★ 5/5
Всё прошло хорошо, исполнитель быстро реагировал на вопросы и помог решить проблему. Спасибо!
Всё прошло хорошо, исполнитель быстро реагировал на вопросы и помог решить проблему. Спасибо!
Настройка vps, настройка сервера
16.12.2025 · ★ 5/5
Все сделали оперативно. Будем и дальше обращаться. Рекомендую!
Все сделали оперативно. Будем и дальше обращаться. Рекомендую!
Настройка vps, настройка сервера
10.12.2025 · ★ 5/5
Все сделали оперативно. Михаил всегда на связи. Будем и дальше обращаться
Все сделали оперативно. Михаил всегда на связи. Будем и дальше обращаться
Настройка vps, настройка сервера
10.12.2025 · ★ 5/5
Михаил, профессионал! Уже ни первый раз показал это на практике.
Михаил, профессионал! Уже ни первый раз показал это на практике.
// Contact
Нужна помощь?
Свяжись со мной и я помогу решить проблему
// Related