Skip to content

Quine Webserver Config

  webserver {
    # whether the webserver should be enabled
    enabled = true

    # Hostname or address of the interface to which the HTTP server should
    # be bound - 0.0.0.0 means "all interfaces"
    # There are two special values which are interpreted dynamically:
    #   1.) "<getHostAddress>" uses the host IP found at runtime
    #   2.) "<getHostName>" uses the host DNS name found at runtime
    address = "0.0.0.0"

    # port to which the HTTP server should be bound
    # setting to `0` will choose an available port at random.
    port = 8080
  }
  # (optional) Configuration to use when advertising this server
  # (e.g., canonical address), if different than bind
  # configuration (e.g., when deployed behind a reverse proxy).
  # webserver-advertise {
    # Hostname or address using which the application should generate
    # user-facing hyperlinks to itself. This should be uniquely
    # resolvable from the end-users' client.
    # address = "localhost"

    # port (on `address`) via which the HTTP server can be reached
    # port = 8080
  # }

Securing Quine

Most enterprise deployments will put Quine behind a reverse proxy, load balancer, or other such network construct. Quine needs to bind to 0.0.0.0 (all interfaces), or a specific network interface, but the end-user reaches quine via a very different address. This may be localhost, quine.mycompany.com, or any other URL. Similarly, Quine may be configured to bind to one port, say, 8080, but be exposed to the user on another port, say 80. This is particularly common when using a containerized deployment of Quine. Any time Quine generates a self-referential URL (e.g., in the interactive rest API documentation or openAPI schema's servers block), it should refer to an end-user resolvable address, rather than an interface's address.

Consider a simple production deployment of Quine in which the JVM is configured to bind to only the loopback interface on port 8080. That is,

quine.webserver {
  # whether the webserver should be enabled
  enabled = true

  # Hostname or address of the interface to which the HTTP server should
  # be bound - 0.0.0.0 means "all interfaces"
  # There are two special values which are interpreted dynamically:
  #   1.) "<getHostAddress>" uses the host IP found at runtime
  #   2.) "<getHostName>" uses the host DNS name found at runtime
  address = "127.0.0.1"

  # port to which the HTTP server should be bound
  # setting to `0` will choose an available port at random.
  port = 8080
}

The Quine is then hosted behind a reverse proxy providing TLS termination and exposing the Quine instance at quine.example.com. The operator wishes to use the interactive rest API documentation. However, by default, the API documentation will render the server URL as //127.0.0.1:8080, and trying to send API requests via documentation UI will cause errors as the user's browser tries to connect to 127.0.0.1, which resolves to the user's machine instead of the Quine host. To fix this, the Quine operator can set:

quine.webserver-advertise {
  # Hostname or address using which the application should generate
  # user-facing hyperlinks to itself. This should be uniquely
  # resolvable from the end-users' client.
  address = "quine.example.com"

  # port (on `address`) via which the HTTP server can be reached
  port = 443
}

The documentation will now report the server's URL as //quine.example.com:443. When the user's browser connects to this URL, their traffic is correctly routed through the TLS termination and reverse proxy to reach their Quine instance.

Adding TLS Security

As of Quine 1.5.7, Quine supports TLS termination within the Quine application. While thatDot recommends customers deploy Quine behind a reverse proxy or load balancer rather than terminating TLS internally, Quine's own TLS termination can provide an additional layer of security and defense-in-depth to a deployment. In order to use Quine for TLS termination, you must have a Java keystore containing a key suitable for usage with TLS1.2 cipher suites.

Quine's webserver configuration is specified in the quine.webserver.ssl portion of the Quine configuration:

quine {
  webserver {
    enabled = true
    address = "0.0.0.0"
    port = 443
    ssl {
      path = "server_key.jks"
      password = "keystore password"
    }
  }
}

The configuration quine.webserver.ssl.path should be set to the path of a jks or PKCS12 keystore file on the machine running the Quine server. As Java keystores are secured by a password, the same password should be provided for access via the quine.webserver.ssl.password configuration.

As an alternative to the default methods of Quine configuration, the environment variables SSL_KEYSTORE_PATH and SSL_KEYSTORE_PASSWORD may be used instead.

Generating a keystore with a self-signed server key

For the best balance of performance, security, and compatibility with a wide variety of clients, we recommend generating an RSA2048 key. Under no circumstances should RC4 be used. The most ergonomic way to generate a self-signed key is via the JDK's keytool, by using the following command and following the prompts that appear. This command will generate a 2048-bit RSA key so use as the server's private key, and convert it to the appropriate format to be consumed by Quine (a Java keystore file):

keytool -genkey -alias server -keyalg RSA -keysize 2048 -keystore server_key.jks

Generally, the tooling used to interact with Quine's keystore is the same as the tooling used for managing Apache Tomcat's keystore. Many resources are available online describing different ways of interacting with Java keystores, including how to import and export keys from other common formats like X.509, or generate certificate signing requests (CSRs) to endorse generated certificates elsewhere along a chain of trust. In addition, keytool's built-in documentation (viewable with man keytool) provides an exhaustive reference for the breadth of command-line arguments available.