Provides

Declares what network endpoints a component exposes. Value is an array of objects.

Field Type Required Default Description
name string no -- Endpoint name for cross-references (e.g. api, metrics)
protocol enum yes -- http, https, tcp, udp, grpc, ws
port integer yes -- Container port (1-65535)
bind string no 0.0.0.0 Bind address
exposed boolean no false Whether the port is reachable from outside the host. Most components in a multi-component app are internal services — only frontends and API gateways typically need exposed: true.
spec map<string, string> no -- API spec references (e.g. openapi: file:docs/openapi.yaml)
tls string or object no -- Names one supports: entry of type certificate on the same component: the certificate this listener serves when native TLS is selected. See Native TLS.
at string or string[] no -- The names this listener answers at, relative to the app host: "@", a DNS label, "*" or "*.*". See Host names under the app host.

Each provides entry's protocol describes what that component's own listener
speaks on that entry's port, in the configuration this Launchfile describes. It
never describes a public endpoint's scheme. A provider may publish an https://
URL while forwarding cleartext HTTP to a component declaring protocol: http;
that is not a mismatch and no tool may report it as one. The app's primary public
scheme is $app.scheme, derived from $app.url; every other published endpoint's
public address is $app.endpoints.<name>.*, reachable by the entry's name:
(Per-endpoint properties, D-63) — a
supplied publication context still asserts the primary's address only
(D-58 rule 4). Declaring one listener configuration
says nothing about the other configurations an app supports — a consumer MUST NOT
infer from protocol: http that a component cannot be configured to serve TLS.

provides:
  - name: api
    protocol: http
    port: 3000
    exposed: true
    spec:
      openapi: file:docs/openapi.yaml

Native TLS with a certificate binding

Some apps terminate TLS on their own listener when they are given a certificate. tls: says so, by naming one supports: entry of type certificate on the same component (D-61):

provides:
  - name: web
    protocol: http       # the baseline listener (D-59)
    port: 3000
    exposed: true
    tls: server-cert     # shorthand for `tls: { certificate: server-cert }`
supports:
  - name: server-cert
    type: certificate
    set_env:
      GITEA__server__PROTOCOL: https
      GITEA__server__HTTP_PORT: "3000"
      GITEA__server__CERT_FILE: $cert_file
      GITEA__server__KEY_FILE: $key_file
env:
  GITEA__server__PROTOCOL: http

"I serve HTTP on 3000. I can serve HTTPS on that same listener with this certificate; here is the wiring."

Declared and effective. Every provides entry has a declared protocol and port — the fields in the file — and an effective protocol and port, which is what the listener speaks in the configuration the deployment selected. They are equal unless a bound certificate is active; then the effective protocol is https and the effective port is the declared port:. Validation, tooling and the audit surface read the declared value; every URL-emitting expression derived from a listener ($components.<name>.url, $components.<name>.<endpoint>.url with its protocol, and $app.url where the provider computes it from its own publication of that listener) reads the effective one. An orchestrator-supplied publication context still wins (PROVIDERS.md §7).

Five rules bind the binding:

  1. It binds one entry, by identity. The named entry must exist in the same component's supports: and declare type: certificate. A certificate named by two provides entries is a validation error, active or not. Naming a requires: entry is a validation error too: required native TLS is out of scope here. The bound entry must speak an HTTP-family protocol — http, https, ws or grpc — because an active binding makes its effective protocol https; tls: on a tcp or udp entry is a validation error naming the entry, the same family line an https-origin endpoint: draws.
  2. Availability is not activation. A certificate being available does not turn the binding on — the consumer selects native TLS, outside the file, the same way any other optional resource is selected (D-8).
  3. Active set_env beats env:. With the binding active the app receives GITEA__server__PROTOCOL: https from set_env, not the http its env: declares; inactive, the env: value applies unchanged and the binding's keys are absent. This holds for every set_env binding, not only certificates — see PROVIDERS.md §7.
  4. It composes with https-origin, and implies nothing about it. A certificate binding does not by itself satisfy an https-origin entry, and an https-origin entry does not imply a certificate. An app may declare both, either, or neither.
  5. Delivery, then refuse or run the baseline. cert_file and key_file arrive through the provider's supplied-resource channel (D-56) and the provider does not verify them. Selected but missing either one, or selected on a provider that cannot activate native TLS, fails before launch naming the entry — never a silent fall back to HTTP. Not selected, the component runs its declared HTTP baseline.

A reader that ignores tls: and the certificate entry launches the declared baseline, which is correct rather than degraded: nobody selected the capability.

Host names under the app host

Some apps serve different surfaces on different host names from one listener: the server reads the Host header and picks a surface. at: says which names a published listener answers at (D-68). Every name is relative to the app host, the value of $app.host. The file never names the app host itself.

provides:
  - name: https
    protocol: https
    port: 443
    exposed: true
    at: ["@", dash, auth, "*", "*.*"]

"Publish this listener. It answers at my host, at dash. and auth. under it, at every other name one label below it, and at every name two labels below it."

at: dash is shorthand for at: [dash]. Nothing expands into extra provides entries: one listener stays one entry, with one name:.

Six rules bind the field:

  1. Three kinds of value. "@" is the app host itself. A label, such as dash, is the name dash.<app host>: one lowercase DNS label of at most 63 characters, with no leading or trailing hyphen and no -- in its third and fourth characters. A pattern is "*", every name exactly one label below the app host, or "*.*", every name exactly two labels below it. *.dash, dash.*, a dotted label and a deeper pattern are validation errors. Labels are lowercase because DNS compares names without case.
  2. Absent means today. Present means exactly this. A file with no at: keeps today's meaning. An entry that declares at: answers at the listed names and no others. Without "@" in the list the app does not answer at the app host, and the platform may put anything there. This describes the app; it is not a filter a provider must apply. A provider that publishes a bare port cannot stop another name from reaching the listener, and is not asked to.
  3. Where it is valid. Only on an entry with exposed: true: an unpublished listener has no public name. Only on an HTTP-family listener — http, https, ws or grpc; on tcp or udp it is a validation error naming the entry and its protocol, the same family line tls: and an https-origin endpoint: draw.
  4. A value occurs once per app, across all components. A second entry that declares dash, or a second "*", is a validation error naming both entries. So each name reaches at most one listener: an exact label matches first, otherwise the pattern of that depth, and no other precedence exists. An entry without at: answers at the app host, so the app's primary endpoint (https-origin rule 3) holds "@" without declaring it; a second entry that declares "@" beside such a primary is the same error. A primary entry that declares at: without "@" is valid and draws a validate warning: $app.url then names a host nothing in the app serves.
  5. Set up the names, or report them. For each value a provider sets up what it can: requests for a matching name reach this entry's listener with the requested host in Host, DNS resolves the name, and the provider serves a certificate valid for the name where it terminates TLS. A provider that publishes the listener directly, with no edge of its own that routes by host name, already delivers every request with its Host intact. For every value a provider does not fully set up, it launches the component and reports at the end of provisioning: the entry, the names, where requests arrive, and the operator's options — map the name with a hosts file or DNS, or use a provider that routes host names. The report is mandatory; a launch that says nothing is non-conformant. One case refuses: a provider whose own edge routes by host name, and would drop a declared name it did not route, routes every declared value or refuses the component before launch, naming the entry and the value. Under an orchestrator-supplied public URL the provider never infers that a value is set up; it launches and returns the same report to the orchestrator, which decides what to do with it. See PROVIDERS.md §7 and §10.
  6. at: changes no reference value. $app.* and $app.endpoints.<name>.* resolve exactly as they do without it. The app builds its own addresses from $app.host, $app.scheme and $app.authority.

Declare only the names the app answers at in the configuration the file describes. A reader that predates at: ignores the field, publishes one host and reports nothing, which is today's result for such an app, not a new one.

esc
Type to search the docs