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

# pound(8)

HTTP/HTTPS reverse-proxy and load-balancer

## NAME

pound - HTTP/HTTPS reverse-proxy and load-balancer

## SYNOPSIS

- **pound**

  \[**-FVcehv**\] \[**-W \[no-\]***FEATURE*\] \[**-f** *CONF-FILE*\] \[**-p** *PID-FILE*\]

## DESCRIPTION

**Pound** is a reverse-proxy load balancing server. It accepts requests from HTTP/HTTPS clients and distributes them to one or more Web servers (*backends*). These requests may be passed to backends as plain HTTP or re-encrypted as HTTPS.

If more than one backend server is defined, **pound** chooses one of them randomly, based on the requested balancing algorithm and backend priorities. By default, **pound** keeps track of associations between clients and backend servers (sessions).

## GENERAL PRINCIPLES

In general **pound** needs three types of objects defined in order to function: *listeners*, *services* and *backends*.

- **Listeners**

  A *listener* is a definition of how **pound** receives requests from the clients (browsers). Listeners of two types are supported: regular HTTP listeners and HTTPS listeners.  In the simplest case, a listener must define the address and port to listen on, with additional requirements for HTTPS listeners.

- **Services**

  A *service* routes requests to backends.  Services may be defined within a listener or in global scope.  When a request is received, **pound** attempts to match it to each service in turn, starting with the services defined in the listener itself and, if needed, continuing with those defined at the global level.  Services may define their own conditions as to which requests they can answer: typically this involves certain URLs (images only, or a certain path) or specific headers (such as the Host header).  A service may also define a *session* mechanism: if so, future requests from a given client will always be answered by the same *backend*.

- **Backends**

  *Backends* are the actual servers for the content requested. By itself, **pound** supplies no responses - all contents must be received from a "real" web server.  A *backend* defines how the server should be contacted.

-

  Several types of backends are defined:

  - *Regular backend*

    Regular backends are the most often used type of backends and the *raison d'etre* of **pound**. A regular backend passes received requests to a backend server, waits for it to respond and sends the response back to the requesting client.

  - *Redirect backend*

    A redirect backend responds to each request with a redirect response. See **Redirect**, below.

  - *ACME backend*

    A special backend designed to handle ACME challenges.  Backends of this type are used to handle HTTP-01 authorization when re-issuing *LetsEncrypt* certificates.

  -

    See the **ACME** section below.

  - *Error backend*

    An error backend creates and returns an HTTP status response.

  - *Emergency backend*

    A special case of regular backend which will be used only if all other regular backends fail to respond.

-

  Multiple backends may be defined within a service, in which case **pound** will balance the load between the available backends.

-

  Two types of load-balancing strategies are implemented: random balancing (default), and interleaved weighted round-robin balancing.

-

  If a backend fails to respond, it will be considered "dead", in which case **pound** will stop sending requests to it. Dead *backends* are periodically checked for availability, and once they respond again they are "resurrected" and requests are sent again their way. If no backends are available (none were defined, or all are "dead"), then **pound** will reply with "503 Service Unavailable", without checking additional services.

-

  Normally, the connection between **pound** and its backends is via plain HTTP.  It is, however, possible to use HTTPS as well.

A working **pound** configuration may define multiple listeners and services.  They can be identified either by 0-based ordinal number within the configuration (or, for services, within the listener) or by their symbolic name. Backends are identified by their ordinal number within service.

## REQUEST BALANCING

*Load balancing strategy* defines algorithm used to distribute incoming requests between multiple regular backends.  Each backend is assigned a *priority* -- a positive number indicating its relative weight among other backends. The share of requests a backend handles can be estimated as:

-

  ```
  Pi / S(P),
  ```

where **Pi** is priority of the backend with index **i**, and **S(P)** is sum of all priorities.

Two balancing strategies are implemented:

- **Weighted Random Balancing**

  This is the default strategy.  The backend to use for each request is determined at random taking into account backend priorities, so that backends with numerically greater priorities have proportionally greater chances of being selected than the ones with lesser priorities.

- **Interleaved Weighted Round Robin Balancing**

  This strategy cycles over all active backends, considering each one in its turn.  An integer ordinal number is assigned to each round, which is incremented (modulo number of backends) each time a new round is started.  A backend is assigned a request only if its priority is greater than the round number.

-

  This strategy offers several advantages compared with the previous one.  First, it results in a more even distribution of the requests.  Secondly, the resulting distribution is predictable.

Within each **Service**, multiple backends are grouped in *balancer groups*. Each such group is assigned a unique integer *priority*, which defines the order in which the groups are tried.  When selecting a backend, a group with the numerically lesser priority is selected and a suitable backend is looked up among backends defined in the group, using one of the balancing strategies discussed above.  If no backend can be selected (e.g. all backends are unavailable), next group is tried.  The process continues until either a backend is chosen or the list of balancer groups is exhausted.

By default, backends declared using the **Backend** keyword are assigned to the balancer group 0.  These are backends used during normal operation.  Backends declared using the **Emergency** keyword are assigned to the balancer group 65535.  These backends form a pull of *high availability* backends, which will be tried only if all of the normal backends fail.

More backend groups can be added using dynamic backends, discussed below.

## WORKER MODEL

Each incoming request is processed by a specific *worker*, i.e. a thread in the running program.  The number of running workers is controlled by three configuration parameters.  **WorkerMinCount** defines the minimum number of workers that should always be running (5, by default). Another parameter, **WorkerMaxCount** sets the upper limit on the number of running workers (it defaults to 128).

At each given moment, a worker can be in one of two states: *idle* or *active* (processing a request).  If an incoming request arrives when all running workers are active, and total number of workers is less than **WorkerMaxCount**, a new thread is started and the new request is handed to it.  If the number of active workers has already reached maximum, the new request is added to the *request* *queue*, where it will wait for a worker to become available to process it.

The third parameter, **WorkerIdleTimeout**, specifies maximum time a thread is allowed to spend in the *idle* state.  If a worker remains idle longer than that and total number of workers is greater than the allotted minimum (**WorkerMinCount**), the idle worker is terminated.

## OPTIONS

The following command line options are available:

- **-c**

  Check only: **pound** will exit immediately after parsing the configuration file. This may be used for running a quick syntax check before actually activating a server.

- **-e**

  Log to standard error (standard output for **LOG\_DEBUG** and **LOG\_INFO** severity levels).  This option implies *foreground mode* (**-F**) and overrides the *LogLevel* configuration setting.

- **-F**

  Foreground mode.  The program will not detach from the controlling terminal and will remain in foreground after startup.  This overrides the **Daemon** configuration setting.  The log stream (syslog facility or stderr) requested in the configuration remains in effect. See also the **-e** option, above.

- **-f** *FILE*

  Location of the configuration file (see below for a full description of the format).  Default is *$sysconfdir/pound.cfg*, where *$sysconfdir* stands for the system configuration directory, as determined at build time.  Most often it is either */usr/local/etc*, or */etc*.

- **-h**

  Print short command line usage summary and exit.

- **-p** pid\_file

  Location of the PID file. **Pound** will write its own PID into this file. Normally this is used for shell scripts that control starting and stopping of the daemon. See the description of **PIDFile** statement in the **GLOBAL DIRECTIVES** section below, for a detailed discussion of this file.

- **-v**

  Verbose mode: during startup, error messages will be sent to stderr (stdout for **LOG\_DEBUG** and **LOG\_INFO** severity levels).  If **pound** was configured to log to syslog, error diagnostics will be duplicated there as well.  After startup the configuration settings take effect.

- **-V**

  Print version: **pound** will exit immediately after printing the current version, licensing terms, and configuration flags.

- **-W \[no-\]***FEATURE*

  Enable or disable (if prefixed with **no-**) additional **pound** features.  As of this version, the following *FEATURE*s are implemented:

  - \[**no-**\]**warn-deprecated**

    Warn if any deprecated statements are used in configuration file.

  - \[**no-**\]**dns**

    Resolve host names found in configuration file.  This is the default. You can disable it if your configuration file refers to backends only by their IP addresses, in order to suppress potentially lengthy network host address lookups.

  - **no-include-dir**

    Don't set the include directory to the system configuration directory.  This means that each relative filename used in arguments to the directives in the configuration file will be looked up in the current working directory.  This feature is useful mainly in testsuite.

  - **include-dir=***DIR*

    Override the default include directory setting.  Set it to *DIR*. See the discussion of the **IncludeDir** directive in section **GLOBAL DIRECTIVES**, below.

## CONFIGURATION FILE

Each line in the file is considered a complete configuration directive. Empty lines and comments are ignored. Comments are introduced with a **#** sign and extend to the end of line on which it appears.

There are three types of directives: **global** directives (they affect the settings for the entire program instance), **listener** directives (they define which requests **pound** will listen for), and **service** directives (they affect only a specific group of requests).

In general, a directive consists of a *keyword* and one or more *values*, separated by any amount of whitespace.  Leading and trailing whitespace is ignored. Keywords are case-insensitive. A *value* can be:

- *Numeric*

  A decimal number.

- *Boolean*

  The words **yes**, **true**, **on**, or **1** indicating *true*, and **no**, **false**, **off**, or **0** indicating *false*. All words are case-insensitive.

- *String*

  Any sequence of characters between double-quotes.  A backslash is treated as an escape character: if it is followed by a double-quote or another backslash, it is removed and the character after it is read literally.  If it is followed by any other character, a warning message is printed.

- *Identifier*

  A sequence of characters starting with an ASCII letter and consisting of letters, digits and underscores.

- *IP address*

  An IPv4 or IPv6 address in numeric form, or a hostname.

Unless specified otherwise, directives may appear in any order.

## GLOBAL DIRECTIVES

Global directives may appear anywhere at the top level within the configuration file, although it is customary for them to be at the start.

- **User** "*user\_name*"

  Specify the user **pound** will run as (must be defined in the system user database).

- **Group** "*group\_name*"

  Specify the group **pound** will run as (must be defined in the system group database).

- **RootJail** "*directory*"

  Specify the directory that **pound** will chroot to at runtime.

- **HeaderOption** *opt*...

  Sets default options for header addition.  *opt* is one of: **none** to disable additional headers, **forwarded** to enable adding **X-Forwarded-For**, **X-Forwarded-Proto**, and **X-Forwarded-Port** headers, and **ssl** to enable passing information about SSL certificates in various **X-SSL-\*** headers.  The default is

-

  **HeaderOption forwarded ssl**

-

  This setting can be overridden on a per-listener basis.  See the description of **HeaderOption** directive in **HTTP Listener** section, and section **BUILT-IN HEADERS**, for a detailed discussion of various header modification directives and their effect.

- **Balancer** **random** \| **iwrr**

  Defines the load-balancing strategy to use.  Possible arguments are: **random**, to use weighted random balancing algorithm. an **iwrr**, meaning interleaved weighted round robin balancing. See **REQUEST BALANCING**, above, for a detailed discussion of these balancing strategies.

-

  The **Balancer** statement in global scope applies to all **Service** directives that don't contain **Balancer** definitions of their own.

- **Daemon** *bool*

  Have **pound** run in the foreground (if *false*) or as a daemon (if *true*). By default **pound** runs as a daemon (detaches itself from the controlling terminal and puts itself in the background). By specifying this option you can force **pound** to work like a regular process. Useful for debugging or if you want to use something like *daemontools*.

- **Supervisor** *bool*

  When running in daemon mode, start a *supervisor* process first. This process will monitor the subordinate **pound** process, restarting it if it fails.

- **WorkerMinCount** *N*

  Sets minimum number of worker threads that must always be running. The default is 5. See the section **WORKER MODEL** above for a detailed discussion.

- **WorkerMaxCount** *N*

  Sets maximum number of worker threads.  The default is 128. See the section **WORKER MODEL** above for a detailed discussion.

- **WorkerIdleTimeout** *SEC*

  Sets idle timeout for a worker thread.  Default is 30 seconds. See the section **WORKER MODEL** above for a detailed discussion.

- **Threads** *N*

  This statement, retained for backward compatibility with previous versions of **pound**, is equivalent to:

-

  ```
  WorkerMinCount N
  WorkerMaxCount N
  ```

- **LogFacility** *ident*

  Specify the log facility to use.  The *ident* is one of the following: **auth**, **authpriv**, **cron**, **daemon**, **ftp**, **kern**, **lpr**, **mail**, **news**, **syslog**, **user**, **uucp**, **local0** through **local7**. The default value is **daemon**. Using a **-** (dash) for the facility name causes **pound** to log to stdout/stderr.

- **LogFormat** "*name*" "*format\_def*"

  Define HTTP log format.  *Name* is a string uniquely identifying this format.  *Format\_def* is the format string definition.  See below, section **REQUEST LOGGING**, for a detailed description.

- **LogLevel** *n*

  Specify the logging level using built-in format indices: 0 for no logging, 1 (default) for regular logging, 2 for extended logging (show chosen backend server as well), 3 for Apache-like format (Combined Log Format with Virtual Host), 4 (same as 3 but without the virtual host information) and 5 (same as 3 but with information about the **Service** and **Backend** used). This value can be overridden for specific listeners.

-

  See below, section **REQUEST LOGGING**, for a detailed description.

- **LogLevel** "*name*"

  Select a named format for logging HTTP requests.  *Name* can be either one of five built-in format names (**null**, **regular**, **extended**, **vhost\_combined**, **combined**, or **detailed**), or a format name defined earlier via the **LogFormat** directive.  See section **REQUEST LOGGING**, for a detailed discussion.

- **LogTag** "*string*"

  Sets the string to tag log messages with.  This is used when log output goes to syslog.  Default is the name with which **pound** was started.

- **ForwardedHeader** *name*

  Defines the name of the HTTP header that carries the list of proxies the request has passed through.  It is used to report the originator IP address when logging.  See the description of **%a** specifier in **REQUEST LOGGING**. The default is **X-Forwarded-For**.

- **TrustedIP**

  Defines a list of *trusted proxy* IP addresses, which is used to determine the originator IP.  See the description of **%a** specifier in **REQUEST LOGGING**, for a detailed discussion.

-

  This statement is a special form of **ACL** statement, described below.  It can appear as a *section* or *directive*.  When used as a section, it is followed by a list of one or more CIDRs each appearing on a separate line.  The **End** keyword terminates the statement, e.g.:

-

  ```
  TrustedIP
    "127.0.0.1/8"
    "10.16.0.0/16"
  End
  ```

-

  In directive form, this statement takes single argument, the name of an access control list defined earlier using the **ACL** statement, e.g.

-

  ```
  TrustedIP "proxy_addresses"
  ```

- **IgnoreCase** *bool*

  Ignore case when doing regex matching (default: *false*). This directive sets the default for the following service matching directives: **URL**, **Path**, **QueryParam**, **Query**, **StringMatch**, as well as for the **DeleteHeader** modification directive.  Its value can be overridden for specific services.

-

  This statement is deprecated and will be removed in future versions. Please, use the **-icase** option to the service matching directive instead.  See the discussion of *options* in **Service Matching Directives** section below.

- **Alive** *n*

  Specify how often **pound** will check for resurrected backend hosts (default: 30 seconds). In general, it is a good idea to set this as low as possible - it will find resurrected hosts faster. However, if you set it too low it will consume resources - so beware.

- **Client** *n*

  Specify for how long **pound** will wait for a client request (default: 10 seconds). After this long has passed without the client sending any data **pound** will close the connection. Set it higher if your clients time-out on a slow network or over-loaded server, lower if you start getting DOS attacks or run into problems with IE clients. This value can be overridden for specific listeners.

- **TimeOut** *n*

  How long should **pound** wait for a response from the backend (in seconds). Default: 15 seconds. This value can be overridden for specific backends.

- **ConnTO** *n*

  How long should **pound** wait for a connection to the backend (in seconds). Default: the **TimeOut** value. This value can be overridden for specific backends.

- **WSTimeOut** *n*

  How long should **pound** wait for data from either backend or client in a connection upgraded to a WebSocket (in seconds). Default: 600 seconds. This value can be overridden for specific backends.

- **Grace** *n*

  How long should **pound** continue to answer existing connections after a receiving a INT or HUP signal (default: 30 seconds). The configured listeners are closed immediately. You can bypass this behaviour by stopping **pound** with a TERM or QUIT signal, in which case the program exits without any delay.

- **SSLEngine** "*name*"

  Use an OpenSSL hardware acceleration card called *name*. Available only if OpenSSL-engine is installed on your system.

- **ECDHcurve** "*name*"

  Use the named curve for elliptical curve encryption (default: prime256v1).

- **Control** "*pathname*"

  Set the control socket path. See the **Control socket** section below, for a detailed description of this feature.

- **CombineHeaders** ... **End**

  Declare names of the headers that can appear multiple times in a message, and that should be combined into one value.  Header names must appear one per line between **CombineHeaders** and **End**.

-

  See the section **MULTI-VALUE HEADERS**, for a detailed discussion of this feature.

- **IncludeDir** "*dir*"

  Sets the *include directory*.  This is the directory where *pound* looks for relative file names that appear in other configuration directives (e.g. *Include*).  The default value is the system configuration directory as set at compile time (you can check its value in the output of **pound -V**).  This initial value can be changed in the command line using the **-W include-dir=***name* option or reset to the current working directory using the **-W no-include-dir** option (see the discussion of **-W** below).

- **Include** "*file*"

  Include the file as though it were part of the configuration file.  If *file* is a relative file name, it will be looked in the *include* *directory* (see above).

-

  This directive is allowed both at topmost level and in any subsections of the configuration file.

- **Anonymise**

  (alternative spelling **Anonymize** also accepted) Replace the last byte of the client address with 0 for logging purposes. Default: log the client address in full.

- **ACL** "*name*"

  Define a *named access control list* (*ACL*).  An ACL is a list of network addresses in CIDR notation, one address per line, terminated with an **End** directive on a line by itself.  E.g.:

-

  ```
  ACL "secure"
     "192.0.2.0/26"
     "203.0.113.0/24"
  End
  ```

-

  The **Include** directive is allowed within **ACL**.

-

  Named ACLs can be used in **Service** definitions to make services available from certain IP addresses only.

- **PIDFile** "*filename*"

  Sets the name of the file where to store program PID.  It can be overridden by the **-p** command line option.

-

  *Notice* the following:

  - 1\.

    When running with a supervisor, this file holds PID of the supervisor process.  Otherwise, it holds PID of the main **pound** process.  This means it is always suitable for signalling the program using the traditional **kill \`cat filename\`** technique.

  - 2\.

    Before shutting down, **pound** removes this file.  However, this may be not possible if it switches to privileges of another user after startup (at least one of **User** or **Group** are set in the configuration file) and the file is stored in a directory whose permissions forbid write access for that user.

- **RegexType posix** \| **pcre** \| **perl**

  Sets the type of regular expressions to use in request matching statements. **posix** selects POSIX extended regular expressions and **pcre** or **perl** select Perl-compatible regular expressions.  The latter requires compile-time support.  The selected regular expression type remains in effect until next **RegexType** statement or end of the configuration file, whichever occurs first.

### Control socket

**Pound** can be instructed to listen for management requests, which will allow you to obtain information about the running instance, change state of configured listeners, services, and backends, etc.  These requests may be issued by using the [**poundctl**(8)](/poundctl/8.md) utility.

Usually, a UNIX socket is used to communicate with the management interface. It is configured via the **Control** statement.  This statement has two forms.  In *inline* form, the statement takes a single argument, specifying the name of the UNIX socket file to create and listen on.  For example:

```
Control "/run/pound.sock"
```

The file will be owned by the user that started **pound** (normally root) and will have mode 0600.

The block form allows you to specify file mode and, to certain extent, the socket file ownership:

```
Control
    Socket "/run/pound.sock"
    Mode 660
    ChangeOwner true
End
```

The substatements are:

- **Socket *filename***

  Specifies the name of the socket file to use.  This is the only mandatory statement in the block form.

- **Mode *octal***

  Sets the mode of the socket file.

- **ChangeOwner *bool***

  This statement takes effect if at least one of **User** or **Group** global statements is used.  When set to **true** it will change the owner of the socket file to that specified by those two statements.

It is also possible to have **pound** listen for management requests on an INET or INET6 address.  See below, the section **Backend definitions**, description of the **Control** statement.

## HTTP Listener

An HTTP listener defines an address and port that **pound** will listen on for HTTP requests.  The listener declaration begins with the keyword **ListenHTTP** on a separate line.  The keyword may be followed by a quoted string supplying listener name.  This name is a unique label that identifies the listener.

All configuration directives enclosed between **ListenHTTP** and **End** are specific to a single HTTP listener.  At the very least you must specify IP address and port for each listener. The following directives are available:

- **Address** *address*

  The address that **pound** will listen on. This can be a numeric IP address, or a full pathname of a UNIX socket.  If neither this directive nor **SocketFrom** (see below) is given, *::0* is assumed.

- **Port** *port*

  The port number or service name that **pound** will listen on.  If not given, default port number is assumed, i.e. 80, for **ListenHTTP**, and 443, for **ListenHTTPS** (see below).

- **SocketFrom** "*pathname*"

  Read the socket to listen on from the UNIX socket given as argument. If this parameter is supplied, neither **Address** nor **Port** may be used.  This parameter is intended for testing **pound**.

- **xHTTP** *n*

  Defines which HTTP verbs are accepted. The possible values are:

-

  **0** (default) accept only standard HTTP requests (GET, POST, HEAD).

-

  **1** additionally allow extended HTTP requests (PUT, PATCH, DELETE).

-

  **2** additionally allow standard WebDAV verbs (LOCK, UNLOCK, PROPFIND, PROPPATCH, SEARCH, MKCOL, MOVE, COPY, OPTIONS, TRACE, MKACTIVITY, CHECKOUT, MERGE, REPORT).

-

  **3** additionally allow MS extensions WebDAV verbs (SUBSCRIBE, UNSUBSCRIBE, NOTIFY, BPROPFIND, BPROPPATCH, POLL, BMOVE, BCOPY, BDELETE, CONNECT).

- **Client** *n*

  Override the global *Client* time-out value.

- **CheckURL** "*pattern*"

  Define a pattern that must be matched by each request sent to this listener. A request that does not match is considered to be illegal. By default **pound** accepts all requests (i.e. the pattern is ".\*"), but you are free to limit it to something more reasonable. Please note that this applies only to the request path - **pound** will still check that the request is syntactically correct.

- **ErrorFile** *NNN* "*filename*"

  Read the content to be returned along with the HTTP status code *NNN* from the file *filename*.  The file will be read exactly once, at the program startup.

-

  Allowed values for *NNN* are: **400**, **401**, **404**, **405**, **413**, **414**, **500**, **501**, **503**.

- **Err***NNN* "*filename*"

  This statement is equivalent to

-

  ```
  ErrorFile NNN "filename"
  ```

-

  It is provided for compatibility with previous versions of the program.

- **MaxRequest** *n*

  Maximum allowed size of incoming request. All requests will be limited to these many bytes. If a request contains more data than allowed, an error 413 is returned. Default: unlimited.

- **MaxURI** *n*

  Maximum allowed length of an URI.  If the URI of a request is longer than *n* bytes, an error 414 is returned. Default: unlimited.

- **RewriteLocation** 0\|1\|2

  If set to 1, force **pound** to change the Location: and Content-location: headers in responses. If they point to the backend itself or to the listener (but with the wrong protocol), the response will be changed to show the virtual host in the request. Default: 1 (active).  If the value is set to 2, only the backend address is compared; this is useful for redirecting a request to an HTTPS listener on the same server as the HTTP listener.

- **RewriteDestination** *bool*

  If set to *true, force* **pound** *to change the "Destination:" header in requests. The header is changed* *to point to the backend itself with the correct protocol. Default:* *false*.

- **LogLevel** *n*

  Log HTTP requests using built-in format *n*.  This statement configures logging specific for this listener, overriding the global **LogLevel** setting.  See **REQUEST LOGGING**, for a detailed discussion.

- **LogLevel** "*name*"

  Select a named format for logging HTTP requests.  *Name* can be either one of five built-in format names (**null**, **regular**, **extended**, **vhost\_combined**, **combined**, or **detailed**), or a format name defined earlier via the **LogFormat** directive.

-

  This statement configures logging specific for this listener, overriding the global **LogLevel** setting.  See section **REQUEST LOGGING**, for a detailed discussion.

- **ForwardedHeader** *name*

  Defines the name of the HTTP header that carries the list of proxies the request has passed through.  It is used to report the originator IP address when logging.  See the description of **%a** specifier in **REQUEST LOGGING**. This statement overrides the **ForwardedHeader** directive from the global scope.

-

  The default is **X-Forwarded-For**.

- **TrustedIP**

  Defines a list of *trusted proxy* IP addresses, which is used to determine the originator IP.  See the description of **%a** specifier in **REQUEST LOGGING**, for a detailed discussion.

-

  This statement overrides the **TrustedIP** directive from the global scope.

- **Service** \[ "*name*" \]

  This defines a private service (see below for service definition syntax). This service will be used only by this listener. Optional *name* supplies the label, that can be used in [**poundctl**(8)](/poundctl/8.md) requests to identify the service.  This label must be unique among all services within the enclosing listener, or, for global services, within the configuration.

- **ACME** "*directory*"

  Serve ACME challenge requests from the given *directory*. See section **ACME** below.

- **HeaderOption** *opt*...

  Modifies global header addition options for this listener.  Global options are set by the **HeaderOption** directive in the global scope and default to **forwarded ssl**.  *opt* is one of:

  - **all**

    Enable all additional headers.

  - **none**

    Disable all additional headers.

  - **forwarded**

    Enable adding **X-Forwarded-For**, **X-Forwarded-Proto**, and **X-Forwarded-Port** headers.

  - **ssl**

    Enable passing information about SSL certificates in various **X-SSL-\*** headers.

-

  Each option except **none** can be prefixed with **no-** to revert its meaning.

-

  For example, to disable adding the **X-SSL-\*** headers for a listener, one would use:

-

  **HeaderOption no-ssl**

-

  See the description of **HeaderOption** directive in **GLOBAL** **DIRECTIVES** section, and section **BUILT-IN HEADERS**, for a detailed discussion of various header modification directives and their effect.

### String expansion

Some of the statements described below take as their arguments string values that undergo several *expansions* before use.  These expansions are as follows:

- **Backreference expansion**

  Backreference is a construct that refers to a *parenthesized* *group* within a regular expression matched by one of service matching directives described above.  During backreference expansion, each occurrence of such construct in a string is replaced with the actual value of that parenthesized group.

-

  Syntactically backreference can take two forms.  The construct **$***N* (*N* is a decimal number) refers to *N*th parenthesized subexpression of the most recently matched statement, and **$***N***(***M***)** refers to *N*th parenthesized subexpression of *M*th recently matched statement.  Numbering of subexpressions starts at 1 (**$0** refers to the entire matching string).  Numbering of matches starts at 0.

-

  For example, given the following statements

-

  ```
  Host -re "www\.(.+)"
  Header -re -icase "^Content-Type: *(.*)"
  Path "^/static(/.*)?"
  ```

-

  **$1** refers to the subgroup of **Path**, **$1(1)** - to that of **Header**, and **$1(2)** - to that of **Host**.

-

  Curly braces may be used to avoid incorrectly parsing text fragment that follows the reference as being its part.  This is useful if the reference is immediately followed by a decimal digit or opening parenthesis, as in: **"${1}(text)"**.

-

  To insert a literal dollar or percent sign in *url*, use **$$** or **$%**, correspondingly.

- **Request accessor interpretation**

  Request accessor is **%\[***name***\]**, where *name* denotes a part of the incoming request to access.  Accessors are interpreted and replaced with the corresponding part of the request.  Some accessors take an argument, which is specified after accessor name and is delimited from it by one or more whitespace characters.

-

  The following accessors are defined:

  - **url**

    Request URL.

  - **path**

    Request path.

  - **query**

    Query part.

  - **param** *NAME*

    The value of the query parameter *NAME*.

  - **header** *NAME*

    The value of HTTP header *NAME*.

  - **host**

    Hostname part of the **Host** header.  If the latter does not include port number, it is equivalent to **%\[header** **host\]**. **port** If the value of the **Host** header includes port number, **%\[port\]** evaluates to port number with the leading colon character. Otherwise, it evaluates to empty string.

### Modification directives

The following directives modify the incoming request prior to passing it to the selected service. These are discussed in detail in section **REQUEST MODIFICATION**, below.

- **DeleteHeader** "*header***:** *pattern*"

  Remove certain headers from the incoming requests. All occurrences of the matching header will be removed. The argument is treated verbatim.

- **SetHeader** "*header***:** *value*"

  Add header to the request passed to the backend server. Argument undergoes string expansion as described above. The expanded value must be a valid header line.

- **SetURL** "*value*"

  Sets the URL part of the request. Argument is subject to string expansion.

- **SetPath** "*value*"

  Sets the path part of the request. Argument is subject to string expansion.

- **SetQuery** "*value*"

  Sets the query part of the request. Argument is subject to string expansion.

- **SetQueryParam** "*name*" "*value*"

  Modifies the query.  Sets the query parameter *name* to *value*. The *value* argument is subject to string expansion.

- **Rewrite** \[**request**\|**response**\] ... \[ **Else** ... \] **End**

  Conditionally modify request or response depending on whether it matches certain conditions.  If the argument is omitted, **request** is assumed.

-

  Request modification is described in detail in section **REQUEST MODIFICATION DIRECTIVES .**

-

  Response modification is covered by section **RESPONSE MODIFICATION**.

### Compatibility directives

The following directives are retained for compatibility with previous versions of **pound**. They will be removed in future releases.

- **HeaderAdd** "*header***:** *value*"

  Same as **SetHeader**.

- **AddHeader** "*header***:** *value*"

  Same as **SetHeader**.

- **HeaderRemove** "*pattern*"

  Same as **DeleteHeader**.

- **HeadRemove** "*pattern*"

  Same as **DeleteHeader**.

## HTTPS Listener

HTTPS listener defines an address and port that **pound** will listen on for HTTPS requests.  The listener declaration begins with the keyword **ListenHTTPS** on a separate line.  The keyword may be followed by a quoted string supplying listener name.  This name is a unique label that identifies the listener.

All configuration directives enclosed between **ListenHTTPS** and **End** are specific to a single HTTPS listener. At the very least you must specify an address, a port and a server certificate for each listener. All directives defined for HTTP listeners are applicable to HTTPS listeners as well. The following additional directives are also available:

- **Cert** "*filename*"

  Specify the server certificate.  *Filename* is either a *certificate file* name, or the name of a directory containing certificate files.

-

  *Certificate file* is a file containing the certificate, possibly a certificate chain and the signature for this server, in that order.

-

  This directive is **mandatory** for HTTPS listeners.

-

  Please note that multiple **Cert** directives are allowed if your OpenSSL version supports SNI. In such cases, the first directive is the default certificate, with additional certificates used if the client requests them.

-

  The ordering of the directives is important: the first certificate where the CN matches the client request will be used, so put your directives in the most-specific-to-least specific order (i.e. wildcard certificates **after** host-specific certificates).

-

  **Cert** directives **must** precede all other SSL-specific directives.

- **ClientCert** 0\|1\|2\|3 *depth*

  Ask for the client's HTTPS certificate: 0 - don't ask (default), 1 - ask, 2 - ask and fail if no certificate was presented, 3 - ask but do not verify. *Depth* is the depth of verification for a client certificate (up to 9). The default depth limit is 9, allowing for the peer certificate and additional 9 CA certificates that must be verified.

- **Disable** SSLv2\|SSLv3\|TLSv1\|TLSv1\_1\|TLSv1\_2

  Disable the protocol **and all lower protocols as well**. This is due to a limitation in OpenSSL, which does not support disabling a single protocol. For example, **Disable TLSv1** would disable SSLv2, SSLv3 and TLSv1, thus allowing only TLSv1\_1 and TLSv1\_2.

- **Ciphers** "*cipher\_list*"

  This is the list of ciphers that will be accepted by the SSL connection; it is a string in the same format as in OpenSSL **ciphers**(1) and **SSL\_CTX\_set\_cipher\_list**(3).

- **SSLHonorCipherOrder** *bool*

  If set to *true*, the server will broadcast a preference to use ciphers in the order supplied in the **Ciphers** directive.  If the value is *false*, the server will accept any cipher from the **Ciphers** list.  Default value is *false*.

- **SSLAllowClientRenegotiation** 0\|1\|2

  If this value is 0, client initiated renegotiation will be disabled. This will mitigate DoS exploits based on client renegotiation, regardless of the patch status of clients and servers related to "Secure renegotiation".  If the value is 1, secure renegotiation is supported.  If the value is 2, insecure renegotiation is supported, with unpatched clients. **This can lead to a DoS and a Man in the** **Middle attack!** The default value is 0.

- **CAlist** "*filename*"

  Set the list of "trusted" CA's for this server. The *filename* is the name of a file containing a sequence of CA certificates (PEM format). The names of the defined CA certificates will be sent to the client on connection.

- **VerifyList** "*filename*"

  Set the CA (Certificate Authority). The *filename* is a file that contains the CA root certificates (in PEM format).

-

  *Please note*: there is an important difference between the CAlist and the VerifyList. The CAlist tells the client (browser) which client certificates it should send. The VerifyList defines which CAs are actually used for the verification of the returned certificate.

- **CRLlist** "*filename*"

  Set the CRL (Certificate Revocation List) file. The *filename* is a file that contains the CRLs (in PEM format).

- **NoHTTPS11** 0\|1\|2

  Behave like an HTTP/1.0 server for HTTPS clients. If this value is 0, disable the check. If the value is 1, do not allow multiple requests on SSL connections. If the value is 2 (default), disable multiple requests on SSL connections only for MSIE clients. Required work-around for a bug in certain versions of IE.

## Service

A service is a definition of which backend servers **pound** will use to reply to incoming requests. A service may be defined as part of a listener (in which case it will be used only by that listener), or globally (which makes it available to all listeners). **Pound** selects a listener based on user-supplied conditions that analyze the incoming request URL and/or headers.  It will always scan listener-specific services first.  If none matches, it will try the global ones.  Services are tried in the same order as they are defined in configuration.

All configuration directives enclosed between **Service** and **End** are specific to a single service. They can be subdivided into two categories: *service matching directives* and *backend* *definitions*.

### Service Matching Directives

These directives determine whether a particular request should be handled by this service.  When a request arrives, each service is considered in turn (first services defined within the listener that received the request, then the ones defined in global scope).  First service that matches the request will be used.  If no service matches, a 503 "Service unavailable" error is returned.

Unless explicitly stated in the configuration file, all matching directives are joined by a boolean **AND**.

A service with no matching directives always matches.

- **ACL** "*name*"

  Match the source IP address against the named ACL.  The ACL must have been defined earlier (see the **ACL** statement in **GLOBAL DIRECTIVES** section above).  If the IP doesn't match, then this service will be skipped and next one tried.

- **ACL**

  This statement defines an unnamed ACL to match the source IP against. This line must be followed by one or more lines defining CIDRs, as described in the **GLOBAL DIRECTIVES** section above. The ACL definition is finished with a **End** keyword on a line by itself.

  Semantically it is equivalent to the named ACL reference described above.

- **BasicAuth** "*filename*"

  Evaluates to true if the incoming request passes basic authorization as described in RFC 7617.  *filename* is the name of a plain text file containing usernames and passwords, created with [**htpasswd**(1)](/htpasswd/1.md) or similar utility.  Unless it starts with a slash, it is taken relative to the **IncludeDir** directory.  The file is cached in the memory on the first authorization attempt, so that further authorizations do not result in disk operations.  The file will be rescanned if **Pound** notices that its modification time has changed.

-

  See the section entitled **BASIC AUTHENTICATION**, for a detailed discussion.

- **ClientCert** "*filename*"

  Evaluates to *true* if the client presented the certificate matching that from the file *filename* (PEM format).

-

  This conditional cannot be used in standalone services (i.e. services that are defined in global scope), or if the **ListenHTTPS** section that hosts the service has the **ClientCert** statement on its own.

- **Header** \[*options*\] "*pattern*"

  The request must contain at least one header matching the given *pattern*.  By default, *pattern* is treated as case-insensitive extended regular expression.  This can be changed by *options*, described below.

- **Host** \[*options*\] "*hostname*"

  The request must contain a **Host** header whose value matches *hostname*.  In the absence of *options*, case-insensitive exact match is assumed, i.e. this construct is equivalent to

-

  **Header** "Host:\[\[:space:\]\]\**qhost*"

-

  where *qhost* is the "*hostname*" argument in quoted form, i.e. with all characters that have special meaning in regular expressions escaped.

-

  See below for the discussion of *options* and their effect on matching.

-

  This statement is provided to facilitate handling of *virtual* *hosts*.  See the **EXAMPLES** section.

- **Path** \[*options*\] "*pattern*"

  Match the path part of the incoming request.

- **Query** \[*options*\] "*pattern*"

  Match the query part of the incoming request. The argument must be properly percent-encoded, if it contains whitespace or other non-printable characters.

- **QueryParam** "*name*" \[*options*\] "*pattern*"

  Match the value of the query parameter *name*.

- **StringMatch** "*string*" \[*options*\] "*pattern*"

  Expand *string* as described in **String expansion** (see below) and match the resulting value against *pattern*.

- **URL** \[*options*\] "*pattern*"

  Match the URL of the incoming request.  By default, *pattern* is treated as case-sensitive extended regular expression.  This can be changed by *options*, described below.

The *options* argument in the above directives can be used to select the comparison method.  It consists of zero or more option flags from the following list:

- **-beg**

  Exact match at the beginning of string (prefix match).

- **-case**

  Case-sensitive comparison.

- **-contain**

  Match substring.

- **-end**

  Exact match at the end of string (suffix match).

- **-exact**

  Exact string match.

- **-file**

  Treat *pattern* as the name of a file to read patterns from.  If the name is relative, it will be looked up in the *include* *directory* (see the discussion of the **IncludeDir** directory above).  Patterns are read from the file line by line.  Leading and trailing whitespace is removed.  Empty lines and comments (lines starting with **#**) are ignored.

- **-icase**

  Case-insensitive comparison.

- **-pcre** or **-perl**

  Use Perl-compatible regular expression (requires compilation-time support).  This overrides global **RegexType** settings.

- **-posix**

  Use POSIX extended regular expression.  This overrides global **RegexType** settings.

- **-re**

  Use regular expression matching, as set by the **RegexType** statement.

For example, the following will match any request whose **Host** header begins with "www." (case-insensitive):

Host -icase -beg "www."

```

```

### Compatibility directives

The following directives are provided for backward compatibility with older versions of **pound**. They will be removed in future versions.

- **HeadRequire** "*pattern*"

  Same as **Header**.

- **HeadDeny** "*pattern*"

  A shortcut for

-

  **Not header** "*pattern*"

-

  In other words: the request may **not** contain any header matching the given pattern.  See the **Negation** section, below.

### Negation

Prefixing any of the directives discussed above with **not** will revert the sense of comparison.  For example,

```
Not url "^/static/"
```

will match any request, whose URL *does not* begin with "/static/".

Negating compound statements is allowed as well, e.g.:

```
Not ACL
   "192.0.2.0/26"
   "203.0.113.0/24"
End
```

### Match statement

A **Match** statement allows you to group matching directives using arbitrary boolean operations.  The syntax is:

```
Match OP
  directives...
End
```

where *OP* is **AND** to use boolean and, and **OR** (case-insensitive) to use boolean *or*, and *directives* stand for any number of matching directives discussed above (including the **Match** directive).

Prefixing **Match** directive with a word **not** reverts its result.

**Match** directives can be nested to any depth.

Technically, an implicit **Match AND** block is created around unenclosed matching directives on the top level of a **Service** block.

### Modification directives

The following directives modify the incoming request prior to passing it to the selected backend.  These are discussed in detail in the section **REQUEST MODIFICATION**, below.

- **DeleteHeader** "*header***:** *pattern*"

  Remove matching headers from the incoming requests.

- **SetHeader** "*header***:** *value*"

  Add the defined header to the request passed to the backend server.

- **SetURL** "*value*"

  Sets the URL part of the request.

- **SetPath** "*value*"

  Sets the path part.

- **SetQuery** "*value*"

  Sets the query part.

- **SetQueryParam** "*name*" "*value*"

  Modifies the query.  Sets the query parameter *name* to *value*.

- **Rewrite** \[**request**\|**response**\] ... \[ **Else** ... \] **End**

  Conditionally modify request or response depending on whether it matches certain conditions.  If the argument is omitted, **request** is assumed.

-

  Request modification is described in detail in section **REQUEST MODIFICATION DIRECTIVES .**

-

  Response modification is covered by section **RESPONSE MODIFICATION**.

### Backend definitions

- **Balancer** **random** \| **iwrr**

  Defines the load-balancing strategy to use.  Possible arguments are: **random**, to use weighted random balancing algorithm. an **iwrr**, meaning interleaved weighted round robin balancing. See **REQUEST BALANCING**, above, for a detailed discussion of these balancing strategies.

-

  This directive overrides the **Balancer** directive in global scope.

- **Backend**

  Directives enclosed between **Backend** and the following **End** directives define a single backend server (see below for details). You may define multiple backends per service, in which case **pound** will attempt to load-balance between them.

- **Control**

  Enables a special **control backend** -- a management interface that returns information about the running **pound** server, makes it possible to change state of configured listeners, services and backends, and provides other management facilities.  The management interface is discussed in detail in section **Control socket**, above.  The **Control** backend provides remote access to this interface.  Be careful to properly protect the control interface by use of HTTPS, ACLs and/or basic authorization, e.g.:

-

  ```
  ListenHTTPS
      Address 192.0.2.1
      Port 443
      Cert "/etc/ssl/priv/example.pem"
      Service
          Not BasicAuth "pound/htpasswd"
          Rewrite response
              SetHeader "WWW-Authenticate: Basic realm=
          End
          Error 401
      End
      Service
          ACL "secure"
          Control
      End
  End
  ```

- **Redirect** \[*code*\] "*url*"

  This is a special type of backend. Instead of sending the request to a backend **pound** replies immediately with a redirection to the given URL.

-

  It is allowed to define multiple redirectors in a service, as well as mixing them with regular backends, but there is little if any justification for such usage, so it is deprecated.

-

  Optional *code* can be one of: **301**, **302** (the default), **303**, **307**, or **308**.

-

  The redirection destination is determined by the actual *url* you specify.  It is expanded as described in **String expansion** above.

-

  For compatibility with previous **pound** versions, if no **$***N* references are found in *url*, the following logic is used: if it is a "pure" host (i.e. with no path) then the client will be redirected to the host you specified, with the original request path appended. If your *url* does contain a path, then the request path is ignored.

-

  Examples: the following swaps the first two path components of the original URL:

-

  ```
  Service
      Host -re "(.+)"
      URL "^/([^/]+)/([^/]+)(/.*)?"
      Redirect "http://$0(1)/$2/$1$3"
  End
  ```

-

  Notice the use of **Host** to supply hostname part for the redirect.

-

  Using request accessors, the above example can be rewritten as:

-

  ```
  Service
      URL "^/([^/]+)/([^/]+)(/.*)?"
      Redirect "http://%[header host]/$2/$1$3"
  End
  ```

-

  Compatibility syntax: if you specified

-

  ```
  Redirect "http://abc.example"
  ```

-

  and the client requested *http://xyz/a/b/c* then it will be redirected to *http://abc.example/a/b/c*, but if you specified

-

  ```
  Redirect "http://abc.example/index.html"
  ```

-

  it will be sent to *http://abc.example/index.html*.

- **Error** *STATUS* \[*FILE*\]

  Special case of backend that returns HTTP error page.  The *STATUS* argument supplies HTTP status code.  Optional *FILE* argument is the name of a disk file with the error page content (HTML).  If not supplied, the text is determined as usual: first the **ErrorFile** *STATUS* statement for the enclosing listener is consulted.  If it is not present, the default error page is used.

-

  The **Error** directive is useful in a catch-all service, which outputs an error page if no service matching the incoming request was found.  See the **EXAMPLES** section for details.

- **Emergency**

  Directives enclosed between **Emergency** and the following **End** directives define an emergency backend server (see below for details). You may define any number of emergency servers.  A backend will be selected from emergency backends if all regular backends are down.

- **Metrics**

  Special backend type that implements Openmetrics protocol output.  See the section **Metrics** below for a detailed discussion.

- **Session**

  Directives enclosed between **Session** and the following **End** directives define a session-tracking mechanism for the current service. See below for details.

### Other directives

- **IgnoreCase** *bool*

  Override the global **IgnoreCase** setting.

-

  This statement is deprecated and will be removed in future versions. Please, use the **-icase** option to the **URL** directive instead.  See the discussion of *options* in **Service Matching Directives** section above.

- **Disabled** *bool*

  Start **pound** with this service disabled (*true*) or enabled (*false*). If started as disabled, the service can be later enabled with [**poundctl**(8)](/poundctl/8.md).

- **ForwardedHeader** *name*

  Defines the name of the HTTP header that carries the list of proxies the request has passed through.  It is used to report the originator IP address when logging.  See the description of **%a** specifier in **REQUEST LOGGING**. This statement overrides the **ForwardedHeader** directive from the listener scope.

-

  The default is **X-Forwarded-For**.

- **TrustedIP**

  Defines a list of *trusted proxy* IP addresses, which is used to determine the originator IP.  See the description of **%a** specifier in **REQUEST LOGGING**, for a detailed discussion.

-

  This statement overrides the **TrustedIP** directive from the listener scope.

- **LogSuppress** *class*

  Suppresses HTTP logging for requests that resulted in status codes from the specified *class*. Valid status classes are:

-

  - *info* or *1*

    *1xx* response codes.

  - *success* or *2*

    *2xx* response codes.

  - *redirect* or *3*

    *3xx* response codes.

  - *clterr* or *4*

    *4xx* response codes.

  - *srverr* or *5*

    *5xx* response codes.

  - *all*

    All response codes.

-

  Multiple arguments are allowed.

-

  This statement is designed for services that receive a constant stream of similar HTTP requests from a controlled set of IP addresses, such as e.g. Openmetric services.  See the **Metric** section below for an example.

## ACME

This statement creates a *service* specially crafted for answering ACME HTTP-01 challenge requests (see **https://letsencrypt.org/docs/challenge-types/#http-01-challenge**). It takes a single argument specifying a directory where ACME challenges are stored. The argument is subject to string expansion (see the subsection **String expansion**, above).

It is supposed that another program is started periodically, which checks for certificates approaching their expiration, issues renewal requests and stores the obtained ACME challenges in that directory.

## Backend

A backend is a definition of a single backend server **pound** will use to reply to incoming requests.  Backends are defined via a **Backend** statement.  There are two forms of this statement: *service-specific* and *global* (or *named*) backend.  These will be discussed later in this section. All configuration directives enclosed between **Backend** and **End** are specific to a single backend.

The following directives are available:

- **Address** *address*

  The address that **pound** will connect to. This can be a numeric IP address, a symbolic host name that must be resolvable at run-time, or a full pathname of a UNIX socket. If the name cannot be resolved to a valid address, **pound** will assume that it represents the path for a Unix-domain socket. This is a **mandatory** parameter.

- **Port** *port*

  The port number or service name that **pound** will connect to. This is a **mandatory** parameter for non Unix-domain backends.

- **HTTPS**

  The backend is using HTTPS.

- **ServerName** "*name*"

  Specify the name to use for server name identification (**SNI**). This directive also rewrites the **Host:** header for this particular backend.  This means you don't have to use **SetHeader** in addition to it.

-

  This directive may appear only after the **HTTPS** directive.

- **Cert** "*filename*"

  Specify the certificate that **pound** will use as a client. The *filename* is the file containing the certificate, possibly a certificate chain and the signature. This directive may appear only after the **HTTPS** directive.

- **Disable** SSLv2\|SSLv3\|TLSv1\|TLSv1\_1\|TLSv1\_2

  Disable the protocol **and all lower protocols as well**. This is due to a limitation in OpenSSL, which does not support disabling a single protocol. For example, **Disable TLSv1** would disable SSLv2, SSLv3 and TLSv1, thus allowing only TLSv1\_1 and TLSv1\_2. This directive may appear only after the **HTTPS** directive.

- **Ciphers** "*cipherlist*"

  This is the list of ciphers that will be accepted by the SSL connection; it is a string in the same format as in OpenSSL **ciphers**(1) and **SSL\_CTX\_set\_cipher\_list**(3). This directive may appear only after the **HTTPS** directive.

- **Priority** *n*

  The priority of this backend. Higher priority backends will be used more often than lower priority ones, so you should define higher priorities for more capable servers. Exact scheduling and allowed values for this keyword depend on the load balancing strategy in use (see the section **REQUEST BALANCING**, above).  For *weighted random balancing*, allowed values for **Priority** are between 0 and 9, inclusive.  For *interleaved weighted round robin balancing*, allowed range is 0 to 65535, inclusive.

-

  Default value is 5.

- **TimeOut** *n*

  Override the global **TimeOut** value.

- **ConnTO** *n*

  Override the global **ConnTO** value.

- **WSTimeOut** *n*

  Override the global **WSTimeOut** value.

- **Disabled** *bool*

  Start **pound** with this backend disabled (1) or enabled (0). If started as disabled, the backend can be later enabled with [**poundctl**(8)](/poundctl/8.md).

### Dynamic backends

Dynamic backends are created and updated on the fly based on the information from DNS.  A backend is declared as dynamic by the **Resolve** statement.  Its value defines what type of DNS record is used to generate dynamic backends:

- **first**

  Resolve the symbolic host name from the **Address** directive and use first IP from the DNS response as the address of the created dynamic backend.  Thus, at most one dynamic backend will be produced.

- **all**

  Resolve the symbolic host name from the **Address** directive and create one backend for each address from the DNS response.  This enables load balancing between created backends.  Each backend will be assigned the same priority.

- **srv**

  Obtain SRV records for the host name and use them to generate backends.  Each record produces new dynamic backend of the **Resolve all** type, which produces regular backends as described above.  The weight field of the SRV record is mapped to the priority field of each generated backend.  The SRV priority field identifies the balancer group where the backend will be hosted.

The following directives further configure dynamic backends:

- **Family any** \| **inet** \| **inet6**

  **Selects the family of the addresses to look for:**

  - **any**

    **Use all address families available.  This is the default.**

  - **inet**

    **Use only IPv4 addresses (A** DNS RRs).

  - **inet6**

    Use only IPv6 addresses (**AAAA** DNS RRs).

- **IgnoreSRVWeight** *bool*

  When using **SRV** records, ignore their *weight* fields and assign priorities for the generated backends from the priority of the producing backend.

  This directive is valid when used together with **Resolve srv**.

- **OverrideTTL** *N*

  Query DNS each *N* seconds for possible changes in configuration of the existing dynamic backends.  If this statement is not used, the TTL value returned with the DNS response will be used instead.

- **RetryInterval** *N*

  Retry failed DNS queries each *N* seconds.  Default is 600.

### Global and per-service backends

A **Backend** definition can appear as a part of the service, i.e. in a **Service** section. or globally.  In the latter case, the **Backend** keyword must be followed by a symbolic name assigned to this backend, e.g.:

```
Backend "name"
  ...
End
```

This name must uniquely identify the backend among other globally defined backends.  A global backend is attached to a service using the **UseBackend** statement.  It takes the symbolic name of the backend as its argument. The statement

```
UseBackend "name"
```

has essentially the same effect as if full backend definition appeared instead of it in this place.  A substantial difference between the use of service-specific and global backends is that a single global backend can be used in multiple services.  In a way, **UseBackend** statement *expands* to a backend definition within the service.

Furthermore, you can also adjust the **Priority** and **Disabled** parameters of the global backend definition for use in a particular service.  To do so, use the following syntax:

```
Backend "name"
  Priority 3
  Disabled no
End
```

In this form, the **Backend** statement acts as **UseBackend**. Two directives can appear within such **Backend** statement: **Priority**, and **Disabled**. They override the settings defined in the global backend "*name*".

Notice, that in spite of their similarity, the two *named* forms of the **Backend** statement serve different purposes: when used in global scope, a named **Backend** *defines* a backend for further use in various services, and when used within a service, it *creates a copy* of the backend defined elsewhere and *attaches* it to this service.

The actual global definition may appear before as well as after service or services it is used in.

## Resolver

The **Resolver** section controls DNS lookups for dynamic backend generation (see above).  It can contain the following directives:

- **CNAMEChain** *N*

  Maximum allowed length of a *CNAME chain*.  CNAME chains are formed by DNS CNAME records pointing to another CNAME.  Although prohibited by the RFC, such usage does occur sometimes.  By default, **pound** does not accept CNAME chains.  If you work with nameserver that returns them, set this statement to a small integer value, defining maximum number of CNAMEs in the chain that can be accepted.  The value of 2 or 3 should suffice in most cases.

- **ConfigFile** "*FILE*"

  Read the resolver configuration from *FILE*, instead of the default **/etc/resolv.conf**.

- **ConfigText** ... **End**

  Alternative way to supply resolver configuration.  The material within this section is read verbatim and used as the content of the resolver configuration file.

-

  If both **ConfigFile** and **ConfigText** are used, the last used statement wins.

- **debug** *bool*

  Whether to enable DNS debugging info.

- **RetryInterval** *N*

  Interval in seconds, after which to retry failed DNS queries or queries that returned no RRs.  This value is used unless the backend defines its own retry interval value.

## Emergency

Emergency servers will be used once all existing backends are "dead". All configuration directives enclosed between **Emergency** and **End** are specific to a single service.  For the list of directives allowed for use in **Emergency** sections, refer to the description of **Backend**.

## Session

Defines how a service deals with possible HTTP sessions.  All configuration directives enclosed between **Session** and **End** are specific to a single service. Once a session is identified, **pound** will attempt to send all requests within that session to the same backend server.

The following directives are available:

- **Type** IP\|BASIC\|URL\|PARM\|COOKIE\|HEADER

  What kind of sessions are we looking for: IP (the client address), BASIC (basic authentication), URL (a request parameter), PARM (a URI parameter), COOKIE (a certain cookie), or HEADER (a certain request header). This is a **mandatory** parameter.

- **TTL** *n*

  How long can a session be idle (in seconds). A session that has been idle for longer than the specified number of seconds will be discarded. This is a **mandatory** parameter.

- **ID** "*name*"

  The session identifier. This directive is permitted only for sessions of type URL (the name of the request parameter we need to track), COOKIE (the name of the cookie) and HEADER (the header name).

See below for some examples.

## Metrics

The following service definition enables Openmetric telemetry output on endpoint **/metrics:**

```
Service
    URL "/metrics"
    Metrics
End
```

To control access to the telemetry endpoint, use the **ACL** statement.

The **LogSuppress** directive can be used in openmetric services to suppress logging of served HTTP requests.

For example:

```
Service
    URL "/metrics"
    Metrics
    ACL "secure"
    LogSuppress success
End
```

The metrics output is sufficiently self-documented by **# HELP** descriptor lines.

## HIGH-AVAILABILITY

**Pound** attempts to keep track of active backend servers, and will temporarily disable servers that do not respond (though not necessarily dead: an overloaded server that **pound** cannot establish a connection to will be considered dead). However, every **Alive** seconds, an attempt is made to connect to the dead servers in case they have become active again. If this attempt succeeds, connections will be initiated to them again.

In general it is a good idea to set this time interval as low as is consistent with your resources in order to benefit from resurrected servers at the earliest possible time. The default value of 30 seconds is probably a good choice.

The clients that happen to hit a dead backend server will just receive a *503 Service Unavailable* message.

## REQUEST MODIFICATION DIRECTIVES

Several statements are provided to modify the incoming requests prior to passing them to the backend.  These statements can be present both in **ListenHTTP** (**ListenHTTPS**) and in **Service** sections.

Basic request modification directives are:

- **SetURL** "*value*"

  Set the URL of the incoming request to *value*.

- **SetPath** "*value*"

  Set the path part of the URL to the given string.

- **SetQuery** "*value*"

  Set the query part of the URL to the given string.  *value* must be a valid query with the special characters properly encoded using percent encoding.

- **SetQueryParam** "*name*" "*value*"

  Set the query parameter *name* to the *value*.  Value must be properly encoded if it contains reserved characters.

- **SetHeader** "*name***:** *value*"

  Sets the HTTP header.  If the header *name* already exists, it will be overwritten.  Otherwise, new header will be added to the end of the header list.

- **DeleteHeader** \[*options*\] "*pattern*"

  Remove from the request all headers matching *pattern*.  By default, *pattern* is treated as extended POSIX regular expression.  The *options* argument can be used to change this behavior.  It consists of zero or more option flags from the following list:

  - **-beg**

    Exact match at the beginning of string (prefix match).

  - **-case**

    Case-sensitive comparison.

  - **-contain**

    Match substring.

  - **-end**

    Exact match at the end of string (suffix match).

  - **-exact**

    Use exact string matching.

  - **-icase**

    Case-insensitive comparison.

  - **-pcre** or **-perl**

    Use Perl-compatible regular expression (requires compilation-time support).  This overrides global **RegexType** settings.

  - **-posix**

    Use POSIX extended regular expression.  This overrides global **RegexType** settings.

  - **-re**

    Use regular expression matching, as set by the **RegexType** statement.

The *value* argument in the above directives is subject to string expansion. Refer to subsection **String expansions**, for details.

The **Rewrite** block statement is used to associate one or more of the above directives with request matching directives (discussed in the subsection **Service Matching Directives** above), so that request modification takes place only when the request matches certain conditions.

Syntactically, a **Rewrite** block is:

```
Rewrite [request]
.
.
.
Else
.
.
.
End
```

where dots stand for any number of request matching and request modification statements.  The **Else** part is optional; any number of **Else** blocks can be supplied, thus providing for conditional branching. The following concocted example illustrates it:

```
Rewrite
   Path "\.(jpg|gif)$"
   SetPath "/images%[path]"
Else
   Match AND
     Host "example.org"
     Path "\.[^.]+$"
   End
   SetPath "/static%[path]"
Else
   Path "\.[^.]+$"
   SetPath "/assets%[path]"
End
```

Here, if a path ends with a filename with suffix ".jpg" or ".gif", "/images" is prepended to it (notice that path always starts with a slash, hence it should not be used explicitly).  If the path ends with any other extension, the action depends on the host being addressed.  The path is prefixed with "/static" if the host is "example.org", and with "/assets" otherwise.

To illustrate the effects of string expansion, here's the the above example rewritten using backreference expansion instead of request accessors:

```
Rewrite
   Path ".*\.(jpg|gif)$"
   SetPath "/images$0"
Else
   Match AND
     Host "example.org"
     Path ".*\.[^.]+$"
   End
   SetPath "/static$0"
Else
   Path ".*\.[^.]+$"
   SetPath "/assets$0"
End
```

Request modification directives from **ListenHTTP** (or **ListenHTTPS**) section are applied first, followed by directives from the **Service** section.  Directives appearing within a single section are applied in the same order as they appear in the configuration file.

## BUILT-IN HEADERS

In addition to the **SetHeader** and **DeleteHeader** directives discussed above, the **HeaderOption** directive controls insertion of the built-in headers:

- **HeaderOption** *opt*...

  There are two kinds of such headers: *forwarded* headers that convey information about original destination of the request, and *ssl* headers (for **HTTPS** connections), that hold information about server and client SSL certificates.  These are discussed in detail below.

By default, both kinds of built-in additional headers are enabled. This default can be changed by using the **HeaderOption** directive. Placed in global scope, this directive sets global options.  Used within a **ListenHTTP** or **ListenHTTPS** block, it affects only settings for that listener.

The *opt* values passed to the directive are:

- **none**

  Disable both kinds of additional headers.

- **forwarded**

  Enable forwarded headers.

- **no-forwarded**

  Disable forwarded headers.

- **ssl**

  Enable ssl headers.

- **no-ssl**

  Disable ssl headers.

The built-in headers are added before request modification directives are applied.  Thus, you can use **DeleteHeader** and **SetHeader** to trim down headers added by **HeaderOptions**.

### Forwarded Headers

The headers in the *forwarded* header group are:

- **X-Forwarded-For**

  The IP address of the HTTP client that sent the request,

- **X-Forwarded-Proto**

  The protocol (**http** or **https**) that the client used to connect to **pound**.

- **X-Forwarded-Port**

  Destination port that the client used to connect to **pound**.

### HTTPS Headers

If a client browser connects to **pound** via HTTPS and the *ssl* header group is enabled, then the following header is added:

- **X-SSL-Cipher**

  Contains SSL version followed by a slash and active cipher algorithm.

Additionally, if the client presented its certificate, the following headers are added that describe the client certificate:

- **X-SSL-Subject**

  Details about the certificate owner.

- **X-SSL-Issuer**

  Details about the certificate issuer (Certificate Authority).

- **X-SSL-NotBefore**

  Starting date of certificate validity.

- **X-SSL-NotAfter**

  Ending date of certificate validity.

- **X-SSL-Serial**

  Certificate serial number (decimal).

- **X-SSL-Certificate**

  The full client certificate (PEM-format multi-line)

## RESPONSE MODIFICATION

Headers in the response obtained from a regular backend or generated with a **Error** backend can be modified before sending them back to the requesting server.  A special form of the **Rewrite** directive is provided for this purpose:

```
Rewrite response
.
.
.
Else
.
.
.
End
```

where dots stand for any number of response matching and modification statements.  The **Else** part is optional; any number of **Else** blocks can be supplied, thus providing for conditional branching.

This directive can be used in **ListenHTTP**, **ListenHTTPS**, and **Service** definitions.

Response modification directives from the **Service** section are applied first, followed by directives from the **ListenHTTP** (or **ListenHTTPS**) section.  Directives appearing within a single section are applied in the same order as they appear in the configuration file.

Response matching statements are:

- **Header** \[*options*\] "*pattern*"

  Matches if the response contains at least one header matching the given *pattern*.

- **StringMatch** "*string*" \[*options*\] "*pattern*"

  Expand *string* as described in **String expansion** (see below) and match the resulting value against *pattern*.

-

  By default, *pattern* is treated as case-insensitive extended regular expression.  This can be changed by *options*, as described in section **Service Matching Directives**, above.

- **Match**

  The **Match** statement is as described in section **Match statement**, except that only directives described above are allowed within it.

- **Not**

  Placed before any of the above directives, reverts its result.

Following *response modification* statements are defined:

- **DeleteHeader** "*header***:** *pattern*"

  Remove matching headers from the response.

- **SetHeader** "*header***:** *value*"

  Add header to the response.  Argument undergoes string expansion as described above. The expanded value must be a valid header line.

## MULTI-VALUE HEADERS

HTTP protocol allows for certain headers to appear in the message multiple times.  Namely, multiple headers with the same header name are permitted if that header field is defined as a comma-separated list.  The standard specifies that such fields can be combined in a single *header: value* pair, by appending each subsequent field value to the previous one, each separated by a comma.

**Pound** is able to perform such combining both on incoming requests and on responses.  To enable this feature, declare names of headers that can be combined using the **CombineHeaders** section statement.  This statement must be followed by header names, each on a separate line, and terminated with an **End** statement.  E.g.:

```
CombineHeaders
    "Accept"
    "Allow"
    "Forwarded"
End
```

You can also store header names in a file, and include that file after **CombineHeaders**, e.g.:

```
CombineHeaders
    Include "multivalue.txt"
End
```

## BASIC AUTHENTICATION

To limit access to a service or services to certain authenticated users, use a combination of **BasicAuth** matching and response modification.

The **BasicAuth** matching directive evaluates to true, if the incoming request contains Authorization header with scheme "Basic", such that user name and password obtained from it match a line in the given disk file.  The file must be a plain-text file created with [**htpasswd**(1)](/htpasswd/1.md) or similar utility, i.e. each non-empty line of it must contain username and password hash separated by a colon.  Password hash can be one of:

- 1\.

  Password in plain text.

- 2\.

  Hash created by the system [**crypt**(3)](/crypt/3.md) function.

- 3\.

  Password hashed using SHA1 algorithm and encoded in base64. This hash must be prefixed by **{SHA}**.

- 4\.

  Apache-style *apr1* hash.

Combined with the response rewriting described above, this can be used to implement basic HTTP authentication in **Pound** as shown in the following example:

```
  Service "auth"
      Not BasicAuth "/etc/pound/htpass"
      Rewrite response
          SetHeader "WWW-Authenticate: Basic realm=\"Restricted access\""
      End
      Error 401
  End
```

Placing this service definition before others ensures that services defined below it will be tried only if the incoming request passes basic authentication.

## REQUEST LOGGING

Logging of HTTP requests and responses is controlled by **LogLevel** directive.  This directive can appear either in global scope, in which case it affects all listeners defined below it, or in listener scope, in which case it affects only this listener, overriding the global setting.

Argument to the **LogLevel** directive can be either an integer number in range 0 through 5 (inclusive), or a quoted string.  Numeric value identifies one of the *built-in* log formats, described later in this section.  String value refers either to a built-in format name, or to a user-defined format name. In the latter case, the named format must be defined earlier using the **LogFormat** statement.

### Format specification

The syntax of the **LogFormat** statement is:

```
LogFormat "name" "format_string"
```

First argument, *name*, is a unique identifier for this format, which will be used later to refer to it.  *Format\_string* is a character string composed of ordinary characters (not **%**), which are copied unchanged to the resulting log message, and conversion specifications, each of which are replaced by a corresponding piece of information about the request or reply.

Conversion specifications are single characters prefixed with a percent sign.  Depending on the specification, an optional *conversion argument* in curly brackets may appear between **%** and conversion character.

The following conversion characters are defined:

- **%%**

  Replaced with the percent sign.

- **%a**

  Originator IP address of the request.  If the request contains the **X-Forwarded-For** header and **TrustedIP** ACL is defined, the value of the header is consulted to obtain the IP address.  The value must be a comma-delimited list of intermediate useragent IP addresses.  To determine the actual useragent IP, the list is traversed from right to left, until an IP is found that is not listed in **TrustedIP** ACL.

-

  If **X-Forwarded-For** header is not present, or **TrustedIP** is not defined, or the above algorithm does not return an IP address, **%a** expands to the actual remote IP address the request came from (same as **%h**).

-

  The **TrustedIP** ACL can be defined in global scope, or in **ListenHTTP** (**ListenHTTPS**) section, or in **Service** section.  Most-specific ACL overrides least-specific ones, that is **TrustedIP** defined in **Service** will be used, if it is defined.  If not, the one defined in listener will be used, etc. The syntax of the **TrustedIP** statement is the same as that of **ACL**, i.e.

-

  ```
  TrustedIP "name"
  ```

-

  refers to the named ACL *name* (which must be defined earlier), and

-

  ```
  TrustedIP
    "CIDR0"
    "CIDR1"
    ...
  End
  ```

-

  defines the list of trusted IPs in place.

-

  **ForwardedHeader** statement defines the name of the header to use instead of **X-Forwarded-For**.  As **TrustedIP**, this statement can appear in global, listener, or in service scope.

- **%A**

  Local IP address of the listener.

- **%B**

  Size of response in bytes, excluding headers.

- **%b**

  Same as **%B**, but in *CLF* format, i.e. a dash is used when response size is zero.

- **%D**

  The time taken to serve the request, in microseconds.

- **%h**

  Client IP address of the request.

- **%H**

  The request protocol.

- **%{***VARNAME***}i**

  The contents of *VARNAME:* header line in the request.  Changes made by header modification directives affect this.

- **%{***VARNAME***}I**

  Same as **%i**, except that if no such header is present in the request, a dash is substituted.

- **%{***OBJNAME***}L**

  Location of the **Pound** object that is involved in handling the request.  Valid values for *OBJNAME* are: **listener**, **service**, and **backend**. The location gives position in the configuration file where the object was defined, and is formatted as

-

  ```
  NAME:LN1.COL1-LN2.COL2
  ```

-

  where *NAME* is the configuration file name, *LN1* and *COL1* are number of line and column where the object definition begins, and *LN2* and *COL2* are number of line and column where it ends.  Line and column numbers start with 1.

- **%m**

  The request method.

- **%{***OBJNAME***}N**

  Name of the **Pound** object that is involved in handling the request.  Valid values for *OBJNAME* are: **listener**, **service**, and **backend**.

- **%P**

  Thread ID of the serving thread.

- **%q**

  The query string prepended with a **?** if it exists, otherwise an empty string.

- **%r**

  First line of request.

- **%s**

  Response status code.

- **%\>s**

  First line of the response.

- **%t**

  Time the request was received, in the format **\[18/Sep/2011:19:18:28 -0400\]**. The last number indicates the timezone offset from UTC.

- **%{format}t**

  Time the request was received, in the format specified by the argument ([**strftime**(3)](/strftime/3.md)). If the format starts with **begin:** (default) the time is taken at the beginning of the request processing.  If it starts with end: it is the time after the response from the backend has been sent back to the requester.  In addition to [**strftime**(3)](/strftime/3.md) formats, the following specifications are recognized:

- **sec**

  Number of seconds since the Epoch.

- **msec**

  Number of milliseconds since the Epoch.

- **usec**

  Number of microseconds since the Epoch.

- **msec\_frac**

  Millisecond fraction of the time.

- **usec\_frac**

  Microsecond fraction of the time.

- **%T**

  The time taken to process the request, in seconds.

- **%{***UNIT***}T**

  The time taken to process the request, in a time unit given by *UNIT*.  Valid units are **ms** for milliseconds, **us** for microseconds, **s** for seconds, and **f** for seconds with fractional part.  Using **s** gives the same result as **%T** without any format; using **us** gives the same result as **%D**.

- **%u**

  Remote user if the request was authenticated.

- **%U**

  The URL path requested.  This is affected by request modification directives.

- **%v**

  The listener name.

### Built-in formats

There are five built-in formats.  These can be identified either by their numeric index in the format table, or by symbolic name.  The table below describes each built-in format using the format specification string:

- **0**, **null**

  No request logging at all.

- **1**, **regular**

  ```
  "%a %r - %>s"
  ```

- **2**, **extended**

  ```
  "%a %r - %>s (%{Host}i/%{service}N -> %{backend}N) %{f}T sec"
  ```

- **3**, **vhost\_combined**

  (Split in two lines for readability)

  ```
  "%{Host}I %a - %u %t \"%r\" %s %b \"%{Referer}i\" \
  \"%{User-Agent}i\""
  ```

- **4**, **combined**

  ```
  "%a - %u %t \"%r\" %s %b \"%{Referer}i\" \"%{User-Agent}i\""
  ```

- **5**, **detailed**

  (Split in two lines for readability)

  ```
  "%{Host}I %a - %u %t \"%r\" %s %b \"%{Referer}i\" \
  \"%{User-Agent}\" (%{service}N -> %{backend}N) %{f}T sec"
  ```

## SECURITY

In general, **pound** does not read or write to the hard-disk. The exceptions are reading the configuration file and (possibly) the server certificate file(s) and error message(s), which are opened read-only on startup, read, and closed, and the pid file which is opened on start-up, written to and immediately closed. Following this there is no disk access whatsoever, so using a **RootJail** directive is only for extra security bonus points.

**Pound** tries to sanitize all HTTP/HTTPS requests: the request itself, the headers and the contents are checked for conformance to the RFCs and only valid requests are passed to the backend servers. This is not absolutely fool-proof - as the recent Apache problem with chunked transfers demonstrated. However, given the current standards, this is the best that can be done - HTTP is an inherently weak protocol.

## DEPRECATED FEATURES

### Configuration statements

The following configuration statements are retained for backward compatibility with earlier **pound** versions.  They will disappear from future releases:

- **HeadRequire**

  Use **Header** instead.  See **Service Matching Directives**, for details.

- **HeadDeny**

  Use **Not Header**. For details, see the **Negation** subsection in **Service Matching Directives**.

- **AddHeader** and **HeaderAdd**

  Use **SetHeader** instead.  See the section **REQUEST MODIFICATION DIRECTIVES**, for details.

- **HeaderRemove** and **HeadRemove**

  Use **DeleteHeader** instead. See the section **REQUEST MODIFICATION DIRECTIVES**, for details.

- **IgnoreCase**

  Use the **-icase** option to the **URL** directive instead.  See the discussion of *options* in the **Service Matching Directives** section.

- **Err***NNN*

  (where *NNN* is one of: **400**, **401**, **403**, **404**, **413**, **414**, **500**, **501**, **503**)

-

  Use the **ErrorFile** directive, described in the section **HTTP**Listener**,** above.

### Redirect request hack

The use of the *redirect request* hack in the **Redirect** statement is deprecated as well. Instead of relying on the trailing slash to append the original URL to the redirect location, use URL backreferences.  For example, instead of

```
  Redirect "http://example.org/"
```

use:

```
  URL ".*"
  Redirect "http://example.org$0"
```

### Multiple redirect backends

Use of multiple **Redirect** backends in a single service is deprecated, as well as using  **Redirect** backends together with regular ones.  If you know of any valid usage for such configuration, please drop a note to the authors (see **REPORTING BUGS**, below).

## ADDITIONAL NOTES

**Pound** uses the system log for messages (default facility **LOG\_DAEMON**). If using **rsyslog**, you can use the following configuration fragment to redirect **pound** messages to a separate file:

```
:programname, startswith, "pound" {
  /var/log/pound.log
  stop
}
```

The format requested by **LogLevel 3** is understood by most log analyzers.

Translating HTTPS to HTTP is an iffy proposition: no client information is passed to the server itself (certificates, etc) and the backend server may be misled if it uses absolute URLs. **Pound** tries to handle this by adding various **X-Forwarded-\*** and **X-SSL-\*** headers.  See **HEADER MODIFICATION** above, for a detailed discussion.

**Pound** deals with (and sanitizes) HTTP/1.1 requests. Thus even if you have an HTTP/1.0 server, a single connection to an HTTP/1.1 client is kept, while the connection to the backend server is re-opened as necessary.

**Pound** attempts to resolve the names of the hosts that appear in various requests and/or responses.  That means it needs a functioning resolver of some kind (be it **/etc/hosts**, DNS or something else). However, the use of DNS can be disabled using the **-W no-dns** command line option.

## EXAMPLES

To translate HTTPS requests to a local HTTP server (assuming your network address is 192.0.2.1):

```
ListenHTTPS
    Address 192.0.2.1
    Port    443
    Cert    "/etc/pound/server.pem"
    Service
        Backend
            Address 127.0.0.1
            Port    80
        End
    End
End
```

To distribute the HTTP/HTTPS requests to three Web servers, where the third one is a newer and faster machine:

```
ListenHTTP
    Address 192.0.2.1
    Port    80
End
ListenHTTPS
    Address 192.0.2.1
    Port    443
    Cert    "/etc/pound/server.pem"
End
Service
    Backend
        Address 192.168.0.10
        Port    80
    End
    Backend
        Address 192.168.0.11
        Port    80
    End
    Backend
        Address 192.168.0.12
        Port    80
        Priority 3
    End
End
```

To separate between image requests and other Web content and send all requests for a specific URL to a secure server:

```
ListenHTTP
    Address 192.0.2.1
    Port    80
End
# Images server(s)
Service
    URL ".*.(jpg|gif)"
    Backend
        Address 192.168.0.12
        Port    80
    End
End
# redirect all requests for /forbidden
Service
    Url         -beg "/forbidden"
    Redirect    "https://xyzzy.com"
End
# Catch-all server(s)
Service
    Backend
        Address 192.168.0.10
        Port    80
    End
    Backend
        Address 192.168.0.11
        Port    80
    End
    Session
        Type    BASIC
        TTL     300
    End
End
```

Here is a more complex example: assume your static images (GIF/JPEG) are to be served from a single backend 192.168.0.10. In addition, 192.168.0.11 is to do the hosting for *www.myserver.com* with URL-based sessions.  Two backends, 192.168.0.20 and 192.168.0.21, will handle the rest of requests (cookie-based sessions).  Among these, the latter (192.168.0.21) is less powerful than the former, so care should be taken that it gets less requests.  The logging will be done by backend servers.  All plain HTTP requests are to be redirected to HTTPS and all requests directed to *myserver.com* - to *www.myserver.com*.  The configuration file may look like this:

```
User        "nobody"
Group       "nogroup"
RootJail    "/var/pound/jail"
Alive       60
LogLevel    0
# HTTP: redirect all requests to the corresponding HTTPS server.
ListenHTTP
    Address 192.0.2.1
    Port    80
    Client  10
    Service
        Host -re ".+"
        URL ".*"
        Redirect 301 "https://$0(1)$0"
    End
End
ListenHTTPS
    Address 192.0.2.1
    Port    443
    Cert    "/etc/pound/pound.pem"
    Client  20
End
# Image server
Service
    URL ".*.(jpg|gif)"
    Backend
        Address 192.168.0.10
        Port    80
    End
End
# Virtual host www.myserver.com
Service
    URL         ".*sessid=.*"
    Host        "www.myserver.com"
    Backend
        Address 192.168.0.11
        Port    80
    End
    Session
        Type    URL
        ID      "sessid"
        TTL     120
    End
End
# Virtual host myserver.com - redirects to www.
Service
    Host        "myserver.com"
    URL         ".*"
    Redirect 301 "https://www.myserver.com$0"
End
# Virtual host server1.com and www.server1.com
Service
    Host        -re "^(www.)?server1.com$"
    Backend
        Address 192.168.0.20
        Port    80
        Priority 5
    End
    Backend
        Address 192.168.0.21
        Port    80
        Priority 4
    End
    Session
        Type    COOKIE
        ID      "userid"
        TTL     180
    End
End
# Return custom error page if no matching service was found.
Service
    Error 404 "/var/lib/pound/notfound.html"
End
```

## FILES

- **/var/run/pound.pid**

  This is where **pound** will attempt to record its process id.  The exact location is determined at compile time by the value of the **--localstatedir** configuration switch.  It can be changed at runtime using the **-p** command line option.   Use **pound -V** to inspect the actual default.

- **/etc/pound.cfg**

  The default configuration file.  The exact location is determined at compile time by the value of the **--sysconfdir** configuration switch.  It can be changed at runtime using the **-f** command line option.  Use **pound -V** to inspect the actual default.

- **/usr/local/etc/pound/cert.pem**

  the certificate file(s) for HTTPS. The location must be defined in the configuration file - this is only a suggestion. The file must contain a PEM-encoded certificate, optionally a certificate chain from a known Certificate Authority to your server certificate and a PEM-encoded private key (not password protected). See [**openssl**(1)](/openssl/1.md) for details. This file should be well protected, lest someone gets your server private key.

## AUTHOR

Written by Robert Segall (Apsis GmbH), and Sergey Poznyakoff.

## REPORTING BUGS

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

## COPYRIGHT

Copyright © 2002-2010 Apsis GmbH.\
 Copyright © 2018-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.
