Documentation

You are viewing the documentation for the 3.0.2 release. The latest stable release series is 3.0.x.

§Production Configuration

There are a number of different types of configuration that you can configure in production. The three mains types are:

Each of these types have different methods to configure them.

§General configuration

Play has a number of configurable settings. You can configure database connection URLs, the application secret, the HTTP port, SSL configuration, and so on.

Most of Play’s configuration is defined in various .conf files, which use the HOCON format. The main configuration file that you’ll use is the application.conf file. You can find this file at conf/application.conf within your project. The application.conf file is loaded from the classpath at runtime (or you can override where it is loaded from). There can only be one application.conf per project.

Other .conf files are loaded too. Libraries define default settings in reference.conf files. These files are stored in the libraries’ JARs—one reference.conf per JAR—and aggregated together at runtime. The reference.conf files provide defaults; they are overridden by any settings defined in the application.conf file.

Play’s configuration can also be defined using system properties and environment variables. This can be handy when settings change between environments; you can use the application.conf for common settings, but use system properties and environment variables to change settings when you run the application in different environments.

System properties override settings in application.conf, and application.conf overrides the default settings in the various reference.conf files.

You can override runtime configuration in several ways. This can be handy when settings vary between environments; you can changing the configuration dynamically for each environment. Here are your choices for runtime configuration:

§Specifying an alternate configuration file

The default is to load the application.conf file from the classpath. You can specify an alternative configuration file if needed:

§Using -Dconfig.resource

This will search for an alternative configuration file in the application classpath (you usually provide these alternative configuration files into your application conf/ directory before packaging). Play will look into conf/ so you don’t have to add conf/.

$ /path/to/bin/<project-name> -Dconfig.resource=prod.conf

§Using -Dconfig.file

You can also specify another local configuration file not packaged into the application artifacts:

$ /path/to/bin/<project-name> -Dconfig.file=/opt/conf/prod.conf

Note that you can always reference the original configuration file in a new prod.conf file using the include directive, such as:

include "application.conf"

key.to.override=blah

§Overriding configuration with system properties

Sometimes you don’t want to specify another complete configuration file, but just override a bunch of specific keys. You can do that by specifying then as Java System properties:

$ /path/to/bin/<project-name> -Dplay.http.secret.key=ad31779d4ee49d5ad5162bf1429c32e2e9933f3b -Ddb.default.password=toto

§Specifying the HTTP server address and port using system properties

You can provide both HTTP port and address easily using system properties. The default is to listen on port 9000 at the 0.0.0.0 address (all addresses).

$ /path/to/bin/<project-name> -Dhttp.port=1234 -Dhttp.address=127.0.0.1

§Specifying the HTTP server address and port using environment variables

You can provide both HTTP port and address easily using environment variables, e.g. when using Bash in Linux:

export PLAY_HTTP_PORT=1234
export PLAY_HTTPS_PORT=1235
export PLAY_HTTP_ADDRESS=127.0.0.1

These variables are picked up last, meaning any already defined port or address in application.conf or via system properties will override these environment variables.

§Changing the path of RUNNING_PID

It is possible to change the path to the file that contains the process id of the started application. Normally this file is placed in the root directory of your play project, however it is advised that you put it somewhere where it will be automatically cleared on restart, such as /var/run:

$ /path/to/bin/<project-name> -Dpidfile.path=/var/run/play.pid

Make sure that the directory exists and that the user that runs the Play application has write permission for it.

Using this file, you can stop your application using the kill command, for example:

$ kill $(cat /var/run/play.pid)

To prevent Play from creating it’s own PID, you can set the path to /dev/null in your application.conf file:

pidfile.path = "/dev/null"

§Using environment variables

You can also reference environment variables from your application.conf file:

my.key = defaultvalue
my.key = ${?MY_KEY_ENV}

Here, the override field my.key = ${?MY_KEY_ENV} simply vanishes if there’s no value for MY_KEY_ENV, but if you set an environment variable MY_KEY_ENV for example, it would be used.

§Server configuration options

Play’s default HTTP server implementation is Pekko HTTP, and this provides a large number of ways to tune and configure the server, including the size of parser buffers, whether keep alive is used, and so on.

A full list of server configuration options, including defaults, can be seen here:

# Copyright (C) from 2022 The Play Framework Contributors <https://github.com/playframework>, 2011-2021 Lightbend Inc. <https://www.lightbend.com>

# Configuration for Play's PekkoHttpServer
play {

  server {
    # The server provider class name
    provider = "play.core.server.PekkoHttpServerProvider"

    pekko {
      # How long to wait when binding to the listening socket
      bindTimeout = 5 seconds

      # How long a request takes until it times out. Set to null or "infinite" to disable the timeout.
      requestTimeout = infinite

      # Enables/disables automatic handling of HEAD requests.
      # If this setting is enabled the server dispatches HEAD requests as GET
      # requests to the application and automatically strips off all message
      # bodies from outgoing responses.
      # Note that, even when this setting is off the server will never send
      # out message bodies on responses to HEAD requests.
      # For Play to work correctly with WebSockets, you should avoid setting this config to "on",
      # see https://github.com/playframework/playframework/pull/7060
      transparent-head-requests = off

      # If this setting is empty the server only accepts requests that carry a
      # non-empty `Host` header. Otherwise it responds with `400 Bad Request`.
      # Set to a non-empty value to be used in lieu of a missing or empty `Host`
      # header to make the server accept such requests.
      # Note that the server will never accept HTTP/1.1 request without a `Host`
      # header, i.e. this setting only affects HTTP/1.1 requests with an empty
      # `Host` header as well as HTTP/1.0 requests.
      # Examples: `www.spray.io` or `example.com:8080`
      default-host-header = ""

      # The default value of the `Server` header to produce if no
      # explicit `Server`-header was included in a response.
      # If this value is null and no header was included in
      # the request, no `Server` header will be rendered at all.
      server-header = null
      server-header = ${?play.server.server-header}

      # Configures the processing mode when encountering illegal characters in
      # header value of response.
      #
      # Supported mode:
      # `error`  : default mode, throw an ParsingException and terminate the processing
      # `warn`   : ignore the illegal characters in response header value and log a warning message
      # `ignore` : just ignore the illegal characters in response header value
      illegal-response-header-value-processing-mode = warn

      # Enables/disables inclusion of an Tls-Session-Info header in parsed
      # messages over Tls transports (i.e., HttpRequest on server side and
      # HttpResponse on client side).
      #
      # See Pekko HTTP `pekko.http.server.parsing.tls-session-info-header` for
      # more information about how this works.
      tls-session-info-header = on

      # The maximum number of requests that are accepted (and dispatched to
      # the application) on one single connection before the first request
      # has to be completed.
      # Incoming requests that would cause the pipelining limit to be exceeded
      # are not read from the connections socket so as to build up "back-pressure"
      # to the client via TCP flow control.
      # A setting of 1 disables HTTP pipelining, since only one request per
      # connection can be "open" (i.e. being processed by the application) at any time.
      # This value must be > 0 and <= 1024.
      # ATTENTION:
      # Only enable HTTP pipelining if you _really_ know what you are doing. Nowadays, HTTP pipelining
      # is mostly used for benchmarks anyway. Basically all web browser and most common clients (like curl)
      # removed support for HTTP pipelining, since most client and server implementations were error prone.
      # Also the implemention used by Play can cause unexpected behaviour, e.g. see
      # https://github.com/playframework/playframework/issues/12351
      pipelining-limit = 1
    }
  }

}

You can also use Netty as the HTTP server, which also provides its own configurations. A full list of Netty server configuration, including the defaults, can be seen below:

# Copyright (C) from 2022 The Play Framework Contributors <https://github.com/playframework>, 2011-2021 Lightbend Inc. <https://www.lightbend.com>

play.server {

  # The server provider class name
  provider = "play.core.server.NettyServerProvider"

  netty {

    # The default value of the `Server` header to produce if no explicit `Server`-header was included in a response.
    # If this value is the null and no header was included in the request, no `Server` header will be rendered at all.
    server-header = null
    server-header = ${?play.server.server-header}

    # The number of event loop threads. 0 means let Netty decide, which by default will select 2 times the number of
    # available processors.
    eventLoopThreads = 0

    # When Netty shuts down, it ensures that no tasks (requests) are submitted for 'the quiet period' before it finally shuts down.
    # If a task is submitted during the quiet period, it is guaranteed to be accepted and the quiet period will start over.
    #
    # For more details see:
    # https://netty.io/4.1/api/io/netty/util/concurrent/EventExecutorGroup.html#shutdownGracefully-long-long-java.util.concurrent.TimeUnit-
    #
    # Play keeps using Netty's default of 2 seconds:
    # https://github.com/netty/netty/blob/netty-4.1.92.Final/common/src/main/java/io/netty/util/concurrent/AbstractEventExecutor.java#L40
    shutdownQuietPeriod = 2 seconds

    # The maximum length of the initial line. This effectively restricts the maximum length of a URL that the server will
    # accept, the initial line consists of the method (3-7 characters), the URL, and the HTTP version (8 characters),
    # including typical whitespace, the maximum URL length will be this number - 18.
    maxInitialLineLength = 4096

    # The maximum length of body bytes that Netty will read into memory at a time.
    # This is used in many ways.  Note that this setting has no relation to HTTP chunked transfer encoding - Netty will
    # read "chunks", that is, byte buffers worth of content at a time and pass it to Play, regardless of whether the body
    # is using HTTP chunked transfer encoding.  A single HTTP chunk could span multiple Netty chunks if it exceeds this.
    # A body that is not HTTP chunked will span multiple Netty chunks if it exceeds this or if no content length is
    # specified. This only controls the maximum length of the Netty chunk byte buffers.
    maxChunkSize = 8192

    # Whether the Netty wire should be logged
    log.wire = false

    # The transport to use, either jdk or native.
    # Native socket transport has higher performance and produces less garbage but are only available on linux 
    transport = "jdk"

    # Netty options. Possible keys here are defined by:
    #
    # https://netty.io/4.1/api/io/netty/channel/ChannelOption.html
    # For native socket transport:
    # https://netty.io/4.1/api/io/netty/channel/unix/UnixChannelOption.html
    # https://netty.io/4.1/api/io/netty/channel/epoll/EpollChannelOption.html
    #
    # Options that pertain to the listening server socket are defined at the top level, options for the sockets associated
    # with received client connections are prefixed with child.*
    option {

      # Set the size of the backlog of TCP connections.  The default and exact meaning of this parameter is JDK specific.
      # SO_BACKLOG = 100

      child {
        # Set whether connections should use TCP keep alive
        # SO_KEEPALIVE = false

        # Set whether the TCP no delay flag is set
        # TCP_NODELAY = false

        # Example how to set native socket transport options
        # (Full qualified class name + "#" + option)
        # "io.netty.channel.unix.UnixChannelOption#SO_REUSEPORT" = true
        # "io.netty.channel.ChannelOption#TCP_FASTOPEN" = 1
      }

    }

  }
}

Note: The Netty server backend is not the default in 2.6.x, and so must be specifically enabled.

The configurations above are specific to the Pekko HTTP and Netty server backend, but other more generic configurations are also available:

# Copyright (C) from 2022 The Play Framework Contributors <https://github.com/playframework>, 2011-2021 Lightbend Inc. <https://www.lightbend.com>

play {

  server {

    # The root directory for the Play server instance. This value can
    # be set by providing a path as the first argument to the Play server
    # launcher script. See `ServerConfig.loadConfiguration`.
    dir = ${?user.dir}

    # HTTP configuration
    http {
      # The HTTP port of the server. Use a value of "disabled" if the server
      # shouldn't bind an HTTP port.
      port = 9000
      port = ${?PLAY_HTTP_PORT}
      port = ${?http.port}

      # The interface address to bind to.
      address = "0.0.0.0"
      address = ${?PLAY_HTTP_ADDRESS}
      address = ${?http.address}

      # The idle timeout for an open connection after which it will be closed
      # Set to null or "infinite" to disable the timeout, but notice that this
      # is not encouraged since timeout are important mechanisms to protect your
      # servers from malicious attacks or programming mistakes.
      idleTimeout = 75 seconds
    }

    # HTTPS configuration
    https {

      # The HTTPS port of the server.
      port = ${?PLAY_HTTPS_PORT}
      port = ${?https.port}

      # The interface address to bind to
      address = "0.0.0.0"
      address = ${?PLAY_HTTPS_ADDRESS}
      address = ${?https.address}

      # The idle timeout for an open connection after which it will be closed
      # Set to null or "infinite" to disable the timeout, but notice that this
      # is not encouraged since timeout are important mechanisms to protect your
      # servers from malicious attacks or programming mistakes.
      idleTimeout = ${play.server.http.idleTimeout}

      # The SSL engine provider
      engineProvider = "play.core.server.ssl.DefaultSSLEngineProvider"
      engineProvider = ${?play.http.sslengineprovider}

      # HTTPS keystore configuration, used by the default SSL engine provider
      keyStore {
        # The path to the keystore
        path = ${?https.keyStore}

        # The type of the keystore
        type = "JKS"
        type = ${?https.keyStoreType}

        # The password for the keystore
        password = ""
        password = ${?https.keyStorePassword}

        # The algorithm to use. If not set, uses the platform default algorithm.
        algorithm = ${?https.keyStoreAlgorithm}
      }

      # HTTPS truststore configuration
      trustStore {

        # If true, does not do CA verification on client side certificates
        noCaVerification = false
      }

      # Whether JSSE want client auth mode should be used. This means, the server
      # will request a client certificate, but won't fail if one isn't provided.
      wantClientAuth = false

      # Whether JSSE need client auth mode should be used. This means, the server
      # will request a client certificate, and will fail and terminate the session
      # if one isn't provided.
      needClientAuth = false
    }

    # The path to the process id file created by the server when it runs.
    # If set to "/dev/null" then no pid file will be created.
    pidfile.path = ${play.server.dir}/RUNNING_PID
    pidfile.path = ${?pidfile.path}

    websocket {
      # Maximum allowable frame payload length. Setting this value to your application's
      # requirement may reduce denial of service attacks using long data frames.
      frame.maxLength = 64k
      frame.maxLength = ${?websocket.frame.maxLength}

      # Periodic keep alive may be implemented using by sending Ping frames
      # upon which the other side is expected to reply with a Pong frame,
      # or by sending a Pong frame, which serves as unidirectional heartbeat.
      # Valid values:
      #   ping - default, for bi-directional ping/pong keep-alive heartbeating
      #   pong - for uni-directional pong keep-alive heartbeating
      periodic-keep-alive-mode = ping

      # Interval for sending periodic keep-alives
      # If a client does not send a frame within this idle time, the server will sent the the keep-alive frame.
      # The frame sent will be the one configured in play.server.websocket.periodic-keep-alive-mode
      # `infinite` by default, or a duration that is the max idle interval after which an keep-alive frame should be sent
      # The value `infinite` means that *no* keep-alive heartbeat will be sent, as: "the allowed idle time is infinite"
      periodic-keep-alive-max-idle = infinite
    }

    debug {
      # If set to true this will attach an attribute to each request containing debug information. If the application
      # fails to load (e.g. due to a compile issue in dev mode), then this configuration value is ignored and the debug
      # information is always attached.
      #
      # Note: This configuration option is not part of Play's public API and is subject to change without the usual
      # deprecation cycle.
      addDebugInfoToRequests = false
    }

    # The maximum length of the HTTP headers. The most common effect of this is a restriction in cookie length, including
    # number of cookies and size of cookie values.
    max-header-size = 8k

    # If a request contains a Content-Length header it will be checked against this maximum value.
    # If the value of a given Content-Length header exceeds this configured value, the request will not be processed
    # further but instead the error handler will be called with Http status code 413 "Entity too large".
    # If set to infinite or if no Content-Length header exists then no check will take place at all
    # and the request will continue to be processed.
    # Play uses the concept of a `BodyParser` to enforce this limit, so we set it to infinite.
    max-content-length = infinite

    # Timeout after which all requests and connections shall be forcefully terminated
    # when shutting down the server. When this timeout gets applied, already the server is not bound to ports
    # and therefore not accepting new connections anymore. It will default to Coordinated Shutdown service-requests-done
    # phase timeout. Because of that default, Play will trigger the timeout 100 milliseconds earlier than actually configured
    # via this config to make sure it fires before the service-requests-done phase ends.
    # Value must be a duration, for example:
    #   play.server.terminationTimeout = 5 seconds
    # This should be less than or equal to the value for `pekko.coordinated-shutdown.phases.service-requests-done.timeout`
    # to prevent early server terminations by the underlying Pekko Coordinated Shutdown system.
    terminationTimeout = null

    # The delay to wait before the server will shut down requests and connections via "graceful" termination. When
    # this delay gets applied, already the server is not bound to ports and therefore not accepting new connections anymore.
    # This config might help you do work around a bug which causes the pekko-http backend to not take response entity streams into account
    # during graceful termination, giving those responses time to finish: https://github.com/akka/akka-http/issues/3209
    # By default, no delay is applied.
    # Value must be a duration, for example:
    #   play.server.waitBeforeTermination = 2 seconds
    # Be aware that `waitBeforeTermination` and `terminationTimeout` both happen within the Coordinated Shutdown `service-requests-done` phase.
    # Therefore, the total value of the two configs should not be longer than the total timeout of the `service-requests-done` phase.
    waitBeforeTermination = 0

    # If body parsing should happen before executing actions defined via action composition (default) or if it should
    # be deferred to a later point in time.
    # Depending on the used Play plugin (PlayScala or PlayJava), setting this config to true will behave slightly differently.
    # Please see the docs for more details:
    # PlayScala
    # https://playframework.com/documentation/latest/ScalaActionsComposition#Action-composition-in-interaction-with-body-parsing
    # PlayJava
    # https://playframework.com/documentation/latest/JavaActionsComposition#Action-composition-in-interaction-with-body-parsing
    deferBodyParsing = false
  }

  editor = ${?PLAY_EDITOR}

}

§Logging configuration

Logging can be configured by creating a logback configuration file. This can be used by your application through the following means:

§Bundling a custom logback configuration file with your application

Create an alternative logback config file called logback.xml and copy that to <app>/conf

You can also specify another logback configuration file via a System property. Please note that if the configuration file is not specified then play will use the default logback.xml that comes with play in the production mode. This means that any log level settings in application.conf file will be overridden. As a good practice always specify your logback.xml.

§Using -Dlogger.resource

Specify another logback configuration file to be loaded from the classpath:

$ /path/to/bin/<project-name> -Dlogger.resource=prod-logger.xml

§Using -Dlogger.file

Specify another logback configuration file to be loaded from the file system:

$ /path/to/bin/<project-name> -Dlogger.file=/opt/prod/prod-logger.xml

§Using -Dlogger.url

Specify another logback configuration file to be loaded from an URL:

$ /path/to/bin/<project-name> -Dlogger.url=http://conf.mycompany.com/logger.xml

Note: To see which file is being used, you can set a system property to debug it: -Dlogback.debug=true.

§JVM configuration

You can specify any JVM arguments to the application startup script. Otherwise the default JVM settings will be used:

$ /path/to/bin/<project-name> -J-Xms128M -J-Xmx512m -J-server

Next: Setting up a front end HTTP server