For the complete documentation index, see llms.txt. This page is also available as Markdown.

How to Build Your Own Template in Custom Harness Template Library

Build a new Harness Solutions Factory template from scratch in Custom Harness Template Library, from Terraform scaffold to registered IDP workflow.

In this tutorial you will build a new template for the Harness Solutions Factory (HSF) Template Library from scratch. You start from the Terraform scaffold, author the Harness YAML templates, test the module locally, and finish with a registered workflow that any user can run from the Harness Internal Developer Portal (IDP).


What will you learn?

  • Scaffold a template: Generate the standard Terraform directory structure in your Custom Harness Template Library repo.

  • Write the Terraform module: Define providers, variables, locals, data sources, resources, and outputs using the HSF conventions.

  • Author Harness YAML templates: Build the pipeline, stage, step, and step group definitions that Terraform renders.

  • Test locally: Validate, deploy, and tear down your module before it reaches IDP.

  • Register the workflow: Publish your catalog_template.yaml so users can run it from the IDP catalog.


Before you begin

  • Custom Harness Template Library repo: When HSF is deployed into your account, it automatically creates a repository called custom-harness-template-library in the Harness Platform Management organization. Navigate to Harness Platform Management > Repositories, then clone custom-harness-template-library locally. Go to Using your own SCM for Custom Harness Template Library to use your own SCM provider instead.

  • Harness account access: You need access to the Harness account where HSF is deployed. Go to Getting started with Harness Platform to create or access an account.

  • Template permissions: You need View, Create, and Edit for Templates at the scope where you deploy (account, org, or project).

  • Pipeline permissions: You need View and Execute for Pipelines on the Solutions Factory project, so you can trigger the IACM workspace pipeline.

  • IDP workflow permissions: You need View, Create / Edit, and Execute for Workflow in IDP. Go to RBAC in Harness and Manage roles to have an administrator assign a role that includes these permissions.

  • Harness API token: The IDP workflow submits your token when it triggers the provisioning pipeline. Go to Manage API keys to create a token with the permissions listed above.

  • Account-level HSF variables: The last page of your catalog workflow reads these account variables, which HSF creates during deployment. Navigate to Account Settings > Account Resources > Variables and confirm all five exist with non-empty values: solutions_factory_endpoint, solutions_factory_org, solutions_factory_project, custom_template_library_connector, and custom_template_library_repo.

  • Local tools: Terraform or OpenTofu, git, and optionally Docker and mise. Go to Developer Environment Setup to install them, or open the repo in the bundled .devcontainer/ and select Reopen in Container to get every tool preinstalled.

  • Optional, mise: mise (mise-en-place) is a task runner and tool version manager. It reads .mise.toml at the repo root and gives you consistent commands across operating systems. Every step below also gives the make equivalent, so mise is not required. Go to Local Development Using mise to set it up, then run mise tasks to list the available tasks.


Step 1: Create a branch and scaffold

Always start on a new branch.

Generate the template scaffold, replacing my-new-template with your chosen name.

NAMING RULES

Use lowercase letters and hyphens only, for example maven-cicd-k8s or delegate-fleet-management. Be descriptive and concise. Go to Naming Convention Standards to review the full conventions.

The scaffold creates the following structure:

The snippets/ subdirectory is not always created by the scaffold. If your stage templates need it, create it manually:

Step 2: Set provider versions

Open terraform.tf. This file declares which providers your template needs. Copy the standard configuration into it:

WHY THE TIME PROVIDER?

The Harness API is eventually consistent, so it sometimes needs a brief pause between resource creates. The time_sleep resource used in Step 7 handles this. Include the provider by default even if you are not sure you need it yet.

Step 3: Define your variables

Open variables.tf. Every input to your template goes here. The library uses three standard groups. Copy them in order.

Group 1: Platform configuration (always required)

Group 2: Build infrastructure (include if your template creates CI or STO pipelines)

THE "SKIPPED" CONVENTION

HSF uses the string "skipped" as a "not provided" signal throughout the library. When kubernetes_connector = "skipped", the template automatically switches to Harness Cloud infrastructure. The same pattern appears in the YAML conditionals in Step 6.

Group 3: Your custom variables

Add any inputs specific to your template below the standard groups:

Step 4: Add computed values in locals.tf

locals.tf holds the logic that turns raw variables into values ready for use in resources. Copy the standard block into the file, then add any custom locals below it.

Use length(var.kubernetes_node_selectors) > 0 rather than comparing the map to {}. Direct map comparison is unreliable for map(any) types and can silently evaluate the wrong branch.

Step 5: Add data sources

Create a data.tf file if your template targets an existing organization or project. These lookups confirm that the organization and project actually exist before Terraform tries to create anything inside them, which turns a confusing apply failure into a clear plan failure with a helpful error message.

Step 6: Author the Harness YAML template files

The files inside templates/ define the actual Harness resources: pipelines, stages, steps, and step groups. Terraform renders them through the templatefile() function, so they use interpolation placeholders rather than plain YAML.

Go to Configuring Stage Infrastructure to review examples of inputs and templates with stage infrastructure details blended in.

To reduce the potential for errors, copy these files from a template that Harness Template Library already provides, then adapt them.

Naming convention

Prefix every file based on its type, with an underscore separating the prefix from the name.

Prefix
Type
Example filename

pipe_

Pipeline

pipe_my_pipeline.yaml

sta_

Stage

sta_my_stage.yaml

stp_

Step

stp_my_step.yaml

stg_

Step Group

stg_my_step_group.yaml

Always use the .yaml extension, not .yml. Go to Naming Convention Standards to review the full prefix list and the directory layout used across the factory.

Step 7: Create Terraform resources in main.tf

Connect the YAML templates to Terraform resources using harness_platform_template.

SCOPE AND TIER_HANDLER

All templates in a single module must live at the same scope: account, org, or project. You cannot mix scopes, for example a step at account level referenced by a stage at project level. local.tier_handler injects the correct scope prefix automatically based on the organization_id and project_id variables you provide.

Step 8: Define outputs

Open outputs.tf. Always expose the IDs and versions of every template you create. These values are returned to the IDP workflow and shown to the user after deployment.

How outputs surface in IDP

The IDP workflow reads Terraform outputs through this path pattern:

Each top-level key in your outputs.tf becomes the <output_name> at the end of the path. In the example above, step_template and stage_template are the output names. If you add more outputs, for example pipeline_template, reference them in catalog_template.yaml using the same path with your new output name substituted at the end. Step 10 shows where these paths are consumed in the workflow output block.

Step 9: Complete terraform.tfvars.example

Users copy this file when they configure the template themselves, so every variable must appear here with its description as a comment.

Step 10: Create the IDP catalog workflow

This is the most important file, because it defines the form users see in IDP. Open .harness/catalog_template.yaml and apply these rules before you write anything.

Rule 1: token must be on the first page. The ui:field: HarnessAuthToken field type is a built-in plugin that ships with HSF and auto-populates the user's token. If it renders as a plain text box, confirm the Harness IDP backend plugin is enabled in your account.

Rule 2: Solutions Factory Connection must be the last page, with all fields hidden. Users never see this page. Every field is populated from the account-level variables you verified in Before you begin. If those variables are missing, the fields silently pass empty strings and the pipeline fails.

Rule 3: Set template_library_directory and workspace_type to your directory name. These two fields tell HSF which folder in your repo to run Terraform from. They must match the directory name you chose in Step 1.

About infra_defaults: The hidden default account.buildfarm_infrastructure is a Kubernetes connector created by the Central Build Farm Setup factory. If you have not run that factory, the Central Build Farm option in the form does not work, but Harness Cloud and Self-Hosted Kubernetes still function correctly. Go to Central Build Farm Workflow to deploy it.

About RESOURCE_NAME: This is the unique identifier for the IACM workspace that runs your Terraform. Two deployments with the same RESOURCE_NAME share, and potentially overwrite, the same workspace state. Use a descriptive constant that is unique to this template. If your template needs to be deployed multiple times independently, make this a user-provided input.

About RESOURCE_OWNER: HSF_Admins is a user group created automatically during HSF deployment, so you do not need to create it manually. Reference it consistently as group:account/HSF_Admins.

Step 11: Test locally

Test your Terraform module directly before you touch IDP. This confirms the Terraform code is correct without merging or registering anything.

Create your local configuration file:

Edit terraform.tfvars with real values from your account, then run the following sequence.

  1. Run a plan to confirm no resources are created yet:

  2. Apply, then confirm your templates appear under Account Settings > Templates:

  3. Check idempotency. The cycle target runs init, destroy, apply, and plan, and the final plan must propose no changes:

  4. Tear down when you are finished. The teardown target runs destroy and testing_cleanup:

Go to Local Testing Using Make to review every available target.

  1. Run a dry run to confirm no resources are created yet:

  2. Deploy, then confirm your templates appear under Account Settings > Templates:

  3. Check idempotency. Run the cycle task and confirm the final plan proposes no changes:

  4. Tear down when you are finished:

Run mise tasks to confirm these task names exist in your copy of the repo.

Step 12: Generate the README and commit

Generate the resources, inputs, and outputs tables for your README.

Install terraform-docs, then run the following from your template directory:

To bootstrap terraform.tfvars.example from your variables, run:

Commit everything and push:

Open a pull request against main. Once it is merged, continue to Step 13.

Step 13: Register the IDP workflow

After your changes are merged to main, register the workflow by running the Register Custom IDP Templates pipeline in the Solutions Factory project.

  1. In Harness, navigate to Harness Platform Management > Solutions Factory > Pipelines.

  2. Find Register Custom IDP Templates, then click Run.

  3. When the pipeline succeeds, navigate to Internal Developer Portal > Workflows and confirm your workflow appears with the name you set in catalog_template.yaml.

  4. Run your workflow. A successful execution creates an IACM workspace named after your RESOURCE_NAME, applies your Terraform, and returns the output values in the Deployment Summary block. Confirm your new templates are listed under Account Settings > Templates.

RE-REGISTERING AFTER CHANGES

Any time you update catalog_template.yaml and merge to main, run the Register Custom IDP Templates pipeline again. It handles re-registration automatically.


Next steps

You have built, tested, and registered a custom template that any user in your account can deploy from the IDP catalog. Extend it by adding stage infrastructure options, or use the same pattern to build additional templates in your library.

Last updated

Was this helpful?