2014-09-26 23:23:38 +02:00
---
2020-08-15 03:51:06 +02:00
layout: "language"
2019-03-05 21:18:40 +01:00
page_title: "Creating Modules"
2014-09-26 23:23:38 +02:00
sidebar_current: "docs-modules"
2014-10-22 05:21:56 +02:00
description: |-
2019-03-05 21:18:40 +01:00
A module is a container for multiple resources that are used together.
2014-09-26 23:23:38 +02:00
---
2019-03-05 21:18:40 +01:00
# Creating Modules
2014-09-26 23:23:38 +02:00
2020-10-02 20:02:59 +02:00
> **Hands-on:** Try the [Reuse Configuration with Modules](https://learn.hashicorp.com/collections/terraform/modules?utm_source=WEBSITE&utm_medium=WEB_IO&utm_offer=ARTICLE_PAGE&utm_content=DOCS) collection on HashiCorp Learn.
2019-03-05 21:18:40 +01:00
A _module_ is a container for multiple resources that are used together.
Modules can be used to create lightweight abstractions, so that you can
describe your infrastructure in terms of its architecture, rather than
directly in terms of physical objects.
2014-09-26 23:23:38 +02:00
2019-03-05 21:18:40 +01:00
The `.tf` files in your working directory when you run [`terraform plan` ](/docs/commands/plan.html )
or [`terraform apply` ](/docs/commands/apply.html ) together form the _root_
website: Break up main Modules and Module Development pages
This one is a lot like the previous two commits, but slightly more complex:
- Only adding one new meta-argument page, for `providers`; otherwise, it just
re-uses the dual-purpose pages I made in the resources commit.
- About that `providers` argument: The stuff that was relevant to consumers of a
module went in that meta-argument page, but there was also a huge deep dive on
how the _author_ of a re-usable module should handle provider configurations
in cases where inheriting the default providers isn't sufficient. THAT, I
moved into a new page in the module development section. (For the consumer of
a module, this should all be an implementation detail; the module README
should tell you which aliased providers you need to configure and pass, and
then you just do it, without worrying about proxy configuration blocks etc.)
- The "standard module structure" recommendations in the main module development
page gets a page of its own, to make it more prominent and discoverable.
- Same deal with using the old URL as a landing page, at least for the main
module calls page. It didn't seem necessary for the module development page.
2020-11-13 03:21:35 +01:00
module. That module may [call other modules ](/docs/configuration/blocks/modules/syntax.html#calling-a-child-module )
2019-03-05 21:18:40 +01:00
and connect them together by passing output values from one to input values
of another.
2017-04-27 12:27:16 +02:00
website: Break up main Modules and Module Development pages
This one is a lot like the previous two commits, but slightly more complex:
- Only adding one new meta-argument page, for `providers`; otherwise, it just
re-uses the dual-purpose pages I made in the resources commit.
- About that `providers` argument: The stuff that was relevant to consumers of a
module went in that meta-argument page, but there was also a huge deep dive on
how the _author_ of a re-usable module should handle provider configurations
in cases where inheriting the default providers isn't sufficient. THAT, I
moved into a new page in the module development section. (For the consumer of
a module, this should all be an implementation detail; the module README
should tell you which aliased providers you need to configure and pass, and
then you just do it, without worrying about proxy configuration blocks etc.)
- The "standard module structure" recommendations in the main module development
page gets a page of its own, to make it more prominent and discoverable.
- Same deal with using the old URL as a landing page, at least for the main
module calls page. It didn't seem necessary for the module development page.
2020-11-13 03:21:35 +01:00
To learn how to _use_ modules, see [the Modules configuration section ](/docs/configuration/blocks/modules/index.html ).
2019-03-05 21:18:40 +01:00
This section is about _creating_ re-usable modules that other configurations
can include using `module` blocks.
## Module structure
Re-usable modules are defined using all of the same
[configuration language ](/docs/configuration/ ) concepts we use in root modules.
Most commonly, modules use:
* [Input variables ](/docs/configuration/variables.html ) to accept values from
the calling module.
* [Output values ](/docs/configuration/outputs.html ) to return results to the
calling module, which it can then use to populate arguments elsewhere.
2020-11-13 03:30:52 +01:00
* [Resources ](/docs/configuration/blocks/resources/index.html ) to define one or more
2019-03-05 21:18:40 +01:00
infrastructure objects that the module will manage.
To define a module, create a new directory for it and place one or more `.tf`
files inside just as you would do for a root module. Terraform can load modules
either from local relative paths or from remote repositories; if a module will
be re-used by lots of configurations you may wish to place it in its own
version control repository.
Modules can also call other modules using a `module` block, but we recommend
keeping the module tree relatively flat and using [module composition ](./composition.html )
as an alternative to a deeply-nested tree of modules, because this makes
the individual modules easier to re-use in different combinations.
## When to write a module
In principle any combination of resources and other constructs can be factored
out into a module, but over-using modules can make your overall Terraform
configuration harder to understand and maintain, so we recommend moderation.
A good module should raise the level of abstraction by describing a new concept
in your architecture that is constructed from resource types offered by
providers.
For example, `aws_instance` and `aws_elb` are both resource types belonging to
the AWS provider. You might use a module to represent the higher-level concept
"[HashiCorp Consul](https://www.consul.io/) cluster running in AWS" which
happens to be constructed from these and other AWS provider resources.
We _do not_ recommend writing modules that are just thin wrappers around single
other resource types. If you have trouble finding a name for your module that
isn't the same as the main resource type inside it, that may be a sign that
your module is not creating any new abstraction and so the module is
adding unnecessary complexity. Just use the resource type directly in the
calling module instead.