CLI tool
hashicorp/consul-template avatar
hashicorp/consul-template

consul-template: rendering Consul and Vault data into files, and when that is the wrong tool

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

4,824 stars801 forksGoMPL-2.0

At a glance

What is it?
consul-template watches Consul, Vault or Nomad and rewrites files on disk plus optional reload commands. It fits config files that must track service discovery, not application code that can call an API.
Who is it for?
Adopt consul-template when a file on disk has to follow Consul or Vault state and the process that reads it only reloads on a signal, which is the nginx and haproxy case the examples folder is built around. Do not adopt it for per-request configuration or for data an application can fetch from the Consul HTTP API itself; the daemon writes files, it does not serve them.
Can I use it commercially?
Yes, with conditions. MPL-2.0 is a weak copyleft licence: you can use it inside commercial and closed-source software, but if you distribute changes to its own files, you must publish those changes under the same licence.
Is it still maintained?
Yes. The repository last received commits 3 days ago.
What is it written in?
Mainly Go, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What consul-template does that a Consul client library does not

Consul holds service registrations, health check results and a key-value store. Vault holds secrets. Nomad holds job and service information. A program can read all of that over an HTTP API, and most programs should. consul-template exists for the programs that cannot: nginx, haproxy, varnish, and anything else configured by a file that is read at startup and re-read when it receives a signal. The README states the daemon "queries a Consul, Vault, or Nomad cluster and updates any number of specified templates on the file system", and can "optionally run arbitrary commands when the update process completes". That second clause is the whole design in one sentence. The tool is a loop: watch a data source, render a file, run a command. The audience is operators who manage load balancers and reverse proxies, not application developers. If your service can import a Consul client and watch for changes in process, consul-template adds a file, a daemon and a restart path you do not need.

The watch, render, reload loop and its configuration model

The repository layout shows the split: watch/ holds the watchers for Consul, Vault and Nomad, template/ holds the templating engine and its functions, renderer/ writes output, manager/ coordinates, and config/ parses settings. A template is a text file with actions in double braces. The README's quick example uses a key lookup, and the templating language documents API functions, Scratch, helper functions and math functions, with Sprig v3 among the dependencies in go.mod, so the helper set is not limited to what HashiCorp wrote.

Configuration is deliberately not hot-reloaded. The README explains that on start consul-template reads configuration files and templates from disk into memory, and that from then on "changes to the files on disk do not propagate to running process without a reload". Reload is triggered by SIGHUP, and the stated reason is pre-flight validation: an operator may want to check a template before it goes live, or update configuration and templates together. That is a defensible choice and an operational cost. Every template edit becomes a two-step action: write the file, send HUP. Config file syntax is documented in docs/configuration.md, which the README links for both the file format and the command line flags.

Installing consul-template and rendering a first file

The README gives three install steps: download a pre-compiled release from the Consul Template releases page, extract it with unzip or tar, and move the binary into $PATH. Building from source is delegated to the contributing section. The quick example assumes a local Consul. Start an agent in dev mode first.

bash
consul agent -dev

Author a template named in.tpl that reads a key from the KV store. The README shows exactly this body.

liquid
{{ key "foo" }}

Run consul-template against that template with -once, which renders and exits rather than staying resident.

bash
consul-template -template "in.tpl:out.txt" -once

Write a value into Consul, then read the file consul-template produced.

bash
consul kv put foo bar
cat out.txt

The README states the file contains bar. Drop -once when you want the daemon to keep watching; the same -template flag then re-renders out.txt whenever the key changes. The README points to the examples folder for nginx, haproxy, varnish, Vault PKI and Vault transit scenarios, and to HashiCorp Learn guides for Consul KV, the Consul catalog and Vault Agent templates.

File permissions and the Docker image are the first failure mode

The Docker section of the README is unusually blunt about a trap. The Alpine image supports an external volume for rendered templates, and if you mount one, "you will need to make sure that the consul-template user in the docker image has write permissions to the directory". The image creates that user with "a UID of 100 and a GID of 1000", and the Dockerfile confirms the defaults: ARG UID=100, ARG GID=1000, an adduser call, and USER ${BIN_NAME}:${BIN_NAME} before CMD. Two in-image directories are named: /consul-template/config, used to add configuration when the image is a parent, and /consul-template/data, exported as a VOLUME.

The practical consequence is that a host directory owned by root, or by a user with a different numeric ID, will fail to render. This is not a bug to report; it is the cost of running the daemon as a non-root user, which is the right default. Plan the ownership of the output directory before the first deploy, not after the first permission denied in the logs. The README also notes that this affects images you build yourself from these as a base.

Where consul-template is the wrong tool

Three cases stand out. First, per-request data. consul-template writes files and runs commands; it does not answer queries. If a service needs the current healthy instances of a dependency on every request, it should query Consul directly or use a client library, because a rendered file is a snapshot taken at render time.

Second, secrets that must never touch disk. Vault templates are a documented use case, and the examples folder includes vault-pki and vault-transit, but the output is a file on the filesystem. Vault Agent templates exist as a separate path, and the README links to Vault's own agent template documentation rather than claiming consul-template is the only option. If your threat model forbids secrets in files, this is the wrong layer.

Third, environments where a reload command is not safe. The daemon's value comes from the command it runs after rendering, and the README's commands section covers environment and multiple commands. If the consuming process cannot reload without dropping connections, or has no signal handler, consul-template will faithfully write a file that nothing reads until the next restart, and you have added a daemon for no benefit. The caveats section also covers termination on error and dots in service names, which are worth reading before you template a service name that contains a dot.

How it compares with Vault Agent templates and a plain Consul client

The closest alternative for secrets is Vault Agent's own template stanza, which the README links under Learn Guides. Both render templates and both can run commands. The difference is scope and identity: Vault Agent is a Vault client that also renders templates, with Vault's auto-auth and sink mechanisms, while consul-template is a multi-source renderer that talks to Consul, Vault and Nomad through the API clients listed in go.mod. If every value you need comes from Vault and you already run the agent for authentication, the agent's template stanza avoids a second daemon. If you need Consul service catalog data and Vault secrets in the same file, consul-template is the tool that reaches both.

The other alternative is no daemon at all: have the application read Consul through a client library and reconfigure itself in process. That removes the file, the SIGHUP step and the UID 100 permission problem, and it is the right answer for services you control. consul-template wins where you do not control the consumer, which is exactly the nginx and haproxy territory the examples folder targets.

Licence, release cadence and what upgrading costs

consul-template is licensed MPL-2.0, and the Dockerfile carries the same identifier in its LABEL licenses line and its SPDX header. MPL-2.0 is file-level copyleft: modifications to covered files stay under the licence, while separate files you write generally do not. That is a summary, not legal advice; your counsel decides how it applies to your distribution.

The release history shows v0.43.0 on 2026-09-10, v0.42.1 on 2026-07-08 and v0.42.0 on 2026-04-15, with the last push to main on 2026-09-11. The project is not archived. The upgrade cost is concentrated in one place: the README warns that its documentation corresponds to the main branch and "may contain unreleased features or different APIs" than the released version, and directs readers to the git tag matching their version. So the template functions and configuration keys you read on GitHub may not exist in the binary you downloaded. Pin the release, then read that tag's documentation. The version/ package and the Makefile's version target are what the build system uses to stamp a binary, so `consul-template -version` is the way to confirm what you actually have.

Editorial conclusion

Adopt consul-template when a file on disk has to follow Consul or Vault state and the process that reads it only reloads on a signal, which is the nginx and haproxy case the examples folder is built around. Do not adopt it for per-request configuration or for data an application can fetch from the Consul HTTP API itself; the daemon writes files, it does not serve them. Verify first that the process you plan to restart tolerates a reload command, that the consul-template user can write the target directory (UID 100, GID 1000 in the Docker image), and that the template syntax you copy matches the release you installed, since the README documents main and points readers to the matching git tag.

Frequently asked questions

What is consul-template?

It is a daemon that queries a Consul, Vault or Nomad cluster, renders the results into template files on the filesystem, and can run commands after each update. The README describes it as a convenient way to populate values from Consul into the file system.

What is a consul-template alternative?

For Vault secrets, Vault Agent's own template stanza is the closest option and the README links to Vault's agent template documentation. For applications you control, a Consul client library that watches for changes in process removes the file and the reload step entirely.

How do I install consul-template?

Download a pre-compiled release from the Consul Template releases page, extract it with unzip or tar, and move the binary into $PATH. Compiling from source is covered in the contributing section of the README.

How do I render a template once instead of running the consul-template daemon?

Pass -once together with -template, as in consul-template -template "in.tpl:out.txt" -once. The README's quick example uses this form and shows the rendered value appearing in out.txt.

Does consul-template reload templates when I edit the files on disk?

No. The README states that configuration and templates are read into memory at startup and that later changes do not propagate without a reload. Send SIGHUP to the running process to reload configuration and templates from disk.

What user does the consul-template Docker image run as?

The image creates a consul-template user with UID 100 and GID 1000, and the Dockerfile sets USER to that account before CMD. The README warns that a mounted template volume must be writable by that user.

Official sources

  1. hashicorp/consul-template on GitHub
  2. License: MPL-2.0
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/hashicorp-consul-template.svg)](https://hysenlabs.com/projects/hashicorp-consul-template)