Need help with consul-template?
Click the “chat” button below for chat support from the developer who created it, or find similar developers for support.

About the developer

4.3K Stars 697 Forks Mozilla Public License 2.0 2.1K Commits 123 Opened issues


Template rendering, notifier, and supervisor for @HashiCorp Consul and Vault data.

Services available


Need anything else?

Contributors list

Consul Template

CircleCI Go Documentation

This project provides a convenient way to populate values from Consul into the file system using the


The daemon

queries a Consul or Vault cluster and updates any number of specified templates on the file system. As an added bonus, it can optionally run arbitrary commands when the update process completes. Please see the examples folder for some scenarios where this functionality might prove useful.

The documentation in this README corresponds to the master branch of Consul Template. It may contain unreleased features or different APIs than the most recently released version.

Please see the Git tag that corresponds to your version of Consul Template for the proper documentation.

Table of Contents

Community Support

If you have questions about how consul-template works, its capabilities or anything other than a bug or feature request (use github's issue tracker for those), please see our community support resources.

Community portal:

Other resources:

Additionally, for issues and pull requests, we'll be using the :+1: reactions as a rough voting system to help gauge community priorities. So please add :+1: to any issue or pull request you'd like to see worked on. Thanks.


  1. Download a pre-compiled, released version from the Consul Template releases page.

  2. Extract the binary using

  3. Move the binary into


To compile from source, please see the instructions in the contributing section.

Quick Example

This short example assumes Consul is installed locally.

  1. Start a Consul cluster in dev mode:
  $ consul agent -dev
  1. Author a template
    to query the kv store:
  {{ key "foo" }}
  1. Start Consul Template:
  $ consul-template -template "in.tpl:out.txt" -once
  1. Write data to the key in Consul:
  $ consul kv put foo bar
  1. Observe Consul Template has written the file
  $ cat out.txt

For more examples and use cases, please see the examples folder in this repository.

Learn Guides

In addition to these examples, HashiCorp has published guides and official documentation to help walk through a few common use cases for Consul Template. * Consul KV * Consul Catalog * Vault Agent Templates * Vault Secrets


Configuration documentation has been moved to docs/

Reload Configuration and Templates

While there are multiple ways to run Consul Template, the most common pattern is to run Consul Template as a system service. When Consul Template first starts, it reads any configuration files and templates from disk and loads them into memory. From that point forward, changes to the files on disk do not propagate to running process without a reload.

The reason for this behavior is simple and aligns with other tools like haproxy. A user may want to perform pre-flight validation checks on the configuration or templates before loading them into the process. Additionally, a user may want to update configuration and templates simultaneously. Having Consul Template automatically watch and reload those files on changes is both operationally dangerous and against some of the paradigms of modern infrastructure. Instead, Consul Template listens for the

syscall to trigger a configuration reload. If you update configuration or templates, simply send
to the running Consul Template process and Consul Template will reload all the configurations and templates from disk.

Templating Language

Templating Language documentation has been moved to docs/


Docker Image Use

The Alpine Docker image is configured to support an external volume to render shared templates to. If mounted you will need to make sure that the consul-template user in the docker image has write permissions to the directory. Also if you build your own image using these you need to be sure you have the permissions correct.

The consul-template user in docker has a UID of 100 and a GID of 1000.

This effects the in image directories /consul-template/config, used to add configuration when using this as a parent image, and /consul-template/data, exported as a VOLUME as a location to render shared results.

Previously the image initially ran as root in order to ensure the permissions allowed it. But this ran against docker best practices and security policies.

If you build your own image based on ours you can override these values with


Dots in Service Names

Using dots

in service names will conflict with the use of dots for TAG delineation in the template. Dots already interfere with using DNS for service names, so we recommend avoiding dots wherever possible.

Termination on Error

By default Consul Template is highly fault-tolerant. If Consul is unreachable or a template changes, Consul Template will happily continue running. The only exception to this rule is if the optional

exits non-zero. In this case, Consul Template will also exit non-zero. The reason for this decision is so the user can easily configure something like Upstart or God to manage Consul Template as a service.

If you want Consul Template to continue watching for changes, even if the optional command argument fails, you can append

|| true
to your command. Note that
is a "shell-ism", not a built-in function. You will also need to run your command under a shell:
$ consul-template \
  -template "in.ctmpl:out.file:/bin/bash -c 'service nginx restart || true'"

In this example, even if the Nginx restart command returns non-zero, the overall function will still return an OK exit code; Consul Template will continue to run as a service. Additionally, if you have complex logic for restarting your service, you can intelligently choose when you want Consul Template to exit and when you want it to continue to watch for changes. For these types of complex scripts, we recommend using a custom sh or bash script instead of putting the logic directly in the

command or configuration file.



The current processes environment is used when executing commands with the following additional environment variables:


These environment variables are exported with their current values when the command executes. Other Consul tooling reads these environment variables, providing smooth integration with other Consul tools (like

consul maint
consul lock
). Additionally, exposing these environment variables gives power users the ability to further customize their command script.

Multiple Commands

The command configured for running on template rendering must take one of two forms.

The first is as a single command without spaces in its name and no arguments. This form of command will be called directly by consul-template and is good for any situation. The command can be a shell script or an executable, anything called via a single word, and must be either on the runtime search PATH or the absolute path to the executable. The single word limination is necessary to eliminate any need for parsing the command line. For example..

command = "/opt/foo"
or, if on PATH,
command = "foo"

The second form is as a multi-word command, a command with arguments or a more complex shell command. This form requires a shell named

be on the executable search path (eg. PATH on *nix). This is the standard on all *nix systems and should work out of the box on those systems. This won't work on, for example, Docker images with only the executable and not a minimal system like Alpine. Using this form you can join multiple commands with logical operators,
, use pipelines with
, conditionals, etc. Note that the shell
is normally
on *nix systems and is either a POSIX shell or a shell run in POSIX compatible mode, so it is best to stick to POSIX shell syntax in this command. For example..

command = "/opt/foo && /opt/bar"

command = "if /opt/foo ; then /opt/bar ; fi"

Using this method you can run as many shell commands as you need with whatever logic you need. Though it is suggested that if it gets too long you might want to wrap it in a shell script, deploy and run that.

Multi-phase Execution

Consul Template does an n-pass evaluation of templates, accumulating dependencies on each pass. This is required due to nested dependencies, such as:

{{ range services }}
{{ range service .Name }}
  {{ .Address }}
{{ end }}{{ end }}

During the first pass, Consul Template does not know any of the services in Consul, so it has to perform a query. When those results are returned, the inner-loop is then evaluated with that result, potentially creating more queries and watches.

Because of this implementation, template functions need a default value that is an acceptable parameter to a

function (or similar), but does not actually execute the inner loop (which would cause a panic). This is important to mention because complex templates must account for the "empty" case. For example, the following will not work:
{{ with index (service "foo") 0 }}
# ...
{{ end }}

This will raise an error like:

: error calling index: index out of range: 0

That is because, during the first evaluation of the template, the

key is returning an empty slice. You can account for this in your template like so:
{{ with service "foo" }}
{{ with index . 0 }}
{{ .Node }}{{ end }}{{ end }}

This will still add the dependency to the list of watches, but will not evaluate the inner-if, avoiding the out-of-index error.


Consul Template can print verbose debugging output. To set the log level for Consul Template, use the

$ consul-template -log-level info ...
 [INFO] (cli) received redis from Watcher
 [INFO] (cli) invoking Runner
# ...

You can also specify the level as debug:

$ consul-template -log-level debug ...
 [DEBUG] (cli) creating Runner
 [DEBUG] (cli) creating Consul API client
 [DEBUG] (cli) creating Watcher
 [DEBUG] (cli) looping for data
 [DEBUG] (watcher) starting watch
 [DEBUG] (watcher) all pollers have started, waiting for finish
 [DEBUG] (redis) starting poll
 [DEBUG] (service redis) querying Consul with &{...}
 [DEBUG] (service redis) Consul returned 2 services
 [DEBUG] (redis) writing data to channel
 [DEBUG] (redis) starting poll
 [INFO] (cli) received redis from Watcher
 [INFO] (cli) invoking Runner
 [DEBUG] (service redis) querying Consul with &{...}
# ...


Q: How is this different than confd?
A: The answer is simple: Service Discovery as a first class citizen. You are also encouraged to read this Pull Request on the project for more background information. We think confd is a great project, but Consul Template fills a missing gap. Additionally, Consul Template has first class integration with Vault, making it easy to incorporate secret material like database credentials or API tokens into configuration files.

Q: How is this different than Puppet/Chef/Ansible/Salt?
A: Configuration management tools are designed to be used in unison with Consul Template. Instead of rendering a stale configuration file, use your configuration management software to render a dynamic template that will be populated by Consul.


To build and install Consul-Template locally, you will need to install Go.

Clone the repository:

$ git clone

To compile the

binary for your local machine:
$ make dev

This will compile the

binary into
as well as your
and run the test suite.

If you want to compile a specific binary, set

or run the following to generate all binaries:
$ make build

If you want to run the tests, first install consul and vault locally, then:

$ make test

Or to run a specific test in the suite:

go test ./... -run SomeTestFunction_name

We use cookies. If you continue to browse the site, you agree to the use of cookies. For more information on our use of cookies please see our Privacy Policy.