Skip to main content

Configure HTTP

The http block in your config.cap.yaml defines how your application's web server is exposed and configured. This includes basic settings like ports and replicas, as well as more advanced options like internal routing and health checks.

http:
  enable: true
  port: 8080
  replicas: 2

Options

Property Type Description Default
enable boolean Whether to serve HTTP traffic for your application. true
port integer The port your container listens on. 8080
replicas integer The number of web server instances. See Autoscaling to let this number follow traffic. 2
hostname string or string[] The hostnames these web servers serve. Write it as null in a group to serve none of them. The environment's hostname
path string The path prefix these web servers serve. Requests below it are routed to them. /
groups object Additional groups of web servers, keyed by name. Each takes every property on this page. See Groups. None
metrics boolean or object Whether these web servers are collected from, and how. See Configure Metrics. false
scale boolean or object Whether to match the number of web server instances to incoming traffic. See Autoscaling. false
scale.enable boolean Whether to match the number of web server instances to incoming traffic. false
scale.requestRate integer The number of requests per second a single instance is expected to handle. 12
scale.maxReplicas integer The highest number of web server instances traffic can grow to. 10
resources.cpu integer or string CPU allocated to each web server instance. See Resources. 125m
resources.memory integer or string Memory allocated to each web server instance. See Resources. 256Mi
internal boolean or object Whether to give your application a private address next to its public one. See Internal routing. false
internal.enable boolean Whether to give your application a private address next to its public one. false
session.connection.service string The name of a dragonfly service declared under services. See Sessions. None
session.connection.database integer The database index sessions are stored on. 10
timeout integer The proxy timeout in seconds. 60
maxBodySize integer or string The maximum body size for HTTP requests. An integer in kilobytes, or a string with units such as 10MB. 2MB
healthCheck.enable boolean Whether to check that your application is responding. See Health checks. true
healthCheck.path string The path to request for the health check. /ping
variables object Environment variables for the web server only, on top of the global ones. See Environment Variables. None

Hostnames and paths

Your web servers serve the hostnames you configure, and path limits them to the requests below a prefix.

http:
  hostname: example.com
  path: /

Each hostname gets its own certificate.

Writing hostname outside http keeps working but is discouraged. If possible move to the new syntax.

Groups

A single application can run more than one set of web servers, each with its own size, hostnames and path, while running the same image. Declare a group under groups and give it the properties that differ:

http:
  hostname: example.com
  replicas: 2

  groups:
    main:
      path: /            # example.com, 2 replicas

    heavy:
      path: /reports     # example.com/reports, 3 replicas
      replicas: 3

example.com/reports is served by three dedicated instances and everything else by the two main inherits, so a slow endpoint cannot exhaust the instances serving the rest of your application. Both groups inherit the hostname written above them.

Declaring a group replaces the servers you would otherwise get, so the properties beside groups are only inherited by them and serve nothing themselves. Write a group for every set of servers you want, main above included.

A group inherits every property written above groups, so it only states what differs. Set a property to nothing to opt out of what it would inherit, which is how a group serves no traffic:

http:
  hostname: example.com

  groups:
    web:
      path: /

    worker:
      hostname: ~       # Serves nothing, whatever is inherited

Serving only one prefix needs nothing else: declare the one group you want.

http:
  groups:
    api:
      hostname: example.com
      path: /api        # Only example.com/api is served

Each group scales, gets sessions and receives environment variables independently:

http:
  hostname: example.com

  groups:
    main:
      replicas: 2

    heavy:
      path: /reports
      replicas: 1
      scale:
        enable: true
        maxReplicas: 5
      resources:
        cpu: 1000m
        memory: 2Gi
      env:
        REPORT_MODE: batch

A hostname and path can only be served once. Two groups serving the same combination are rejected. Groups without a hostname serve nothing, so any number of them can sit on the same path.

Set metrics on a group to collect metrics from its servers; see Configure Metrics.

A group runs the same image and command as the rest of your application. It is a second set of instances in front of a different path, not a second application.

Autoscaling

CAP can match the number of web server instances to the traffic your application receives, adding instances as requests rise and removing them again when traffic falls off.

http:
  scale: true

Write scale as a block to tune it:

http:
  replicas: 2
  scale:
    enable: true
    requestRate: 12
    maxReplicas: 10

replicas is the lowest number of instances, held even when no traffic arrives. Values of maxReplicas below replicas are rejected.

Scaling follows the traffic arriving on your application's hostname, so an application without one stays at its configured replicas.

Resources

You can specify CPU and memory resources for your HTTP servers using the resources property.

http:
  resources:
    cpu: 500m
    memory: 1Gi

See the YAML Schema Reference for more details on computeResources syntax.

Internal routing

The internal option adds a second, private address to your application. Your other applications can reach it on that address without the traffic leaving Cloudbear, which is useful when they call each other directly.

http:
  internal: true

internal does not make your application private. It only adds an address: the hostnames you configure stay reachable from the internet exactly as before, on the same certificate, and requests to them are unaffected.

The private address is http://{application}-ingress.{application}-{environment}, for example http://my-app-ingress.my-app-production. A named group has the group's name on the end of the first part, so api is reached at http://my-app-ingress-api.my-app-production. On an instance other than the default, the instance name is part of the application name: http://my-app-eu-ingress.my-app-production.

The address resolves only from your other applications on Cloudbear, and is not reachable from the internet. It serves plain HTTP on port 80, unlike your public hostnames, which are served over HTTPS.

Rather than writing the address out, you can template it into an environment variable. Name the group whose address you want, or default for the servers configured directly under http:

variables:
  INTERNAL_URL: "{{ http.groups.default.internal.url }}"

See Connections for every value available.

Reachable only from your other applications

The hostname is what makes web servers reachable from the internet, and a group inherits it from the http block above it. Setting internal on its own adds the private address and leaves that hostname in place, so those servers stay public.

To serve a group on the private address alone, set internal and clear the hostname with ~:

http:
  hostname: example.com

  groups:
    web:
      path: /

    api:
      internal: true
      hostname: ~

web serves example.com as usual. api is reachable only at http://my-app-ingress-api.my-app-production, from your other applications on Cloudbear, because it serves no hostname of its own.

Each group gets an address of its own, named after the group, so any number of them can have one:

http:
  hostname: example.com

  groups:
    api:
      internal: true
      hostname: ~
    admin:
      internal: true
      hostname: ~

variables:
  API_URL: "{{ http.groups.api.internal.url }}"
  ADMIN_URL: "{{ http.groups.admin.internal.url }}"

Sessions

If your application uses sessions that need to be shared across replicas, point session.connection at a Dragonfly service. You do not need to declare that service under connections: naming it here is enough, and the session store is wired up for you.

services:
  cache:
    type: dragonfly

http:
  session:
    connection:
      service: cache

Sessions get their own database index, so they never collide with data your application caches on the same service through a regular connection:

http:
  session:
    connection:
      service: cache
      database: 0

Auth forward

authForward puts another one of your applications in front of this one as an authentication check. Every request that arrives is first offered to that application, which decides whether it may continue. Requests it accepts are passed on to your application; requests it rejects never reach it, and the caller gets the rejecting application's response.

authForward:
  app: my-iam
  path: /api/decision
Property Type Description Default
app string The slug of the application that decides whether a request is allowed.
path string The path on that application a decision is requested from. A leading / is optional. /auth
headers.fromAuth string[] Headers taken from the decision response and passed on to your application. []
headers.forAuth string[] Accepted, but has no effect on the decision request. [Authorization]

The authenticating application answers 2xx to allow a request and any other status to refuse it. Its response body is discarded when it allows the request; when it refuses, that body is what the caller receives.

The request body is never sent along, so a decision is made on the method, path and headers alone.

authForward is a top-level property and can be set per instance and per environment like any other. See Configuration Hierarchy.

The authenticating application

app is the slug of one of your own applications, deployed by CAP. The decision request reaches it privately, without leaving Cloudbear, so that application does not need a hostname of its own.

The environment is matched: the same configuration sends production requests to the authenticating application's production deployment, and staging requests to its staging deployment. In an environment where that application is not deployed there is nothing to answer the check, and requests to your application fail rather than being allowed through.

Passing identity to your application

An authenticating application usually establishes who the caller is, and your application needs that too. List the headers it returns under headers.fromAuth and they are copied off the decision response onto the request your application receives.

authForward:
  app: my-iam
  path: /api/decision
  headers:
    fromAuth:
      - X-USER-UUID
      - X-GROUP-UUID

Your application then reads X-USER-UUID and X-GROUP-UUID off every request that got through. Headers the authenticating application sets but that are not listed here are dropped.

What the decision request contains

The decision request carries the original request's headers, so a Cookie or Authorization header the caller sent is available to base the decision on. These headers describe the request being judged:

Header Value
X-Forwarded-Method The method of the original request.
X-Forwarded-Uri The path and query string of the original request.
X-Forwarded-Host The hostname the original request was sent to.
X-Forwarded-Server The hostname the original request was sent to.
X-Forwarded-Port The port the original request arrived on.
X-Forwarded-Proto The scheme of the original request.
X-Forwarded-For The caller's address, appended to any it received.

Auth forward applies to requests arriving on your application's hostname. It does not cover the private address from internal routing, so your other applications keep reaching this one directly without a decision being requested.

IP whitelist

whitelist restricts who may reach your application over its hostnames. List the addresses and ranges that are allowed, and every request from anywhere else is refused before it reaches your application.

whitelist:
  - 203.0.113.7
  - 198.51.100.0/24
Property Type Description Default
whitelist string[] The IPv4 and IPv6 addresses and CIDR ranges that may reach your application. None

An empty or absent whitelist places no restriction, which is the default: your hostnames are reachable from the internet.

Writing entries

An entry is a single address or a CIDR range, in IPv4 or IPv6:

whitelist:
  - 203.0.113.7          # one IPv4 address
  - 198.51.100.0/24      # an IPv4 range
  - 2001:db8::1          # one IPv6 address
  - 2001:db8::/32        # an IPv6 range

A single address needs no prefix length. Written without one it allows exactly that address.

An entry that is not a valid address or range is reported when you validate your configuration, and is ignored rather than rejecting the deployment. The remaining entries still apply, so a typo narrows who may reach your application rather than widening it.

What it covers

whitelist applies to requests arriving on the hostnames your web servers serve, across every group. One list covers the whole deployment; it cannot be set per group.

The whitelist does not cover the private address from internal routing. Your other applications keep reaching this one on that address whatever the whitelist says, and their addresses do not need to be listed.

A Mercure hub has a public hostname of its own and is not covered either; see Services.

Setting it per environment

whitelist is a top-level property and can be set per instance and per environment like any other. Entries add up down the hierarchy rather than replacing each other, so a list written on an environment extends the one above it:

whitelist:
  - 203.0.113.7

environments:
  staging:
    whitelist:
      - 198.51.100.0/24

staging allows both 203.0.113.7 and 198.51.100.0/24. Every other environment allows 203.0.113.7 alone.

Because entries add up, a whitelist cannot be narrowed or removed further down the hierarchy. Writing whitelist: [] on an environment does not open it up, and listing fewer entries does not drop the others. To restrict only some environments, leave the top level without a whitelist and write one on each environment that needs it.

An environment with no whitelist anywhere above it stays reachable from the internet, so restricting one environment does not close the others:

environments:
  staging:
    whitelist:
      - 203.0.113.7

Here staging is reachable only from 203.0.113.7, while production is open. See Configuration Hierarchy.

Request timeout

You can configure the proxy timeout for HTTP requests.

http:
  timeout: 60

Maximum body size

Define the maximum allowed body size for incoming HTTP requests.

http:
  maxBodySize: 10M

An integer is read as a number of kilobytes instead:

http:
  maxBodySize: 10240

Health checks

Health checks are used to determine if your application is running correctly. CAP can perform HTTP health checks on a specified path.

http:
  healthCheck:
    enable: true
    path: /ping

The specific health check path (healthCheck.path) may vary depending on your application's framework or configuration. Consult your application's documentation for the correct path.