// DevOps
Cómo domé Terraform: migración del estado de Git a Cloudflare R2
Publicado el 10.04.2026
Cuando empecé a trabajar en la infraestructura del proyecto, guardar terraform.tfstate localmente (o, lo confieso, subirlo a Git) me parecía una solución razonable. Pero en cuanto mis colegas se sumaron al trabajo, entendí rápido: el state local es un barril de pólvora.
Uno olvidó hacer git pull, otro aplicó cambios desde su máquina — y me pasaba medio día «resolviendo» conflictos en la infraestructura. En cierto momento se hizo evidente: necesitaba un Remote State.
Como backend elegí Cloudflare R2. La razón es simple: es un almacenamiento compatible con S3 sin coste por salida de datos (zero egress fees), y me llevó literalment unos minutos configurarlo.
Por qué renuncié al state local
El problema principal del archivo local es la falta de sincronización y control.
Riesgo de sobrescribir cambios ajenos
Si dos personas ejecutan terraform apply simultáneamente, Terraform no evita la carrera sin mecanismos de bloqueo. Al final gana quien escribió el state por último.
Secretos a la vista
En terraform.tfstate pueden estar contraseñas, tokens y claves — a menudo en claro. Tener eso en Git es, francamente, una mala idea.
Imposibilidad de un CI/CD decente
Sin un estado remoto, cada ejecución de Terraform en CI ve «su» propio mundo, lo que hace la automatización inútil.
Cómo lo configuré
Dado que R2 soporta la API S3, usé el backend estándar s3. Pero como no es AWS, tuve que desactivar varias comprobaciones de Terraform.
Saqué la configuración a un archivo separado backend.hcl, para no ensuciar el código principal:
bucket = "my-infrastructure-state"
key = "prod/main.tfstate"
region = "auto"
# Importante para R2
use_path_style = true
# Desactivo comprobaciones específicas de AWS
skip_credentials_validation = true
skip_metadata_api_check = true
skip_region_validation = true
skip_requesting_account_id = true
# A veces es necesario según la versión de Terraform
skip_s3_checksum = true
endpoints = {
s3 = "https://<YOUR_ACCOUNT_ID>.r2.cloudflarestorage.com"
}
En el código principal de Terraform dejé el bloque mínimo:
terraform {
backend "s3" {}
}
Cómo resolví el problema de los bloqueos (State Locking)
El esquema clásico para el backend S3 es usar DynamoDB para los locks. Pero en el caso de Cloudflare R2 no tengo esa opción, porque no es AWS.
Probé a usar:
use_lockfile = true
Ese parámetro apareció en versiones nuevas de Terraform (a partir de la 1.10) y permite usar un archivo en el bucket como mecanismo de bloqueo.
Pero en la práctica entendí algo importante:
esto no es un reemplazo completo del locking con DynamoDB.
Qué significa esto en la práctica
- el bloqueo funciona bajo el principio de best-effort
- no hay garantía de atomicidad completa
- teóricamente las carreras aún son posibles
Cómo lo manejo
No confié solo en el lockfile e introduje reglas simples para mí:
- no ejecuto
terraform applyen paralelo con otros - procuro sacar los apply al CI/CD
- considero el locking en R2 como protección adicional, no como garantía
Si tuviera una infraestructura crítica, haría un pipeline estricto solo en CI con un mecanismo externo de bloqueo.
Cómo migré
La migración se hizo con un solo comando:
terraform init \
-backend-config=backend.hcl \
-migrate-state
Terraform por sí mismo:
- encontró el
terraform.tfstatelocal - solicitó confirmación
- lo trasladó a R2
Después de eso borré el archivo local y lo añadí a .gitignore.
Qué obtuve al final
Tranquilidad
Ahora el state no está en mi máquina.
Además activé versionado en el bucket de R2 para poder retroceder si es necesario.
Trabajo en equipo
Incluso sin un locking perfecto:
- tengo una única fuente de verdad
- desaparecieron las preguntas «¿quién tiene el state actualizado?»
Seguridad
- los secretos ya no están en Git
- el acceso se regula mediante API tokens de Cloudflare
- es posible restringir permisos
Conclusiones prácticas
Si vuelvo a configurar un backend Terraform en R2, seguro que:
- activo versionado
- separo entornos (prod/stage)
- no ejecuto apply desde distintas máquinas
- siempre que sea posible, saco los apply al CI/CD
Conclusión
Si sigo guardando el state localmente o en Git — me estoy provocando problemas a propósito.
Cloudflare R2 me dio una forma rápida de pasar a Remote State sin AWS. Sí, tiene limitaciones, especialmente en lo relativo a bloqueos, pero sigue siendo un gran paso adelante.
Para mí es uno de esos cambios infraestructurales pequeños que realmente ahorraron tiempo, nervios y me libraron de una clase de problemas que antes parecían «normales».
// Reviews
Reseñas relacionadas
Hubo varios problemas, tanto en la parte técnica como en la comprensión general. Mijaíl respondió rápido a la solicitud, ayudó a aclarar las cosas y resolvió los problemas técnicos; por ello, muchas gracias. Estoy satisfecho con el resultado.
Hubo varios problemas relacionados tanto con la parte técnica como con la comprensión en general. Mijaíl respondió rápidamente a la solicitud, ayudó a aclarar las cosas y resolvió los problemas técnicos, por lo que le …
Configuración de VPS, configuración del servidor
18.02.2026 · ★ 5/5
Todo se hizo de manera rápida y precisa. Lo recomiendo.
Todo se hizo rápido y con precisión. Lo recomiendo.
Configuración de VPS, configuración del servidor
17.01.2026 · ★ 5/5
Todo salió bien, el profesional respondió rápidamente a las preguntas y ayudó a resolver el problema. ¡Gracias!
Todo fue bien, el profesional respondió rápidamente a las preguntas y ayudó a resolver el problema. ¡Gracias!
Configuración de VPS, configuración del servidor
16.12.2025 · ★ 5/5
Lo hicieron todo con rapidez. Seguiremos acudiendo. ¡Lo recomiendo!
Todo lo hicieron con rapidez. Seguiremos acudiendo. ¡Lo recomiendo!
Configuración de VPS, configuración del servidor
10.12.2025 · ★ 5/5
Hicieron todo rápidamente. Mijaíl siempre está disponible. Seguiremos recurriendo a él.
Todo se hizo con rapidez. Михаил siempre está en contacto. Seguiremos recurriendo a él
Configuración de VPS, configuración del servidor
10.12.2025 · ★ 5/5
¡Mijaíl es un profesional! Ya no es la primera vez que lo demuestra en la práctica.
Михаил, ¡un profesional! Ya lo ha demostrado en la práctica más de una vez.
// Contact
¿Necesitas ayuda?
Escríbeme y te ayudaré a resolver el problema
// Related