---
component: ROOT
version: "2026.3"
slug: ROOT/reference/standalone
canonical_url: "https://docs.develocity.ai/2026.3/reference/helm-charts/standalone/"
title: "Standalone Helm Chart Configuration Guide"
description: "Configure and manage a Develocity standalone installation with Helm, including storage, the embedded database and object storage, the Edge node, and TLS."
keywords:
  - "Helm"
  - "standalone"
status: current
---

<!-- llms-index: https://docs.develocity.ai/llms.txt -->

# Standalone Helm Chart Configuration Guide

<a id="preamble"></a>

Develocity is a Kubernetes-based application, distributed as a [Helm](https://helm.sh/) chart. Helm is a package manager for Kubernetes applications.

Helm manages all Develocity components.

<a id="helm_overview"></a>

## Helm Overview

To use Helm, users must first import a Helm chart. A Helm chart is a Kubernetes manifest template, with variables that can be provided at installation time.

<a id="providing-configuration-to-helm"></a>

### Providing Configuration to Helm

Helm uses a `values.yaml` file to populate these variables and generate the Kubernetes manifests.

The variables in `values.yaml` configure the Develocity installation with information such as networking, database, or hostname settings.

Here is a sample `values.yaml` file:

**values.yaml:**

```
global:
  hostname: develocity.example.com
database:
  location: embedded
ingress:
  enabled: true
```

Helm configuration can be provided in several ways, in that documentation, we will prioritize `values.yaml` usage for clarity and simplicity.

> [!NOTE]
> Unless otherwise indicated, most values are optional and have usable defaults.

<a id="example-helm-values-file"></a>

### Example Helm Values File

A complete example of the values file can be found [here](#values_yaml_download).

<a id="considerations"></a>

### Considerations

Each section below contains an overview of Develocity installation options and their corresponding `values.yaml` variables:

1.  Global (Hostname, License)
    
2.  Database Type (Embedded or External)
    
3.  Storage Settings
    
4.  Edge Node
    
5.  MCP Server
    
6.  Networking (Ports, Proxies, SSL)
    
7.  Object Storage Configuration
    
8.  Unattended Configuration
    
9.  Using an external Bazel cache
    
10.  Automatic Resource Management
     
11.  JVM Off-Heap Memory
     

For installations on hosts with limited to no network connectivity, see the additional section:

12.  Airgap Installation
     

Access control policies are configured in the final section:

13.  Access Control Policies
     

By the end of this guide, you will have a complete `values.yaml` file, ready for your Develocity installation with storage, networking, database settings, and more.

<a id="helm-options"></a>

## Helm Options

<a id="global_options"></a>

### 1. Global

<a id="hostname"></a>

#### Hostname

When installing Develocity, a hostname such as `develocity.example.com` is required.

This should be the hostname that users of the installation use to access it and therefore should resolve within your network. It’s usually the name of the Develocity host or the hostname of a reverse proxy if one is being used.

> [!NOTE]
> Develocity will only accept requests with this hostname in their `Host` header.

A hostname for the application is supplied in the Helm values file as follows:

**values.yaml:**

```
global:
  hostname: develocity.example.com
```

<a id="license"></a>

#### License

You have been provided with a Develocity license file called `develocity.license`.

This file can be used in any testing, staging or production deployments of Develocity.

Only the "data" part of the license is needed in the Helm value file, but it’s acceptable to include the entire license file contents:

**values.yaml:**

```
global:
  license:
    file: R0VMRgF4nBWOSZKCMAAAX+QUu3BUIJAIwUQiwsViEwMIDKOyvH701n3p6nJBYxoRHnAUnwHwKLjb...
```

> [!TIP]
> The license file can also be supplied as a `helm` argument using `--set-file`.

<a id="custom_labels_and_annotations"></a>

#### Custom Labels and Annotations

You can apply custom labels and annotations to every Develocity workload for ownership tracking and other organization-wide Kubernetes tooling.

Set `global.workload.labels` and `global.workload.annotations` to maps of key-value pairs:

**values.yaml:**

```
global:
  workload:
    labels:
      cost-center: platform-eng
      team: developer-productivity
    annotations:
      example.com/owner: platform-team
```

These labels and annotations are added to both the object metadata and the pod template of every workload the chart deploys (`Deployment`, `Job`, and `CronJob` objects). Immutable selector fields, such as `spec.selector` and `matchLabels`, are never modified, and other resources such as `Ingress`, `Secret`, and `ConfigMap` objects are not affected.

Per-component annotations set through `global.pod.annotations` or `global.job.annotations` take precedence over `global.workload.annotations` when they define the same key. The chart reserves some keys and rejects them at render time: keys under the prefixes `app.kubernetes.io/`, `gradle.com/`, `develocity.gradle.com/`, `checksum.`, `azure.workload.identity/`, `helm.sh/`, or `kubectl.kubernetes.io/`, and the bare labels `app` and `component`.

> [!IMPORTANT]
> Changing these values triggers a rolling restart of the affected workloads on the next `helm upgrade`.

<a id="database_type"></a>

### 2. Database

Develocity can store data in either:

*   An **embedded database** that uses a local directory or volume to store its data.
    
*   A **user-managed database** that’s completely separate from Develocity.
    

There are tradeoffs to consider for each option:

🔍 **Embedded database tradeoffs**

When using the embedded database, Develocity will run a PostgreSQL database in a container and store data in a local directory. In this mode Develocity can run backups on a regular or cron-like schedule.

The embedded database has several advantages:

*   Simple setup with no additional configuration needed.
    
*   Automatic updates to the latest PostgreSQL version supported.
    
*   Features that require disk space information are supported.
    
*   Typically more affordable for smaller installations.
    

However, there are downsides to the embedded database, in particular for larger installations:

*   Disk I/O throughput can be a bottleneck on a busy system and is difficult to address.
    
*   Backup management is slow for larger databases, creates a load on the server, and consumes a lot of memory.
    
*   It isn’t possible to keep a standby database.
    
*   The database is a single point of failure.
    

🔍 **User-managed database tradeoffs**

A user-managed database can be any PostgreSQL database compatible with versions 15 through 18. Popular options also include cloud-based database providers such as Amazon RDS or Aurora. The [compatibility matrix](https://docs.develocity.ai/2026.3/miscellaneous/compatibility/#user_managed_database) lists the supported versions for every Develocity release. There are several advantages, particularly in large installations:

*   Database customizations and optimizations are possible (memory, CPU, I/O throughput, etc…​).
    
*   Resources can be allocated for cost-effectiveness.
    
*   Third party tools to snapshot the database can be used.
    
*   Many cloud databases allow for easy scaling of resources post installation.
    
*   A standby database for fail-over protection can be used.
    

There are some downsides to using a user-managed database:

*   Extra system(s) are needed for provisioning and configuration.
    
*   Database connectivity and network latency is a factor.
    
*   Backups must be managed by an administrator or a tool.
    
*   Disk space management and alerting are required.
    
*   Develocity features related to disk space aren’t available.
    
*   Security considerations such as credential cycling must be considered.
    
*   Customer support may be limited for disaster recovery or backup restores.
    

By default, Develocity will use an embedded database. For this configuration, no additional values are needed in the Helm values file.

<a id="user_managed_database_configuration"></a>

#### User-Managed Database Configuration

When Develocity is configured to store data in a user-managed database, it must be provided with connection settings and credentials for the database.

<a id="connection-settings"></a>

##### Connection Settings

Standard connection settings like host, port, and database name must be provided in the values file. JDBC parameters can be optionally specified as well:

**values.yaml:**

```
database:
  location: user-managed
  connection:
    host: database.example.com (1)
    port: 5432 (2)
    databaseName: gradle_enterprise (3)
    params: "?connectTimeout=60" (4)
```

1. The database URL.
2. The port property is optional.
3. The database must have already been created using CREATE DATABASE, the createdb command or an equivalent mechanism in a cloud database interface before configuring Develocity with connection details.
4. The params property is optional.

<a id="credentials"></a>

##### Credentials

There are three options for credentials:

🔍 **Option 1** - superuser

If provided with credentials for a database superuser (such as the `postgres` user that’s common on PostgreSQL database instances), Develocity can perform the database setup.

A superuser can be added to the values file in the database section:

**values.yaml:**

```
database:
  location: user-managed
  connection:
    host: db.example.com # ...
  credentials:
    superuser:
      username: postgres
      password: the_password
```

> [!NOTE]
> In some installations, often cloud-based, the default credentials provided aren’t a superuser. For example, the supplied `postgres` account in Amazon RDS PostgreSQL databases isn’t a superuser, but has the `rds_superuser` role. Such accounts are typically acceptable to use with Develocity.

🔍 **Option 2** - no superuser

To set up your database without database superuser credentials, run the `setup.sh` script from the [database setup scripts](#database_setup_download) **for your Develocity version** against it. The script will set up less privileged accounts for the application to use, and some privileged functions needed for the application to run.

> [!WARNING]
> The installation will fail if you don’t run the database setup scripts.

The credentials for the accounts must be set by you and provided to Develocity via Helm configuration.

To set up your database without database superuser credentials, the values file must be updated as follows:

**values.yaml:**

```
database:
  location: user-managed
  connection:
    host: db.example.com # ...
  credentials:
    app:
      password: app_password
    migrator:
      password: migrator_password
```

<a id="database_iam_authentication"></a>🔍 **Option 3** - AWS IAM database authentication (with or without superuser)

Develocity can be configured to acquire short-lived passwords dynamically using [IAM database authentication](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.IAMDBAuth.html), rather than using any stored password credentials. This makes it possible to for you to manage access to the Develocity database without managing passwords directly. Using IAM database authentication requires that your database is an instance of either Amazon RDS or Amazon Aurora, and that your Develocity instance is running on an Amazon EC2 instance.

To configure Develocity to use IAM database authentication, your database credentials Helm config needs to include information about your database provider and how Develocity should acquire short-lived passwords. If you want Develocity to perform database setup automatically when starting, you also need to configure [superuser access](#database_setup_with_iam_database_authentication).

The Helm value `database.provider` must be set to `aws-rds`, and the Helm value `database.credentials.type` must be set to `instanceProfile`, which refers to the use of [EC2 instance profiles](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use_switch-role-ec2_instance-profiles.html).

Instance profile credentials can only be used if your Develocity installation is running on an Amazon EC2 instance.

You must set up the appropriate permissions in AWS beforehand in order for Develocity to be able to get short-lived passwords using an EC2 instance profile. The steps to do this are described in the [IAM database authentication for RDS](https://docs.develocity.ai/2026.3/installation/aws/aws-ec2-standalone/#rds_iam_authentication) section of our Amazon EC2 Standalone Installation Guide.

To configure Develocity to get short-lived database passwords using instance profile credentials, update your Helm values file as follows:

**values.yaml:**

```
database:
  location: user-managed
  connection:
    host: db.example.com # ...
  provider: aws-rds
  credentials:
    type: instanceProfile
```

<a id="database_setup_with_iam_database_authentication"></a>

**Database setup with IAM database authentication**

Database setup must either be performed automatically by Develocity on startup by connecting to the database as a superuser, or it must be performed manually by you prior to installation by running the `setup.sh` script from the [database setup scripts](#database_setup_download) **for your Develocity version** against the database.

If you want Develocity to be able to connect to the database as a superuser for automatic database setup, you need to provide either the username of a superuser (in which case Develocity will try to connect as the superuser using IAM authentication), or both the username and password of a superuser (in which case Develocity will try to connect as the superuser using the configured password). These can be provided directly using the Helm values `database.credentials.superuser.username` and `database.credentials.superuser.password`, or in a Kubernetes Secret, whose name must be provided in the Helm value `database.credentials.superuser.secretName` and which contains just either a `username`, or both a `username` and a `password`.

If you want to specify superuser credentials using a Kubernetes Secret, it should have the typical `username` and `password` keys, encoded using Base64:

```yaml
---
apiVersion: v1
kind: Secret
metadata:
  name: my-example-db-superuser-credentials
data:
  username: "cG9zdGdyZXM="
  password: "ZXhhbXBsZS1wYXNzd29yZA=="
```

<a id="storage"></a>

### 3. Storage Settings

By default, the Develocity standalone distribution stores its data at `/opt/gradle`, and logs and backups are stored in subdirectories of that directory. To simplify managing disk space, however, Gradle recommends mounting a different persistent storage volume for Develocity data, logs, and backups.

To alter the location of backups, update the `values.yaml` file as follows:

**values.yaml:**

```
global:
  storage:
    directory: /mnt/high-performant-volume/develocity-data           # Default /opt/gradle
    logs:
      directory: /mnt/standard-volume/develocity-logs       # Default (global.storage.directory)/logs
    backup:
      directory: /mnt/big-volume/develocity-backups       # Default (global.storage.directory)/backups
```

> [!NOTE]
> Develocity standalone installations don’t permit configuring different storage volumes for the Build Cache and the database.

<a id="edge_node"></a>

### 4. Edge Node

An [Edge](https://docs.develocity.ai/2026.3/administration/build-acceleration/edge/) node is a Develocity component that gives build and AI agents fast, local access to cached data. Develocity deploys a co-located Edge node as part of the standalone installation. The co-located Edge node provides a low-latency near-cache and exposes the same Develocity services as an externally provisioned Edge node, so your build agents and AI agents can use the same services without separately provisioning Edge infrastructure.

Registration with Develocity is handled automatically by the Helm chart, so no manual registration key configuration is required.

The Edge node stores its cache on the host filesystem under `global.storage.directory` (`/opt/gradle` by default, in the `data/edge-node` subdirectory), so its size counts toward the capacity provisioned for that volume. The cache persists across restarts and upgrades.

The default cache size is `50Gi` and can be adjusted with `edgeNode.storage.data.capacity`:

**values.yaml:**

```
edgeNode:
  storage:
    data:
      capacity: 100Gi  # default 50Gi
```

The Edge node’s cache is independent of the Build Cache **target storage size**, which governs the durable Build Cache in object storage and is set separately (see [Space Management](https://docs.develocity.ai/2026.3/administration/build-acceleration/build-cache/#build_cache_space_management)). For the best hit rate, size `edgeNode.storage.data.capacity` to your active working set; there’s no benefit to going beyond the Build Cache **target storage size**, since a cache larger than the durable Build Cache only wastes capacity.

By default, the co-located Edge node requests `2` CPU units, and the standalone chart applies its CPU requests and limits. Its memory limit comes from [automatic resource management](#automatic-resource-management), which sizes it from the host. Increase `edgeNode.resources.requests.cpu` and `edgeNode.resources.limits.cpu` when sustained CPU is saturated under typical concurrent client load, or when network throughput is constrained. When the working set of frequently-requested cache entries grows large enough to cause memory pressure, set `edgeNode.resources.limits.memory` to pin the Edge node’s limit. Automatic resource management reserves that memory before it sizes the other components.

**values.yaml:**

```
edgeNode:
  resources:
    requests:
      cpu: 4       # default 2
    limits:
      cpu: 4       # default 2
      memory: 8Gi  # pinned; sized automatically when unset
```

While automatic resource management is enabled, `edgeNode.resources.requests.memory` has no effect, because the chart leaves the memory request unset. Switching the feature off applies the `edgeNode.resources` memory values again, defaulting to `4` GiB for both the request and the limit when you set neither.

If unsure, start at the defaults and raise resources only in response to observed saturation. See [Changes](https://docs.develocity.ai/2026.3/operations/upgrade/changes/) for the action required when upgrading from 2026.2.0.

> [!NOTE]
> A standalone installation runs a single Edge node. To scale the co-located Edge node horizontally for greater throughput and higher availability, use a Kubernetes cluster installation. For build agents distributed across multiple regions, provision additional externally-managed Edge nodes in each region. The co-located Edge node only serves clients in the same region as the standalone instance.

<a id="mcp_server"></a>

### 5. MCP Server

Develocity can run a co-located [MCP Server](https://docs.develocity.ai/2026.3/integrations/agentic-ai/mcp-servers/) that serves the Develocity MCP tools to AI agents from the instance’s `/mcp` endpoint. Unlike the co-located Edge node, the MCP Server is disabled by default in standalone installations. Enable it by setting `mcpServer.enabled` to `true`.

When enabled, the standalone chart applies the `mcpServer.resources` CPU requests and limits, which default to `1` CPU unit. Its memory limit comes from [automatic resource management](#automatic-resource-management); set `mcpServer.resources.limits.memory` to pin it instead. Adjust the CPU values for your expected AI agent load:

**values.yaml:**

```
mcpServer:
  enabled: true
  resources:
    requests:
      cpu: 2       # default 1
    limits:
      cpu: 2       # default 1
      memory: 4Gi  # pinned; sized automatically when unset
```

While automatic resource management is enabled, `mcpServer.resources.requests.memory` has no effect, because the chart leaves the memory request unset. Switching the feature off applies the `mcpServer.resources` memory values again, defaulting to `2` GiB for both the request and the limit when you set neither.

For instructions on connecting AI agents, see the [MCP Server installation manual](https://docs.develocity.ai/2026.3/integrations/agentic-ai/mcp-servers/installation/).

<a id="networking"></a>

### 6. Networking

There are several considerations for Develocity related to connectivity:

*   HTTP or HTTPS (with SSL certificates)
    
*   Application Ports
    
*   Proxies
    

<a id="https"></a>

#### HTTP or HTTPS

Develocity can be configured to securely serve traffic over HTTPS based on user-provided certificates.

If certificates aren’t supplied, self-signed certificates will be generated and used, though this isn’t recommended for production operation.

<a id="https_using_ingress"></a>

##### HTTPS Terminated at Ingress

When using the Develocity supplied Ingress, HTTPS is enabled by default.

It can be disabled to serve traffic over HTTP only:

**values.yaml:**

```
ingress:
  enabled: true
  ssl:
    enabled: false
```

SSL certificates (trusted or untrusted) can be provided inline in the values file:

**values.yaml:**

```
ingress:
  enabled: true
  ssl:
    cert: |
      -----BEGIN CERTIFICATE-----
      MIIDKjCCAhKgAwIBAgIRAPNTIHf6/oUuzMKm3ffGNOgwDQYJKoZIhvcNAQELBQAw
      HDEaMBgGA1UEAxMRYXV0by1nZW5lcmF0ZWQtY2EwHhcNMjExMTMwMTU1NDU5WhcN
      ...
      Cn/3yUirFVTslrSYKAemLw8btLO6FDF9dc/lq1o7tKsYVuhEcjqnTah7puJjEN9h
      z+P5RmRxU/kaaFB+Vuw1pRezbaAtZNorVgXnBwrdseY4zLGyhAcGcR9v+VtCiQ==
      -----END CERTIFICATE-----
    key: |
      -----BEGIN RSA PRIVATE KEY-----
      MIIEpQIBAAKCAQEA4qV8JlqDMi7y85Ykq8dn7uIsi609D6KuFtlc+UvNYjatz0+u
      QzIr3iw//qf7sM8nx8fhGwuWvUWeCE6zbgKjuxDH82J9NQ0ctf70n0qVTeyW1CKR
      ...
      XlOfXr/xvkXA66PROgvVxfwpN/GNrLXFi1HvMg7MVZJUZQpNzpAzw5JTk2MbawOl
      G7tI0qQ6F20e5R4tPpEDKCFZykyvgGMhfLzsvVlrgaVW8QbVK4YWNtQ=
      -----END RSA PRIVATE KEY-----
```

> [!TIP]
> This file can also be passed using the `--set-file` flag with your `helm` command.

<a id="https_ssl_certificate"></a>

###### HTTPS SSL Certificate

It’s strongly recommended that production installations of Develocity are configured to use HTTPS with a trusted certificate.

Develocity natively supports serving traffic over HTTPS when configured with a certificate and key. If you intend to use an Ingress controller for directing external traffic to Develocity, you may opt to terminate HTTPS there. It’s also possible to terminate HTTPS connections in an external reverse proxy.

<a id="untrusted_ssl_certificates"></a>

###### Untrusted SSL Certificates

By default, Develocity uses the default trust settings of the Java runtime that’s included when connecting to other systems using SSL.

If your organization uses certificates that aren’t signed by a trusted certificate authority, you must perform additional configuration for this to work. This may be the case if you use self-signed certificates or an internal certificate authority.

<a id="trusted-and-additional-tls-certificates"></a>

###### Trusted and Additional TLS Certificates

Additional trusted certificates can be specified at installation time using the `global.additionalTrust` Helm value. This value accepts one of two mutually exclusive subkeys:

**certificates** — The X509 certificates to trust, inlined in PEM format and newline-separated if there is more than one.

**configMapName** — The name of an existing ConfigMap in the release namespace. The ConfigMap must expose the trusted certificates in PEM format under the `tls.crt` key. Use this when you prefer to manage certificate material outside the Helm values file.

**values.yaml (inline certificates):**

```
global:
  additionalTrust:
    certificates: |
      -----BEGIN CERTIFICATE-----
      MIIDfzCCAmegAwIBAgIURqPslYGu7cHXs22q3RK6e5L87PwwDQYJKoZIhvcNAQEL
      ...
      s10yB5VjVBES6A22rYwYb8mImpQiVP/mr4ao5U5m+h50l3E=
      -----END CERTIFICATE-----
      -----BEGIN CERTIFICATE-----
      DSE3a3CCAmegAwIBAgIURqPslYGu7cHXs22q3RK6e5L87PwwDQYJKoZIhvcNAQEL
      ...
      s10yB5VjVBES6A22rYwYb8mImpQiVP/mr4ao5U5m+h50l3E=
      -----END CERTIFICATE-----
```

**values.yaml (reference an existing ConfigMap):**

```
global:
  additionalTrust:
    configMapName: additional-trust
```

> [!IMPORTANT]
> As of Develocity 2026.2, specifying additional trusted certificates through the unattended configuration mechanism (using the network.additionalTrust field) is deprecated. Use global.additionalTrust instead. The legacy method continues to work for existing deployments and is shown below for reference.

**values.yaml (legacy unattended configuration, deprecated):**

```
global:
  unattended:
    configuration:
      version: 17
      systemPassword: "«hashed-system-password»"
      network:
        additionalTrust: |
          -----BEGIN CERTIFICATE-----
          MIIDfzCCAmegAwIBAgIURqPslYGu7cHXs22q3RK6e5L87PwwDQYJKoZIhvcNAQEL
          ...
          s10yB5VjVBES6A22rYwYb8mImpQiVP/mr4ao5U5m+h50l3E=
          -----END CERTIFICATE-----
          -----BEGIN CERTIFICATE-----
          DSE3a3CCAmegAwIBAgIURqPslYGu7cHXs22q3RK6e5L87PwwDQYJKoZIhvcNAQEL
          ...
          s10yB5VjVBES6A22rYwYb8mImpQiVP/mr4ao5U5m+h50l3E=
          -----END CERTIFICATE-----
```

<a id="https_terminated_externally"></a>

##### HTTPS Terminated Externally

In many setups, a reverse proxy or load balancer will perform SSL termination. In this case, SSL certificates must be configured accordingly.

Develocity needs to know that the application will be accessed over externally terminated HTTPS. This is done with the following configuration:

**values.yaml:**

```
global:
  hostname: develocity.example.com
  externalSSLTermination: true
```

If you’re using the provided Ingress, you may want to communicate between the load balancer and the application using HTTP by disabling SSL at the Ingress:

**values.yaml:**

```
ingress:
  enabled: true
  ssl:
    enabled: false
```

Re-encrypting between the load balancer and the Ingress is the better choice. Forwarding plain HTTP sends credentials over that hop in clear text, and breaks sign-in through an external identity provider. See [Routing and TLS Termination](https://docs.develocity.ai/2026.3/installation/standalone-installation/#routing_and_tls).

<a id="application-ports"></a>

#### Application Ports

The ports that the application accepts traffic on can be altered from the default of 443 (or 80 if accepting plain HTTP) as follows:

**values.yaml:**

```
ingress:
  enabled: true
  port:
    http: 8080
    https: 8443
```

<a id="proxy_configuration"></a>

#### Proxy Configuration

By default, Develocity requires an internet connection to make several outbound HTTP requests (such as license validation).

In case your organization requires all outbound HTTP traffic to go through an HTTP proxy, you must perform additional configuration for this to work as part of the [unattended configuration](#helm_config_unattended_configuration).

<a id="helm_config_object_storage"></a>

### 7. Object Storage Configuration

> [!WARNING]
> The new monitoring system introduced in 2025.1 requires some extra configuration to be fully operational. Review the changes in the Develocity 2025.2 Upgrade Guide before upgrading.

Develocity can store different kinds of data in a user-managed Object Storage service, such as Amazon S3:

*   Build Scan data is stored in the [database](#database_type) by default, but [Develocity can be configured to store Build Scan data in an object store](#object_storage_for_build_scans) instead.
    
*   Build Cache data is stored in embedded object storage - a persistent volume backed server installed with Develocity - by default, but can be configured to store Build Cache data in a user-managed object store instead.
    
*   Monitoring data, the metrics and logs collected during application lifetime.
    

> [!NOTE]
> Storing data in different buckets allows you to apply various strategies, such as access control, replication, soft-delete, backup, and more. You can use a single bucket for all data, or store monitoring data and Build Cache data in separate buckets; this is an operational decision based on your practices. By default, all data is stored using the parent objectStorage. configuration. To store monitoring data separately, add an optional monitoring block under the provider - see Separate Monitoring Data Storage (Optional). To store Build Cache data separately (for example, to apply different retention, storage-class, or backup policies), add an optional cache block under the provider - see Separate Build Cache Data Storage (Optional). Build Scan data and all other application data always use the parent configuration.

The [Build Scan object storage section of the Administration Manual](https://docs.develocity.ai/2026.3/administration/build-scan/build-scan-storage/#build_scan_object_storage) discusses the tradeoffs of using object storage rather than a database for Build Scan data. We recommend that your object storage is hosted close to your Develocity installation to minimise latency and network usage costs. For example, if using S3 as an object storage service, verify that your S3 bucket and Develocity installation reside in the same AWS region.

Most popular object storage services are supported. Alternatively, Develocity has the ability to run an embedded object store as one of its components. The rest of this section describes how to configure Develocity to use Amazon S3, an S3-compatible object storage service, Google Cloud Storage, Microsoft Azure Blob Storage, or the embedded object storage.

> [!NOTE]
> To finish configuring Develocity to store Build Scan data in the configured object storage, you must also configure Develocity with an unattended configuration stanza in your Helm `values.yaml` file. See [Object Storage for Build Scan Data](#object_storage_for_build_scans) for details.

> [!NOTE]
> If Develocity is connected to a user-managed object storage service, then Develocity will switch to storing Build Cache data there, instead of embedded object storage.

<a id="object_storage_s3"></a>

#### Amazon S3

For steps to set up a bucket in S3 with an appropriate access policy, see the [Amazon S3 appendix of the EKS Installation Guide](https://docs.develocity.ai/2026.3/installation/aws/aws-eks-cluster/#s3) for Kubernetes cluster deployments, or the [Amazon S3 appendix of the EC2 Installation Guide](https://docs.develocity.ai/2026.3/installation/aws/aws-ec2-standalone/#s3) for VM standalone deployments.

To use Amazon S3 as the object store for Develocity, you need to set the type of the object storage as `s3` and configure the bucket name and region.

**values.yaml:**

```
objectStorage:
  type: s3
  s3:
    bucket: develocity-application-data (1)
    region: aws-region (2)
    credentials:
      type: keys # ...
```

1. Your S3 bucket name, used for all application data (Build Scan data and Build Cache) and monitoring data, unless a separate cache or monitoring block is configured.
2. The cloud provider region where your object storage resides.

> [!TIP]
> To store Build Cache data or monitoring data in a separate bucket or with different credentials, see [Separate Build Cache Data Storage (Optional)](#object_storage_cache_override) and [Separate Monitoring Data Storage (Optional)](#object_storage_monitoring_override).

It’s necessary to provide credentials to access the bucket. There are several options to do this as documented below.

> [!NOTE]
> If Develocity is hosted on AWS, it’s strongly recommended to set up and configure access to the S3 bucket via a VPC endpoint to reduce access cost and latencies. Refer to the [official Amazon VPC endpoint documentation](https://docs.aws.amazon.com/whitepapers/latest/aws-privatelink/what-are-vpc-endpoints.html) to learn more.

<a id="object_storage_s3_credentials_instance_profile"></a>

##### Instance Profile Credentials Configuration

You can provision credentials to Develocity dynamically using [EC2 instance profiles](https://docs.develocity.ai/2026.3/installation/aws/aws-ec2-standalone/#s3_create_ec2_instance_profile).

**values.yaml:**

```
objectStorage:
  type: s3
  s3:
    bucket: develocity-application-data
    region: aws-region
    credentials:
      type: instanceProfile
```

<a id="object_storage_s3_credentials_keys"></a>

##### Keys Credentials Configuration

To provide an access key and secret key as credentials in the Helm chart, set `type` to `keys` and provide the `accessKey` and `secretKey`.

**values.yaml:**

```
objectStorage:
  type: s3
  s3:
    bucket: develocity-application-data
    region: aws-region
    credentials:
      type: keys
      keys:
        accessKey: "AKIA1234ABCD7890"
        secretKey: "dfml3s9rfdlsok390wledck30rkdfs"
```

<a id="object_storage_s3_custom_endpoint"></a>

##### Custom Endpoint

There are circumstances in which it’s necessary to specify the endpoint URL of the service:

*   If you need to connect to S3 directly from a VPC using a [gateway VPC endpoint](https://docs.aws.amazon.com/vpc/latest/privatelink/vpc-endpoints-s3.html).
    
*   If your object storage service isn’t S3 but provides an S3-compatible interface.
    

To do this, set the `endpoint` property to point to the service endpoint:

**values.yaml:**

```
objectStorage:
  type: s3
  s3:
    bucket: develocity-application-data
    endpoint: https://object-store.example.com
    credentials:
      type: keys # ...
```

> [!NOTE]
> Amazon S3 supports two styles of endpoint URLs: virtual-hosted-style and path-style URL access. In either case, the bucket name must NOT be included in the URL. For example, for the following virtual-hosted-style URL `https://develocity-application-data.s3.«region-code».amazonaws.com` you configure bucket as `develocity-application-data` and endpoint as `https://s3.«region-code».amazonaws.com`.

<a id="object_storage_gcs"></a>

#### Google Cloud Storage

For steps to create a bucket and configure access, see the [Google Cloud Storage appendix of the GKE Installation Guide](https://docs.develocity.ai/2026.3/installation/google-cloud/gke-kubernetes/#google_cloud_storage) for Kubernetes cluster deployments, or the [Google Cloud Storage appendix of the GCE Installation Guide](https://docs.develocity.ai/2026.3/installation/google-cloud/gce-standalone/#google_cloud_storage) for VM standalone deployments.

To use Google Cloud Storage as the object storage, set the `type` of object storage as `googleCloudStorage` and configure the `bucket`.

**values.yaml:**

```
objectStorage:
  type: googleCloudStorage
  googleCloudStorage:
    bucket: develocity-application-data
    credentials:
      type: serviceAccount # ...
```

It’s necessary to provide credentials to access the bucket. There are several options to do this as documented below.

<a id="object_storage_gcs_credentials_gce_service_account"></a>

##### GCE Service Account credentials configuration

To use the service account attached to the underlying Compute Engine instance, set `type` to `gceServiceAccount`. Develocity then reads credentials from the instance metadata server, so there’s no key to create, store, or rotate.

**values.yaml:**

```
objectStorage:
  type: googleCloudStorage
  googleCloudStorage:
    bucket: develocity-application-data
    credentials:
      type: gceServiceAccount
```

<a id="object_storage_gcs_credentials_service_account"></a>

##### Service Account Key credentials configuration

To provide the service account key as credentials in the Helm chart, set `type` to `serviceAccount` and provide the `key`. The key is a long-lived secret that ends up in your Helm values file, so protect that file accordingly.

> [!TIP]
> Prefer [GCE Service Account credentials configuration](#object_storage_gcs_credentials_gce_service_account), which needs no key at all.

**values.yaml:**

```
objectStorage:
  type: googleCloudStorage
  googleCloudStorage:
    bucket: develocity-application-data
    credentials:
      type: serviceAccount
      serviceAccount:
        key: |
          {
            "type": "service_account",
            "project_id": "PROJECT_ID",
            "private_key_id": "KEY_ID",
            "private_key": "-----BEGIN PRIVATE KEY-----\nPRIVATE_KEY\n-----END PRIVATE KEY-----\n",
            "client_email": "SERVICE_ACCOUNT_EMAIL",
            "client_id": "CLIENT_ID",
            "auth_uri": "https://accounts.google.com/o/oauth2/auth",
            "token_uri": "https://accounts.google.com/o/oauth2/token",
            "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
            "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/SERVICE_ACCOUNT_EMAIL"
          }
```

<a id="object_storage_azure"></a>

#### Azure Blob Storage

For steps to set up the storage account and configure access, see the [Azure Blob Storage appendix of the AKS Installation Guide](https://docs.develocity.ai/2026.3/installation/azure/azure-aks-cluster/#azure_blob_storage) for Kubernetes cluster deployments, or the [Azure Blob Storage appendix of the Azure VM Installation Guide](https://docs.develocity.ai/2026.3/installation/azure/azure-vm-standalone/#azure_blob_storage) for VM standalone deployments.

To use Azure Blob Storage as the object storage, set the `type` of the object storage as `azureBlobStorage` and configure the `container` name.

**values.yaml:**

```
objectStorage:
  type: azureBlobStorage
  azureBlobStorage:
    container: develocity-application-data
    credentials:
      type: accountInformation # ...
```

It’s necessary to provide credentials to access the bucket.

<a id="object_storage_azure_credentials_account_information"></a>

##### Account Key Credentials Configuration

To provide an account name and key in the Helm chart, set `type` to `accountInformation` and provide the `accountName` and `accountKey` properties. The account key is a long-lived secret that ends up in your Helm values file, so protect that file accordingly.

**values.yaml:**

```
objectStorage:
  type: azureBlobStorage
  azureBlobStorage:
    container: develocity-application-data
    credentials:
      type: accountInformation
      accountInformation:
        accountName: "develocity-application-data-account"
        accountKey: "dfml3s9rfdlsok390wledck30rkdfs"
```

<a id="object_storage_azure_credentials_connection_string"></a>

##### Connection String Credentials Configuration

To provide a connection string in the Helm chart, set `type` to `accountInformation` and provide the `connectionString` property. The connection string embeds the account key, so it needs the same protection as the key itself.

**values.yaml:**

```
objectStorage:
  type: azureBlobStorage
  azureBlobStorage:
    container: develocity-application-data
    credentials:
      type: accountInformation
      accountInformation:
        connectionString: "DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=http://devstoreaccount1.gradle-enterprise.svc.cluster.local:10000"
```

<a id="object_storage_embedded"></a>

#### Embedded Object Storage

Embedded object storage is a component that’s deployed as part of the Develocity installation if no other object storage is configured.

Data will be stored on the local disk under the configured [storage directory](#storage).

The default embedded object storage size limit is 50 GiB. The limit can be increased by setting a custom value for `objectStorage.embedded.storage.buildCache.capacity`.

**values.yaml:**

```
objectStorage:
  type: embedded
  embedded:
    storage:
      buildCache:
        capacity: 70Gi  # Default 50Gi
```

> [!WARNING]
> Data in the embedded object store isn’t part of a Develocity database backup.

<a id="object_storage_monitoring_override"></a>

#### Separate Monitoring Data Storage (Optional)

By default, monitoring data (metrics and logs) is stored in the same location as application data, using the parent `objectStorage.<provider>` configuration. To store monitoring data in a separate bucket or with different credentials, add an optional `monitoring` block under the provider.

The following example uses S3 with an instance profile for application data and a different bucket with access keys for monitoring data:

**values.yaml:**

```
objectStorage:
  type: s3
  s3:
    bucket: develocity-application-data
    region: aws-region
    credentials:
      type: instanceProfile
    monitoring: (1)
      bucket: develocity-monitoring-data (2)
      region: aws-region
      credentials:
        type: keys
        keys:
          accessKey: "AKIA1234ABCD7890"
          secretKey: "dfml3s9rfdlsok390wledck30rkdfs"
```

1. Optional. When omitted, the parent objectStorage.<provider> configuration (bucket, region, credentials, endpoint) is reused for monitoring data.
2. A separate bucket and credentials for monitoring data, independent from application data.

> [!IMPORTANT]
> The monitoring block is all-or-nothing: if defined, it must contain the full provider configuration (bucket or container, region, credentials, and so on). Individual fields aren’t merged with the parent configuration. This override pattern applies to s3, googleCloudStorage, and azureBlobStorage providers. It doesn’t apply to the embedded object storage, which has a separate monitoring credentials structure.

<a id="object_storage_cache_override"></a>

#### Separate Build Cache Data Storage (Optional)

By default, when Develocity is connected to a user-managed object storage service, Build Cache data is stored alongside your other application data (such as Build Scan data), using the parent `objectStorage.<provider>` configuration. To store Build Cache data in a separate bucket or with different credentials, add an optional `cache` block under the provider. Build Scan data and all other application data continue to use the parent configuration.

Storing Build Cache data in its own bucket lets you apply different policies to it than to your other data, for operational cost, security, or other policy reasons: a different retention policy, storage class, access controls, or backup and replication strategy.

The following example uses S3 with an instance profile for application data and a separate bucket with access keys for Build Cache data:

**values.yaml:**

```
objectStorage:
  type: s3
  s3:
    bucket: develocity-application-data
    region: aws-region
    credentials:
      type: instanceProfile
    cache: (1)
      bucket: develocity-build-cache-data (2)
      region: aws-region
      credentials:
        type: keys
        keys:
          accessKey: "AKIA1234ABCD7890"
          secretKey: "dfml3s9rfdlsok390wledck30rkdfs"
```

1. Optional. When omitted, the parent objectStorage.<provider> configuration (bucket, region, credentials, endpoint) is reused for Build Cache data.
2. A separate bucket and credentials for Build Cache data, independent from Build Scan data and other application data.

> [!IMPORTANT]
> The cache block is all-or-nothing: if defined, it must contain the full provider configuration (bucket or container, region, credentials, advancedParams, and so on). Individual fields aren’t merged with the parent configuration. If omitted, advancedParams aren’t inherited. No entries are carried over, whether they tune the client, such as client.maxConcurrency, or change how data is transferred, such as presignedUrl.enabled. Repeat any parent entries the Build Cache store also needs. Omitting presignedUrl.enabled, for example, means Edge nodes continue to replicate Build Cache data through the Develocity server instead of transferring it directly to object storage. This override pattern applies to s3, googleCloudStorage, and azureBlobStorage providers. It doesn’t apply to the embedded object storage.

<a id="object_storage_advanced_params"></a>

#### Configuring Advanced Parameters

Each object storage provider can be further configured using `advancedParams`. You should only configure advanced parameters if the Develocity support has directed you to do so.

**values.yaml:**

```
objectStorage:
  type: s3
  s3:
    bucket: develocity-application-data
    region: aws-region
    credentials:
      type: keys
      #...
    advancedParams:
      client.maxConcurrency: 12
```

<a id="helm_config_unattended_configuration"></a>

### 8. Unattended Configuration

Many aspects of Develocity’s behavior can be configured via the Admin user interface or by providing an unattended configuration file. These settings are described in the [unattended configuration](https://docs.develocity.ai/2026.3/administration/unattended-configuration/) section of the Develocity Administration Manual.

> [!TIP]
> Unattended configuration settings can also be in their own yaml file and given to the `helm` command as follows: `--set-file global.unattended.configuration=./unattended-config.yaml`

While most of Develocity can be configured post-installation, there are two items that can and should be configured at installation time:

*   Proxy settings
    
*   Object Storage for Build Scan Data
    

You will need the hashed system user password and a configuration version to use the unattended configuration in your Helm values file, and you must install the [Develocity command line tool](https://docs.develocity.ai/develocityctl/1.24/) (develocityctl).  
Full instructions are available [in the Administration Manual](https://docs.develocity.ai/2026.3/administration/unattended-configuration/).

<a id="proxy-settings"></a>

#### Proxy Settings

HTTP proxy configuration can be specified under the `network` section in the unattended configuration section:

**values.yaml:**

```
global:
  unattended:
    configuration:
      version: 17 (1)
      systemPassword: "«hashed-system-password»" (2)
      network:
        proxy:
          protocol: http (3)
          host: proxy.gradle.com (4)
          port: 8080 (5)
          excludedHosts: (6)
            - some.external
            - '*.internal'
          auth: (7)
            username: proxy_user
            password: "aes256:B0uVHRDhng+PraUI:2bOz71vKTexz0QH5:z7lO+1wOC/tA3izLAwV0BXMugg=="
```

1. The version of the unattended configuration. See the Administration Manual.
2. Your hashed system password. See the Administration Manual.
3. The protocol used to connect to the proxy. Note that this isn’t the protocol used to connect to the destination/target addresses. Supported values are http and https, if no value is provided http will be used as the default protocol.
4. HTTP proxy hostname.
5. HTTP proxy port, if no value is provided 80 will be used ad the default port.
6. A comma-delimited list that controls what hosts shouldn’t be proxied. The list can contain individual host names as well as domain patterns (for example, '*.internal') which match all hosts for a particular domain. Any requests sent to these hosts will be sent directly rather than being sent through the HTTP proxy.
7. A username and password used to authenticate with the HTTP Proxy.

<a id="object_storage_for_build_scans"></a>

#### Object Storage for Build Scan Data

To configure Develocity to store incoming Build Scan data using your object storage service bucket or container, add the following to your Helm values file:

**values.yaml:**

```
global:
  unattended:
    configuration:
      version: 17 (1)
      systemPassword: "«hashed-system-password»" (2)
      buildScans:
        incomingStorageType: objectStorage

objectStorage: (3)
  type: s3
  s3:
    bucket: develocity-application-data
    region: aws-region
    credentials:
      type: instanceProfile
```

1. The version of the unattended configuration. See the Administration Manual.
2. Your hashed system password. See the Administration Manual.
3. The object storage stanza you created in 7. Object Storage Configuration. If you set incomingStorageType to objectStorage, then you must configure an object storage service with this stanza in values.yaml for your Develocity instance.

> [!NOTE]
> On Kubernetes cluster installations, storing Build Scan data in object storage calls for more application memory, configured with the `enterprise.resources` Helm values. On standalone installations, [automatic resource management](#automatic-resource-management) sizes the application’s memory from the host, and it sizes it the same way whether or not Build Scan data goes to object storage. Near the documented host minimum, that leaves the application below the figure the cluster guidance calls for, so read the applied limit and set `enterprise.resources.limits.memory` if you need more.

<a id="helm_config_bazel_cache_client"></a>

### 9. Using an external Bazel cache

If you want to use the Build Scan for your Bazel builds while using a [remote cache](https://docs.develocity.ai/bazel/bazel-config/) other than the one built into Develocity, you will need to configure the necessary details. Note that your remote cache must expose a gRPC endpoint for Develocity to be able to speak to it.

The only mandatory value is the host and port of your external cache:

**values.yaml:**

```
enterprise:
    bazel:
        remoteCacheConnection:
            url: grpc{s}://<hostname>:<port>
```

If your external cache allows anonymous reads, this is the only value you need. Otherwise, see [the section on authentication](#helm_config_bazel_cache_client_auth).

<a id="helm_config_bazel_cache_client_tls"></a>

#### Trusting a Server Certificate

See the section on [untrusted SSL certificates](#untrusted_ssl_certificates).

<a id="helm_config_bazel_cache_client_auth"></a>

#### Authenticating to an External Bazel Cache

All configuration of authentication to a Bazel cache will take the following form:

**values.yaml:**

```
enterprise:
    bazel:
        remoteCacheConnection:
            url: grpc{s}://<hostname>:<port>
            authType: <AUTH_TYPE>
            auth:
                <AUTH_TYPE>:
                    ...
```

Note that any credentials you provide must allow a user to **read** from the cache.

The following authentication methods are supported:

<a id="helm_config_bazel_cache_client_auth_bearer"></a>

##### Bearer Token Authentication

In this authentication method, an external token will be passed to the server in the Authorization header prefixed by "Bearer" - `Bearer <token>`. The configuration for this scenario should look like this:

**values.yaml:**

```
enterprise:
    bazel:
        remoteCacheConnection:
            url: grpc{s}://<hostname>:<port>
            authType: bearerToken
            auth:
                bearerToken:
                    token: <TOKEN>
```

<a id="helm_config_bazel_cache_client_auth_tls"></a>

##### TLS Client Authentication

In this authentication method, a client certificate + key will be used to authenticate to the cache. The certificate and key must be separate values and in [PEM format](https://en.wikipedia.org/wiki/Privacy-Enhanced_Mail). You can provide these values directly, in which case the configuration looks like this:

**values.yaml:**

```
enterprise:
    bazel:
        remoteCacheConnection:
            url: grpc{s}://<hostname>:<port>
            authType: tls
            auth:
                tls:
                    cert: |-
                        <PEM_FORMATTED_CERT>
                    key: |-
                        <PEM_FORMATTED_KEY>
```

<a id="automatic-resource-management"></a>

### 10. Automatic Resource Management

A standalone installation sizes the memory limit of every long-running Develocity container from the memory the host makes available, so you do not have to tune those limits by hand. Automatic resource management is enabled by default, and applies to standalone installations only. On a standalone installation the host is the cluster’s single node, and this section uses "host" throughout; the webhook’s own messages say "node" for the same thing.

> [!NOTE]
> A host that meets the [CPU & Memory](https://docs.develocity.ai/2026.3/installation/standalone-installation/#cpu_memory) requirements and runs the components Develocity enables by default needs none of the values in this section. Change them only when you have a preference the defaults do not meet, or when you would rather size memory yourself.

Develocity installs an admission webhook that computes the limits and applies them as Pods are created. It runs the `standalone-operator` image as the `admission-webhook` Deployment, in a Namespace of its own that the Helm chart creates if it does not already exist. If it does exist, it must carry the label `app.kubernetes.io/for=admission-webhook` or the chart refuses the render rather than adopt a Namespace that belongs to something else; `preflight` turns that refusal off. The webhook sizes only the Pods the chart labels `develocity.gradle.com/automatic-resource-management`, which excludes Develocity’s Jobs, its init containers, and anything else running in the same Namespace.

Four terms describe what it does:

**headroom** — The memory the webhook holds back from the host’s allocatable memory and never hands out. Defaults to `1024Mi`.

**budget** — The allocatable memory less the headroom. This is what the webhook shares out.

**plan** — The set of memory limits the webhook computes from the budget. It is recomputed whenever an input changes.

**ceiling** — The point past which extra memory stops helping a given container, fixed per container by Develocity. The webhook’s log calls this the cap. Not every container has one, and a limit you set yourself is honored whether or not there is a ceiling above it.

Every container starts at the memory it needs to run. The webhook raises the containers above that base in proportion to how much each one gains from extra memory, until one reaches its ceiling. Memory that a container at its ceiling cannot take flows to the containers that can still use it.

Develocity sets no memory request of its own. Kubernetes rejects a Pod whose request exceeds its limit, so the chart leaves the request unset, and Kubernetes then treats the request as equal to the computed limit. Five components keep a request you set beside your own limit; see [Pinning a Component’s Memory Limit](#pinning-a-components-memory-limit).

The plan follows your configuration. When an input changes, such as the components you enable or a limit you set by hand, the next `helm upgrade` recreates the sized Pods so that they start under the new plan.

These Helm values control the feature.

**values.yaml:**

```
global:
  automaticResourceManagement:
    memory:
      enabled: true (1)
      headroom: 2Gi (2)
    namespace: dv-system (3)
    preflight: true (4)
```

1. Defaults to true, as shown. Set it to false to return to the chart’s own memory limits, which cover only some components.
2. The memory to hold back from the plan so that Develocity’s own Jobs can run. Defaults to 1024Mi; the example raises it.
3. The Namespace the webhook runs in. Defaults to the release namespace with -system appended, such as develocity-system. It must differ from the release namespace, because the webhook cannot admit its own Pods.
4. Defaults to true, as shown. Set it to false to skip the three render-time checks that read the cluster. The node check covers both the host’s size and that there is exactly one node. The image pull secret check runs only when you set global.image.imagePullSecret. The third is whether an existing webhook Namespace can be adopted. The checks that read only your values still run. The chart reads the webhook’s Namespace whether or not preflight is on, because it has to know whether to create it. What preflight governs is those checks and the reads they need: the Node, the image pull secret when you set one, and whether an existing Namespace carries the label that offers it for adoption. Turn it off when one of them reads something untrue of your cluster: an image pull secret that reaches the webhook’s Namespace by replication, registry credentials held by the host itself, an existing Namespace you want adopted as it stands, or an installing account that cannot list nodes.

Two further values are rarely needed: `global.automaticResourceManagement.logLevel` sets the webhook’s own log level, and `global.automaticResourceManagement.resources` sets the CPU and memory of the webhook’s own Pod. Others under this key are support knobs, to be set only when Develocity support asks.

The chart installs the webhook through Helm hooks, and Helm does not own hook resources, so `helm uninstall` leaves the webhook Namespace and its cluster-scoped resources behind. See [Removing the Admission Webhook](https://docs.develocity.ai/2026.3/operations/uninstall/#removing-admission-webhook) for the steps to delete them.

<a id="preparing-the-webhook-namespace"></a>

#### Preparing the Webhook Namespace

The chart creates and labels the Namespace the webhook runs in, so most installations need to do nothing here. Setting `global.image.imagePullSecret` is the exception. Preparing the Namespace yourself is then required, and skipping it stops the render before anything reaches the running installation.

The webhook needs those registry credentials in its own Namespace before it can pull its image, and the chart holds the secret’s name rather than the credentials behind it, so it cannot copy one across. Create the same Secret there yourself, under the name the chart already looks for. The Namespace has to exist first, and on a first install or a first upgrade it does not. In the commands below, `«release-namespace»` is the Namespace you installed Develocity into:

```shell
kubectl create namespace «release-namespace»-system

kubectl label namespace «release-namespace»-system app.kubernetes.io/for=admission-webhook

kubectl create secret docker-registry «image-pull-secret» \
  --namespace «release-namespace»-system \
  --docker-server=«registry» --docker-username=«username» --docker-password=«password»
```

<a id="former-application-heap-memory"></a>

#### Former Application Heap Memory

The heap memory setting is no longer required, as the optimal heap memory is determined by the container’s limit. The previous values are displayed read-only and will only become active again if automatic resource management is disabled.

Off-heap memory is set separately and the feature never changes it, but the heap calculation does take it into account: raising off-heap memory lowers the heap the component arrives at within the same limit. See [JVM Off-Heap Memory](#jvm_off_heap_memory).

<a id="reserving-memory-for-jobs-and-other-workloads"></a>

#### Reserving Memory for Jobs and Other Workloads

Develocity runs short-lived Jobs for work such as database migration and Keycloak configuration. Those Jobs are not part of the plan, and on a standalone installation they declare no memory request or limit of their own, so nothing reserves memory for them. The headroom is what leaves the host enough free memory to run them.

Raise the headroom when the host also runs workloads that are not part of Develocity, and raise it by the memory those workloads **request**. A sized container’s request equals its limit, so the headroom is the only memory on the host left outside the plan; a workload asking for more than remains of it stays Pending. The webhook’s own Pod is the first claim on it, requesting `64Mi`. Develocity’s Jobs request nothing, so they are always scheduled, but they then compete for whatever the headroom still holds and are evicted or OOM-killed if it is not enough.

<a id="pinning-a-components-memory-limit"></a>

#### Pinning a Component’s Memory Limit

A memory limit you set yourself is kept. The webhook reserves that memory out of the budget before it sizes everything else, so you can pin one component without turning the feature off for the rest.

These components accept a memory limit:

*   `enterprise.resources.limits.memory`
    
*   `authenticationBroker.resources.limits.memory`
    
*   `database.resources.limits.memory`
    
*   `edgeNode.resources.limits.memory`
    
*   `mcpServer.resources.limits.memory`
    
*   `objectStorage.embedded.resources.limits.memory`
    
*   `operator.resources.limits.memory`
    
*   `testDistribution.resources.limits.memory`
    
*   `monitoring.logging.resources.limits.memory` (Loki)
    
*   `monitoring.metrics.database.resources.limits.memory` (Mimir)
    
*   `monitoring.metrics.scraper.resources.limits.memory` (`vmagent`)
    

`proxy.resources.limits.memory` is accepted by the schema but has no effect: standalone installations no longer deploy the deprecated `gradle-proxy` component, unless `routedBy` has been reset to `proxy`.

Four containers the webhook sizes have no values key at all and cannot be pinned: `vector`, `sql-exporter`, `frontend`, and the database’s scheduled tasks.

**values.yaml:**

```
edgeNode:
  resources:
    limits:
      memory: 8Gi
```

> [!IMPORTANT]
> To size `enterprise`, `authenticationBroker`, `database`, `objectStorage.embedded` or `testDistribution` yourself, pin a limit here rather than turning the feature off: with it off, those five render no memory limit at all, whatever you set. See [Disabling Automatic Resource Management](#disabling-automatic-resource-management).

Whether a memory **request** you set alongside a limit is applied depends on the component:

*   For `enterprise` (the application), `authenticationBroker` (Keycloak), `database`, `objectStorage.embedded` and `testDistribution`, a request is applied when you set a limit beside it, and dropped when it stands alone.
    
*   For every other component in the list, the request is always dropped.
    

The chart drops a request it cannot pair with a limit of yours, because the webhook then injects a limit the request could exceed, and Kubernetes rejects a Pod whose request exceeds its limit. For the five components above it keeps a request paired with your own limit, and that pair stands exactly as you wrote it.

CPU is never sized automatically, so `resources.requests.cpu` and `resources.limits.cpu` are applied as you set them, for every component in the list.

<a id="disabling-automatic-resource-management"></a>

#### Disabling Automatic Resource Management

Switching the feature off returns the chart to what it did before automatic resource management, which is not a memory limit everywhere. The Edge node, MCP Server, operator, `frontend`, `loki`, `mimir`, `vmagent` and `sql-exporter` get the chart’s own memory limit. The application, Keycloak, the database and its tasks, embedded object storage, the Test Distribution broker and `vector` then run with no memory limit at all. The application and the Test Distribution broker then size their heap from the Develocity configuration, not from the container, so a larger host does not give them a larger heap. Keycloak has no such setting, so its JVM sizes its heap from the host’s memory; the database, object storage and `vector` are not JVMs at all.

**values.yaml:**

```
global:
  automaticResourceManagement:
    memory:
      enabled: false
```

<a id="resizing-the-host"></a>

#### Resizing the Host

The host’s allocatable memory is the one input the Helm chart cannot see, so resizing the host changes the plan without changing any Pod. The webhook picks the new figure up within seconds, but a running Pod keeps the limit it started with. Restart the Develocity workloads to size them against the resized host:

> [!WARNING]
> This restarts Develocity, which is unavailable while its Pods roll.

```shell
kubectl rollout restart deployment \
  --namespace «release-namespace» \
  --selector app.kubernetes.io/part-of=gradle-enterprise
```

The selector restarts Develocity’s own Deployments and leaves any other workload on the host alone. Every workload the webhook sizes is a Deployment, so nothing is missed.

<a id="verifying-the-applied-limits"></a>

#### Verifying the Applied Limits

Read the limits Kubernetes applied:

```shell
kubectl get pods --namespace «release-namespace» \
  -o custom-columns='POD:.metadata.name,MEMORY:.spec.containers[*].resources.limits.memory'
```

The webhook logs a plan when it first computes one and whenever the plan changes, so restarting a sized workload produces no new line unless the plan itself moved:

```shell
kubectl logs deployment/admission-webhook --namespace «release-namespace»-system
```

The figures below are illustrative; yours depend on the host and on the components you enable.

```text
Planned memory against 63488Mi allocatable less 1024Mi headroom, a budget of 62464Mi across 14 containers
  enterprise-app/gradle-enterprise-app 19407Mi (injected)
  edge-node/edge-node 8192Mi (reserved)
  monitoring/mimir 1344Mi (at cap)
  monitoring/loki 1229Mi (injected)
  ... (the remaining containers)
```

Each line names the component and the container within it, then the limit, then where the limit came from. The component is the `app.kubernetes.io/component` label, not the Deployment name, so `database/database` is the Deployment `gradle-database`. `(injected)` marks a limit the webhook computed, `(reserved)` a limit you set by hand, and `(at cap)` a container that reached its ceiling and cannot grow on a larger host.

<a id="troubleshooting-automatic-resource-management"></a>

#### Troubleshooting Automatic Resource Management

K3s restarts a component that goes over its limit. A restart of the Develocity application is visible, because the instance stops answering while it comes back. A restart of a background component such as `vector`, `mimir` or `loki` is invisible, and so is the slowdown a component shows under a limit tight enough to keep it collecting garbage. The symptom that reaches an operator is that Develocity is slower or less reliable, not that anything failed. Send [Develocity support](https://support.gradle.com/) a support bundle, and we will check whether your installation needs optimization.

When the budget does not cover what the enabled components need, the chart refuses the render and `helm upgrade` fails before anything is applied:

```text
The node is too small for the enabled Develocity components: 16384Mi of allocatable memory
less 1024Mi of headroom leaves a budget of 15360Mi, but the enabled components need at least
21114Mi before any of the node is shared out. Automatic resource management is on by default
from this release, and its webhook would deny every Develocity pod rather than plan a node it
cannot fit them on.
...
```

Move to a larger host, or stop running components on it. Each one you stop running leaves its base memory to the rest, largest first: embedded object storage and the Edge node free `4096Mi` each, the Test Distribution broker `2048Mi`, the monitoring components `1896Mi` between them, and an external database frees `1024Mi`. The MCP Server is already off unless you enabled it, so disabling it frees nothing. Lower the headroom only when you know what the host’s Jobs and other workloads need, because the headroom is what keeps memory free for them. Setting `global.automaticResourceManagement.memory.enabled` to `false` gets a wedged installation running again while you resize the host, at the cost of the limits described in [Disabling Automatic Resource Management](#disabling-automatic-resource-management). For the memory a standalone host requires, see [CPU & Memory](https://docs.develocity.ai/2026.3/installation/standalone-installation/#cpu_memory).

The same shortfall reaches the webhook if the host shrinks after installation, or if the render-time check was skipped with `preflight`. The webhook then has no plan, and Kubernetes refuses to create the Pods the chart labels rather than create them without a memory limit. Other workloads in the Namespace are never gated. Check that the webhook is running and ready:

```shell
kubectl get deployment admission-webhook --namespace «release-namespace»-system
```

<a id="jvm_off_heap_memory"></a>

### 11. JVM Off-Heap Memory

You can optionally configure Java off-heap memory for the `enterprise` and `testDistribution` components as Helm values. This allows cluster operators to manage memory settings alongside other infrastructure configuration in the Helm values file, supporting separation of duties from Develocity administrators.

**values.yaml:**

```
enterprise:
  resources:
    jvm:
      memory:
        offHeap: 512 (1)
testDistribution:
  resources:
    jvm:
      memory:
        offHeap: 512 (2)
```

1. Off-heap memory (MiB) for the application, corresponding to the value in Administration/Advanced > Application > Off heap memory (MiB).
2. Off-heap memory (MiB) for the Test Distribution broker, corresponding to the value in Administration/Advanced > Test Distribution broker > Off heap memory (MiB).

When you configure off-heap memory via Helm, Develocity disables the "Off-heap memory (MiB)" setting in the "Administration/Advanced" user interface for the selected components. Develocity ignores existing values in the user interface and the unattended configuration file.

> [!NOTE]
> If you configure off-heap memory as a Helm value and also use an unattended configuration file, consider removing these settings from the unattended configuration file to keep a single source of truth for memory settings.

<a id="airgap"></a>

### 12. Airgap Installations

Develocity can be run on hosts without internet connectivity, referred to as an _airgap_ installation.

<a id="airgap-configuration"></a>

#### Airgap Configuration

In an airgap installation, Helm is configured so that no attempt is made to pull images from the outside world with the values below:

**values.yaml:**

```
global:
  image:
    imagePullPolicy: Never
```

<a id="13-access-control-policies"></a>

### 13. Access Control Policies

Develocity will use a set of access control policies that are secure by default. The settings can be customized to better match your organization’s policies.

<a id="access-keys-max-lifespan"></a>

#### Access Keys Max Lifespan

Develocity, by default, requires access keys to have a finite lifespan. The maximum allowed lifespan can be adjusted, or this policy can be disabled entirely.

**values.yaml:**

```
accessControl:
  accessKeys:
    maxLifespan:
      enabled: true (1)
      duration: "P365D" (2)
```

1. Whether the maximum access key lifespan policy should be enabled; default true
2. The maximum access key lifespan to allow when the policy is enabled; ISO 8601 duration with default of "P365D" (365 days)

If the maximum lifespan policy for access keys is **enabled**, all access keys must have an expiration date no greater than the current date plus the maximum lifespan duration. This is applied automatically to newly created access keys. Any non-compliant access keys are brought into compliance on startup by applying the maximum allowed expiration date.

If the maximum lifespan policy for access keys is **disabled**, _newly created_ access keys won’t be assigned an expiration date. Even if the maximum lifespan policy is **disabled**, existing access key expiration dates will be retained and enforced.

<a id="trusted-oauth-issuers"></a>

#### Trusted OAuth Issuers

Develocity can accept OAuth 2.0 access tokens from authorization servers you trust, alongside access keys, when an AI agent calls the [Develocity MCP Server](https://docs.develocity.ai/2026.3/integrations/agentic-ai/mcp-servers/). Configuring at least one issuer makes OAuth sign-in available; access keys stay enabled.

Configure the issuers in this one place. Develocity handles token exchange and maintains the trusted issuer list, which is automatically shared with the Develocity MCP Server.

**values.yaml:**

```
accessControl:
  externalOauth:
    issuers:
      - uri: https://idp.example.com (1)
        accessTokenFormat: jwt (2)
        allowedDomains: [example.com] (3)
        allowedJwtAudiences: ["https://develocity.example.com/mcp"] (4)
        jwksUri: https://idp.example.com/keys (5)
        claimMapping: email (6)
    opaqueTokenFanOut: false (7)
```

1. The issuer URI, which must match the iss claim present in issued tokens; required
2. Whether this issuer mints jwt or opaque access tokens, which decides how Develocity validates them; required, with no default
3. Allowed email domains for users authenticating through this issuer; required unless restrictByDomain is false
4. Accepted aud values for JWT validation, identifying this Develocity instance as the resource the token was issued for; required for a jwt issuer unless restrictByJwtAudience is false
5. The JWKS endpoint used to fetch and update public key sets for signature verification
6. The token claim used to identify the user: email, sub, or preferredUsername; default email
7. Whether an opaque token may be presented to each opaque issuer in turn; default false, and required when more than one issuer mints opaque tokens

A `jwt` issuer requires exactly one of `jwksUri` and `jwkSet`; configuring neither or both is refused. An `opaque` issuer requires neither, and configuring either one is refused.

The remaining per-issuer settings depend on what your authorization server emits:

**jwkSet** — An inline JSON Web Key Set, provisioned rather than fetched, for an instance that cannot reach the authorization server.

**restrictByDomain** — Default `true`. Set it to `false` to admit every identity from this issuer regardless of email domain. Restricting by domain reads the access token’s email claim, so an issuer that keeps this enabled needs one even when `claimMapping` is `sub`.

**restrictByJwtAudience** — Default `true`. Set it to `false` to stop validating the audience for this issuer, which cannot be combined with a non-empty `allowedJwtAudiences`.

**requireEmailVerified** — Default `true`. Set it to `false` for an issuer that omits the `email_verified` claim.

**allowedJwtTypes** — Defaults to `JWT`, `at+jwt` and `application/at+jwt`. The `typ` header values accepted from this issuer’s JWTs. Issuers differ in the `typ` they set, and a mismatch rejects every token from that issuer; a token that omits `typ` altogether is accepted either way.

For how the sign-in flow works, and how to choose between fetched and provisioned keys, see [Authentication](https://docs.develocity.ai/2026.3/integrations/agentic-ai/mcp-servers/authentication/).

Your `values.yaml` file is complete. You can return to the installation manual.

<a id="changing_configuration_values"></a>

## Changing Configuration Values

You can also specify configuration values using the `--set` or `--set-file` parameters. However, these options aren’t saved, and you must specify all the options **again** whenever you make changes.

First, you need to specify the currently installed Develocity version to change configuration values without updating the Develocity version.

> [!IMPORTANT]
> It’s important to specify the Develocity version, because if you don’t, you may accidentally install a newer version and initiate an upgrade rather than merely a configuration change.  
> **Such accidental upgrades may be irreversible.**

**Use case:** You have an existing configuration and want to update the license value and disable Ingress SSL, but keep the rest of the configuration.

Check the deployed Develocity version:

```shell
helm history --namespace develocity develocity-standalone --max 1
```

To apply new configuration values to a Helm-managed online installation, run:

```shell
helm upgrade \
  --namespace develocity \
  develocity-standalone gradle/gradle-enterprise-standalone \
  --version «deployed-version» \(1)
  --reuse-values \
  --set-file global.license.file=./develocity.license \(2)
  --set ingress.ssl.enabled=false \(3)
```

1. «deployed-version» is the deployed version of Develocity.
2. The path to the new license file.
3. Disable the Ingress SSL.

Or for a Helm-managed airgap installation:

```shell
helm upgrade \
  --namespace develocity \
  develocity-standalone gradle-enterprise-standalone-«deployed-version».tgz \(1)
  --version «deployed-version» \
  --reuse-values \
  --set-file global.license.file=./develocity.license \(2)
  --set ingress.ssl.enabled=false \(3)
```

1. «deployed-version» is the deployed version of Develocity.
2. The path to the new license file.
3. Disable the Ingress SSL.

> [!WARNING]
> Running helm upgrade with --reset-values will cause any previous values to be lost. Consult the upgrade guide to learn more about it.

<a id="values_yaml_download"></a>

## Appendix A: Example Helm Values File

You can download and verify the example Helm values file with the following commands:

```shell
curl -L -o example.values.yaml https://docs.develocity.ai/downloads/gradle-enterprise-standalone-values/gradle-enterprise-standalone-values-2026.3.0.yaml
```

```shell
curl -L -o example.values.yaml.sha256 https://docs.develocity.ai/downloads/gradle-enterprise-standalone-values/gradle-enterprise-standalone-values-2026.3.0.yaml.sha256
```

```shell
echo "$(cat example.values.yaml.sha256)  example.values.yaml" | sha256sum -c -
```

A direct download is available below.

**2026.3.0**

*   [Download Example Helm Values File](https://docs.develocity.ai/downloads/gradle-enterprise-standalone-values/gradle-enterprise-standalone-values-2026.3.0.yaml)
    
*   [Download Example Helm Values File SHA256 Checksum](https://docs.develocity.ai/downloads/gradle-enterprise-standalone-values/gradle-enterprise-standalone-values-2026.3.0.yaml.sha256)
    
*   [Download Example Helm Values File PGP Signature](https://docs.develocity.ai/downloads/gradle-enterprise-standalone-values/gradle-enterprise-standalone-values-2026.3.0.yaml.asc)
    
*   [Download Example Helm Values File SHA256 PGP Signature](https://docs.develocity.ai/downloads/gradle-enterprise-standalone-values/gradle-enterprise-standalone-values-2026.3.0.yaml.asc.sha256)
    

> [!NOTE]
> Older versions example values file can be found in the Legacy Documentation. Refer to the Standalone Helm Chart Configuration Guide of the Develocity version you are looking for.

<a id="database_setup_download"></a>

## Appendix B: Database Setup Scripts

**2026.3.0**

*   [Download Database Setup Scripts](https://docs.develocity.ai/downloads/gradle-enterprise-database-setup-zip/gradle-enterprise-database-setup-zip-2026.3.0.zip)
    
*   [Download SHA256 Checksum](https://docs.develocity.ai/downloads/gradle-enterprise-database-setup-zip/gradle-enterprise-database-setup-zip-2026.3.0.zip.sha256)
    

> [!NOTE]
> Older versions (prior of Develocity 2025.3) of the Database Setup Scripts can be found in the legacy Develocity User-Managed Database Migration Guide. Refer to the 2025.3 Develocity User-Managed Database Migration Guide for the config schema version used in Develocity 2025.3.