diff --git a/.gitlab/README.md.template b/.gitlab/README.md.template
index 53feabfa637d99881edb8860458d0ab3dbab0151..523109be86f2e01a9b23b326eba7f20846026a44 100644
--- a/.gitlab/README.md.template
+++ b/.gitlab/README.md.template
@@ -125,9 +125,10 @@ The base image OS can be specified with the `base_os` input.
 ### GitLab-managed Terraform state backend
 
 This component - by leveraging the [`gitlab-tofu`](src/gitlab-tofu.sh) CLI internally -
-automatically configures the
+can automatically define and configure the
 [GitLab-managed Terraform state backend](https://docs.gitlab.com/ee/user/infrastructure/iac/terraform_state.html).
-The only thing required is that the Terraform configuration must specify an empty `http` backend block, like this:
+
+By default the HTTP backend must be defined manually using the following HCL:
 
 ```hcl
 terraform {
@@ -135,8 +136,9 @@ terraform {
 }
 ```
 
-We recommend having a dedicated `backend.tf` file inside your `root_dir`
-with the aforementioned block.
+However, you may simply enable the `auto_define_backend` so that the component takes care of this step.
+
+**Note**: in future versions of this component we may enable `auto_define_backend` by default.
 
 ### State and Plan Encryption
 
diff --git a/README.md b/README.md
index 88d55c01c420caee75d7b77d8b369d36ad4cadda..82e05faff9fea8038dc36a938fe52eb3d74da7c4 100644
--- a/README.md
+++ b/README.md
@@ -127,9 +127,10 @@ The base image OS can be specified with the `base_os` input.
 ### GitLab-managed Terraform state backend
 
 This component - by leveraging the [`gitlab-tofu`](src/gitlab-tofu.sh) CLI internally -
-automatically configures the
+can automatically define and configure the
 [GitLab-managed Terraform state backend](https://docs.gitlab.com/ee/user/infrastructure/iac/terraform_state.html).
-The only thing required is that the Terraform configuration must specify an empty `http` backend block, like this:
+
+By default the HTTP backend must be defined manually using the following HCL:
 
 ```hcl
 terraform {
@@ -137,8 +138,9 @@ terraform {
 }
 ```
 
-We recommend having a dedicated `backend.tf` file inside your `root_dir`
-with the aforementioned block.
+However, you may simply enable the `auto_define_backend` so that the component takes care of this step.
+
+**Note**: in future versions of this component we may enable `auto_define_backend` by default.
 
 ### State and Plan Encryption
 
@@ -315,7 +317,8 @@ The following environment variables are respected by the `gitlab-tofu` script:
 - `GITLAB_TOFU_AUTO_ENCRYPTION`: if set to true, enables auto state and plan encryption. Defaults to `false`.
 - `GITLAB_TOFU_AUTO_ENCRYPTION_PASSPHRASE`: the passphrase to use for state and plan encryption. Required if `GITLAB_TOFU_AUTO_ENCRYPTION` is true.
 - `GITLAB_TOFU_AUTO_ENCRYPTION_ENABLE_MIGRATION_FROM_UNENCRYPTED_ENABLED`: if set to true, enables a fallback for state and plan encryption to migrate unencrypted plans and states to encrypted ones. Defaults to `false`.
-- `GITLAB_TOFU_ALLOW_DEVELOPER_ROLE: Users with the Developer role are not able to lock the state. Thus a regular `tofu plan` fails. When set to `true` a `-lock=false` is passed to plan.
+- `GITLAB_TOFU_ALLOW_DEVELOPER_ROLE`: Users with the Developer role are not able to lock the state. Thus a regular `tofu plan` fails. When set to `true` a `-lock=false` is passed to plan.
+- `GITLAB_TOFU_AUTO_DEFINE_BACKEND`: if set to true, automatically creates a file with a HTTP backend configuration block.
 
 #### Respected OpenTofu Environment Variables
 
diff --git a/src/gitlab-tofu.sh b/src/gitlab-tofu.sh
index e5ecfc1505eaddb0480a84eaeeb77f61d24dae45..8a339e09122a14d3a0a37391ee1e6fb80b1ba855 100644
--- a/src/gitlab-tofu.sh
+++ b/src/gitlab-tofu.sh
@@ -30,7 +30,8 @@
 # - `GITLAB_TOFU_AUTO_ENCRYPTION`: if set to true, enables auto state and plan encryption. Defaults to `false`.
 # - `GITLAB_TOFU_AUTO_ENCRYPTION_PASSPHRASE`: the passphrase to use for state and plan encryption. Required if `GITLAB_TOFU_AUTO_ENCRYPTION` is true.
 # - `GITLAB_TOFU_AUTO_ENCRYPTION_ENABLE_MIGRATION_FROM_UNENCRYPTED_ENABLED`: if set to true, enables a fallback for state and plan encryption to migrate unencrypted plans and states to encrypted ones. Defaults to `false`.
-# - `GITLAB_TOFU_ALLOW_DEVELOPER_ROLE: Users with the Developer role are not able to lock the state. Thus a regular `tofu plan` fails. When set to `true` a `-lock=false` is passed to plan.
+# - `GITLAB_TOFU_ALLOW_DEVELOPER_ROLE`: Users with the Developer role are not able to lock the state. Thus a regular `tofu plan` fails. When set to `true` a `-lock=false` is passed to plan.
+# - `GITLAB_TOFU_AUTO_DEFINE_BACKEND`: if set to true, automatically creates a file with a HTTP backend configuration block.
 #
 # #### Respected OpenTofu Environment Variables
 #
@@ -163,6 +164,7 @@ fi
 # ============================
 
 # Backend related variables
+auto_define_backend=${GITLAB_TOFU_AUTO_DEFINE_BACKEND:-false}
 backend_username="gitlab-ci-token"
 backend_password="${CI_JOB_TOKEN}"
 backend_state_name="$(jq -rn --arg x "${GITLAB_TOFU_STATE_NAME:-default}" '$x|@uri')"
@@ -177,6 +179,8 @@ if [ -n "${GITLAB_TOFU_ROOT_DIR}" ]; then
 
   default_tf_plan_cache="${abs_tf_root}/${base_plan_name}.cache"
   default_tf_plan_json="${abs_tf_root}/${base_plan_name}.json"
+else
+  abs_tf_root=$(realpath "${CI_PROJECT_DIR}")
 fi
 
 # Init related variables
@@ -227,6 +231,26 @@ fi
 # Helper functions
 # ================
 
+# define_http_backend defines the HTTP backend in a file called __gitlab-opentofu-backend.tf if no backend can be found.
+# The backend configuration is attempted to be found with a simple grep.
+define_http_backend() {
+  if ! $auto_define_backend; then
+    return
+  fi
+
+  if ! grep -q '^[[:space:]]*backend[[:space:]]\+"http"[[:space:]]\+{.*$' "${abs_tf_root}" -r 2>/dev/null; then
+    echo "gitlab-tofu: automatically defining the HTTP backend in __gitlab-opentofu-backend.tf. If that is a mistake, please disable it with the auto_define_backend: false input."
+
+    cat <<EOF > __gitlab-opentofu-backend.tf
+terraform {
+  backend "http" {}
+}
+EOF
+  else
+    echo "gitlab-tofu: auto_define_backend is enabled, but found manually configured HTTP backend, doing nothing."
+  fi
+}
+
 # configure_variables_for_tofu sets and exports all relevant variables for subsequent `tofu` command invocations.
 configure_variables_for_tofu() {
   # Use terraform automation mode (will remove some verbose unneeded messages)
@@ -352,6 +376,7 @@ EOF
 }
 
 # We always want to configure the tofu variables, even in source-mode.
+define_http_backend
 configure_variables_for_tofu
 configure_encryption_for_tofu
 
diff --git a/templates/apply.yml b/templates/apply.yml
index 9ee6039a4643d35a65806a0ed4e9f9ad0bbba88e..3b98e55eeb8db936292b6a73e0ac272c2fd6b585 100644
--- a/templates/apply.yml
+++ b/templates/apply.yml
@@ -98,6 +98,10 @@ spec:
       default: false
       type: boolean
       description: 'Whether to setup automatic state and plan encryption for currently unencrypted state. This is only temporarily useful when migrating from an unencrypted state.'
+    auto_define_backend:
+      default: false
+      type: boolean
+      description: 'Whether to automatically define the HTTP backend configuration block.'
 
 ---
 
@@ -124,6 +128,7 @@ spec:
     GITLAB_TOFU_AUTO_ENCRYPTION: '$[[ inputs.auto_encryption ]]'
     GITLAB_TOFU_AUTO_ENCRYPTION_PASSPHRASE: '$[[ inputs.auto_encryption_passphrase ]]'
     GITLAB_TOFU_AUTO_ENCRYPTION_ENABLE_MIGRATION_FROM_UNENCRYPTED: '$[[ inputs.auto_encryption_enable_migration_from_unencrypted ]]'
+    GITLAB_TOFU_AUTO_DEFINE_BACKEND: '$[[ inputs.auto_define_backend ]]'
   image:
     name: '$[[ inputs.image_registry_base ]]/$[[ inputs.image_name ]]:$[[ inputs.version ]]-opentofu$[[ inputs.opentofu_version ]]-$[[ inputs.base_os ]]$[[ inputs.image_digest ]]'
   script:
diff --git a/templates/destroy.yml b/templates/destroy.yml
index 90b1e55d43a753681b82c43d8df0636a6621bee5..fa350f8b0f2fb24c07358cd81c3cce32e1bee4da 100644
--- a/templates/destroy.yml
+++ b/templates/destroy.yml
@@ -102,6 +102,10 @@ spec:
       default: false
       type: boolean
       description: 'Whether to automatically delete the Terraform state. This only makes sense when using the GitLab-managed state backend. It is equivalent to running the delete-state job.'
+    auto_define_backend:
+      default: false
+      type: boolean
+      description: 'Whether to automatically define the HTTP backend configuration block.'
 
 ---
 
@@ -128,6 +132,7 @@ spec:
     GITLAB_TOFU_AUTO_ENCRYPTION: '$[[ inputs.auto_encryption ]]'
     GITLAB_TOFU_AUTO_ENCRYPTION_PASSPHRASE: '$[[ inputs.auto_encryption_passphrase ]]'
     GITLAB_TOFU_AUTO_ENCRYPTION_ENABLE_MIGRATION_FROM_UNENCRYPTED: '$[[ inputs.auto_encryption_enable_migration_from_unencrypted ]]'
+    GITLAB_TOFU_AUTO_DEFINE_BACKEND: '$[[ inputs.auto_define_backend ]]'
   image:
     name: '$[[ inputs.image_registry_base ]]/$[[ inputs.image_name ]]:$[[ inputs.version ]]-opentofu$[[ inputs.opentofu_version ]]-$[[ inputs.base_os ]]$[[ inputs.image_digest ]]'
   script:
diff --git a/templates/full-pipeline.yml b/templates/full-pipeline.yml
index f4f22f14c7f4b0a1f17d87a7d9d4499563ccf52f..290e81bb2925a828d76275a7c2aa2b78ef390dfb 100644
--- a/templates/full-pipeline.yml
+++ b/templates/full-pipeline.yml
@@ -198,6 +198,10 @@ spec:
       default: false
       type: boolean
       description: 'Users with the Developer role are not able to lock the state. Thus a regular `tofu plan` fails. When set to `true` a `-lock=false` is passed to plan.'
+    auto_define_backend:
+      default: false
+      type: boolean
+      description: 'Whether to automatically define the HTTP backend configuration block.'
 
 ---
 
@@ -236,6 +240,7 @@ include:
       auto_encryption: $[[ inputs.auto_encryption ]]
       auto_encryption_passphrase: $[[ inputs.auto_encryption_passphrase ]]
       auto_encryption_enable_migration_from_unencrypted: $[[ inputs.auto_encryption_enable_migration_from_unencrypted ]]
+      auto_define_backend: $[[ inputs.auto_define_backend ]]
   - local: '/templates/test.yml'
     rules:
       - if: '"$[[ inputs.trigger_in_child_pipeline ]]" == "true"'
@@ -259,6 +264,7 @@ include:
       auto_encryption: $[[ inputs.auto_encryption ]]
       auto_encryption_passphrase: $[[ inputs.auto_encryption_passphrase ]]
       auto_encryption_enable_migration_from_unencrypted: $[[ inputs.auto_encryption_enable_migration_from_unencrypted ]]
+      auto_define_backend: $[[ inputs.auto_define_backend ]]
   - local: '/templates/plan.yml'
     rules:
       - if: '"$[[ inputs.trigger_in_child_pipeline ]]" == "false"'
@@ -282,6 +288,7 @@ include:
       auto_encryption_passphrase: $[[ inputs.auto_encryption_passphrase ]]
       auto_encryption_enable_migration_from_unencrypted: $[[ inputs.auto_encryption_enable_migration_from_unencrypted ]]
       allow_developer_role: $[[ inputs.allow_developer_role_to_plan ]]
+      auto_define_backend: $[[ inputs.auto_define_backend ]]
   - local: '/templates/apply.yml'
     rules:
       - if: '"$[[ inputs.trigger_in_child_pipeline ]]" == "false"'
@@ -302,6 +309,7 @@ include:
       auto_encryption: $[[ inputs.auto_encryption ]]
       auto_encryption_passphrase: $[[ inputs.auto_encryption_passphrase ]]
       auto_encryption_enable_migration_from_unencrypted: $[[ inputs.auto_encryption_enable_migration_from_unencrypted ]]
+      auto_define_backend: $[[ inputs.auto_define_backend ]]
   - local: '/templates/destroy.yml'
     rules:
       - if: '"$[[ inputs.trigger_in_child_pipeline ]]" == "false"'
@@ -321,6 +329,7 @@ include:
       auto_encryption: $[[ inputs.auto_encryption ]]
       auto_encryption_passphrase: $[[ inputs.auto_encryption_passphrase ]]
       auto_encryption_enable_migration_from_unencrypted: $[[ inputs.auto_encryption_enable_migration_from_unencrypted ]]
+      auto_define_backend: $[[ inputs.auto_define_backend ]]
   - local: '/templates/delete-state.yml'
     rules:
       - if: '"$[[ inputs.trigger_in_child_pipeline ]]" == "false"'
@@ -408,6 +417,7 @@ stages:
           auto_encryption_passphrase: $[[ inputs.auto_encryption_passphrase ]]
           auto_encryption_enable_migration_from_unencrypted: $[[ inputs.auto_encryption_enable_migration_from_unencrypted ]]
           allow_developer_role_to_plan: $[[ inputs.allow_developer_role_to_plan ]]
+          auto_define_backend: $[[ inputs.auto_define_backend ]]
           trigger_in_child_pipeline: false
     forward:
       yaml_variables: true
diff --git a/templates/graph.yml b/templates/graph.yml
index 02da5178c8b6ef647298a4e0261abe490b0c0562..c78cde0ae86b353bdd6d2a1719f1dd817cc31e6c 100644
--- a/templates/graph.yml
+++ b/templates/graph.yml
@@ -96,6 +96,10 @@ spec:
       default: false
       type: boolean
       description: 'Whether to setup automatic state and plan encryption for currently unencrypted state. This is only temporarily useful when migrating from an unencrypted state.'
+    auto_define_backend:
+      default: false
+      type: boolean
+      description: 'Whether to automatically define the HTTP backend configuration block.'
 
 ---
 
@@ -116,6 +120,7 @@ spec:
     GITLAB_TOFU_AUTO_ENCRYPTION: '$[[ inputs.auto_encryption ]]'
     GITLAB_TOFU_AUTO_ENCRYPTION_PASSPHRASE: '$[[ inputs.auto_encryption_passphrase ]]'
     GITLAB_TOFU_AUTO_ENCRYPTION_ENABLE_MIGRATION_FROM_UNENCRYPTED: '$[[ inputs.auto_encryption_enable_migration_from_unencrypted ]]'
+    GITLAB_TOFU_AUTO_DEFINE_BACKEND: '$[[ inputs.auto_define_backend ]]'
   image:
     name: '$[[ inputs.image_registry_base ]]/$[[ inputs.image_name ]]:$[[ inputs.version ]]-opentofu$[[ inputs.opentofu_version ]]-$[[ inputs.base_os ]]$[[ inputs.image_digest ]]'
   script:
diff --git a/templates/job-templates.yml b/templates/job-templates.yml
index 387f02f11691b2372a24189596f314543df3deae..eaa2d306161fccc811d3318729eef823ccab3066 100644
--- a/templates/job-templates.yml
+++ b/templates/job-templates.yml
@@ -103,6 +103,10 @@ spec:
       default: false
       type: boolean
       description: 'Users with the Developer role are not able to lock the state. Thus a regular `tofu plan` fails. When set to `true` a `-lock=false` is passed to plan.'
+    auto_define_backend:
+      default: false
+      type: boolean
+      description: 'Whether to automatically define the HTTP backend configuration block.'
 
 ---
 
@@ -134,6 +138,7 @@ include:
       auto_encryption: $[[ inputs.auto_encryption ]]
       auto_encryption_passphrase: $[[ inputs.auto_encryption_passphrase ]]
       auto_encryption_enable_migration_from_unencrypted: $[[ inputs.auto_encryption_enable_migration_from_unencrypted ]]
+      auto_define_backend: $[[ inputs.auto_define_backend ]]
   - local: '/templates/graph.yml'
     inputs:
       as: '$[[ inputs.job_name_prefix ]]graph'
@@ -148,6 +153,7 @@ include:
       auto_encryption: $[[ inputs.auto_encryption ]]
       auto_encryption_passphrase: $[[ inputs.auto_encryption_passphrase ]]
       auto_encryption_enable_migration_from_unencrypted: $[[ inputs.auto_encryption_enable_migration_from_unencrypted ]]
+      auto_define_backend: $[[ inputs.auto_define_backend ]]
   - local: '/templates/test.yml'
     inputs:
       as: '$[[ inputs.job_name_prefix ]]test'
@@ -164,6 +170,7 @@ include:
       auto_encryption: $[[ inputs.auto_encryption ]]
       auto_encryption_passphrase: $[[ inputs.auto_encryption_passphrase ]]
       auto_encryption_enable_migration_from_unencrypted: $[[ inputs.auto_encryption_enable_migration_from_unencrypted ]]
+      auto_define_backend: $[[ inputs.auto_define_backend ]]
   - local: '/templates/plan.yml'
     inputs:
       as: '$[[ inputs.job_name_prefix ]]plan'
@@ -183,6 +190,7 @@ include:
       auto_encryption_passphrase: $[[ inputs.auto_encryption_passphrase ]]
       auto_encryption_enable_migration_from_unencrypted: $[[ inputs.auto_encryption_enable_migration_from_unencrypted ]]
       allow_developer_role: $[[ inputs.allow_developer_role_to_plan ]]
+      auto_define_backend: $[[ inputs.auto_define_backend ]]
   - local: '/templates/apply.yml'
     inputs:
       as: '$[[ inputs.job_name_prefix ]]apply'
@@ -200,6 +208,7 @@ include:
       auto_encryption: $[[ inputs.auto_encryption ]]
       auto_encryption_passphrase: $[[ inputs.auto_encryption_passphrase ]]
       auto_encryption_enable_migration_from_unencrypted: $[[ inputs.auto_encryption_enable_migration_from_unencrypted ]]
+      auto_define_backend: $[[ inputs.auto_define_backend ]]
   - local: '/templates/destroy.yml'
     inputs:
       as: '$[[ inputs.job_name_prefix ]]destroy'
@@ -217,6 +226,7 @@ include:
       auto_encryption: $[[ inputs.auto_encryption ]]
       auto_encryption_passphrase: $[[ inputs.auto_encryption_passphrase ]]
       auto_encryption_enable_migration_from_unencrypted: $[[ inputs.auto_encryption_enable_migration_from_unencrypted ]]
+      auto_define_backend: $[[ inputs.auto_define_backend ]]
   - local: '/templates/delete-state.yml'
     inputs:
       as: '$[[ inputs.job_name_prefix ]]delete-state'
diff --git a/templates/plan.yml b/templates/plan.yml
index 752c37c99f7d1cebf2e4827a54f31c2e19c81bb2..73b4a5118416234e0b2bfe08d384d34baeda9690 100644
--- a/templates/plan.yml
+++ b/templates/plan.yml
@@ -109,6 +109,10 @@ spec:
       default: false
       type: boolean
       description: 'Users with the Developer role are not able to lock the state. Thus a regular `tofu plan` fails. When set to `true` a `-lock=false` is passed to plan.'
+    auto_define_backend:
+      default: false
+      type: boolean
+      description: 'Whether to automatically define the HTTP backend configuration block.'
 
 ---
 
@@ -175,6 +179,7 @@ spec:
     GITLAB_TOFU_AUTO_ENCRYPTION_PASSPHRASE: '$[[ inputs.auto_encryption_passphrase ]]'
     GITLAB_TOFU_AUTO_ENCRYPTION_ENABLE_MIGRATION_FROM_UNENCRYPTED: '$[[ inputs.auto_encryption_enable_migration_from_unencrypted ]]'
     GITLAB_TOFU_ALLOW_DEVELOPER_ROLE: '$[[ inputs.allow_developer_role ]]'
+    GITLAB_TOFU_AUTO_DEFINE_BACKEND: '$[[ inputs.auto_define_backend ]]'
   image:
     name: '$[[ inputs.image_registry_base ]]/$[[ inputs.image_name ]]:$[[ inputs.version ]]-opentofu$[[ inputs.opentofu_version ]]-$[[ inputs.base_os ]]$[[ inputs.image_digest ]]'
   script:
diff --git a/templates/test.yml b/templates/test.yml
index 79b2b0b717b1061ea8378be15023478ab0dde33d..a76e3293c24b73d6d05dc913cc4e1951152aa795 100644
--- a/templates/test.yml
+++ b/templates/test.yml
@@ -98,6 +98,10 @@ spec:
       default: false
       type: boolean
       description: 'Whether to setup automatic state and plan encryption for currently unencrypted state. This is only temporarily useful when migrating from an unencrypted state.'
+    auto_define_backend:
+      default: false
+      type: boolean
+      description: 'Whether to automatically define the HTTP backend configuration block.'
 
 ---
 
@@ -119,6 +123,7 @@ spec:
     GITLAB_TOFU_AUTO_ENCRYPTION: '$[[ inputs.auto_encryption ]]'
     GITLAB_TOFU_AUTO_ENCRYPTION_PASSPHRASE: '$[[ inputs.auto_encryption_passphrase ]]'
     GITLAB_TOFU_AUTO_ENCRYPTION_ENABLE_MIGRATION_FROM_UNENCRYPTED: '$[[ inputs.auto_encryption_enable_migration_from_unencrypted ]]'
+    GITLAB_TOFU_AUTO_DEFINE_BACKEND: '$[[ inputs.auto_define_backend ]]'
   image:
     name: '$[[ inputs.image_registry_base ]]/$[[ inputs.image_name ]]:$[[ inputs.version ]]-opentofu$[[ inputs.opentofu_version ]]-$[[ inputs.base_os ]]$[[ inputs.image_digest ]]'
   script:
diff --git a/templates/validate-plan-apply.yml b/templates/validate-plan-apply.yml
index 6924516558cabbc5ab96f5c8ca1c04ae4acd4f12..f1c50051c4fbb540644bcf1cbab08ec7602a38f6 100644
--- a/templates/validate-plan-apply.yml
+++ b/templates/validate-plan-apply.yml
@@ -162,6 +162,10 @@ spec:
       default: false
       type: boolean
       description: 'Users with the Developer role are not able to lock the state. Thus a regular `tofu plan` fails. When set to `true` a `-lock=false` is passed to plan.'
+    auto_define_backend:
+      default: false
+      type: boolean
+      description: 'Whether to automatically define the HTTP backend configuration block.'
 
 ---
 
@@ -201,6 +205,7 @@ include:
       auto_encryption: $[[ inputs.auto_encryption ]]
       auto_encryption_passphrase: $[[ inputs.auto_encryption_passphrase ]]
       auto_encryption_enable_migration_from_unencrypted: $[[ inputs.auto_encryption_enable_migration_from_unencrypted ]]
+      auto_define_backend: $[[ inputs.auto_define_backend ]]
   - local: '/templates/plan.yml'
     rules:
       - if: '"$[[ inputs.trigger_in_child_pipeline ]]" == "false"'
@@ -225,6 +230,7 @@ include:
       auto_encryption_passphrase: $[[ inputs.auto_encryption_passphrase ]]
       auto_encryption_enable_migration_from_unencrypted: $[[ inputs.auto_encryption_enable_migration_from_unencrypted ]]
       allow_developer_role: $[[ inputs.allow_developer_role_to_plan ]]
+      auto_define_backend: $[[ inputs.auto_define_backend ]]
   - local: '/templates/apply.yml'
     rules:
       - if: '"$[[ inputs.trigger_in_child_pipeline ]]" == "false"'
@@ -246,6 +252,7 @@ include:
       auto_encryption: $[[ inputs.auto_encryption ]]
       auto_encryption_passphrase: $[[ inputs.auto_encryption_passphrase ]]
       auto_encryption_enable_migration_from_unencrypted: $[[ inputs.auto_encryption_enable_migration_from_unencrypted ]]
+      auto_define_backend: $[[ inputs.auto_define_backend ]]
 
 
 # NOTE: the following configuration is only used if `trigger_in_child_pipeline` is enabled.
@@ -303,6 +310,7 @@ stages:
           auto_encryption_passphrase: $[[ inputs.auto_encryption_passphrase ]]
           auto_encryption_enable_migration_from_unencrypted: $[[ inputs.auto_encryption_enable_migration_from_unencrypted ]]
           allow_developer_role_to_plan: $[[ inputs.allow_developer_role_to_plan ]]
+          auto_define_backend: $[[ inputs.auto_define_backend ]]
           trigger_in_child_pipeline: false
     forward:
       yaml_variables: true
diff --git a/templates/validate-plan-destroy.yml b/templates/validate-plan-destroy.yml
index c6a54b711f241431874d9ec7cff9bda8bcd69897..1d303fd6eaef9113cd84dadbc85c78b7b7614f63 100644
--- a/templates/validate-plan-destroy.yml
+++ b/templates/validate-plan-destroy.yml
@@ -168,6 +168,10 @@ spec:
       default: false
       type: boolean
       description: 'Users with the Developer role are not able to lock the state. Thus a regular `tofu plan` fails. When set to `true` a `-lock=false` is passed to plan.'
+    auto_define_backend:
+      default: false
+      type: boolean
+      description: 'Whether to automatically define the HTTP backend configuration block.'
 
 ---
 
@@ -207,6 +211,7 @@ include:
       auto_encryption: $[[ inputs.auto_encryption ]]
       auto_encryption_passphrase: $[[ inputs.auto_encryption_passphrase ]]
       auto_encryption_enable_migration_from_unencrypted: $[[ inputs.auto_encryption_enable_migration_from_unencrypted ]]
+      auto_define_backend: $[[ inputs.auto_define_backend ]]
   - local: '/templates/plan.yml'
     rules:
       - if: '"$[[ inputs.trigger_in_child_pipeline ]]" == "false"'
@@ -232,6 +237,7 @@ include:
       auto_encryption_passphrase: $[[ inputs.auto_encryption_passphrase ]]
       auto_encryption_enable_migration_from_unencrypted: $[[ inputs.auto_encryption_enable_migration_from_unencrypted ]]
       allow_developer_role: $[[ inputs.allow_developer_role_to_plan ]]
+      auto_define_backend: $[[ inputs.auto_define_backend ]]
   - local: '/templates/destroy.yml'
     rules:
       - if: '"$[[ inputs.trigger_in_child_pipeline ]]" == "false"'
@@ -254,6 +260,7 @@ include:
       auto_encryption: $[[ inputs.auto_encryption ]]
       auto_encryption_passphrase: $[[ inputs.auto_encryption_passphrase ]]
       auto_encryption_enable_migration_from_unencrypted: $[[ inputs.auto_encryption_enable_migration_from_unencrypted ]]
+      auto_define_backend: $[[ inputs.auto_define_backend ]]
   - local: '/templates/delete-state.yml'
     rules:
       - if: '"$[[ inputs.trigger_in_child_pipeline ]]" == "false"'
@@ -336,6 +343,7 @@ stages:
           auto_encryption_passphrase: $[[ inputs.auto_encryption_passphrase ]]
           auto_encryption_enable_migration_from_unencrypted: $[[ inputs.auto_encryption_enable_migration_from_unencrypted ]]
           allow_developer_role_to_plan: $[[ inputs.allow_developer_role_to_plan ]]
+          auto_define_backend: $[[ inputs.auto_define_backend ]]
           trigger_in_child_pipeline: false
     forward:
       yaml_variables: true
diff --git a/templates/validate-plan.yml b/templates/validate-plan.yml
index 96d199e6fb0db2007e827cd7cbc99c7aa9b4320f..ed976b6f333474f60bed15a95a26b4bcec0b4559 100644
--- a/templates/validate-plan.yml
+++ b/templates/validate-plan.yml
@@ -146,6 +146,10 @@ spec:
       default: false
       type: boolean
       description: 'Users with the Developer role are not able to lock the state. Thus a regular `tofu plan` fails. When set to `true` a `-lock=false` is passed to plan.'
+    auto_define_backend:
+      default: false
+      type: boolean
+      description: 'Whether to automatically define the HTTP backend configuration block.'
 
 ---
 
@@ -185,6 +189,7 @@ include:
       auto_encryption: $[[ inputs.auto_encryption ]]
       auto_encryption_passphrase: $[[ inputs.auto_encryption_passphrase ]]
       auto_encryption_enable_migration_from_unencrypted: $[[ inputs.auto_encryption_enable_migration_from_unencrypted ]]
+      auto_define_backend: $[[ inputs.auto_define_backend ]]
   - local: '/templates/plan.yml'
     rules:
       - if: '"$[[ inputs.trigger_in_child_pipeline ]]" == "false"'
@@ -209,6 +214,7 @@ include:
       auto_encryption_passphrase: $[[ inputs.auto_encryption_passphrase ]]
       auto_encryption_enable_migration_from_unencrypted: $[[ inputs.auto_encryption_enable_migration_from_unencrypted ]]
       allow_developer_role: $[[ inputs.allow_developer_role_to_plan ]]
+      auto_define_backend: $[[ inputs.auto_define_backend ]]
 
 
 # NOTE: the following configuration is only used if `trigger_in_child_pipeline` is enabled.
@@ -263,6 +269,7 @@ stages:
           auto_encryption_passphrase: $[[ inputs.auto_encryption_passphrase ]]
           auto_encryption_enable_migration_from_unencrypted: $[[ inputs.auto_encryption_enable_migration_from_unencrypted ]]
           allow_developer_role_to_plan: $[[ inputs.allow_developer_role_to_plan ]]
+          auto_define_backend: $[[ inputs.auto_define_backend ]]
           trigger_in_child_pipeline: false
     forward:
       yaml_variables: true
diff --git a/templates/validate.yml b/templates/validate.yml
index e4dcb8e17a20118fb06f8618b3fc01bb438f8ae0..14154a195b7b0b668e41a8ad6861c94f22c8d6e1 100644
--- a/templates/validate.yml
+++ b/templates/validate.yml
@@ -95,6 +95,10 @@ spec:
       default: false
       type: boolean
       description: 'Whether to setup automatic state and plan encryption for currently unencrypted state. This is only temporarily useful when migrating from an unencrypted state.'
+    auto_define_backend:
+      default: false
+      type: boolean
+      description: 'Whether to automatically define the HTTP backend configuration block.'
 
 ---
 
@@ -116,6 +120,7 @@ spec:
     GITLAB_TOFU_AUTO_ENCRYPTION: '$[[ inputs.auto_encryption ]]'
     GITLAB_TOFU_AUTO_ENCRYPTION_PASSPHRASE: '$[[ inputs.auto_encryption_passphrase ]]'
     GITLAB_TOFU_AUTO_ENCRYPTION_ENABLE_MIGRATION_FROM_UNENCRYPTED: '$[[ inputs.auto_encryption_enable_migration_from_unencrypted ]]'
+    GITLAB_TOFU_AUTO_DEFINE_BACKEND: '$[[ inputs.auto_define_backend ]]'
   image:
     name: '$[[ inputs.image_registry_base ]]/$[[ inputs.image_name ]]:$[[ inputs.version ]]-opentofu$[[ inputs.opentofu_version ]]-$[[ inputs.base_os ]]$[[ inputs.image_digest ]]'
   script:
diff --git a/tests/iac-auto-define-backend/main.tf b/tests/iac-auto-define-backend/main.tf
new file mode 100644
index 0000000000000000000000000000000000000000..6f610dcb023f602dc4d7920121c713d25e627fc7
--- /dev/null
+++ b/tests/iac-auto-define-backend/main.tf
@@ -0,0 +1,19 @@
+resource "local_file" "foo" {
+  content  = "foo!"
+  filename = "${path.module}/foo.bar"
+}
+
+locals {
+  ts = plantimestamp()
+}
+
+// NOTE: always force a change.
+resource "null_resource" "this" {
+  triggers = {
+    timestamp = local.ts
+  }
+}
+
+output "this_always_changes" {
+  value = local.ts
+}
diff --git a/tests/iac-auto-define-backend/tests/main.tftest.hcl b/tests/iac-auto-define-backend/tests/main.tftest.hcl
new file mode 100644
index 0000000000000000000000000000000000000000..fedf96e4c458eee084740b05980a52ffe64362a1
--- /dev/null
+++ b/tests/iac-auto-define-backend/tests/main.tftest.hcl
@@ -0,0 +1,6 @@
+run "test" {
+  assert {
+    condition     = file(local_file.foo.filename) == "foo!"
+    error_message = "Incorrect content in ${local_file.foo.filename}"
+  }
+}
diff --git a/tests/integration-tests/AutoDefineBackend.gitlab-ci.yml b/tests/integration-tests/AutoDefineBackend.gitlab-ci.yml
new file mode 100644
index 0000000000000000000000000000000000000000..4a64e52cafecf9fc001f5a2dca1e185f76f875ba
--- /dev/null
+++ b/tests/integration-tests/AutoDefineBackend.gitlab-ci.yml
@@ -0,0 +1,20 @@
+include:
+  - component: $CI_SERVER_FQDN/$CI_PROJECT_PATH/full-pipeline@$CI_COMMIT_SHA
+    inputs:
+      image_registry_base: $GITLAB_OPENTOFU_IMAGE_BASE
+      version: $CI_COMMIT_SHA
+      base_os: $GITLAB_OPENTOFU_BASE_IMAGE_OS
+      opentofu_version: $OPENTOFU_VERSION
+      root_dir: $TEST_GITLAB_TOFU_ROOT_DIR
+      state_name: $TEST_GITLAB_TOFU_STATE_NAME
+      auto_define_backend: true
+      # Required to run everything immediately, instead of manually.
+      fmt_rules: [{when: always}]
+      validate_rules: [{when: always}]
+      test_rules: [{when: always}]
+      plan_rules: [{when: always}]
+      apply_rules: [{when: always}]
+      destroy_rules: [{when: always}]
+      delete_state_rules: [{when: always}]
+
+stages: [validate, test, build, deploy, cleanup]
diff --git a/tests/integration.gitlab-ci.yml b/tests/integration.gitlab-ci.yml
index c9298a573791c160dc6e1af085ba4bf823ea5ef4..f5ed0b8e88b23543c0a6c8f2a335c8457b73ae6d 100644
--- a/tests/integration.gitlab-ci.yml
+++ b/tests/integration.gitlab-ci.yml
@@ -17,6 +17,23 @@ full-pipeline:
           - alpine
           - debian
 
+auto-define-backend:
+  stage: test-integration
+  variables:
+    OPENTOFU_VERSION: $LATEST_OPENTOFU_VERSION
+    TEST_GITLAB_TOFU_STATE_NAME: ci-integration-$CI_JOB_NAME_SLUG-$CI_PIPELINE_IID-$CI_NODE_INDEX
+    TEST_GITLAB_TOFU_ROOT_DIR: tests/iac-auto-define-backend
+  trigger:
+    include: tests/integration-tests/$PIPELINE_NAME.gitlab-ci.yml
+    strategy: depend
+  parallel:
+    matrix:
+      - PIPELINE_NAME:
+          - AutoDefineBackend
+        GITLAB_OPENTOFU_BASE_IMAGE_OS:
+          - alpine
+          - debian
+
 validate-plan-apply:
   stage: test-integration
   variables: