> For the complete documentation index, see [llms.txt](https://developer.harness.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://developer.harness.io/infrastructure-as-code-management/registry/module-registry/module-registry.md).

# Register a Module

Register an OpenTofu or Terraform module in the Harness IaCM Module Registry using the onboarding pipeline flow, including storage type selection, auto-sync, and org/project scoping.

Registering a module connects a Git repository to the Module Registry and makes its tagged versions available for consumption. During registration, you configure the module's repository, storage type, scope, and onboarding pipeline. Go to [Module Artifacts](/infrastructure-as-code-management/registry/module-registry/module-registry-artifacts.md) for a detailed explanation of how artifact storage and the onboarding pipeline work.

You can register a module through the **Add New Module** wizard or the `harness_platform_infra_module` Terraform resource.

***

## Before you begin <a href="#before-you-begin" id="before-you-begin"></a>

* **Git tag**: A module version is a Git tag. Create a tag or release on your module's repository before you register, otherwise there are no versions for the registry to pick up. Go to [Tags](/code-repository/use-harness-code/collaborate-and-develop/tag.md) to tag with Harness Code Repository.
* **Module structure**: Your repository must follow the expected layout. Go to [Set Up a Module](/infrastructure-as-code-management/registry/module-registry/module-structure.md) to prepare the repository.
* **Pipeline permissions**: You need **View**, **Create/Edit**, and **Execute** permissions on Pipelines in the target project. Go to [RBAC in Harness](/harness-ai/use-harness-platform/platform-access-control.md) to configure roles.
* **Git authentication**: Your Git connector must be able to access the module repository. This is separate from the `TF_TOKEN_app_harness_io` authentication used when a workspace consumes the registered module at runtime. Go to [Use a Module](/infrastructure-as-code-management/registry/module-registry/registered-module-settings.md#use-a-module) to configure runtime authentication.

{% hint style="info" %}
**DELEGATE VERSION**

If you connect to your code repository through a [delegate](/harness-ai/use-harness-platform/delegates/delegate/delegate-concepts/delegate-overview.md), ensure the delegate version is `25.01.85000` or later.
{% endhint %}

***

## Understand module tags and versions <a href="#understand-module-tags-and-versions" id="understand-module-tags-and-versions"></a>

The Module Registry uses three different tag-related concepts. Only Git tags represent module versions.

| Term                         | What it is                                                                                      |
| ---------------------------- | ----------------------------------------------------------------------------------------------- |
| **Tags** field on the module | Optional organizational labels inside Harness for search and filtering. These are not versions. |
| **Git Tag Pattern** field    | A wildcard filter (for example, `SQSv*`) that limits which Git tags become module versions.     |
| Git tags in the repository   | The actual Git tags that correspond to module versions.                                         |

For example, if your repository has tags `SQSv.1.0.0`, `SQSv.1.0.1`, `S3v.1.0.0`, and `S3v.1.0.1`, set **Git Tag Pattern** to `SQSv*` to onboard only the SQS module versions.

***

## Module scopes <a href="#module-scopes" id="module-scopes"></a>

You can register a module at the **account**, **organization**, or **project** scope. The scope controls where the module is visible and who can consume it. To view modules created for a specific scope, navigate to the respective scope settings.

| Scope        | Visibility                                                  |
| ------------ | ----------------------------------------------------------- |
| Account      | Available to all organizations and projects in the account. |
| Organization | Available to all projects within the selected organization. |
| Project      | Available only within the selected project.                 |

Regardless of module scope, the onboarding pipeline always runs inside a Harness project. Select the org and project in Step 2 of the wizard where your shared onboarding pipelines live.

Scopes are not combined in the Module Registry. For example, an account-scoped module does not appear in an organization's or project's Module Registry, even though workspaces in that organization or project can still consume it. To view all modules registered at the account scope, navigate to **Account Settings** and select **Module Registry**.

***

### Existing account-scoped modules <a href="#existing-account-scoped-modules" id="existing-account-scoped-modules"></a>

Modules registered before Organization and Project scoping was available remain account-scoped.

After you upgrade, these modules continue to appear only in the account-level Module Registry, even if workspaces in an organization or project consume them. The modules, their versions, and existing workspace configurations are not affected.

To view these modules, navigate to **Account Settings** and select **Module Registry**.

***

## Register a module <a href="#register-a-module" id="register-a-module"></a>

Registration is a three-step wizard titled **Add New Module**. You can also register using the Terraform/OpenTofu provider.

{% tabs %}
{% tab title="Step-by-step" %}

### Step 1: Module details <a href="#step-1-module-details" id="step-1-module-details"></a>

1. In the Harness left navigation, select **Infrastructure as Code Management**, then select **Module Registry**.
2. Click **New Module**.
3. Under **Basic information**, configure the module identity:
   * In the **Name** field, enter a module name. This identifier is used when referencing the module in OpenTofu or Terraform configurations.
   * In the **Provider** field, enter the provider name (for example, `aws`, `gcp`, or `azurerm`).
   * Optionally, select the **Edit** icon next to **Description** to add a description.
   * Optionally, select the **Edit** icon next to **Tags** to add organizational labels for search and filtering. Tags are not version identifiers.
4. Under **Repository**, configure the source:
   * For **Select Git Provider**, select **Harness Code Repository** or **Third-party Git provider**.
   * From the **Git Connector** dropdown, select the connector that has read access to your module repository.
   * From the **Git Fetch Type** dropdown, select how Harness retrieves the module. The default is **Latest from Branch**.
   * From the **Git Branch** dropdown, select or enter the target branch.
   * Optionally, in the **Folder Path** field, enter the path to your module if it is not at the repository root. Go to [Register a module from a subdirectory](#register-a-module-from-a-subdirectory) for details.
5. Select **Advanced** to expand storage options, then configure:
   * Under **Storage type**, select **Artifact** (recommended) or **Git reference**. Artifact is preselected.

     | Storage type               | How it works                                                                                                                                              | When to use                                                                                  |
     | -------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------- |
     | **Artifact** (recommended) | Packages each version as a ZIP artifact on the IaCM server. No Git credentials are needed at workspace runtime.                                           | Use for all new modules.                                                                     |
     | **Git reference** (legacy) | Links directly to a specific Git tag in your repository. Workspaces retrieve the module from Git during execution and require Git credentials at runtime. | Only if you have a specific reason to retain legacy behavior. This flow is being deprecated. |

     <div data-gb-custom-block data-tag="hint" data-style="warning" class="hint hint-warning"><p><strong>GIT REFERENCE CONSTRAINT</strong></p><p>Git reference is supported only when a single Git connector is consistently used across all modules in the registry.</p></div>
   * Optionally, in the **Git Tag Pattern** field, enter a wildcard filter to limit which Git tags become module versions (for example, `SQSv*`). Go to [Understand module tags and versions](#understand-module-tags-and-versions) for details.
6. Click **Next**.

### Step 2: Organization and Project <a href="#step-2-organization-and-project" id="step-2-organization-and-project"></a>

1. From the **Organization** dropdown, select the organization where the onboarding pipeline will run.
2. From the **Project** dropdown, select the project.

{% hint style="info" %}
**ONBOARDING RUNS IN A PROJECT**

Even when a module is registered at account or org scope, the onboarding pipeline runs inside a Harness project. Harness recommends keeping onboarding pipelines in a dedicated project, separate from your working workspaces.
{% endhint %}

3. Click **Next**.

### Step 3: Execution pipeline <a href="#step-3-execution-pipeline" id="step-3-execution-pipeline"></a>

The execution pipeline fetches your module's metadata from Git and populates the registry. Each time you push a new matching Git tag, the pipeline runs and the new version appears in the Module Registry.

1. From the pipeline list, select a pipeline to fetch module metadata:
   * **Default Pipelines** lists the auto-generated onboarding pipeline (`iacm_auto_generated_onboarding_pipeline`). Select it if you do not need a custom onboarding flow.
   * **Custom Pipelines** lists any pipelines already in the selected project. Select a custom pipeline if you need a modified onboarding flow.
   * If no pipeline exists in the selected project, Harness creates `iacm_auto_generated_onboarding_pipeline` automatically when you click **Create**.
2. Confirm the **Enable auto-sync** checkbox is selected. When enabled, Harness creates a webhook trigger on the selected pipeline so each new matching Git tag triggers a sync automatically, without manual re-registration.

   If you do not enable auto-sync, you can trigger a sync manually by clicking the **Sync** button on the module page at any time.
3. Click **Create**.

{% hint style="info" %}
**CUSTOMIZE THE ONBOARDING PIPELINE**

To inspect or customize the pipeline before running it, create it manually first in **Infrastructure > Pipelines > Create a Pipeline**, then select it here. The pipeline must contain an IaCM stage with a `module-onboarding` step and the `moduleId` variable set. The module ID appears on the module detail page after the module is created.
{% endhint %}
{% endtab %}

{% tab title="Interactive guide" %}
{% embed url="<https://demo.arcade.software/f1PBSt1bwI4Qq8bl0E68?embed&embed_mobile=tab&embed_desktop=inline&show_copy_link=true>" %}
{% endtab %}

{% tab title="Terraform/OpenTofu provider" %}
Register a module with the `harness_platform_infra_module` resource. The `repository` field is the repository **name only**, not a URL.

```hcl
resource "harness_platform_infra_module" "example" {
  name        = "my-module"
  description = "Example module"
  system      = "aws"  # the provider

  # Repository name only, not a URL
  repository           = "tf-aws-vpc"
  repository_branch    = "main"
  repository_path      = "modules/network"  # optional; re-roots resolution
  repository_connector = "account.mygithub"

  # Onboarding pipeline (Module Artifacts flow)
  onboarding_pipeline         = "iacm_auto_generated_onboarding_pipeline"
  onboarding_pipeline_org     = "default"
  onboarding_pipeline_project = "IaCM_Project"
  onboarding_pipeline_sync    = true  # enable auto-sync
}
```

{% hint style="warning" %}
**REPOSITORY FIELD FORMAT**

The `repository` field must be the repository **name only**, not a full URL. Entering a full URL causes registration to fail.
{% endhint %}

**Bootstrap the onboarding pipeline first.** The pipeline must already exist before Terraform can reference it. Create it one of two ways:

* **Register one module through the UI first.** The Add New Module wizard creates `iacm_auto_generated_onboarding_pipeline` automatically. All subsequent Terraform registrations can point to it.
* **Create it via the onboarding API**:

```bash
curl -X POST \
  'https://app.harness.io/gateway/iacm/api/modules/pipeline/onboarding' \
  -H 'Harness-Account: ACCOUNT_ID' \
  -H 'x-api-key: HARNESS_PAT' \
  -H 'Content-Type: application/json' \
  -d '{ "org": "default", "project": "my_project" }'
```

{% endtab %}
{% endtabs %}

***

## Register a module from a subdirectory <a href="#register-a-module-from-a-subdirectory-register-a-module-from-a-subdirectory" id="register-a-module-from-a-subdirectory-register-a-module-from-a-subdirectory"></a>

By default, the registry expects the root module (`main.tf`) at the repository root and submodules inside a `modules/` folder. If your module does not sit at the repository root, for example in a monorepo holding multiple modules, set the **Folder Path** field when you register it. **Folder Path** maps to the `repository_path` argument on the `harness_platform_infra_module` Terraform resource.

Setting **Folder Path** re-roots all resolution, including where the registry looks for the `modules/` folder, so submodules are discovered relative to the path you set.

**Example**: Root module lives in `terraform/infrastructure`:

```
.
├── README.md
└── terraform/
    └── infrastructure/
        ├── main.tf
        ├── variables.tf
        ├── outputs.tf
        └── modules/
            └── submoduleA/
                └── main.tf
```

Set **Folder Path** during registration:

1. In the **New Module** wizard, configure the module name, provider, connector, and repository.
2. In the **Folder Path** field, enter the path from the repository root to the directory containing the root module, for example `terraform/infrastructure`.
3. Complete the remaining fields and click **Create**.

Or set the equivalent `repository_path` argument in Terraform:

```hcl
resource "harness_platform_infra_module" "example" {
  name                 = "my-module"
  system               = "aws"
  repository           = "tf-aws-vpc"
  repository_branch    = "main"
  repository_path      = "terraform/infrastructure"
  repository_connector = "account.mygithub"
}
```

{% hint style="info" %}
**SUBMODULES NOT APPEARING?**

Confirm that **Folder Path** points at the directory containing `main.tf` and that submodules sit in a `modules/` folder directly under that path. Metadata collection is one level deep, so deeply nested submodules are not surfaced even though they remain usable through the `//` subpath syntax.
{% endhint %}

***

## Troubleshooting <a href="#troubleshooting" id="troubleshooting"></a>

<details>

<summary>Onboarding pipeline fails on the clone step in Harness IaCM Module Registry</summary>

Verify that the Git connector has read access to the module repository and that the repository name and branch are correct in the module configuration.

</details>

<details>

<summary>A previously visible module is missing from the Module Registry in Harness IaCM</summary>

Check which scope you are browsing from. The Module Registry shows only the modules registered at that scope: Account, Organization, or Project settings each list a different set. An account-scoped module does not appear in an organization's or project's Module Registry, even though workspaces there can still consume it. Go to [Module scopes](#module-scopes) for details. Navigate to Account Settings and select Module Registry to find account-scoped modules.

</details>

<details>

<summary>No module versions appear after the onboarding pipeline completes in Harness IaCM</summary>

Confirm that the repository has at least one matching Git tag. The onboarding pipeline processes tagged versions; branches are not synced.

</details>

<details>

<summary>Auto-sync does not trigger on new tags in Harness IaCM Module Registry</summary>

Confirm that Enable auto-sync is selected and that the webhook was created successfully. Select the pipeline's Triggers tab to verify the trigger is active. If it shows a Failed status, verify that the Git connector has permissions to register webhooks on the repository, then delete the failed trigger and re-enable auto-sync.

</details>

***

## Next steps <a href="#next-steps" id="next-steps"></a>

* Go to [Explore Module Details](/infrastructure-as-code-management/registry/module-registry/registered-module-settings.md) to review your registered module's parsed metadata and published versions.
* Go to [Use a Module](/infrastructure-as-code-management/registry/module-registry/registered-module-settings.md#use-a-module) to reference the registered module from an OpenTofu or Terraform configuration.
* Go to [Test a Module](/infrastructure-as-code-management/registry/module-registry/module-registry-testing.md) to set up automated module testing.

{% @harness-feedback/feedback %}
