Web Server Config

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

    # Hostname or address of the interface to which the HTTP server should
    # be bound
    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

    # Whether the webserver should perform TLS termination
    use-tls = no
  }
  # (optional) Configuration to use when advertising this server
  # quine.webserver-advertise {
    # Hostname or address using which the application should generate
    # user-facing hyperlinks to itself
    # address = "localhost"

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

Serving Quine Behind a Reverse Proxy

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 address. 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 OpenAPI document’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
  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

  # Whether the webserver should perform TLS termination
  use-tls = no
}

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 a third-party API specification viewer. However, by default, the API specification document will render the server URL as http://127.0.0.1:8080, and trying to send API requests via documentation UI will cause errors as the useragent 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
  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 http://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 be used for prototyping or to encrypt the connection to the reverse proxy itself. In order to use Quine for TLS termination, you must have a Java keystore containing a key suitable for usage with your Java version’s supported 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
    tls-enabled = true
  }
}

The system property javax.net.ssl.keyStore 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 password should be provided for access via the javax.net.ssl.keyStorePassword system property.

As an alternative to the standard Java methods of TLS 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 4096 -keystore server_key.jks

Generally, the tooling used to interact with Quine’s keystore is the same as the tooling used for managing any Java application’s keystore; for example, Apache Tomcat, Kafka, or Cassandra. 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 a reference for many of the command-line arguments available.