---
component: provenance-governor
version: "1.7"
slug: provenance-governor/setup-deploy
canonical_url: "https://docs.gradle.com/develocity/provenance-governor/1.7/setup-deploy/"
title: "Deployment"
description: "Deployment instructions for Develocity Provenance Governor."
keywords:
  - "Kubernetes"
  - "Helm chart"
  - "installation"
  - "configuration"
status: current
---

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

# Deployment

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

Develocity Provenance Governor is provided as a container image that runs on a Kubernetes cluster. Make sure you have the prerequisites detailed in [Prerequisites](https://docs.gradle.com/develocity/provenance-governor/1.7/setup-prerequisites/) before proceeding.

> [!TIP]
> Looking for Docker deployment without Kubernetes? See the Docker Deployment Guide.

<a id="audience"></a>

## Audience

This guide is written for a Platform / Infrastructure Engineer. It assumes:

*   Basic familiarity with Kubernetes (namespaces, secrets, configmaps, deployments, ingress)
    
*   Ability to obtain a Develocity license file (`develocity.license`)
    
*   (Optional) Ability to obtain access tokens/keys for Develocity and Artifactory instances
    
*   Access to a DNS domain (optional, for public HTTPS ingress)
    

<a id="quickstart"></a>

## Quickstart

Want to get started quickly with a local k3d cluster and basic HTTP ingress?

See the [Quickstart Guide](https://docs.gradle.com/develocity/provenance-governor/1.7/quickstart/) for condensed setup instructions.

The quickstart will guide you through:

*   Creating a local k3d cluster
    
*   Deploying Develocity Provenance Governor with basic HTTP ingress
    
*   Verifying the deployment
    

After completing the quickstart, return to the sections below to configure additional features like authentication, integrations, and policies.

<a id="deployment-flow"></a>

## Deployment Flow Overview

The recommended order is:

1.  [Choose / create a Kubernetes cluster](#select-kubernetes-distribution) (local k3d or existing)
    
2.  [Create namespace + required secrets](#prepare-kubernetes-namespace-required-secrets) (registry + license)
    
3.  [Configure Ingress](#ingress-optional) (HTTP, then HTTPS + cert-manager) - Optional
    
4.  [Deploy the core workload](#deploy-core-components) (ServiceAccount, Services, Deployment, NetworkPolicy)
    
5.  [Verify rollout & logs](#verification-next-steps)
    
6.  [Create placeholder Secrets/ConfigMaps](#create-placeholders-dynamic-config) for dynamic configuration (`secrets`, `properties`, `policies`)
    
7.  [Add integrations](#develocity-deploy) ([Develocity instances](#develocity-deploy), [Artifactory instances](#artifactory-deploy))
    
8.  [Add signing keys](#signing-keys-deploy)
    
9.  [Enable authentication](#authentication-deploy) (Basic and/or OIDC)
    
10.  [Define policies](#policies-optional) (AccessControl manifests)
     
11.  Roll out config changes as needed
     
12.  [Troubleshoot rollout issues](#troubleshooting-deployment-rollouts)
     

Estimated setup time:

*   **Local k3d (Quickstart)**: 15-30 minutes
    
*   **Production setup with all integrations**: 2-4 hours (depending on external service coordination and certificate setup)
    

<a id="select-kubernetes-distribution"></a>

## Select Kubernetes Distribution

Before proceeding ensure access to a Kubernetes cluster has been provided, otherwise a local k3d cluster is also supported.

<a id="k3d"></a>

### k3d

**Install k3d:**

```
brew install k3d
```

**Create k3d cluster (port 80 exposed for ingress):**

```
k3d cluster create --port "80:80@loadbalancer"
```

<a id="prepare-kubernetes-namespace-required-secrets"></a>

## Prepare the Kubernetes Namespace and Required Secrets

You must create a Kubernetes namespace and the secrets needed for the application to start.

<a id="create-kubernetes-namespace"></a>

### Create Kubernetes Namespace

**Namespace that the Develocity Provenance Governor will be deployed to.:**

```
kubectl create namespace develocity-provenance-governor
```

<a id="docker-registry-secret-required"></a>

### Docker Registry Secret (Required)

Authenticate to `registry.gradle.com` to pull the product image.

```bash
kubectl create secret docker-registry registry-secret \
  --namespace develocity-provenance-governor \
  --docker-server=https://registry.gradle.com \
  --docker-username=user \
  --docker-password=$(cat ./develocity.license)
```

<a id="develocity-license-secret-required"></a>

### Develocity License Secret (Required)

A Develocity license is required for the deployment to be successful.

```shell
kubectl create secret generic license \
  --namespace develocity-provenance-governor \
  --from-file=develocity.license=./develocity.license
```

<a id="ingress-optional"></a>

## Ingress (Optional)

No default ingress is provided. Choose what aligns with organizational standards. Below examples cover:

*   Local development (nip.io hostname)
    
*   HTTPS with cert-manager & Let’s Encrypt
    

**Create Ingress Manifest:**

```
kubectl --namespace develocity-provenance-governor apply -f - <<EOF
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: api.127.0.0.1.nip.io
spec:
  rules:
    - host: api.127.0.0.1.nip.io
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: api-http
                port:
                  number: 80
EOF
```

**Verify Ingress Resource:**

```
kubectl get ingress api.127.0.0.1.nip.io --namespace develocity-provenance-governor
```

**Expected Response:**

```
NAME   CLASS     HOSTS                  ADDRESS      PORTS   AGE
http   traefik   api.127.0.0.1.nip.io   172.18.0.3   80      15s
```

**Verify Route:**

```
curl api.127.0.0.1.nip.io -i
```

**Expected Response:**

```
HTTP/1.1 401 Unauthorized
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Content-Length: 0
Expires: 0
Pragma: no-cache
Referrer-Policy: no-referrer
Www-Authenticate: Basic realm="Realm"
...
```

<a id="ingress-with-cert-manager"></a>

### Ingress with cert-manager

Alternative, ingress manifest using cert-manager, nginx, and signed certificate from Let’s Encrypt. The ingress resource, can be used to expose the api service outside the cluster. Modify the provided manifest to reflect the domain that you control paying close attention to `tls[0].hosts[0]` and `rules[0].host`.

```shell
kubectl --namespace develocity-provenance-governor apply -f - <<EOF
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: https
spec:
  tls:
  - hosts:
    - provenance-governor.example.com
    secretName: https-api-tls
  rules:
  - host: provenance-governor.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: api-http
            port:
              number: 80
EOF
```

At this point, the ingress controller might use a self-signed certificate provided as a default.

**Verify Ingress Resource:**

```
kubectl get ingress https --namespace develocity-provenance-governor
```

**Expected Response:**

```
NAME   CLASS     HOSTS                  ADDRESS      PORTS   AGE
https   traefik   provenance-governor.example.com   xxx.xxx.xx.x   80, 443      15s
```

If not already deployed, install [cert-manager](https://cert-manager.io/docs/tutorials/acme/nginx-ingress/#step-5---deploy-cert-manager)

**Create an Issuer:**

```
kubectl --namespace develocity-provenance-governor create --edit -f - <<EOF
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
  name: lets-encrypt
spec:
  acme:
    # The ACME server URL
    server: https://acme-v02.api.letsencrypt.org/directory
    # Email address used for ACME registration
    email: user@example.com
    # Name of a secret used to store the ACME account private key
    privateKeySecretRef:
      name: lets-encrypt
    # Enable the HTTP-01 challenge provider
    solvers:
      - http01:
          ingress:
            ingressClassName: nginx
EOF
```

> [!NOTE]
> This will create a certificate issuer using the Production Instance of Let’s Encrypt. Edit accordingly based on desired certificate issuer implementation. If using Let’s Encrypt, ensure the ingress is publicly accessible and can handle a http01 challenge provider request to complete certificate issuance. Also, be sure to update the email address.

**Verify the Issuer:**

```
kubectl describe issuer lets-encrypt \
  --namespace develocity-provenance-governor
```

Detailed issuer information should be returned along with `Status.Status: True` and `Status.Type: Ready`.

Edit the `https` ingress resource to use the `lets-encrypt` issuer instead of the self signed certificate issuer.

**Edit ingress resource:**

```
kubectl edit ingress https \
  --namespace develocity-provenance-governor
```

**Add cert-manager.io/issuer: lets-encrypt to annotations::**

```
metadata:
  annotations:
    cert-manager.io/issuer: lets-encrypt
```

**Verify Certificate Issued:**

```
$ kubectl get certificate \
  --namespace develocity-provenance-governor

NAME            READY   SECRET          AGE
https-api-tls   True    https-api-tls   2m31s
```

Verify Https Endpoint

$ curl [https://provenance-governor.example.com](https://provenance-governor.example.com) -i HTTP/2 401 …​

In this example, the request to `[https://provenance-governor.example.com](https://provenance-governor.example.com)` returns a `401 Unauthorized` status code because no credentials were provided. This confirms that the Ingress is correctly routing traffic to the service and that the service is up and running.

To verify the service health:

```bash
curl https://provenance-governor.example.com/readyz -i
```

No SSL negotiation exceptions should be thrown and a 401 should be returned.

<a id="deploy-core-components"></a>

## Deploy Core Components

Apply the workload manifests. (See Quickstart)

Download the [manifest.yaml](https://docs.gradle.com/develocity/provenance-governor/1.7/_attachments/manifest.yaml) file.

```shell
kubectl --namespace develocity-provenance-governor apply -f manifest.yaml
```

**Verify Rollout:**

```
kubectl rollout status deployment/api \
  --timeout=90s \
  --namespace develocity-provenance-governor
```

Expected output: `deployment "api" successfully rolled out`. If rollout fails:

*   Verify `registry-secret` credentials and image digest/tag
    
*   Verify `license` secret presence and correct file content
    

**Verify Logs:**

```
kubectl logs deployment/api \
  --namespace develocity-provenance-governor | grep -i license
```

**Sample lines:**

```
Develocity license enabled, with license [...]
Started ProvenanceGovernor in ...
```

<a id="create-placeholders-dynamic-config"></a>

## Create Placeholders for Dynamic Configuration (Optional but Recommended)

The Deployment mounts (optionally) these resources:

<table class="tableblock frame-all grid-all stretch"><colgroup><col style="width: 20%;"> <col style="width: 20%;"> <col style="width: 20%;"> <col style="width: 20%;"> <col style="width: 20%;"></colgroup><tbody><tr><td class="tableblock halign-left valign-top">Resource</td><td class="tableblock halign-left valign-top">Kind</td><td class="tableblock halign-left valign-top">Purpose</td><td class="tableblock halign-left valign-top">Required</td><td class="tableblock halign-left valign-top">Mounted Path</td></tr><tr><td class="tableblock halign-left valign-top">license</td><td class="tableblock halign-left valign-top">Secret</td><td class="tableblock halign-left valign-top">Develocity product license</td><td class="tableblock halign-left valign-top">Yes</td><td class="tableblock halign-left valign-top">/workspace/config/license</td></tr><tr><td class="tableblock halign-left valign-top">secrets</td><td class="tableblock halign-left valign-top">Secret</td><td class="tableblock halign-left valign-top">Sensitive values (access tokens, private keys)</td><td class="tableblock halign-left valign-top">No</td><td class="tableblock halign-left valign-top">/workspace/config/secrets</td></tr><tr><td class="tableblock halign-left valign-top">properties</td><td class="tableblock halign-left valign-top">ConfigMap</td><td class="tableblock halign-left valign-top">Non-sensitive configuration (URIs, public keys)</td><td class="tableblock halign-left valign-top">No</td><td class="tableblock halign-left valign-top">/workspace/config/properties</td></tr><tr><td class="tableblock halign-left valign-top">policies</td><td class="tableblock halign-left valign-top">ConfigMap</td><td class="tableblock halign-left valign-top">Policy manifests</td><td class="tableblock halign-left valign-top">No</td><td class="tableblock halign-left valign-top">/workspace/config/policies</td></tr></tbody></table>

Create empty resources to prepare for configuration:

```shell
kubectl create secret generic secrets --namespace develocity-provenance-governor || true
kubectl create configmap properties --namespace develocity-provenance-governor || true
kubectl create configmap policies --namespace develocity-provenance-governor || true
```

<a id="develocity-deploy"></a>

## Configure Develocity Instances (Optional)

Use one or more Develocity instances as attestation data sources.

Key patterns:

*   Secret: `develocity.instances.<NAME>.access-key`
    
*   ConfigMap: `develocity.instances.<NAME>.uri`
    

`<NAME>` must be alphanumeric plus dashes or underscores.

**Edit Secret:**

```
kubectl edit secret secrets --namespace develocity-provenance-governor
```

Add access key (use `stringData:` when adding new values):

```yaml
stringData:
  develocity.instances.MY_INSTANCE.access-key: DEVELOCITY_ACCESS_KEY
```

**Edit ConfigMap:**

```
kubectl edit configmap properties --namespace develocity-provenance-governor
```

Add URI:

```yaml
data:
  develocity.instances.MY_INSTANCE.uri: https://develocity.example.com
```

Rollout & Verify:

```shell
kubectl rollout restart deployment/api --namespace develocity-provenance-governor
kubectl rollout status deployment/api --namespace develocity-provenance-governor --timeout=90s
kubectl logs deployment/api --namespace develocity-provenance-governor | grep -i "Develocity support enabled"
```

Expected log snippet:

```text
Develocity support enabled, for instance [MY_INSTANCE:https://develocity.example.com]
```

Troubleshooting: Repeated `Retrying [n/10] request …​` indicates connectivity or credential issues.

<a id="artifactory-deploy"></a>

## Configure Artifactory Instances (Optional)

Used to publish attestation data.

Key patterns:

*   Secret: `artifactory.instances.<NAME>.access-token` (token preferred over legacy key)
    
*   ConfigMap: `artifactory.instances.<NAME>.uri`
    

**Edit Secret:**

```
kubectl edit secret secrets --namespace develocity-provenance-governor
```

Add token:

```yaml
stringData:
  artifactory.instances.MY_ARTIFACTORY.access-token: ARTIFACTORY_ACCESS_TOKEN
```

**Edit ConfigMap:**

```
kubectl edit configmap properties --namespace develocity-provenance-governor
```

Add URI:

```yaml
data:
  artifactory.instances.MY_ARTIFACTORY.uri: https://artifactory.example.com
```

Rollout & Verify:

```shell
kubectl rollout restart deployment/api --namespace develocity-provenance-governor
kubectl rollout status deployment/api --namespace develocity-provenance-governor --timeout=90s
kubectl logs deployment/api --namespace develocity-provenance-governor | grep -i "Artifactory support enabled"
```

Expected log snippet:

```text
Artifactory support enabled, for instance [MY_ARTIFACTORY:https://artifactory.example.com]
```

<a id="signing-keys-deploy"></a>

## Configure Signing Keys (Optional but Recommended for Attestations)

Attestations are wrapped in a [Dead Simple Signing Envelope (DSSE)](https://github.com/secure-systems-lab/dsse/blob/master/background.md) signed by a key pair.

Required key property patterns:

*   Secret (private key, base64 PEM): `signing.key.<FRIENDLY_KEY_NAME>.private-pem`
    
*   ConfigMap (public key PEM block): `signing.key.<FRIENDLY_KEY_NAME>.public-pem`
    

Choose a naming convention like `<ORG_OR_PRODUCT>_YYYY-MM-DD` for rotation clarity.

<a id="create-ed25519-key-pair"></a>

### Create Ed25519 Key Pair

Recommended (128-bit security, small key sizes/signatures).

```shell
openssl genpkey \
  -algorithm Ed25519 \
  -out private-key.pem
```

**Use OpenSSL to create a Public Key based on the Private Key:**

```
openssl pkey \
  -in private-key.pem \
  -pubout \
  -out public-key.pem
```

**Edit Secrets:**

```
kubectl edit secret secrets \
  --namespace develocity-provenance-governor
```

Base64 and add private key (Secret):

```shell
base64 -i private-key.pem | pbcopy
kubectl edit secret secrets --namespace develocity-provenance-governor
```

Paste under `data:` (Kubernetes will not modify pasted base64):

```yaml
data:
  signing.key.FRIENDLY_KEY_NAME.private-pem: <PASTE_BASE64_PRIVATE_KEY>
```

**Add public key (ConfigMap)::**

```
cat public-key.pem | sed 's/^/    /' | pbcopy
kubectl edit configmap properties --namespace develocity-provenance-governor
```

Paste under `data:`:

```yaml
data:
  # PASTE THE PUBLIC KEY BLOCK HERE FROM CLIPBOARD
  signing.key.FRIENDLY_KEY_NAME.public-pem: |
    -----BEGIN PUBLIC KEY-----
    ...
    -----END PUBLIC KEY-----
```

Rollout & Verify:

```shell
kubectl rollout restart deployment/api --namespace develocity-provenance-governor
kubectl logs deployment/api --namespace develocity-provenance-governor | grep -i "Signature support enabled"
```

Expected log:

```text
Signature support enabled, for key pair [name:FRIENDLY_KEY_NAME:keyid:XXXXXX:signing-algorithm:ed25519]
```

Key ID is a 6-character abbreviation of the SHA-256 digest of the public key.

<a id="other-supported-algorithms"></a>

### Other Supported Algorithms

Elliptic Curve (ECDSA) and RSA are also supported. Substitute commands below; follow the same secret/configmap procedure.

<a id="elliptic-curve-prime256v1"></a>

#### Elliptic Curve (prime256v1)

```shell
openssl ecparam -name prime256v1 -genkey -noout -out ec_private.key
openssl pkcs8 -topk8 -inform PEM -in ec_private.key -outform PEM -nocrypt -out private-key.pem
openssl ec -in ec_private.key -pubout -out public-key.pem
```

Expected log algorithm: `SHA256withECDSA`.

<a id="rsa-2048"></a>

#### RSA (2048)

```shell
openssl genrsa -out private-key.pem 2048
openssl rsa -in private-key.pem -pubout -out public-key.pem
```

Expected log algorithm: `SHA256withRSA`.

<a id="authentication-deploy"></a>

## Authentication (Optional)

Supported schemes:

*   [RFC9110 Basic](https://datatracker.ietf.org/doc/html/rfc9110#section-11.1)
    
*   [OpenID Connect](https://openid.net/specs/openid-connect-core-1_0.html) + [OAuth 2.0](https://openid.net/specs/openid-connect-core-1_0.html#RFC6749)
    

<a id="enable-basic-authentication"></a>

### Enable Basic Authentication

Add identities under:

*   Secret key pattern: `basic.identities.<NAME>`
    

`<NAME>` is a human-friendly identifier. No default credentials exist.

```shell
kubectl edit secret secrets --namespace develocity-provenance-governor
```

**Add a new Basic Identity:**

```
stringData:
  basic.identities.some-user: '{noop}some-pass'
```

Recommendation: Replace `{noop}` with `{bcrypt}` and supply a bcrypt-hashed password.

**Rollout Deployment:**

```
kubectl rollout restart deployment/api \
  --namespace develocity-provenance-governor
```

**Verify Basic Authentication Enabled:**

```
kubectl logs deployment/api \
  --namespace develocity-provenance-governor |
  grep -i "Basic Identity support"
```

**Expected Log Line:**

```
Basic Identity support enabled, for identity [some-user]
```

<a id="enable-oidc-authentication"></a>

### Enable OIDC Authentication

OIDC Providers are dynamically discovered based on token issuers specified in policies. See the Policies section for examples.

<a id="policies-optional"></a>

## Policies (Optional)

Policies are YAML documents stored inside the `policies` ConfigMap. Each key corresponds to a file-style name ending with `.yaml`.

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

### Access Control Policies

Define who can do what on which resources.

`identityMatchingStrategy` supported:

*   `withBasicIdentity` – must match a key under `basic.identities.<NAME>` in `secrets`
    
*   `withOidc` – relies on issuer discovery; ensure network accessibility
    

`canPerform` supported actions: \* `publish-attestations` - publish DSSE-wrapped attestations to an Attestation Store (S3 or Artifactory) \* `publish-policy-scans` - publish Policy Scan™ results to an Attestation Store

`withResources` supported patterns:

*   `pkg:pkg-type/pkg-namespace/pkg-name@pkg-vesion` - specific Package URL pattern to match or use wildcards:
    
    *   `pkg:maven/*` - all Maven packages
        
    *   `pkg:oci/*` - all OCI packages (container images)
        
    *   `pkg:maven/org.example/**@**` - all Maven packages in `org.example` namespace and any version
        
    *   `pkg:maven/org.example/acme-app@1.0.0` - specific Maven package
        
    *   `pkg:oci/image-name@v1*` - specific OCI image with wildcard version
        
    
*   `*:REPLACE_WITH_DV_INSTANCE_NAME/*` - allow to read build scans from the Develocity Instance to source data for attestations.
    
*   `*:REPLACE_WITH_ARTIFACTORY_INSTANCE_NAME/*` - allow to publish attestations to the Artifactory instance. Replace `*` with the repository name in Artifactory to restrict access further.
    
*   `s3:REPLACE_WITH_S3_INSTANCE_NAME/*` - allow to publish attestations to the S3 instance.
    
*   `*:*/*` - allows authenticated identity access to all resources (not recommended for production use)
    

<a id="basic-identity-policy-example"></a>

#### Basic Identity Policy Example

```shell
kubectl edit configmap policies --namespace develocity-provenance-governor
```

**Add basic-identity-some-user-full-access.yaml policy:**

```
data:
  basic-identity-some-user-full-access.yaml: |
    apiVersion: policy.gradle.com/v1
    kind: AccessControl
    metadata:
      name: basic-identity-some-user-full-access
    spec:
      identityMatchingStrategy:
        withBasicIdentity:
          - withName: "some-user"
      canPerform:
        - publish-attestations
        - publish-policy-scans
      withResources:
        - "*:*/*"
```

<a id="oidc-policy-example-github-actions"></a>

#### OIDC Policy Example (GitHub Actions)

```shell
kubectl edit configmap policies --namespace develocity-provenance-governor
```

**Add oidc-github-action-full-access.yaml policy:**

```
data:
  oidc-github-action-full-access.yaml: |
    apiVersion: policy.gradle.com/v1
    kind: AccessControl
    metadata:
      name: oidc-github-action-full-access
    spec:
      identityMatchingStrategy:
        withOidc:
          - fromIssuerUri: https://token.actions.githubusercontent.com
            withClaims:
              job_workflow_ref: org/automation-repo/.github/workflows/build-image.yml@*
      canPerform:
        - publish-attestations
        - publish-policy-scans
      withResources:
        - "*:*/*"
```

<a id="public-key-verification-policy-example"></a>

### Public Key Verification Policy Example

```shell
kubectl edit configmap policies --namespace develocity-provenance-governor
```

**Add public-key-verification-policy.yaml policy:**

```
data:
  public-key-verification-policy.yaml: |
    apiVersion: policy.gradle.com/v1
    kind: TrustedPublicKeys
    metadata:
      name: public-keys
    spec:
      resultsLabels: []
      description: Public keys trusted for attestations.
      remediation: Update the list of trusted public keys to ensure only verified attestations are accepted.
      keys:
        DEPLOYMENT_KEY_2025_10_01:
          pem: |
            -----BEGIN PUBLIC KEY-----
            ....
            -----END PUBLIC KEY-----
```

Replace `DEPLOYMENT_KEY_2025_10_01` and the PEM block with your actual trusted public keys, for example the ones used to sign attestations.

**Rollout Deployment:**

```
kubectl rollout restart deployment/api \
    --namespace develocity-provenance-governor
kubectl rollout status deployment/api \
    --namespace develocity-provenance-governor \
    --timeout=90s
```

**Verify Policies Loaded:**

```
kubectl logs deployment/api \
    --namespace develocity-provenance-governor |
    grep -i "Loading Policy Resource from file"
```

**Expected Log Lines:**

```
Loading Policy Resource from file [/workspace/config/policies/public-key-verification-policy.yaml]
```

<a id="troubleshooting-deployment-rollouts"></a>

## Troubleshooting Deployment Rollouts

Common rollout hang:

```text
Waiting for deployment "api" rollout to finish: 1 old replicas are pending termination...
error: timed out waiting for the condition
```

Inspect pods:

```shell
kubectl get pods --namespace develocity-provenance-governor
```

Identify failing pod (e.g., `CrashLoopBackOff`) and fetch logs:

```shell
kubectl logs api-<POD_ID> --namespace develocity-provenance-governor
```

Example configuration error:

```text
***************************
APPLICATION FAILED TO START
***************************

Failed to bind properties under 'artifactory.instances.INSTANCE_NAME_GOES_HERE' ... Reason: java.lang.IllegalArgumentException: uri must not be null
```

Remediation:

*   Missing URI – edit `properties` ConfigMap key `artifactory.instances.<NAME>.uri`
    
*   Missing token – edit `secrets` key `artifactory.instances.<NAME>.access-token`
    

After fixing, restart:

```shell
kubectl rollout restart deployment/api --namespace develocity-provenance-governor
kubectl rollout status deployment/api --namespace develocity-provenance-governor --timeout=90s
```

<a id="verification-next-steps"></a>

## Verification and Next Steps

After completing the deployment, verify that Develocity Provenance Governor is running correctly:

1.  **Check Pod Status**
    
    ```shell
    kubectl get pods -n develocity-provenance-governor
    ```
    
    You should see the `api` pod in `Running` state with `1/1` ready.
    
2.  **Check Application Logs**
    
    ```shell
    kubectl logs deployment/api -n develocity-provenance-governor --tail=50
    ```
    
    Look for messages indicating: **License loaded successfully** Integrations enabled (e.g., "Develocity support enabled", "Artifactory support enabled") **Policies loaded (if configured)** No error messages
    
3.  **Test API Accessibility**
    
    ```shell
    curl -i http://provenance-governor.acme.org
    ```
    
    You should receive a `401 Unauthorized` response, which confirms the application is running and authentication is required.
    
    > [!NOTE]
    > The actuator endpoints (health, readiness, liveness, prometheus) are exposed on port 9090 and not accessible through the public ingress. Develocity Provenance Governor also exposes /livez and /readyz endpoints on the main application port for health checking when Kubernetes probes are enabled.
    
4.  **Verify Integration Configuration**
    
    Check that your configured integrations were loaded:
    
    ```shell
    kubectl logs deployment/api -n develocity-provenance-governor | grep "support enabled"
    ```
    

> [!TIP]
> Successfully deployed? If all verification steps passed and you’re ready to start using Develocity Provenance Governor, proceed to Publishing Attestations to learn how to publish attestations and evaluate policies.

**What to Do Next:**

*   **Configure Your First Integration** - If you haven’t already, set up connections to Develocity and Artifactory. See [Application Configuration](https://docs.gradle.com/develocity/provenance-governor/1.7/app-config-overview/).
    
*   **Set Up Authentication** - Configure access control policies to secure your API. See [Access Control](#access-control).
    
*   **Write Your First Policy** - Define policies for your software supply chain governance. See [Writing Policies](https://docs.gradle.com/develocity/provenance-governor/1.7/writing-policies/).
    
*   **Publish Test Attestations** - Try publishing attestations for a test package. See [Publishing Attestations](https://docs.gradle.com/develocity/provenance-governor/1.7/publishing-attestations/).
    
*   **Integrate with CI/CD** - Add Develocity Provenance Governor to your build and deployment pipelines. See [GitHub Actions](https://docs.gradle.com/develocity/provenance-governor/1.7/ci-cd-integration/#github-actions) or [CI/CD Integration](https://docs.gradle.com/develocity/provenance-governor/1.7/ci-cd-integration/).
    

If you encounter issues, consult the [Troubleshooting](https://docs.gradle.com/develocity/provenance-governor/1.7/troubleshooting/) section.

<a id="summary-cheat-sheet"></a>

## Summary Cheat Sheet

<table class="tableblock frame-all grid-all stretch"><colgroup><col style="width: 20%;"> <col style="width: 20%;"> <col style="width: 20%;"> <col style="width: 20%;"> <col style="width: 20%;"></colgroup><tbody><tr><td class="tableblock halign-left valign-top">Integration</td><td class="tableblock halign-left valign-top">Secret Key Pattern</td><td class="tableblock halign-left valign-top">ConfigMap Key Pattern</td><td class="tableblock halign-left valign-top">Mandatory</td><td class="tableblock halign-left valign-top">Notes</td></tr><tr><td class="tableblock halign-left valign-top">License</td><td class="tableblock halign-left valign-top">(file) develocity.license</td><td class="tableblock halign-left valign-top">n/a</td><td class="tableblock halign-left valign-top">Yes</td><td class="tableblock halign-left valign-top">Provided via license secret</td></tr><tr><td class="tableblock halign-left valign-top">Registry Auth</td><td class="tableblock halign-left valign-top">.dockerconfigjson</td><td class="tableblock halign-left valign-top">n/a</td><td class="tableblock halign-left valign-top">Yes</td><td class="tableblock halign-left valign-top">JSON auth file for image pulls</td></tr><tr><td class="tableblock halign-left valign-top">Develocity Instance</td><td class="tableblock halign-left valign-top">develocity.instances.<name>.access-key</name></td><td class="tableblock halign-left valign-top">develocity.instances.<name>.uri</name></td><td class="tableblock halign-left valign-top">No</td><td class="tableblock halign-left valign-top">Multiple supported</td></tr><tr><td class="tableblock halign-left valign-top">Artifactory Instance</td><td class="tableblock halign-left valign-top">artifactory.instances.<name>.access-token</name></td><td class="tableblock halign-left valign-top">artifactory.instances.<name>.uri</name></td><td class="tableblock halign-left valign-top">No</td><td class="tableblock halign-left valign-top">Token preferred</td></tr><tr><td class="tableblock halign-left valign-top">Signing Key (Private)</td><td class="tableblock halign-left valign-top">signing.key.<key>.private-pem</key></td><td class="tableblock halign-left valign-top">n/a</td><td class="tableblock halign-left valign-top">No</td><td class="tableblock halign-left valign-top">Base64 PEM</td></tr><tr><td class="tableblock halign-left valign-top">Signing Key (Public)</td><td class="tableblock halign-left valign-top">n/a</td><td class="tableblock halign-left valign-top">signing.key.<key>.public-pem</key></td><td class="tableblock halign-left valign-top">No</td><td class="tableblock halign-left valign-top">PEM block</td></tr><tr><td class="tableblock halign-left valign-top">Basic Identity</td><td class="tableblock halign-left valign-top">basic.identities.<name></name></td><td class="tableblock halign-left valign-top">n/a</td><td class="tableblock halign-left valign-top">No</td><td class="tableblock halign-left valign-top">{bcrypt} recommended</td></tr><tr><td class="tableblock halign-left valign-top">Policies</td><td class="tableblock halign-left valign-top">n/a</td><td class="tableblock halign-left valign-top"><policy-name>.yaml in policies ConfigMap</policy-name></td><td class="tableblock halign-left valign-top">No</td><td class="tableblock halign-left valign-top">AccessControl docs</td></tr></tbody></table>