{"id":13505809,"url":"https://github.com/briefercloud/layerform","last_synced_at":"2025-09-30T04:32:01.834Z","repository":{"id":184936070,"uuid":"672364678","full_name":"briefercloud/layerform","owner":"briefercloud","description":"Layerform helps engineers create reusable environment stacks using plain .tf files. Ideal for multiple \"staging\" environments.","archived":true,"fork":false,"pushed_at":"2023-12-26T16:48:59.000Z","size":63595,"stargazers_count":1207,"open_issues_count":18,"forks_count":25,"subscribers_count":8,"default_branch":"main","last_synced_at":"2025-09-03T16:05:04.264Z","etag":null,"topics":["dev-environment","developer-tools","devops","platform-engineering","sre","terraform"],"latest_commit_sha":null,"homepage":"https://layerform.dev","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/briefercloud.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2023-07-29T20:29:39.000Z","updated_at":"2025-07-10T11:15:20.000Z","dependencies_parsed_at":"2023-12-26T18:06:56.889Z","dependency_job_id":"8b7f1352-7f3b-43c5-aa6d-ecf5d1000341","html_url":"https://github.com/briefercloud/layerform","commit_stats":null,"previous_names":["ergomake/layerform","briefercloud/layerform"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/briefercloud/layerform","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/briefercloud%2Flayerform","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/briefercloud%2Flayerform/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/briefercloud%2Flayerform/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/briefercloud%2Flayerform/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/briefercloud","download_url":"https://codeload.github.com/briefercloud/layerform/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/briefercloud%2Flayerform/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":275121427,"owners_count":25409032,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-14T02:00:10.474Z","response_time":75,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dev-environment","developer-tools","devops","platform-engineering","sre","terraform"],"created_at":"2024-08-01T00:01:14.365Z","updated_at":"2025-09-30T04:31:58.325Z","avatar_url":"https://github.com/briefercloud.png","language":"Go","readme":"\u003cp align=\"center\"\u003e\u003cstrong\u003eLayerform is not actively maintained anymore. Ergomake is now \u003ca href=\"https://briefer.cloud\"\u003eBriefer\u003c/a\u003e.\u003c/strong\u003e\u003c/p\u003e\n\n---\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://layerform.dev\"\u003e\n    \u003cpicture\u003e\n      \u003csource width=\"320px\" media=\"(prefers-color-scheme: dark)\" srcset=\"./assets/img/layerformspawn-dark-sm.png\"\u003e\n      \u003csource width=\"320px\" media=\"(prefers-color-scheme: light)\" srcset=\"./assets/img/layerformspawn-light-sm.png\"\u003e\n      \u003cimg width=\"320px\" alt=\"layerform logo\" src=\"./assets/img/layerformspawn-light-sm.png\"\u003e\n    \u003c/picture\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\n\u003ch1 align=\"center\"\u003e\n  Layerform\n\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003e\n    \u003cstrong\u003e\n        Layerform helps engineers create reusable environment stacks using plain `.tf` files.\n    \u003c/strong\u003e\n\u003c/p\u003e\n\n\u003cbr\u003e\n\n\u003ch4 align=\"center\"\u003e\n  \u003ca href=\"https://layerform.dev\"\u003eHome Page\u003c/a\u003e |\n  \u003ca href=\"https://docs.layerform.dev\"\u003eDocumentation\u003c/a\u003e |\n  \u003ca href=\"https://discord.gg/daGzchUGDt\"\u003eDiscord\u003c/a\u003e\n\u003c/h4\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/ergomake/layerform/blob/main/LICENSE\"\u003e\n    \u003cimg src=\"https://img.shields.io/github/license/ergomake/layerform\" alt=\"Layerform is released under the GNU GPLv3 license.\" /\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://discord.gg/daGzchUGDt\"\u003e\n    \u003cimg src=\"https://img.shields.io/discord/1055836143733706874\" alt=\"Discord Chat\" /\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://twitter.com/intent/follow?screen_name=GetErgomake\"\u003e\n    \u003cimg src=\"https://img.shields.io/twitter/follow/GetErgomake.svg?label=Follow%20@GetErgomake\" alt=\"Follow @GetErgomake\" /\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\n\u003cbr\u003e\n\n**After HashiCorp's announcement that they're not using the MPL license anymore, we'll be building on top of OpenTF.**\n\n\u003cbr\u003e\n\n## What is Layerform?\n\n**Layerform is a Terraform wrapper that helps engineers build reusable infrastructure using plain Terraform files.**\n\nTo enable reuse, Layerform introduces the concept of _layers_. Each layer contains some infrastructure and can be stacked up on top of another layer.\n\nIn addition to being much easier to use, Layerform allows teams to reuse core-pieces of infrastructure. That way, development infrastructure is much cheaper and quicker to spin up. With Layerform, Engineers only spawn the infrastructure layers they need.\n\n\u003cp align=\"center\"\u003e\n  \u003cpicture\u003e\n    \u003csource width=\"600px\" media=\"(prefers-color-scheme: dark)\" srcset=\"./assets/img/dev-environments-dark.png\"\u003e\n    \u003csource width=\"600px\" media=\"(prefers-color-scheme: light)\" srcset=\"./assets/img/dev-environments.png\"\u003e\n    \u003cimg width=\"600px\" alt=\"layerform logo\" src=\"./assets/img/dev-environments.png\"\u003e\n  \u003c/picture\u003e\n\u003c/p\u003e\n\n\u003e For those wanting development environments: we don't want to run your text-editor. Layerform is the standard tool for development _infrastructure_. You can keep using your text-editors, IDEs, and other local development directly on your machine.\n\n\u003cbr\u003e\n\n## Why use Layerform\n\n\u003cpicture align=\"right\"\u003e\n  \u003csource  align=\"right\" width=\"384px\" media=\"(prefers-color-scheme: dark)\" srcset=\"./assets/img/crocodile-spawn-dark.png\"\u003e\n  \u003csource align=\"right\" width=\"384px\" media=\"(prefers-color-scheme: light)\" srcset=\"./assets/img/crocodile-spawn.png\"\u003e\n  \u003cimg align=\"right\" width=\"384px\" alt=\"layerform logo\" src=\"./assets/img/crocodile-spawn.png\"\u003e\n\u003c/picture\u003e\n\n### Cheaper and quicker development infrastructure\n\nLayerform is much cheaper and quicker than spinning up an entire `staging` environment for each engineer.\n\nWhen using Layerform, engineers can share the same core-pieces of infrastructure, and only spin up the layers they need on top of it.\n\nFor example, if you run applications in a Kubernetes cluster, you don't have to create a brand new cluster for each engineer's environment. Instead, you can reuse the same cluster and have multiple engineers spin up their applications on top of it.\n\n\u003cbr\u003e\n\n### It's just like production, every time\n\nLayerform's environments are just like production because they are spun up from plain `.tf` files.\n\nWhatever you can set up using a ` .tf` file, you can set up in a Layerform layer.\n\nThat way, **your development infrastructure will be just like production, including Lambdas, DynamoDB instances, and whatever else that you need**.\n\n\u003cbr\u003e\n\n### You own the infrastructure and permissions\n\nLayerform runs in _your_ infrastructure. Layerform will store state and spin up resources in _your_ cloud providers. Therefore, you have full control over who gets access to what, and what resources are currently running, and how much they cost.\n\n\u003cbr\u003e\n\n### Encapsulation / Isolation of concerns\n\nBy breaking infrastructure into layers, your organization can define clearer boundaries between teams. Consequently, it will be easier to [mirror your organization's structure into your system's structure](https://martinfowler.com/bliki/ConwaysLaw.html).\n\n\u003cp align=\"center\"\u003e\n  \u003cpicture\u003e\n    \u003csource width=\"600px\" media=\"(prefers-color-scheme: dark)\" srcset=\"./assets/img/layers-vs-org-dark.png\"\u003e\n    \u003csource width=\"600px\" media=\"(prefers-color-scheme: light)\" srcset=\"./assets/img/layers-vs-org.png\"\u003e\n    \u003cimg width=\"600px\" alt=\"layerform logo\" src=\"./assets/img/layers-vs-org.png\"\u003e\n  \u003c/picture\u003e\n\u003c/p\u003e\n\n\u003cbr\u003e\n\n### Cost attribution and cost savings\n\nIn addition to saving costs by reusing infrastructure, Layerform allows you to automatically track costs for each layer instance.\n\nWhen applying layers, Layerform will automatically tag the resources it creates with the actual name assigned to the layer instance. If you have `production` and `development` base layers, for example, each of those two will contain the tags `layerform_layer_name` and `layerform_layer_instance` with their respective names.\n\nThat way, Layerform can recursively traverse layers' resources to collect cost management information. Consequently, it will be able to tell the cost of your whole `production` and `development` layers, as well as an aggregate cost report of everything on top of those layers.\n\n\u003cbr\u003e\n\n## Getting started\n\nFirst, install the Layerform CLI.\n\n```\n$ go install github.com/ergomake/layerform@latest\n```\n\nThen, create the Terraform files you'll use to create each layer of infrastructure. In the example below, we have two layers: `eks`, which is the \"base\" layer, and `services`.\n\n```\nlayerform/\n├─ services/\n│ ├─ pods.tf\n│ ├─ outputs.tf\n│ └─ inputs.tf\n├─ eks/\n│ ├─ eks.tf\n│ ├─ vpc.tf\n│ ├─ inputs.tf\n│ └─ outputs.tf\n├─ services.tf\n└─ eks.tf\n```\n\nOnce you have your infrastructure defined as code, you'll create the layer definitions that the CLI will use when spawning instances of each layer.\n\n```json\n{\n    \"layers\": [\n        {\n            \"name\": \"base\",\n            \"files\": [\"./layerform/eks.tf\", \"./layerform/eks/**\"]\n        },\n        {\n            \"name\": \"services\",\n            \"files\": [\"./layerform/services.tf\", \"./layerform/services/**\"],\n            \"dependencies\": [\"base\"]\n        }\n    ]\n}\n```\n\nNow, configure the place in which the generated layer definitions will be saved.\n\n```yaml\n# In config inside ~/.layerform\ncurrentContext: remote-context\ncontexts:\n    remote-context:\n        type: s3\n        bucket: layerform-bucket-example\n```\n\nFinally, you should provision S3 with your layer definitions using `layerform configure`.\n\nThe Layerform CLI will then take care of creating unique IDs for each layer and sending the Terraform files' contents to the Layerform back-end, which, in this case, is an S3 bucket.\n\nAfter provisioning layer definitions, you can use `layerform spawn \u003cdefinition_name\u003e \u003cdesired_id\u003e` to create an instance of that particular layer.\n\n```\n$ layerform spawn services my-dev-infra\n```\n\nEach instance of a layer contains all the pieces of infrastructure defined within that layer's files.\n\n\u003cp align=\"center\"\u003e\n  \u003cpicture\u003e\n    \u003csource width=\"500px\" media=\"(prefers-color-scheme: dark)\" srcset=\"./assets/img/default-base-layer-dark.png\"\u003e\n    \u003csource width=\"500px\" media=\"(prefers-color-scheme: light)\" srcset=\"./assets/img/default-base-layer.png\"\u003e\n    \u003cimg width=\"500px\" alt=\"layerform logo\" src=\"./assets/img/default-base-layer.png\"\u003e\n  \u003c/picture\u003e\n\u003c/p\u003e\n\nIn this example, running that command will cause Layerform to also create an instance of the underlying `eks` layer and assign it the ID `default`.\n\nTo spawn yet another `services` layer, just run `layerform spawn services another-dev-infra`. By default, Layerform will try to use underlying layers whose ID is `default` as base layers.\n\n\u003cp align=\"center\"\u003e\n  \u003cpicture\u003e\n    \u003csource width=\"600px\" media=\"(prefers-color-scheme: dark)\" srcset=\"./assets/img/multiple-top-layers-dark.png\"\u003e\n    \u003csource width=\"600px\" media=\"(prefers-color-scheme: light)\" srcset=\"./assets/img/multiple-top-layers.png\"\u003e\n    \u003cimg width=\"600px\" alt=\"layerform logo\" src=\"./assets/img/multiple-top-layers.png\"\u003e\n  \u003c/picture\u003e\n\u003c/p\u003e\n\nAs a general rule, underlying layers are always the ones whose ID is `default`. To specify the desired ID for each underlying layer, you'll have to use the `--base` parameter. For example:\n\n```\n# Creates:\n# 1. An eks layer with ID \"one\"\n# 2. A services layer with ID \"two\"\n\n$ layerform spawn services two --base \"eks=one\"\n```\n\n\u003cp align=\"center\"\u003e\n  \u003cpicture\u003e\n    \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"./assets/img/one-two-layers-dark.png\"\u003e\n    \u003csource media=\"(prefers-color-scheme: light)\" srcset=\"./assets/img/one-two-layers.png\"\u003e\n    \u003cimg alt=\"layerform logo\" src=\"./assets/img/one-two-layers.png\"\u003e\n  \u003c/picture\u003e\n\u003c/p\u003e\n\n\u003cbr\u003e\n\n## Layer immutability and layer rebasing\n\nA layer can only mutate itself or the layers above. For example, if you have a `base` layer and a `backend` layer, the `backend` layer's Terraform files will _not_ be able to mutate any infrastructure in a `base` layer instance. Still, the `base` layer files can mutate any instances of the layers above it.\n\nThe way Layerform prevents undesirable mutations is by analyzing each `terraform plan` and detecting whether any mutation's target belongs to an underlying layer.\n\nThe reason Layerform prevents a layer from mutating its underlying layer is to avoid breaking sibling pieces of infrastructure.\n\nThis design allows for platform teams to \"rebase\" layer instances on top of theirs. For example, assume you have multiple application layers on top of a Kubernetes cluster belonging to a `base` layer. In that case, if the platform team wants to update the Kubernetes version and needs to patch existing application's manifests, they can do so from their own layer by referencing and patching other Terraform resources.\n\nOn the other hand, product engineers on the layers above cannot modify the `base` layer containing the Kubernetes cluster. Otherwise, they could break everyone else's applications.\n\nIn addition to preventing failures, immutability defines clearer communication interfaces between teams and helps organizations avoid lots of lateral channels.\n\n\u003cbr\u003e\n\n## How Layerform works\n\nLayerform has two major components. The Layerform Back-end, and Layerform CLI.\n\n\u003cp align=\"center\"\u003e\n  \u003cpicture\u003e\n    \u003csource width=\"700px\" media=\"(prefers-color-scheme: dark)\" srcset=\"./assets/img/all-components-dark.png\"\u003e\n    \u003csource width=\"700px\" media=\"(prefers-color-scheme: light)\" srcset=\"./assets/img/all-components.png\"\u003e\n    \u003cimg width=\"700px\" alt=\"layerform logo\" src=\"./assets/img/all-components.png\"\u003e\n  \u003c/picture\u003e\n\u003c/p\u003e\n\nThe Layerform CLI is used to provision the Layerform Back-end with all the metadata for each layer, like its name and dependencies, and all the Terraform files associated with that layer.\n\nThe Layerform Back-end stores the data for each layer definition and stores the state for each instance of each layer so that new layers know which base state to use.\n\n\u003e There can be multiple types of back-ends. The most common types of back-end are `local`, for storing data locally, and `s3`, for storing data on the cloud, in an S3 bucket.\n\nFinally, the Layerform CLI also talks to the Layerform Back-end to fetch the files for the layer it wants to apply, and the state for the underlying layer.\n\nThe way the Layerform CLI creates new layers on top of the correct existing layers is by injecting the underlying layer's state when applying each layer.\n\n\u003cbr\u003e\n\n## Layerform design philosophy\n\n\u003cpicture\u003e\n  \u003csource align=\"right\" width=\"384px\" media=\"(prefers-color-scheme: dark)\" srcset=\"./assets/img/bear-spawn-dark.png\"\u003e\n  \u003csource align=\"right\" width=\"384px\" media=\"(prefers-color-scheme: light)\" srcset=\"./assets/img/bear-spawn.png\"\u003e\n  \u003cimg align=\"right\" width=\"384px\" alt=\"layerform logo\" src=\"./assets/img/bear-spawn.png\"\u003e\n\u003c/picture\u003e\n\nOur main goal with Layerform was to make it as easy as possible for engineers to create and share different parts of their infrastructure. That way, we'd empower teams to create their own environments without burdening their organization with unnecessary costs or complex configuration files.\n\nWhen developing Layerform, we also determined it should support virtually _any_ type of infrastructure, including infrastructure for serverless applications. That's why we decided to create a wrapper on top of a community fork of Terraform, which supports Kubernetes/Helm, and already has established providers for all major public clouds.\n\nThird, we decided Layerform should be simple and intuitive. Engineers shouldn't have to learn new proprietary languages or configuration formats to use Layerform. Whenever possible, we should allow them to reuse their existing configurations. Layerform concepts are the only thing engineers will need to learn about. Everything else should be \"just Terraform\".\n\nFinally, we decided Layerform needs to be open and free. It's for that reason we're using a GPL license for the wrapper and using a community-maintained fork. That's also why you don't necessarily need to pay for anything before you can extract value from Layerform.\n\nFor the sake of transparency, the way we intend to make money in the future is by providing a managed service with governance, management, and cost-control features.\n\nIf you wish to bundle the Layerform wrapper itself, the GPL license will take care of ensuring ourselves and the community gets value back.\n\n\u003cbr\u003e\n\n## Usage telemetry\n\nAs of 22nd of August, 2023, we've introduced telemetry to the CLI so we can understand how engineers are using the product and improve it accordingly.\n\nTo _disable_ telemetry, set the `LF_TELEMETRY_DISABLED` environment variable to `1`.\n\n\u003cbr\u003e\n\n## Issues \u0026 Support\n\nYou can find Layerform's users and maintainers in [GitHub Discussions](https://github.com/ergomake/layerform/discussions). There you can ask how to set up Layerform, ask us about the roadmap, and discuss any other related topics.\n\nYou can also reach us directly (and more quickly) on our [Discord server](https://discord.gg/daGzchUGDt).\n\n\u003cbr\u003e\n\n## Other channels\n\n-   [Issue Tracker](https://github.com/ergomake/layerform/issues)\n-   [Twitter](https://twitter.com/GetErgomake)\n-   [LinkedIn](https://www.linkedin.com/company/layerform)\n-   [Ergomake Engineering Blog](https://ergomake.dev/blog)\n\n\u003cbr\u003e\n\n## License\n\nLayerform is open-source.\n\nLicensed under the [GNU GPLv3 License](https://github.com/layerform/layerform/blob/main/LICENSE).\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"./assets/img/lgtm-gnu.png\" alt=\"\" width=\"384px\"\u003e\n\u003c/p\u003e\n\nLayerform is not associated with Terraform. Terraform is a registered trademark of HashiCorp, Inc.\n","funding_links":[],"categories":["Go","Tools","terraform"],"sub_categories":["Community providers"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbriefercloud%2Flayerform","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbriefercloud%2Flayerform","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbriefercloud%2Flayerform/lists"}