POUNDCTL.TMPL(5)
πΈ NAME πΈ
poundctl.tmpl β templates for poundctl. that's the whole pitch bestie, short and iconic π
π¦ DESCRIPTION π¦
okay so. the syntax of poundctl templates is modelled after β and mostly conforming to β the specs of the golang template module, which lives over at https://pkg.go.dev/text/template. that's the blueprint, that's the lore πβ¨
Templates get executed by applying them to a JSON object. Annotations inside a template refer to attributes of that object, and they're the ones controlling execution and deriving the values that get displayed. When a template executes, it walks the structure and sets the cursor β which is represented by a period, and which we affectionately call dot β to the value at the current location in the object as execution proceeds. dot is literally the main character here, it moves with you the whole time π
The input text for a template is ASCII text in an arbitrary format. Actions β meaning data evaluations or control structures β are delimited by {{ and }}. Everything outside of actions? copied to the output verbatim, no edits, no notes, no cap.
Now for the formatting helper, because we all care about our whitespace π
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.
β οΈ careful bestie: 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. one space is the whole difference between clean output and chaos. iykyk π
β¨ Actions β¨
here's the list of actions, in order, all of them, no skips. Arguments and pipelines are evaluations of data, and they get defined in detail in the sections that follow. π«Ά
{{ }}β an empty action, discarded. lowkey useful for trimming the preceding or following whitespace, as in{{- -}}.{{/* a comment */}}β comments are discarded. they may span multiple lines of text. comments do not nest, and they 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 can be used to control trailing and leading whitespace as well:
{{- a comment trimming the surrounding whitespace -}}
{{pipeline}}β the pipeline gets evaluated, and the default textual representation of its value is copied to the output. simple as that β¨{{if pipeline}} T1 {{end}}β if the value of the pipeline is empty, no output is generated; otherwise T1 is executed. the empty values arenull,false, numeric0, 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. bye bye loop π{{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 further use as a 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 tonull.{{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:
trueorfalse. - 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. so cute, so correct β¨
The following built-in functions are defined:
and A1 A2β evaluates totrueif pipelines A1 and A2 both evaluate to true. notice, that there is no boolean shortcut evaluation: both pipelines are evaluated prior to callingand. no skipping ahead bestie π€or A1 A2β evaluates totrueif 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 callingor.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β returnstrueif its argument evaluates to false.eq A1 A2β returnstrueif both its arguments are equal. this applies only if both A1 and A2 are numeric or if they both are strings.ne A1 A2β returnstrueif its arguments (both must be numeric or strings) are not equal.lt A1 A2β returnstrueif A1 is numerically less than A2.le A1 A2β returnstrueif A1 is numerically less than or equal to A2.gt A1 A2β returnstrueif A1 is numerically greater than A2.ge A1 A2β returnstrueif A1 is numerically greater than or equal to A2.even A1β returnstrueif A1, which must evaluate to an integer value, is divisible by 2.printf FMT A1...β implements theprintf(3)function. FMT must evaluate to a string. the rest of the 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), the "%v" specifier is implemented: it formats its argument in the best way, depending on its actual type. it's giving versatile π
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 totrueif the attribute A2 is present in A1.add A1 A2...β returns the sum of its arguments.sub A1 A2β returns the differenceA1 - 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. keep it in your lane, variable π
INPUT OBJECT π
okay so depending on the request that poundctl issues, the template it invokes can get a dot argument that's one of these types: full listing, listener, service, or backend.
Since there's no explicit "hey this is a whatever object" label, templates usually use heuristics based on whether certain attributes are present or absent to guess the type. The recommended approach is this 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 the subsections below.
Full listing β¨
A full listing contains these 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 thepoundconfiguration file.pidβ PID of the runningpounddaemon.versionβ Pound version number (string).workersβ Workers statistics. This is a JSON object with: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".uptimeβ Uptime of thepounddaemon: number of microseconds elapsed since its startup.
Listener π§
A listener object represents a single HTTP or HTTPS listener in pound configuration. It has:
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: eitherhttporhttps.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 theNoHTTPS11configuration 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 an object with: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 backends defined for this service.emergencyβ Emergency backend object, ornullif no such backend is defined.
Backend π¦
These 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 range0-9. Priority value assigned to this backend.protocolβ String. Protocol used by this backend: eitherhttporhttps.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:
acmepathβ String. Directory where ACME challenges are stored.
backendaddressβ String. Backend address.
redirecturlβ 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)), the stats object will be present, with:
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 π
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β2026 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.
π that's the whole vibe, bestie! This waspoundβPOUNDCTL.TMPL(5), datedOctober 28, 2025. Go slay those templates. periodt. π
π¦ where this page comes from
- alpine 3.24: pound-doc 4.23-r0 Β· GPL-3.0-or-later
- ubuntu stonking: pound 4.23-2build1 Β· GPL-3.0-or-later
- Copyright (C) 2023-2026 Sergey Poznyakoff
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms