cloud-devops

انقل Terraform إلى OpenTofu في 2026: شفّر State الخاصة بك

٢٣ يونيو ٢٠٢٦

Migrate Terraform to OpenTofu in 2026: Encrypt Your State

للانتقال من Terraform إلى OpenTofu، قم بتشغيل tofu init -upgrade في مشروعك الحالي، وتأكد من أن tofu plan لا يظهر أي تغييرات، ثم قم بتشغيل tofu apply. يقرأ OpenTofu نفس تنسيق .tfstate، لذا فإن التبديل يكون سلساً للغاية — والفائدة الحقيقية تكمن في تفعيل تشفير الحالة المدمج في OpenTofu بعد ذلك، وهو ما لا توفره واجهة أوامر Terraform.

ملخص

OpenTofu هو نسخة (fork) مرخصة بـ MPL-2.0 من Terraform، والتبديل بينهما هو في الغالب مجرد تبديل للملف البرمجي: tofu init -upgrade، ثم tofu plan (توقع عدم وجود تغييرات)، ثم tofu apply. الميزة التي تبرر الانتقال حقاً هي تشفير الحالة أثناء السكون (state encryption at rest)، والتي لا تزال واجهة أوامر Terraform مفتوحة المصدر تفتقر إليها. يرافقك هذا الدليل في عملية انتقال كاملة لمشروع صغير قابل للتشغيل، ثم يقوم بتشفير ملف حالة موجود وغير مشفر باستخدام عبارة مرور PBKDF2 و AES-GCM، مع استخدام خيار التراجع unencrypted حتى لا تفقد حالتك أبداً. الإصدارات المثبتة: OpenTofu 1.12.0، و hashicorp/random 3.9.0. الوقت المستغرق: حوالي 25 دقيقة.

ما ستتعلمه

  • تثبيت OpenTofu 1.12 واستبدال ملف Terraform البرمجي بـ tofu بشكل نظيف
  • لماذا تتغير بصمات (hashes) المزود في .terraform.lock.hcl بعد التبديل، وكيفية إعادة إنشائها
  • تشفير ملف حالة موجود وغير مشفر باستخدام PBKDF2 + AES-GCM
  • استخدام طريقة التراجع unencrypted للانتقال دون إتلاف ملف الحالة الخاص بك
  • إحكام التشفير باستخدام enforced = true بحيث لا يمكن كتابة نص صريح مرة أخرى أبداً
  • تشفير ملفات الخطة (plan files) وتدوير المفاتيح بأمان باستخدام بلوك fallback
  • التحقق من تشفير الحالة وإصلاح أكثر خمسة أخطاء شائعة في عملية الانتقال

لماذا الانتقال، ولماذا التشفير هو السبب الحقيقي

قامت HashiCorp بتغيير ترخيص Terraform من MPL 2.0 إلى ترخيص المصدر التجاري (BSL 1.1) في 10 أغسطس 2023.1 قام المجتمع بنسخ آخر إصدار مرخص بـ MPL وهو الإصدار 1.5، وأصبح هذا النسخ هو OpenTofu تحت مظلة مؤسسة Linux.1 يظل OpenTofu مرخصاً بـ MPL 2.0 ويقرأ نفس لغة HCL ونفس تنسيق JSON للحالة، لذا فهو بالنسبة لمعظم الإعدادات بديل مباشر تقريباً.

لكن "الحرية في الترخيص" نادراً ما تكون كافية وحدها لتبرير الانتقال. الفوز التشغيلي الملموس هو التالي: يوفر OpenTofu تشفير مدمج للحالة والخطة، وهو متاح بشكل عام منذ الإصدار v1.7، ولا توفر واجهة أوامر Terraform ما يعادله.2 يحتوي ملف الحالة الخاص بك على كل سر تنتجه مواردك — كلمات مرور قواعد البيانات، المفاتيح الخاصة، رموز الوصول — في نص صريح افتراضياً. التشفير أثناء السكون يسد هذه الفجوة. بقية هذا الدليل ستنقلك إلى OpenTofu ثم تفعل التشفير بالطريقة الصحيحة.

المتطلبات الأساسية

  • طرفية (shell) لنظام Linux أو macOS (الأوامر أدناه تستخدم Ubuntu/Debian؛ خطوات التثبيت لنظامي macOS و Windows موجودة في الروابط).
  • مشروع Terraform موجود، أو لا شيء على الإطلاق — سنقوم ببناء مشروع تجريبي صغير يمكنك تشغيله من الصفر باستخدام OpenTofu وحده.
  • OpenTofu 1.12.0 أو أحدث. تم إصدار v1.12.0 في 14 مايو 2026؛ نعتمد عليه لضمان قابلية إعادة الإنتاج.3 التشفير متاح بشكل عام منذ v1.7، لذا فإن أي إصدار 1.7+ سيعمل.2
  • مزود hashicorp/random إصدار 3.9.0 — مزود منطقي لا يحتاج إلى حساب سحابي، لذا فإن الوصول الوحيد للشبكة الذي يتطلبه البرنامج التعليمي هو تنزيل المزود لمرة واحدة.4
  • حوالي 25 دقيقة.

قاعدة واحدة قبل أن تلمس التشفير: قم بعمل نسخة احتياطية لملف الحالة أولاً. يمكن أن يؤدي تكوين تشفير غير صالح، في حالات نادرة، إلى قيام OpenTofu بكتابة ملف حالة فارغ أو غير قابل للقراءة.2 إذا كنت تستخدم واجهة خلفية (backend) عن بُعد (S3، GCS، AzureRM)، فقم بتجربة إجراء الاستعادة الخاص بها مرة واحدة قبل البدء.

الخطوة 1 — تثبيت OpenTofu 1.12

أسرع مسار قابل لإعادة الإنتاج على Debian/Ubuntu هو الملف البرمجي اليدوي، المثبت على إصدار محدد:

TOFU_VERSION="1.12.0"
curl -fsSL -o "tofu.zip" \
  "https://GitHub.com/opentofu/opentofu/releases/download/v${TOFU_VERSION}/tofu_${TOFU_VERSION}_linux_amd64.zip"
sudo apt-get update && sudo apt-get install -y unzip
unzip tofu.zip tofu
sudo mv tofu /usr/local/bin/
sudo chmod +x /usr/local/bin/tofu
tofu version

المخرجات المتوقعة:

OpenTofu v1.12.0
on linux_amd64

تفضل مدير حزم؟ خياران موثقان رسمياً:5

# Snap (ملاحظة: اسم حزمة snap هو "opentofu"، و --classic مطلوب)
sudo snap install --classic opentofu

# APT (بعد إضافة مستودع OpenTofu الرسمي؛ اسم حزمة apt هو "tofu")
sudo apt-get install -y tofu

تتبع حزم snap و apt أحدث إصدار مستقر بدلاً من إصدار محدد، لذا بالنسبة للدروس التعليمية و CI يفضل استخدام الملف البرمجي المحدد أعلاه.

الخطوة 2 — التحقق من خط الأساس لـ Terraform

إذا كنت تقوم بتشغيل Terraform بالفعل، فلا تبدأ عملية الانتقال من حالة "غير نظيفة". قم بتشغيل أدواتك الحالية أولاً وتأكد من عدم وجود انحراف (drift):

terraform init
terraform apply   # تأكد من أن الخطة تظهر "No changes" قبل المتابعة

خط الأساس النظيف مهم لأن الخطوات التالية تفترض أن الكود الخاص بك وبنيتك التحتية الحقيقية متفقان بالفعل. إذا أراد terraform apply تغيير الأشياء، فقم بحل ذلك باستخدام Terraform قبل تقديم OpenTofu — فتصحيح أخطاء الانحراف وتبديل الأدوات في نفس الوقت هو الطريقة التي تفشل بها عمليات الانتقال.

هل تتابع بدون مشروع موجود؟ قم بإنشاء العرض التجريبي. أنشئ مجلداً وملف main.tf:

# main.tf
terraform {
  required_version = ">= 1.12.0"
  required_providers {
    random = {
      source  = "hashicorp/random"
      version = "3.9.0"
    }
  }
}

# قيمة حساسة تنتهي في الحالة بنص صريح — وهذا بالضبط ما نريد تشفيره.
resource "random_password" "db" {
  length  = 24
  special = true
}

resource "random_pet" "stack" {
  length = 2
}

output "stack_name" {
  value = random_pet.stack.id
}

يتم تمييز random_password.db.result كقيمة حساسة، لذا لن يقوم OpenTofu بطباعتها — ولكن يتم كتابتها في terraform.tfstate بنص واضح. هذا هو الهدف الأساسي: الحالة تحتفظ بالأسرار حتى عندما تخفيها واجهة الأوامر.

الخطوة 3 — تبديل الملف البرمجي باستخدام tofu init -upgrade

الآن وجه OpenTofu إلى نفس المجلد. يقوم OpenTofu دائماً بجلب المزودين من سجله الخاص (registry.opentofu.org) افتراضياً، لذا فإن tofu init العادي — وهو بالضبط ما يستخدمه دليل الانتقال الرسمي لـ OpenTofu — يعمل بالفعل.6 السبب لإضافة -upgrade أثناء الانتقال هو ملف القفل: لا يزال ملف .terraform.lock.hcl الحالي يحمل بصمات HashiCorp، ويخبر -upgrade OpenTofu بإعادة اختيار المزودين وتحديث تلك البصمات مقابل سجله الخاص، مما يمنع حدوث خطأ عدم تطابق البصمات في التشغيل الأول:

tofu init -upgrade

ثم تأكد من التكافؤ وأكمل عملية الانتقال:

tofu plan    # يجب أن يبلغ: No changes. Your infrastructure matches the configuration.
tofu apply   # يقوم بتحديث تنسيق ملف الحالة إذا لزم الأمر، وبذلك تكتمل عملية الانتقال

تحدث ثلاثة أشياء في الخلفية، وكل منها قد يسبب ارتباكاً:

  1. تنسيق الحالة متطابق. يقرأ OpenTofu ويكتب نفس ملف JSON .tfstate، ولهذا السبب لا يظهر tofu plan أي تغييرات.6 في مشروع جديد، يقوم tofu init && tofu apply ببساطة بإنشاء تلك الحالة غير المشفرة لأول مرة.
  2. تتغير بصمات ملف القفل. يحتفظ .terraform.lock.hcl بنفس التنسيق، لكن بصمات المزود من registry.opentofu.org تختلف عن بصمات HashiCorp. يقوم tofu init -upgrade بإعادة إنشائها؛ بالنسبة لـ CI متعدد المنصات، قم بتشغيل tofu providers lock -platform=linux_amd64 -platform=darwin_arm64 بحيث يغطي ملف القفل كل بيئة تشغيل.
  • هناك عملية انتقال فعلية. يقوم tofu apply بتحديث تنسيق ملف الحالة (state file) إذا لزم الأمر؛ يضع الدليل الرسمي لـ OpenTofu التراجع في إطار "الاستعادة من النسخة الاحتياطية، ثم تشغيل Terraform"، لذا احتفظ بتلك النسخة الاحتياطية حتى تتأكد من التزامك بالانتقال.6 وبمجرد تمكين التشفير في الخطوة 4، لن يتمكن Terraform من قراءة الحالة على الإطلاق.
  • ملاحظة حول نظافة الكود: إذا كان تكوينك يستخدم عناوين مصدر كاملة مثل registry.terraform.io/hashicorp/aws، فقم باختصارها إلى hashicorp/aws حتى يقوم OpenTofu بحلها مقابل السجل الخاص به.6

    عند هذه النقطة، أنت تعمل بالكامل على OpenTofu — مع ملف حالة غير مشفر. لنقم بإصلاح ذلك.

    الخطوة 4 — تشفير حالة موجودة باستخدام PBKDF2 و AES-GCM

    هذا هو الجزء الذي يتجاهله كل دليل هجرة عام. لا يمكنك ببساطة إضافة كتلة encryption إلى مشروع يحتوي بالفعل على حالة بنص صريح: سوف يرفض OpenTofu قراءة الملف غير المشفر، لأنه بالنسبة لـ OpenTofu، تبدو الحمولة غير المشفرة التي كان يتوقع تشفيرها وكأنها تلاعب.2 الحل هو استخدام تراجع مؤقت إلى unencrypted يسمح لـ OpenTofu بقراءة النص الصريح القديم مرة واحدة وإعادة كتابته مشفراً.

    أولاً، قم بتوفير عبارة المرور خارج النطاق (لا تقم أبداً بإدراجها في الكود). يتطلب PBKDF2 16 حرفاً على الأقل:2

    export TF_VAR_passphrase="correct-horse-battery-staple"
    

    الآن قم بإنشاء encryption.tf. ترتيب الكتل أدناه — طريقة unencrypted، ومزود المفتاح، وطريقة AES-GCM، ثم كتلة state مع fallback — مأخوذ مباشرة من خطوات الهجرة الرسمية لـ OpenTofu:2

    # encryption.tf
    variable "passphrase" {
      type      = string
      sensitive = true
    }
    
    terraform {
      encryption {
        # Step 1: a temporary method that can read the existing plaintext state.
        method "unencrypted" "migrate" {}
    
        # Step 2: derive a key from the passphrase (min 16 chars; 600,000 PBKDF2
        # iterations and SHA-512 are the defaults).
        key_provider "pbkdf2" "passphrase" {
          passphrase = var.passphrase
        }
    
        # Step 3: the real encryption method.
        method "aes_gcm" "encrypted" {
          keys = key_provider.pbkdf2.passphrase
        }
    
        state {
          # Step 4: encrypt state with AES-GCM going forward...
          method = method.aes_gcm.encrypted
    
          # Step 5: ...but allow reading the old plaintext during this one migration.
          fallback {
            method = method.unencrypted.migrate
          }
        }
      }
    }
    

    قم بتطبيقه. يقرأ OpenTofu النص الصريح من خلال التراجع (fallback) ويعيد كتابة الحالة مشفرة:

    tofu apply
    

    سترى No changes للموارد — فالتشفير هو شأن يتعلق بالتخزين، وليس تغييراً في البنية التحتية — ولكن ملف الحالة على القرص أصبح الآن نصاً مشفراً. يقوم OpenTofu دائماً بـ الكتابة باستخدام الطريقة الأساسية (aes_gcm) ويتراجع فقط إلى طريقة unencrypted عند القراءة.2

    بعض الإعدادات الافتراضية التي تستحق المعرفة، وجميعها قابلة للتكوين في مزود المفتاح pbkdf2: القيمة الافتراضية لـ key_length هي 32، و iterations هي 600,000 (بحد أدنى 200,000)، و salt_length هي 32، و hash_function هي sha512.2 الإعدادات الافتراضية معقولة؛ لا تقم بتعديلها إلا إذا كان لديك متطلب امتثال محدد.

    الخطوة 5 — الإغلاق باستخدام enforced = true

    في الوقت الحالي، لا يزال بإمكان تكوينك كتابة نص صريح، لأن التراجع إلى unencrypted لا يزال موجوداً. بمجرد نجاح تطبيق الهجرة وتشفير حالتك، قم بإزالة التراجع وقم بتفعيل الإلزام (enforcement) بحيث يفشل التكوين المفقود أو المعطل للتشفير بشكل واضح بدلاً من كتابة الأسرار في العلن بصمت:2

    # encryption.tf — after a successful migration
    variable "passphrase" {
      type      = string
      sensitive = true
    }
    
    terraform {
      encryption {
        key_provider "pbkdf2" "passphrase" {
          passphrase = var.passphrase
        }
    
        method "aes_gcm" "encrypted" {
          keys = key_provider.pbkdf2.passphrase
        }
    
        state {
          method   = method.aes_gcm.encrypted
          enforced = true   # refuse to write unencrypted state, ever
        }
      }
    }
    

    قم بتشغيل tofu plan مرة أخرى للتأكد من أن OpenTofu لا يزال بإمكانه قراءة الحالة المشفرة باستخدام عبارة المرور الخاصة بك ولا يبلغ عن أي تغييرات. مع enforced = true، إذا كانت عبارة المرور مفقودة، فستفشل العملية بدلاً من إنتاج ملف نصي صريح — وهي بالضبط خاصية الأمان التي تريدها في بيئة CI.

    لا تقم بتغيير اسم key_provider.pbkdf2.passphrase أو method.aes_gcm.encrypted بعد تشفير البيانات. يتم تخزين هذه الأسماء في البيانات الوصفية لتشفير الحالة، وسيؤدي تغيير اسمها إلى كسر عملية فك التشفير. إذا كان لا بد من تغيير الاسم، فقم بتعيين encrypted_metadata_alias على مزود المفتاح، أو قم بالتبديل باستخدام كتلة fallback (الخطوة التالية).2

    الخطوة 6 — تشفير ملفات الخطة وتدوير المفاتيح بأمان

    تحسينان للإنتاج يختتمان عملية الهجرة.

    تشفير ملفات الخطة أيضاً. تتضمن الخطة المحفوظة (tofu plan -out=tfplan) نفس الأسرار التي تتضمنها حالتك. أضف كتلة plan تعيد استخدام الطريقة:

    terraform {
      encryption {
        key_provider "pbkdf2" "passphrase" {
          passphrase = var.passphrase
        }
        method "aes_gcm" "encrypted" {
          keys = key_provider.pbkdf2.passphrase
        }
        state {
          method   = method.aes_gcm.encrypted
          enforced = true
        }
        plan {
          method   = method.aes_gcm.encrypted
          enforced = true
        }
      }
    }
    

    تدوير عبارة المرور دون توقف. عندما تقوم بتغيير عبارة المرور (أو تبديل أنظمة إدارة المفاتيح بالكامل)، احتفظ بالطريقة القديمة متاحة كـ fallback حتى يتمكن OpenTofu من قراءة الحالة المشفرة بالمفتاح السابق. يقرأ بالطريقة الجديدة، ويتراجع إلى القديمة، ويكتب دائماً بالجديدة:2

    terraform {
      encryption {
        key_provider "pbkdf2" "current" {
          passphrase = var.passphrase
        }
        key_provider "pbkdf2" "previous" {
          passphrase = var.old_passphrase
        }
        method "aes_gcm" "new" {
          keys = key_provider.pbkdf2.current
        }
        method "aes_gcm" "old" {
          keys = key_provider.pbkdf2.previous
        }
        state {
          method = method.aes_gcm.new
          fallback {
            method = method.aes_gcm.old
          }
        }
      }
    }
    

    قم بتشغيل tofu apply مرة واحدة مع وجود كلتا الطريقتين لإعادة كتابة الحالة بالمفتاح الجديد، ثم احذف مزود المفتاح previous وكتلة fallback. لاحظ أن التشفير يحمي الحالة أثناء السكون (at rest) فقط — فهو لا يحمي من فقدان الحالة، أو هجمات إعادة التشغيل (replay attacks) باستخدام حالة أو خطة قديمة، أو الشخص الذي يمتلك عبارة المرور ويقوم بتشغيل tofu.2 إذا كنت تدعم مفاتيحك بـ KMS وخوارزمية مثل AES-GCM، فقم بتمكين تدوير المفاتيح التلقائي، لأن AES-GCM له حد استخدام آمن محدود لكل مفتاح.2

    الخلفيات البعيدة (Remote backends): التشفير من جهة العميل مقابل التشفير من جهة الخادم

    يستخدم العرض التوضيحي أعلاه ملف حالة محلياً، ولكن نفس كتلة encryption تعمل دون تغيير مع خلفية S3 أو GCS أو Azure Blob. التفصيل المهم هو أين يحدث التشفير. يقوم OpenTofu بتشفير الحالة على جهازك، قبل كتابتها إلى الخلفية، ويفك تشفيرها فقط عندما يقرأ الحالة مرة أخرى.2 وهذا يختلف جوهرياً عن تشفير S3 من جهة الخادم (SSE)، حيث تنتقل البايتات إلى المستودع (bucket) وتقوم خدمة التخزين بتشفيرها هناك.

    هذه هي بالضبط فجوة الإمكانيات مع Terraform. لا تتوفر في واجهة سطر أوامر Terraform ميزة تشفير الحالة من جهة العميل — حيث تم إغلاق طلب السحب (PR) مفتوح المصدر لهذه الميزة لتقادمه — لذا يعتمد مستخدمو Terraform على خيارات من جهة الخلفية مثل S3 SSE أو تشفير HCP Terraform أثناء السكون.2 مع OpenTofu، أنت تتحكم في المفتاح، وتكون الحالة الموجودة في المستودع غير قابلة للقراءة حتى لشخص يمكنه سرد وتنزيل كل كائن.

    في بيئة الإنتاج، ستحتاج عادةً إلى كلتا الطبقتين: احتفظ بـ S3 SSE كخط أساس، وأضف كتلة encryption الخاصة بـ OpenTofu للدفاع المتعمق. التغيير التشغيلي الوحيد للخلفية البعيدة هو التأكد من وجود عبارة المرور (أو الوصول إلى مفتاح KMS) أينما يتم تشغيل tofu — والأهم من ذلك، في بيئة CI.

    التحقق — إثبات أن الحالة مشفرة بالفعل

    أوضح فحص هو البحث (grep) في الحالة عن شيء كان نصاً صريحاً. قبل التشفير، تكون معرفات الموارد والاسم الأليف موجودة مباشرة في ملف JSON:

    # قبل التشفير — بيانات الموارد موجودة في الحالة (state) بنص صريح
    grep -c random_password terraform.tfstate   # عدد غير صفري
    grep -o random_pet terraform.tfstate | head -n1   # -> random_pet
    

    بعد تنفيذ أمر apply مشفر بنجاح، فإن حمولة الحالة بالكامل — أنواع الموارد، والسمات، والـ result الحساسة — تعيش داخل غلاف مشفر، لذا تختفي النصوص الصريحة حتى لو ظل الملف بتنسيق JSON صالح:

    # بعد التشفير — لا توجد بيانات موارد بنص صريح
    grep -c random_password terraform.tfstate   # 0
    jq empty terraform.tfstate && echo "لا يزال JSON صالحاً (غلاف مشفر)"
    

    إذا أرجع أمر grep الأول القيمة 0 ولا يزال أمر tofu plan الخاص بك يشير إلى عدم وجود تغييرات، فقد نجحت عملية الهجرة: يقوم OpenTofu الآن بقراءة وكتابة الحالة المشفرة باستخدام عبارة المرور الخاصة بك.

    الأخطاء الشائعة

    encountered unencrypted payload without unencrypted method configured — لقد أضفت كتلة encryption إلى مشروع لا تزال حالته بنص صريح، بدون إعداد تراجع الهجرة (migration fallback). أضف method "unencrypted" "migrate" {} و fallback { method = method.unencrypted.migrate } إلى كتلة state، وقم بتنفيذ apply مرة واحدة، ثم قم بإزالتها (الخطوة 4).2

    Unsupported state file format: This state file is encrypted and can not be read without an encryption configuration — المشكلة العكسية: حالتك مشفرة ولكن التشغيل الحالي لا يحتوي على تكوين تشفير أو عبارة مرور. هذا هو فشل CI الكلاسيكي. تأكد من وجود TF_VAR_passphrase (أو كتلة TF_ENCRYPTION كاملة) في بيئة خط الأنابيب (pipeline)، وليس فقط على جهازك المحمول.7

    فشل فك التشفير بعد تغيير عبارة المرور — يفشل توثيق AES-GCM عندما يكون المفتاح خاطئاً، ولا يستطيع OpenTofu قراءة الحالة. لا يوجد استرداد بدون المفتاح الدقيق، ولهذا السبب تصر الخطوة 4 على وجود نسخة احتياطية.2 قم باستعادة النسخة الاحتياطية غير المشفرة، ثم أعد عملية الهجرة، أو استخدم fallback مع المفتاح القديم (الخطوة 6).

    فشل فك التشفير بعد إعادة تسمية مزود المفتاح أو الطريقة — الأسماء مدمجة في البيانات الوصفية لتشفير الحالة. تراجع عن إعادة التسمية، أو استخدم encrypted_metadata_alias في مزود المفتاح حتى يظل مفتاح البيانات الوصفية مستقراً عبر عمليات إعادة التسمية.2

    provider ... was previously installed from registry.terraform.io / عدم تطابق هاش ملف القفل — لا يزال ملف .terraform.lock.hcl الخاص بك يحمل بصمات HashiCorp. قم بتشغيل tofu init -upgrade لإعادة إنشائه مقابل registry.opentofu.org، و tofu providers lock -platform=... لتسجيل الهاش لكل منصة يستخدمها CI الخاص بك (الخطوة 3).6

    الخطوات التالية ومزيد من القراءة

    لديك الآن مشروع OpenTofu تمت هجرته بالكامل مع حالة وملفات خطة مشفرة، ومؤمنة خلف enforced = true. من هنا:

    • انقل عبارة المرور إلى مزود مفاتيح مدار (AWS KMS، أو GCP KMS، أو Vault) بدلاً من PBKDF2، وقم بإعداد تدوير المفاتيح التلقائي.
    • اربط التشفير مع قفل الحالة الأصلي (native state locking) لتبقى عمليات التشغيل المتزامنة آمنة — راجع شرحنا لـ قفل الحالة الأصلي في S3 لـ Terraform و OpenTofu.
    • قم بتشغيل tofu apply فقط من CI، وليس من الأجهزة المحمولة أبداً، حتى لا تخرج عبارة المرور والأسرار المفكوكة من خط الأنابيب. يوضح دليلنا حول عمليات نشر AWS بدون مفاتيح باستخدام GitHub Actions OIDC كيفية القيام بذلك بدون بيانات اعتماد طويلة الأمد.

    للحصول على التفاصيل الموثوقة حول كل مزود مفتاح وطريقة، احتفظ بـ وثائق تشفير الحالة والخطة في OpenTofu مفتوحة أثناء عملك.2

    Footnotes

    1. OpenTofu، "OpenTofu Announces Fork of Terraform" — إعادة ترخيص HashiCorp لـ BSL 1.1 في 10 أغسطس 2023 وتفرع المجتمع MPL 2.0. https://opentofu.org/blog/opentofu-announces-fork-of-terraform/ 2

    2. وثائق OpenTofu، "State and Plan Encryption" — تكوين PBKDF2/AES-GCM، طريقة هجرة unencrypted، كتل fallback، enforced، تدوير المفاتيح، encrypted_metadata_alias، القيم الافتراضية (key_length 32، iterations min 200,000/default 600,000، salt_length 32، hash_function sha512)، ونموذج التهديد للبيانات المخزنة. https://opentofu.org/docs/language/state/encryption/ 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19

    3. OpenTofu، إعلان إصدار "OpenTofu v1.12.0" (14 مايو 2026). https://opentofu.org/blog/opentofu-1-12-0/

    4. HashiCorp Terraform Registry، "random provider" (v3.9.0) — random_password و random_pet؛ يتم تخزين القيم الحساسة في الـ state. https://registry.terraform.io/providers/hashicorp/random/latest/docs

    5. وثائق OpenTofu، "Installing OpenTofu" — ملفات binary يدوية، Snap (أسماء الحزم والأوامر opentofu، --classic)، و APT (tofu). https://opentofu.org/docs/intro/install/

    6. وثائق OpenTofu، "Migration Guide" — tofu init -upgrade، و OpenTofu Registry (registry.opentofu.org)، وإعادة إنشاء .terraform.lock.hcl / tofu providers lock، واختصار مصادر الـ provider المؤهلة بالكامل. https://opentofu.org/docs/intro/migration/migration-guide/ 2 3 4 5

    7. منتدى GitLab، "OpenTofu — Unsupported state file format: can not be read without an encryption configuration" — فقدان إعدادات التشفير/كلمة المرور في الـ CI. https://forum.gitlab.com/t/opentofu-unsupported-state-file-format-can-not-be-read-without-an-encryption-configuration/120379