Tenant Model
The Tenant Model is the JSON document that describes a GitLab Dedicated tenant. Its schema lives in
tenant-model-schema.
This page describes the parts that configure Runway modules: the ModuleSchema object, and the values_override
block that Runway checks on top of it.
Example
Section titled “Example”{ "modular_features": { "modules": { "example-service-dedicated": { "enabled": true, "version": "v1.25.0", "values_override": { "infrastructure": { "s3": { "uploads": {} }, "rds": { "main": { "instance_type": "small" } } }, "helm": { "values": { "environment": { "LOG_LEVEL": "debug" } } } } } } }}modular_features
Section titled “modular_features”| Field | Type | Description |
|---|---|---|
modules |
object | Map of module name to its module configuration. The module name is the Runway service ID. |
runwayctl.version |
string | Version of runwayctl used to deploy the modules: a tag, a branch name, or latest. Defaults to latest. |
Module names must match ^[a-z0-9]([-a-z0-9]{0,51}[a-z0-9])?$: 1 to 53 lowercase letters, digits, and hyphens, starting
and ending with a letter or digit.
Module
Section titled “Module”modular_features.modules.<module-name> (ModuleSchema in the Tenant Model schema) configures one module.
Unknown fields are rejected.
| Field | Type | Description |
|---|---|---|
enabled |
boolean | Required. Enables the module. Defaults to false. |
version |
string | Required. Version of the module to deploy: a release tag such as v1.2.3, or latest. A release tag must be in the Module Catalog. |
values_override |
object | Tenant-specific settings. See values_override. |
values_override
Section titled “values_override”The Tenant Model schema accepts any object as values_override. Runway parses the parts it reads with its own
values_override definition
when it provisions or deploys the module, and fails loudly on unknown fields inside them.
Other top-level fields of values_override are ignored.
| Field | Type | Description |
|---|---|---|
infrastructure |
object | The module’s infrastructure: S3 buckets, PostgreSQL and Redis instances. |
helm |
object | The module’s Helm release. |
connections |
object | The peer modules the module connects to. |
secrets |
object | The module’s private secrets: rotation and deletion. |
infrastructure
Section titled “infrastructure”Tenant-specific overrides of the module’s infrastructure, keyed by the AWS service that implements it, then by the logical name of the bucket or instance. Unknown fields are rejected.
| Field | Type | Description |
|---|---|---|
s3 |
object | Overrides of the module’s S3 buckets. |
rds |
object | Overrides of the module’s PostgreSQL (Amazon RDS) instances. |
elasticache |
object | Overrides of the module’s Redis (Amazon ElastiCache for Valkey) instances. |
Each field is a map from a logical name to the settings of one bucket or instance. The pages linked above list the settings, their built-in defaults, and the rules for logical names, which are at most 45 characters long.
The module sets the defaults of its buckets and instances in its
module manifest, and Runway merges the Tenant Model over them, by logical name
and then field by field. A tenant only sets what differs, and a tenant that is happy with the defaults needs no
infrastructure block at all. Each setting comes from the first of these that sets it:
- The entry in the Tenant Model.
- The entry’s
defaultConfigin the module manifest, from the Module Catalog entry. - The built-in default.
An explicit false or 0 in the Tenant Model overrides a default. An entry in the Tenant Model doesn’t have to be
complete, or valid on its own: it only has to parse. Runway validates the merged result of every enabled entry. A tenant
can also add an entry that has no default, which must then be complete on its own.
Every entry has an enabled field. Unset means enabled. A tenant turns on an entry that the module turns off by default
with enabled: true, and turns off an entry with enabled: false. Runway ignores disabled entries: it doesn’t
provision them, doesn’t deploy a Secret or Helm values for them, and doesn’t check their other settings. Disabling an
entry that was provisioned before has the same effect as removing it: the next provision destroys the bucket or
instance. For PostgreSQL, prevent_db_deletion stops
this.
The module’s Fairway manifest declares whether it needs each dependency (its presence in the Module Catalog entry).
Runway checks the enabled entries of each dependency, after the merge, against it:
| Presence | Enabled entries, after the merge |
|---|---|
REQUIRED |
At least one. |
OPTIONAL |
Any number, including none. |
UNUSED |
None. |
{ "infrastructure": { "s3": { "uploads": { "versioning": false } }, "rds": { "main": { "instance_type": "large" } }, "elasticache": { "cache": { "enabled": true } } }}Tenant-specific settings of the module’s Helm release. Unknown fields are rejected.
| Field | Type | Description |
|---|---|---|
values |
object | Helm values, merged over the default values from the Module Catalog entry. |
registry |
string | OCI registry and repository path of the chart, without a scheme (e.g. registry.gitlab.com/gitlab-org/charts). Replaces helm.registry from the Module Catalog entry. |
chart |
string | Name of the chart’s repository in the OCI registry. Replaces helm.chart from the Module Catalog entry. |
The Helm values are documented in the
Fairway values reference.
Field names can be in camelCase (imagePullPolicy) or snake_case (image_pull_policy).
Runway merges values over the module’s default values (see Helm Values): objects
are merged, lists are replaced. Tenants can override any value, but overrides are an escape hatch: values that every
tenant needs, including templates for tenant-specific values, belong in the
service repository. Runway checks the result in two steps:
valuesmust match the Fairway values structure: unknown fields and wrong types are errors. It doesn’t have to be valid on its own, since it is only a partial structure.- The merged values must be valid.
{ "helm": { "values": { "imagePullPolicy": "Always", "environment": { "LOG_LEVEL": "debug" }, "scalability": { "minInstances": 2 } } }}Chart location
Section titled “Chart location”registry and chart change where Runway pulls the module’s chart from: Runway installs
oci://<registry>/<chart> at the version from the Module Catalog entry. Each field is optional and replaces only its own
field of the catalog entry, so you can, for example, set only registry. They are an escape hatch, for example for a
chart that is published to a registry the tenant can’t reach. The Module Catalog entry remains the source of truth:
remove the overrides once the chart is available from its catalog location.
{ "helm": { "registry": "mirror.example.com/charts", "chart": "my-chart" }}connections
Section titled “connections”Overrides the peer modules the module connects to, from the Module Catalog entry. It has the same shape as connections
in the module manifest, and also accepts modules.add, which
appends peers instead of replacing them. Setting both modules.set and modules.add is an error. See
Connections for the cases.
{ "connections": { "modules": { "add": [{ "name": "artifact-registry-dedicated" }] } }}secrets
Section titled “secrets”Tenant-specific settings of the module’s secrets, keyed by logical name. Each entry
takes the secret settings and is merged over the module’s default of the
same name, field by field, like infrastructure. A tenant can also add a secret that has no default. Two settings are
only allowed here, not in the module manifest:
versionrotates the secret: increase it, then provision and deploy the module. Only ever increase it. See Rotating a secret.prevent_deletionprotects the secret’s value, and istrueunless set.
{ "secrets": { "root-key": { "version": 2 } }}