---
layout: docs
page_title: Controller - Configuration
description: |-
  The controller stanza configures controller-specifc parameters.
---

# `controller` Stanza

The `controller` stanza configures Boundary controller-specific parameters.

```hcl
controller {
  name = "example-controller"
  description = "An example controller"
  database {
    url = "postgresql://<username>:<password>@10.0.0.1:5432/<database_name>"
    max_open_connections = 5
  }
}
```

- `name` - Specifies a unique name of this controller within the Boundary
  cluster. This value can be a direct name string, can refer to a file on disk
  (file://) from which an name will be read; or an env var (env://) from which
  the name will be read.

- `description` - Specifies a friendly description of this controller. This value can be a direct description string,
can refer to a file on disk (file://) from which a description will be read; or an env var (env://) from which the
description will be read.

- `database` - Configuration block with two valid parameters for connecting to Postgres:

  - `url` - Configures the URL for connecting to Postgres. If your Postgres server has TLS disabled,
    Boundary will not be able to connect by default. To run Boundary without a TLS connection
    to Postgres (not recommended for production usage), add the `sslmode=disable` parameter to
    your connection string, such as `url = "postgresql://postgres:boundary@192.168.1.1:5432/boundary?sslmode=disable"`
    This value can refer to a file on disk (file://) from which a URL will be read; an env
    var (env://) from which the URL will be read; or a direct database URL (postgres://).
  - `migration_url` - Can be used to specify a different URL for migrations, as that
    usually requires higher privileges.
    This value can refer to a file on disk (file://) from which a URL will be read; an env
    var (env://) from which the URL will be read; or a direct database URL (postgres://).
  - `max_open_connections` - Can be used to control the maximum number of
    connections that can be opened by the controller.
    The minimum number of connections required is 5.
    Setting this value to 0 will allow the controller to open as many connections as needed.
    This value can be a string or an integer representing the max number of connections,
    or a string that can refer to a file
    on disk (file://) from which the number of connections will be read,
    or an env var (env://) from which the number of connections will be read.
  - `max_idle_connections` - Can be used to control the maximum number of
    idle connections in the idle connection pool.
    If `max_open_connections` is greater than 0 but less than
    `max_idle_connections`, then `max_idle_connections` will be reduced to match the `max_open_connections` limit.
    Setting this value to 0 will mean that no idle connections are retained.
    If not set or set to less than 0, the default
    [sql.DB](https://pkg.go.dev/database/sql#DB.SetMaxIdleConns) setting will be used.
    This value can be a string or an integer representing the max number of connections,
    or a string that can refer to a file on disk (file://) from which the number of connections will be read,
    or an env var (env://) from which the number of connections will be read.
  - `max_idle_time` - Can be used to control the maximum amount of time
    a connection may be idle.
    Setting this value to 0 will mean that connections are not closed due to a
    connections idle time.
    If not set or set to less than 0, the default
    [sql.DB](https://pkg.go.dev/database/sql#DB.SetConnMaxIdleTime) setting will be used.
    This value can be a string representing the duration,
    or a string that can refer to a file on disk (file://) from which the duration will be read,
    or an env var (env://) from which the duration will be read.
    Valid time units are anything specified by Golang's
    [ParseDuration()](https://golang.org/pkg/time/#ParseDuration) method.

- `public_cluster_addr` - Specifies the public host or IP address (and
  optionally port) at which the controller can be reached _by workers_. This will
  be used by workers after initial connection to controllers via the worker's
  `controllers` block. This defaults to the address of the listener marked for
  `cluster` purpose. This is especially useful for cloud environments that do not
  bind a publicly accessible IP to a NIC on the host directly, such as an Amazon
  EIP. This value can be a direct address string, can refer to a file on disk (file://)
  from which an address will be read; an env var (env://) from which the
  address will be read; or a [go-sockaddr template](https://godoc.org/github.com/hashicorp/go-sockaddr/template).

- `auth_token_time_to_live` - Maximum time to live (TTL) for all auth tokens globally (pertains
  to all tokens from all auth methods). Valid time units are anything specified by Golang's
  [ParseDuration()](https://golang.org/pkg/time/#ParseDuration) method. Default is 7 days.

- `auth_token_time_to_stale` - Maximum time of inactivity for all auth tokens globally (pertains
  to all tokens from all auth methods). Valid time units are anything specified by Golang's
  [ParseDuration()](https://golang.org/pkg/time/#ParseDuration) method. Default is 1 day.

- `scheduler` - The configuration block that specifies the job scheduler behavior on the controller.

  - `job_run_interval` - The interval at which the scheduler will call the database to check if
    there are any jobs that need to run. Default is 1 minute.

  - `monitor_interval` - The interval at which the scheduler will check and interrupt any defuncted
  jobs that were running on another scheduler. A job is considered defuncted if it has not reported
  a status to the database for 5 minutes. Once a job is interrupted it will be run immediate on the
  first controller available. Default is 30 seconds.

- `graceful_shutdown_wait_duration` - Amount of time Boundary will wait before initiating the shutdown procedure,
  after receiving a shutdown signal. In this state, Boundary still processes requests as normal but replies
  with `503 Service Unavailable` to any health requests. This is designed to allow an operator to configure
  load-balancers to preemptively stop new traffic to a Boundary instance that is going away. Valid time units
  are anything specified by Go's [ParseDuration()](https://golang.org/pkg/time/#ParseDuration) method. Only
  used when an `ops` listener is set and the Controller is present. Default is 0 seconds.

## KMS Configuration

The controller requires two KMS stanzas for `root` and `worker-auth` purposes:

```hcl
# Root KMS configuration block: this is the root key for Boundary
# Use a production KMS such as AWS KMS in production installs
kms "aead" {
  purpose = "root"
  aead_type = "aes-gcm"
  key = "sP1fnF5Xz85RrXyELHFeZg9Ad2qt4Z4bgNHVGtD6ung="
  key_id = "global_root"
}

# Worker authorization KMS
# Use a production KMS such as AWS KMS for production installs
# This key is the same key used in the worker configuration
kms "aead" {
  purpose = "worker-auth"
  aead_type = "aes-gcm"
  key = "8fZBjCUfN0TzjEGLQldGY4+iE9AkOvCfjh7+p0GtRBQ="
  key_id = "global_worker-auth"
}
```

And optionally, a KMS stanza for recovery purpose:

```hcl
# Recovery KMS block: configures the recovery key for Boundary
# Use a production KMS such as AWS KMS for production installs
kms "aead" {
  purpose = "recovery"
  aead_type = "aes-gcm"
  key = "8fZBjCUfN0TzjEGLQldGY4+iE9AkOvCfjh7+p0GtRBQ="
  key_id = "global_recovery"
}
```

And optionally, a KMS stanza for configuration encryption purpose:

```hcl
# Configuration encryption block: decrypts sensitive values in the
# configuration file. See `boundary config [encrypt|decrypt] -h`.
kms "aead" {
  purpose   = "config"`
  aead_type = "aes-gcm"
  key       = "7xtkEoS5EXPbgynwd+dDLHopaCqK8cq0Rpep4eooaTs="
}
```

Boundary supports many kinds of KMS integrations. For a complete guide to all available
KMS types, see our [KMS documentation](/boundary/docs/configuration/kms).

# Complete Configuration Example

```hcl
# Disable memory lock: https://www.man7.org/linux/man-pages/man2/mlock.2.html
disable_mlock = true

# Controller configuration block
controller {
  # This name attr must be unique across all controller instances if running in HA mode
  name = "demo-controller-1"
  description = "A controller for a demo!"

  # After receiving a shutdown signal, Boundary will wait 10s before initiating the shutdown process.
  graceful_shutdown_wait_duration = "10s"

  # Database URL for postgres. This can be a direct "postgres://"
  # URL, or it can be "file://" to read the contents of a file to
  # supply the url, or "env://" to name an environment variable
  # that contains the URL.
  database {
	  url = "postgresql://boundary:boundarydemo@postgres.yourdomain.com:5432/boundary"
  }
}

# API listener configuration block
listener "tcp" {
  # Should be the address of the NIC that the controller server will be reached on
  address = "10.0.0.1"
  # The purpose of this listener block
  purpose = "api"

  tls_disable = false

  # Uncomment to enable CORS for the Admin UI. Be sure to set the allowed origin(s)
  # to appropriate values.
  #cors_enabled = true
  #cors_allowed_origins = ["https://yourcorp.yourdomain.com", "serve://boundary"]
}

# Data-plane listener configuration block (used for worker coordination)
listener "tcp" {
  # Should be the IP of the NIC that the worker will connect on
  address = "10.0.0.1"
  # The purpose of this listener
  purpose = "cluster"
}

listener "tcp" {
  # Should be the address of the NIC where your external systems'
  # (eg: Load-Balancer) will connect on.
  address = "10.0.0.1"
  # The purpose of this listener block
  purpose = "ops"

  tls_disable = false
}

# Root KMS configuration block: this is the root key for Boundary
# Use a production KMS such as AWS KMS in production installs
kms "aead" {
  purpose = "root"
  aead_type = "aes-gcm"
  key = "sP1fnF5Xz85RrXyELHFeZg9Ad2qt4Z4bgNHVGtD6ung="
  key_id = "global_root"
}

# Worker authorization KMS
# Use a production KMS such as AWS KMS for production installs
# This key is the same key used in the worker configuration
kms "aead" {
  purpose = "worker-auth"
  aead_type = "aes-gcm"
  key = "8fZBjCUfN0TzjEGLQldGY4+iE9AkOvCfjh7+p0GtRBQ="
  key_id = "global_worker-auth"
}

# Recovery KMS block: configures the recovery key for Boundary
# Use a production KMS such as AWS KMS for production installs
kms "aead" {
  purpose = "recovery"
  aead_type = "aes-gcm"
  key = "8fZBjCUfN0TzjEGLQldGY4+iE9AkOvCfjh7+p0GtRBQ="
  key_id = "global_recovery"
}
```
