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.