---
name: "poundctl.tmpl"
section: "5"
platform: "linux"
package: "pound"
version: "4.16-3"
release: "Debian 13 (Trixie)"
platforms: ["linux"]
url: "https://new.carta.tech/poundctl.tmpl"
---

# poundctl.tmpl(5)

templates for poundctl.

## NAME

poundctl.tmpl - templates for poundctl.

## DESCRIPTION

The syntax of **poundctl** templates is modelled after and mostly conforming to the specifications of the golang template module (https://pkg.go.dev/text/template).

Templates are executed by applying them to a JSON object.  Annotations in a template refer to attributes of the object to control execution and derive values to be displayed.  Execution of the template walks the structure and sets the cursor, represented by a period (called *dot*), to the value at the current location in the object as execution proceeds.

The input text for a template is as ASCII text is arbitrary format. *Actions* -- data evaluations or control structures -- are delimited by **{{** and **}}**; all text outside actions is copied to the output verbatim.

To aid in formatting template source code, if **{{** is followed immediately by a minus sign and white space, all trailing white space is trimmed from the immediately preceding text.  Similarly, if **}}** is preceded by white space and a minus sign, all leading white space is trimmed from the immediately following text.  Notice that the presence of the whitespace in these trim markers is mandatory: "{{- 3}}" trims the immediately preceding text and outputs "3", while "{{-3}}" parses as an action containing the number -3.

### Actions

Here is the list of actions. *Arguments* and *pipelines* are evaluations of data, defined in detail in the corresponding sections that follow.

- **{{ }}**

  Empty action is discarded.  It may be useful to trim the preceding or following whitespace, as in **{{- -}} .**

- **{{/\* a comment \*/}}**

  Comments are discarded.  They may span multiple lines of text. Comments do not nest and must start immediately after the opening delimiter (with optional dash and whitespace in between).  A comment may be followed by any action described below.

-

  Comments may be used to control trailing and leading whitespace as well:

-

  ```
  {{- a comment trimming the surrounding whitespace -}}
  ```

- **{{***pipeline***}}**

  *Pipeline* is evaluated, and the default textual representation of its value is copied to the output.

- **{{if** *pipeline***}}** *T1* **{{end}}**

  If the value of the *pipeline* is empty, no output is generated; otherwise, *T1* is executed.  The empty values are **null**, **false**, numeric **0**, empty string (**""**), array (**\[\]**), or object (**{}**).	 Dot is unaffected.

- **{{if** *pipeline***}}** *T1* **{{else}}** *T0* **{{end}}**

  If the value of the pipeline is empty, *T0* is executed; otherwise, *T1* is executed. Dot is unaffected.

- **{{if** *pipeline***}}** *T1* **{{else if** *pipeline***}}** *T2* **{{else}}** *T0* **{{end}}**

  A shortcut to simplify writing the if-else chains.  Equivalent to (newlines added for readability):

-

  ```
  {{if pipeline }}
    T1
  {{else -}}
   {{if pipeline }}
     T2
   {{else}}
     T0
   {{end}}
  {{end}}
  ```

- **{{range** *pipeline***}}** *T1* **{{end}}**

  The value of *pipeline* must be an object or array.  If it is of length zero, nothing is output.  Otherwise, dot is set to the successive elements of the array or object and *T1* is executed.  For objects, the elements will be	visited in sorted key order.

- **{{range** *pipeline***}}** *T1* **{{else}}** *T0* **{{end}}**

  Same as above, except that if the value of the *pipeline* is of length zero, *T0* is executed with dot unaffected.

-

  Within the **{{range}}** action, the following two keywords may appear:

- **{{break}}**

  The innermost **{{range** *pipeline***}}** loop is ended early, stopping the current iteration and bypassing all remaining iterations.

- **{{continue}}**

  The current iteration of the innermost **{{range** *pipeline***}}** loop is stopped, and the loop starts the next iteration.

- **{{define "***name***"}}** *text* **{{end}}**

  The *text* is collected and stored for the further use as template with the given *name*.  It can be invoked using the **{{template}}** action (see below).

- **{{template "***name***"}}**

  The template with the specified *name* (see the **{{define}}** **above) is executed with dot set to null**.

- **{{template "***name***"** *value***}}**

  The template with the specified *name* (see the **{{define}}** **above) is executed with dot set to** *value*.

- **{{block "***name***"** *pipeline***}}** *T1* **{{end}}**

  A block is shorthand for defining a template

-

  ```
  {{define "name"}} T1 {{end}}
  ```

-

  and then executing it in place

-

  ```
  {{template "name" pipeline}}
  ```

- **{{with** *pipeline***}}** *T1* **{{end}}**

  If the value of the *pipeline* is empty, no output is generated; otherwise, dot is set to the value of the *pipeline* and *T1* is executed.

- **{{with** *pipeline***}}** *T1* **{{else}}** *T0* **{{end}}**

  Same as above, but if the value of the *pipeline* is empty, *T0* is executed with dot unchanged.

### Arguments

An *argument* is a simple value, i.e. any of the following:

- Numeric value (integer or floating point)

  - Boolean value: **true** or **false**.

  - Quoted string.

  - A dot (**.**)

  This represents the cursor value.

- Attribute: **.***Attr*

  This is the value of the attribute *Attr* in the current value (dot).

-

  Attribute references can be nested, as in **.***Attr***.***Xattr***.***Yattr*.

- A variable reference: **$***var*.

  Here, *var* is the name of the variable defined in the **range** action.  See the subsection **Variables**, below.

- Function call in parentheses, for grouping.

  ### Pipelines

A *pipeline* is a series of one or more *commands* delimited by pipe sign (**\|**).  Each *command* is either an argument or a *function call*, in form:

```
func arg1 arg2...
```

where *func* is the name of one of the built-in functions discussed below.

Pipelines are executed from left to right, with the result of the previous command implicitly added to the list of arguments of each subsequent command.  For example, the pipeline

```
.attr | eq $x
```

is equivalent to

```
eq $x .attr
```

i.e. it calls the built-in function **eq** with two arguments: the value of the variable **x** and attribute **attr** of the cursor value.

The following built-in functions are defined:

- **and** *A1 A2*

  Evaluates to *true* if pipelines *A1* and *A2* both evaluate to *true*.  Notice, that there is no boolean shortcut evaluation: both pipelines are evaluated prior to calling **and**.

- **or** *A1 A2*

  Evaluates to *true* if at least one of the pipelines *A1* and *A2* evaluates to *true*.  Notice, that there is no boolean shortcut evaluation: both pipelines are evaluated prior to calling **or**.

- **index** *A1 A2...*

  Returns the result of indexing its first argument by the following arguments.  Thus, if **.** is an array, then:

-

  ```
  index . 5
  ```

-

  evaluates to its fifth element (**.\[5\]**).

- **len** *A1*

  Returns the integer length of its argument.

- **not** *A1*

  Returns *true* if its argument evaluates to *false*.

- **eq** *A1 A2*

  Returns *true* if both its arguments are equal.  This applies only if both *A1* and *A2* are numeric or if they both are strings.

- **ne** *A1 A2*

  Returns *true* if its arguments (both must be numeric or strings) are not equal.

- **lt** *A1 A2*

  Returns *true* if *A1* is numerically less than *A2*.

- **le** *A1 A2*

  Returns *true* if *A1* is numerically less than or equal to *A2*.

- **gt** *A1 A2*

  Returns *true* if *A1* is numerically greater than *A2*.

- **ge** *A1 A2*

  Returns *true* if *A1* is numerically greater than or equal to *A2*.

- **even** *A1*

  Returns *true* if **A1**, which must evaluate to an integer value, is divisible by 2.

- **printf** *FMT* *A1*...

  Implements the [**printf**(3)](/printf/3.md) function.  *FMT* must evaluate to a string.  Rest of arguments is interpreted according to the conversion specifications in *FMT*.  The result is a formatted string.

-

  In addition to the standard conversion specifications described in [**printf**(3)](/printf/3.md), the "%v" specifier is implemented: it formats its argument in the best way, depending on its actual type.

- **typeof** *A1*

  Evaluates to the type of its argument, one of: **null**, **bool**, **number**, **integer**, **string**, **array**, **object**.

- **exists** *A1 A2*

  **A1** must evaluate to an object and **A2** to string.  The function evaluates to **true** if the attribute *A2* is present in *A1*.

- **add** *A1 A2*...

  Returns the sum of its arguments.

- **sub** *A1 A2*

  Returns the difference *A1* - *A2*.

- **mul** *A1 A2*

  Multiplies *A1* by *A2*.

- **div** *A1 A2*

  Divides *A1* by *A2*.

### Variables

Variables (referred to as **$***name*) can be defined in **range** and **with** actions.  For **range**, the syntax is:

```
{{range $index, $element = pipeline}} T1 {{end}}
```

where *index* and *element* are arbitrary variable names. When executing this action, during each iteration *$index* and *$element* are set to the index (attribute name) and value of each successive element.  Dot remains unaffected.

For **with**, the syntax is:

```
{{with $var = pipeline}} T1 {{end}}
```

*Pipeline* is evaluated, its result is assigned to *$var* and the *T1* block is executed with dot unchanged.

A variable's scope extends to the **end** action of the control structure (**with** or **range**) in which it is declared.  This includes any nested statements that may appear in between.

## INPUT OBJECT

Depending on the request issued by **poundctl**, the invoked template can receive as its argument (*dot*) an object of the following types: full listing, listener, service, or backend.

Since there is no explicit indication of the object type being passed, templates normally use heuristics based on the presence or absence of certain attribute to deduce the object type in question.  The recommended approach is described in the following pseudo-code fragment:

```
{{if exists . "listeners" }}
  {{/* This is a full listing, as requested by poundctl list. */}}
  ...
{{else if exists . "services"}}
  {{/* Single listener, as requested by poundctl list /L.
       Notice that this attribute is present in the full listing as
       well, so presence of "listeners" should be checked first. */}}
  ...
{{else if exists . "backends"}}
  {{/* Single service, as requested by poundctl list /L/S. */}}
  ...
{{else}}
  {{/* Backend listing (poundctl list /L/S/B) */}}
  ...
{{end}}
```

Structures of each object are discussed in subsections that follow.

### Full listing

A full listing contains the following attributes:

- **listeners**

  An array of *listener* objects.  See below for a description.

- **services**

  An array of *service* objects, representing services defined in the global scope of the **pound** configuration file.

- **pid**

  PID of the running **pound** daemon.

- **version**

  **Pound** version number (string).

- **workers**

  Workers statistics.  This is a JSON object with the following attributes:

  - **active**

    Number of active threads.

  - **count**

    Number of threads currently running.

  - **max**

    Maximum number of threads.

  - **min**

    Minimum number of threads.

  - **timeout**

    Thread idle timeout.

- **queue\_len**

  Number of incoming HTTP requests in the queue (integer).

- **timestamp**

  Current time on the server, formatted as ISO 8601 date-time with microsecond precision, e.g.: "2023-01-05T22:43:18.071559".

### Listener

A *listener* object represents a single HTTP or HTTPS listener in **pound** configuration.  It has the following attributes:

- **address**

  **String**. Address of this listener.  A string formatted as "*IP***:***PORT*" for IPv4 and IPv6 addresses or containing socket file name, for UNIX sockets.

- **protocol**

  **String**. Protocol used: either **http** or **https**.

- **services**

  Array of *service* objects representing services defined in this listener.  See below for the definition of a *service* object.

- **enabled**

  **Boolean**. Whether this listener is enabled or not.

- **nohttps11**

  **Integer**. Value of the **NoHTTPS11** configuration statement for this listener.  One of: 0, 1, 2.

### Service

A *service* object describes a single service.

- **name**

  **String**. Symbolic name of this service.

- **enabled**

  **Boolean**. Whether this service is enabled or not.

- **session\_type**

  **String**. Name of the session handling algorithm for this service.  One of: **IP**, **BASIC**, **URL**, **PARM**, **COOKIE**, **HEADER**.

- **sessions**

  List of active sessions in this service.  Each session is represented as object with the following attributes:

  - **key**

    **String**. Session key.

  - **backend**

    **Integer**. Number of the backend assigned to handle requests with this session.

  - **expire**

    **Timestamp**. Expiration time of this session, with microsecond precision.

- **backends**

  List of *backend*s defined for this service.

- **emergency**

  Emergency *backend* object, or **null** if no such backend is defined.

### Backend

The following attributes are always present in each *backend* object:

- **alive**

  **Boolean**. Whether or not this backend is alive.

- **conn\_to**

  **Integer**. Connection timeout for this backend (seconds).

- **enabled**

  **Boolean**. Whether or not this backend is enabled.

- **io\_to**

  **Integer**. I/O timeout for this backend (seconds).

- **priority**

  **Integer** in range 0-9. Priority value assigned to this backend.

- **protocol**

  **String**. Protocol used by this backend: either **http** or **https**.

- **type**

  **String**. Backend type.  One of: **acme**, **backend**, **control**, **redirect**.

- **ws\_to**

  **Integer** Websocket timeout (seconds).

Depending on the backend type, the following attributes may be present:

- **acme**

  - **path**

    **String**. Directory where ACME challenges are stored.

- **backend**

  - **address**

    **String**. Backend address.

- **redirect**

  - **url**

    **String**. URL to redirect to.

  - **code**

    **Integer**. HTTP code for redirection responses.  One of: 301, 302, 307.

  - **redir\_req**

    **Boolean**. Whether to append the original request path to the resulting location.

If backend statistics is enabled (see **BackendStats** in [**pound**(8)](/pound/8.md)), the **stats** object will be present, with the following attributes:

- **request\_count**

  Total number of requests processed by this backend.

- **request\_time\_avg**

  Average time per request, in nanoseconds.

- **request\_time\_stddev**

  Standard deviation of the above.

## SEE ALSO

[**pound**(8)](/pound/8.md), [**poundctl**(8)](/poundctl/8.md).

## REPORTING BUGS

Report bugs to \<gray@gnu.org\>.  You may also use github issue tracker at https://github.com/graygnuorg/pound/issues.

## COPYRIGHT

Copyright © 2023-2025 Sergey Poznyakoff

License GPLv3+: GNU GPL version 3 or later \<http://gnu.org/licenses/gpl.html\>

This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law.
