The supported method for deploying Anchore Enterprise on Kubernetes is with Helm. The Anchore Enterprise Helm Chart includes configuration options for a full Enterprise deployment.
Always consult the chart README and release notes prior to deployment or upgrade, as they contain the most current information on deployment configuration.
The chart is split into global and service-specific configurations for the core features, as well as global and service-specific configurations for the optional Anchore Enterprise services.
The anchoreConfig section of the values file contains the application configuration for Anchore Enterprise. This includes the database connection information, credentials, and other application settings.
Anchore Enterprise services run as Kubernetes deployments when installed with the Helm chart. Each service has its own section in the values file for making customizations and configuring the Kubernetes deployment spec.
As of Anchore Enterprise 6.0, the chart no longer includes a bundled PostgreSQL database. You must provision an external PostgreSQL 17 database with the pg_cron extension before deploying. See Provision the Database below. Redis, used by the Enterprise UI, is still deployed by the chart.
Prerequisites
Before deploying, ensure you have the following in place:
Requirement
Details
Kubernetes
Any CNCF-certified Kubernetes within the chart’s supported range. The chart declares this in its kubeVersion constraint (1.23–1.36 at the time of writing).
Helm
v3.8 or above
kubectl
Configured for your target cluster
Anchore Enterprise license
A valid license.yaml file
Docker Hub credentials
Access to pull the anchore/enterprise and anchore/enterprise-ui images. Contact Anchore Support to obtain access.
PostgreSQL
An external PostgreSQL 17+ database with the pg_cron extension enabled. See Requirements.
Docker or Podman
Docker Engine 28+ or Podman 6.0+ to build the CNPG image if needed**
See the chart prerequisites in the README for the most current details.
Provision the Database
Anchore Enterprise 6.x requires a customer-managed PostgreSQL 17 database with the pg_cron extension installed and enabled, cron.use_background_workers turned on, and USAGE on the cron schema granted to the Anchore database user. Provision this database before installing the chart. There are two common approaches:
Managed PostgreSQL service (recommended for production) — Use a cloud-provider managed database such as Amazon RDS, Google Cloud SQL, or Azure Database for PostgreSQL. Each cloud-provider deployment guide includes the provider-specific steps to enable pg_cron:
The pg_cron extension is not included in the default PostgreSQL container images. When running PostgreSQL in-cluster, you must build and host a PostgreSQL 17 image that includes pg_cron.
Run PostgreSQL In-Cluster with CloudNativePG
CloudNativePG is a Kubernetes operator that manages the full lifecycle of PostgreSQL clusters. This is a good option for teams who want to run PostgreSQL in-cluster while still getting operator-managed reliability. For production, Anchore still recommends a managed database service.
Build a PostgreSQL 17 image that includes pg_cron. The default CNPG images do not ship with pg_cron, so build and push your own:
Use the CNPG base image (ghcr.io/cloudnative-pg/postgresql) rather than the generic postgres image. The CNPG image includes the tooling the operator expects for lifecycle management, backups, and WAL archiving. This image is your responsibility to maintain and is not an Anchore-supported artifact.
If you are unable to build with APT resources please reach out to Anchore Customer Success for alternative solutions.
Create the PostgreSQL cluster. Create cnpg-cluster.yaml, referencing your custom image. The postgresql.parameters and resources below are starting points — size them to your instance memory and workload, and see Database Tuning for the parameters Anchore recommends adjusting in production:
apiVersion:postgresql.cnpg.io/v1kind:Clustermetadata:name:anchore-pgnamespace:anchorespec:instances:1imageName:<YOUR_REGISTRY>/postgresql-pgcron:17postgresql:shared_preload_libraries:- pg_cronparameters:# These are starting points — size them to your instance/pod memory and workload.# See the Database Tuning guidance on the Requirements page for details and defaults.max_connections:"2000"# each Anchore pod opens ~30-100 connections; size for your replica count (minimum 500)shared_buffers:"4GB"# PostgreSQL's dedicated cache; ~25% of the pod's memory (requires restart)effective_cache_size:"12GB"# planner hint for total cache available (~50-75% of memory); not an allocationwork_mem:"32MB"# memory per sort/hash operation (default 4MB); larger SBOMs/policies benefit.# Allocated per operation, so peak ~= work_mem x concurrent operations — raise graduallymaintenance_work_mem:"512MB"# memory for VACUUM, index builds, and similar maintenancemin_wal_size:"2GB"# WAL floormax_wal_size:"8GB"# larger WAL reduces checkpoint frequency under heavy write/analysis loadrandom_page_cost:"1.1"# lower for SSD/NVMe (gp3/io1) so the planner favors index scans; leave 4.0 for spinning disksautovacuum_max_workers:"5"# more autovacuum workers for write-heavy deployments (requires restart)autovacuum_vacuum_cost_limit:"3000"# let autovacuum do more before pausing; reduces table bloat (reload, no restart)"cron.database_name": "anchore"# database pg_cron runs its jobs in"cron.use_background_workers": "on"# required by Anchore Enterprisebootstrap:initdb:database:anchoreowner:anchorepostInitApplicationSQL:- "CREATE EXTENSION IF NOT EXISTS pg_cron;"- "GRANT USAGE ON SCHEMA cron TO anchore;"- "GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA cron TO anchore;"- "GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA cron TO anchore;"storage:size:100Gi# storageClass: gp3 # set for your environmentresources:requests:memory:"16Gi"cpu:"4"limits:memory:"32Gi"# No CPU limit is set intentionally. Anchore does not recommend a CPU limit on the# database — CPU throttling under load causes query latency spikes. Use requests to# guarantee capacity, and size requests/limits to your workload.
CNPG automatically creates a secret named anchore-pg-app containing the database credentials, and exposes a read-write service (anchore-pg-rw) that always points to the current primary. Use the -rw service as the database endpoint for Anchore Enterprise.
Deleting the CNPG Cluster resource (for example, kubectl delete cluster anchore-pg) permanently destroys the associated PVCs and all data, because CNPG sets owner references on the PVCs. To remove a cluster without losing data, use a StorageClass with reclaimPolicy: Retain, kubectl cnpg destroy –keep-pvc, or declarative hibernation. See the CNPG documentation for details.
Install the Chart
This guide covers deploying Anchore Enterprise with the default configuration against your external database. Refer to the Configuration section of the chart README for additional guidance on production deployments.
Create a Kubernetes secret for Docker Hub credentials. These credentials are required for authenticated access to the private Anchore Enterprise repositories on Docker Hub. Contact Anchore Support to obtain access.
Create a custom values file named anchore_values.yaml to override chart parameters. There are two ways to provide the database connection details: directly in the values file, or via pre-created Kubernetes secrets. Choose one approach.
Option A: Credentials in the values file. The chart creates the necessary Kubernetes secrets for you from these values.
licenseSecretName:anchore-enterprise-licenseimagePullSecretName:anchore-enterprise-pullcredspostgresql:externalEndpoint:<DB_HOSTNAME> # e.g. anchore-pg-rw.anchore.svc for CNPG, or your RDS endpointauth:username:<DB_USERNAME>password:<DB_PASSWORD>database:<DB_NAME>port:5432## Optional: connect to the database over TLS. This requires mounting the## database CA certificate via certStoreSecretName.# certStoreSecretName: anchore-certs# anchoreConfig:# database:# ssl: true# sslMode: verify-full# sslRootCertFileName: <CA_CERT_KEY>
Option B: Using existing Kubernetes secrets. For environments where credentials should not be stored in values files (for example, GitOps workflows), create the secrets manually and reference them. See the Existing Secrets section of the chart README for the full secret format. Your values file then references them:
Default passwords are specified in the chart and must be changed before deploying. The password for the admin user is set via the anchoreConfig.default_admin_password parameter in your custom anchore_values.yaml file. This value is only used during initial creation of the admin user; the password can be changed post-installation via the UI.
Add the chart repository and deploy Anchore Enterprise:
There are 11 Anchore Enterprise pods plus the chart-managed Redis pod (anchore-ui-redis-master-0). PostgreSQL is not listed because it runs externally.
Post-Installation Steps
Anchore Enterprise takes some time to initialize. After the bootstrap phase, it begins a vulnerability feed sync. Image analysis will show zero vulnerabilities and the UI will show errors until the sync is complete. The initial sync typically completes in minutes rather than hours, though low network throughput or high latency to the Anchore Data Service can extend it. The sync process takes place in the background; while it is in progress, anchorectl can be installed and the commands below can be used to check system status.
Feeds are not bundled with Anchore Enterprise. In an air-gapped environment the automatic sync cannot reach the Anchore Data Service, so you must explicitly enable air-gapped operation and upload at least one dataset for your running Anchore Enterprise version. See Air-Gapped Operation.
Export the required parameters to invoke anchorectl:
The port forwarding shown above is intended only for POC purposes or an initial Anchore Enterprise installation and is not recommended for Production use. In a Production environment, an ingress controller or load balancer is recommended for exposing the Anchore Enterprise API and UI services. See the cloud-provider–specific Helm deployment guides (AKS, EKS, GKE, OpenShift) for ingress examples.
List all Helm releases using helm list -n ${NAMESPACE}.
Next Steps
Now that you have Anchore Enterprise running, you can begin learning more about Anchore Enterprise architecture, concepts, and usage.
To learn more about Anchore Enterprise, go to Overview
To learn more about Anchore Enterprise Concepts, go to Concepts
1 - Deploying Anchore Enterprise on Azure Kubernetes Service (AKS)
This document walks you through the deployment of Anchore Enterprise in an Azure Kubernetes Service (AKS) cluster and exposes it on the public internet.
Prerequisites
A running AKS cluster with worker nodes launched. See AKS Documentation for more information on this setup.
As of Anchore Enterprise 6.0, the chart no longer includes a bundled PostgreSQL database. You must provision an external PostgreSQL 17 database with the pg_cron extension. See Azure Database for PostgreSQL below.
Once you have an AKS cluster up and running with worker nodes launched, you can verify it via the following command:
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
aks-agentpool-22798629-vmss000005 Ready <none> 30h v1.34.9
aks-agentpool-22798629-vmss000006 Ready <none> 31h v1.34.9
Anchore Enterprise Helm Chart Deployment
Anchore maintains a Helm chart to simplify the software deployment process. An Anchore Enterprise deployment of the chart includes the following:
Anchore Enterprise software
Redis (7 or higher)
To make the necessary configurations to the Helm chart, create a custom anchore_values.yaml file and reference it during deployment. There are many options for configuration with Anchore Enterprise; this document is intended to cover the minimum required changes to successfully deploy Anchore Enterprise in AKS.
Azure Database for PostgreSQL
For production deployments, Anchore recommends a cloud-provider managed database over running PostgreSQL in-cluster. This ensures the database is isolated from workloads, allowing it to use CPU and memory without contention. We suggest selecting a storage option that allows for automatic size increase.
If you use Azure Database for PostgreSQL Flexible Server, make the following changes in Settings > Server parameters for compatibility with Anchore Enterprise:
pgbouncer.enabled: false — it is very important that this setting be turned off.
idle_in_transaction_session_timeout: 0
max_connections: should be at least 2,000. The default is based on the amount of instance memory. This value may need to be increased for heavier workloads.
Enable pg_cron
Anchore Enterprise 6.x requires the pg_cron extension. On Azure Database for PostgreSQL Flexible Server, pg_cron cannot be loaded with CREATE EXTENSION alone — it must first be added to the server’s preloaded libraries.
Make the following changes in Settings > Server parameters:
azure.extensions: include pg_cron
shared_preload_libraries: include pg_cron
cron.database_name: set to the name of your database (Ex: anchore)
Parameter changes can also be made via the Azure CLI:
az postgres flexible-server parameter set --resource-group <RESOURCE_GROUP> --server-name <SERVER_NAME> --name shared_preload_libraries --value pg_cron
az postgres flexible-server parameter set --resource-group <RESOURCE_GROUP> --server-name <SERVER_NAME> --name azure.extensions --value PG_CRON
az postgres flexible-server parameter set --resource-group <RESOURCE_GROUP> --server-name <SERVER_NAME> --name cron.database_name --value anchore
Restart the server so the parameter changes take affect.
Connect to the database instance (Settings > Connect) and create the database you wish to use for Anchore. Then grant the Anchore user access to the cron schema:
Refer to the chart External Database documentation for the values-file settings. Configuring an external database in the chart is essentially the same for RDS or Azure Database for PostgreSQL.
There are multiple methods in Azure to expose your Anchore Enterprise deployment for access. The example below uses Web App Routing, which provides a more streamlined, low-complexity approach.
If your load balancer or reverse proxy terminates TLS on behalf of Anchore Enterprise, you should set enable_ssl and enable_proxy to True in the Enterprise UI configuration. Without these settings, the UI may not correctly detect the HTTPS connection, which could result in unexpected behavior with session cookies and authentication. For more details, see Enterprise UI Configuration.
Create Namespace and Required Secrets
When configuring the deployment with existing secrets (useExistingSecrets: true), all required secrets must be pre-created in the cluster before installing the Helm chart.
First, create the target namespace:
kubectl create namespace anchore
Next, create the individual secrets for registry credentials, licensing, database authentication, core service environment variables, and UI environment variables:
Image pull credentials for private Anchore Enterprise registry
PostgreSQL is not listed because it runs externally on Azure Database for PostgreSQL.
Check UI Access
Browse to your ingress URL to access the web UI.
Anchore Enterprise login page.
From there you can login using the secret you set for the admin user.
Anchore Enterprise Feeds
It can take a few minutes to fetch all of the vulnerability feeds from the Anchore Data Service. Check on the status of feeds under System > Health.
AnchoreCTL
To access the Anchore API via CLI, see Deploying AnchoreCTL to get started with anchorectl
2 - Deploying Anchore Enterprise on Amazon EKS
This section provides information on how to deploy Anchore Enterprise onto Amazon EKS. Here is the recommended architecture on AWS EKS:
AWS EKS deployment architecture.
Prerequisites
You’ll need a running Amazon EKS cluster with worker nodes. See EKS Documentation for more information on this setup.
Once you have an EKS cluster up and running with worker nodes launched, you can verify it using the following command:
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
ip-192-168-2-164.ec2.internal Ready <none> 10m v1.30.3-eks-a737599
ip-192-168-35-43.ec2.internal Ready <none> 10m v1.30.3-eks-a737599
ip-192-168-55-228.ec2.internal Ready <none> 10m v1.30.3-eks-a737599
To deploy the Anchore Enterprise services, you’ll then need the Helm client installed on your local host. Anchore maintains a Helm chart to simplify the software deployment process.
To make the necessary configurations to the Helm chart, create a custom anchore_values.yaml file and reference it during deployment. There are many options for configuration with Anchore Enterprise. The following is intended to cover the recommended changes for successfully deploying Anchore Enterprise on Amazon EKS.
Configuration
The following configurations should be used when deploying on EKS.
Amazon RDS for PostgreSQL
Anchore Enterprise 6.x requires an external PostgreSQL 17 database with the pg_cron extension; the chart no longer ships a bundled PostgreSQL. On AWS, Anchore strongly recommends Amazon RDS for PostgreSQL as a managed, isolated database service, so the database can scale independently of your cluster workloads. It is suggested to allow the storage to automatically increase as needed.
For details on configuring an external database in the chart, see the chart External Database documentation and the Provision the Database section of the main Helm deployment guide.
Amazon RDS is the strongly recommended database for Anchore Enterprise on EKS. If you cannot use RDS, you can instead run PostgreSQL in-cluster with CloudNativePG, or use any PostgreSQL 17+ instance you manage yourself — provided it has the pg_cron extension enabled and configured as described below.
Enable pg_cron
Anchore Enterprise 6.x requires the pg_cron extension. On Amazon RDS, enable it as follows:
In the DB parameter group attached to your instance, add pg_cron to the shared_preload_libraries parameter.
Set the cron.database_name parameter to your Anchore database name (for example, anchore).
Reboot the instance so the static parameters take effect.
Connect to the Anchore database and create the extension, then grant the Anchore user access to the cron schema:
RDS enables the PostgreSQL background workers that pg_cron needs by default. Confirm your instance class provides sufficient max_worker_processes for your workload. See the AWS guide on scheduling maintenance with pg_cron.
S3 Object Storage
Anchore Enterprise can use S3 as its external object store, offloading large objects — SBOM documents, analysis archives, and other analysis data — out of the database. This reduces database size and total cost of ownership. See the Amazon S3 object store configuration for details. Consider using the iamauto: True option to use IAM roles for access to S3.
When you use an external object store alongside the database, the two hold a single logical dataset and must be backed up together at the same point in time to stay consistent. AWS Backup can protect the RDS database and the S3 bucket together as a coordinated, point-in-time backup. Backing up an S3 bucket with AWS Backup requires S3 Versioning to be enabled on the bucket; adding a lifecycle rule to expire old noncurrent versions is recommended to control storage cost. For the general requirement, see External Object Store.
PVCs
Anchore Enterprise by default uses ephemeral storage for pods, but we recommend configuring Analyzer scratch space, at a minimum. See Scratch Space configuration for further details.
Anchore generally recommends providing EBS-backed storage for analyzer scratch of the gp3 type. Note that you will need to follow the AWS guide on storing K8s volumes with Amazon EBS. Once the CSI driver is configured for your cluster, configure your Helm chart with values similar to this:
analyzer:scratchVolume:details:ephemeral:volumeClaimTemplate:metadata:{}spec:accessModes:- ReadWriteOnceresources:requests:# must be 3xANCHORE_MAX_COMPRESSED_IMAGE_SIZE_MB + analyzer_cache_size# Setting this to 100G would mean the largest image you can scan is 30G (not counting analysis cache if you choose to configure that)storage:100Gi# this would refer to whatever your storage class was namedstorageClassName:"gp3"
We also suggest using a vanity domain (anchore.mydomain.com in the example below) over TLS with Route 53 and ACM; however, this goes beyond the scope of this document.
If your load balancer or reverse proxy terminates TLS on behalf of Anchore Enterprise, you should set enable_ssl and enable_proxy to True in the Enterprise UI configuration. Without these settings, the UI may not correctly detect the HTTPS connection, which could result in unexpected behavior with session cookies and authentication. For more details, see Enterprise UI Configuration.
Here is a sample manifest for use with the AWS LBC or EKS Auto Mode ALB ingress:
ingress:enabled:trueapiPaths:- /v2/- /version/uiPath:/ingressClassName:albannotations:# See https://github.com/kubernetes-sigs/aws-load-balancer-controller/blob/main/docs/guide/ingress/annotations.md for further customization of annotationsalb.ingress.kubernetes.io/scheme:internet-facing# If you do not plan to bring your own hostname (i.e. use the AWS supplied CNAME for the load balancer) then you can leave apiHosts & uiHosts as empty lists:#apiHosts: []#uiHosts: []# If you plan to bring your own hostname then you'll likely want to populate them as follows:apiHosts:- anchore.mydomain.comuiHosts:- anchore.mydomain.com
There are alternative ways to access services within your EKS cluster besides LBC ingress.
You must also configure/change the following from ClusterIP to NodePort:
Anchore Enterprise API Service
# Pod configuration for the Anchore Enterprise API service.api:# kubernetes service configuration for anchore external APIservice:type:NodePortport:8228annotations:{}
Anchore Enterprise UI Service
ui:# kubernetes service configuration for anchore UIservice:type:NodePortport:80annotations:{}sessionAffinity:ClientIP
Amazon ALB Parameters
Users of ALB may want to align the timeout between gunicorn and ALB. The AWS ALB connection idle timeout defaults to 60 seconds. The Anchore Enterprise Helm chart has a timeout setting that defaults to 5 seconds, which should be aligned with the ALB timeout setting. Sporadic HTTP 502 errors may be emitted by the ALB if the timeouts are not in alignment. See this reference.
Change timeout_keep_alive from 5 to 65 to align with the ALB’s default timeout of 60.
anchoreConfig:server:timeout_keep_alive:65
Install Anchore Enterprise
Deploy Anchore Enterprise by following the instructions in the main Helm deployment guide, using the RDS database and anchore_values.yaml customizations described above.
Verify Ingress
Run the following command for details on the deployed ingress resource using the ELB:
$ kubectl describe ingress
Name: anchore-enterprise
Namespace: default
Address: xxxxxxx-default-anchoreen-xxxx-xxxxxxxxx.us-east-1.elb.amazonaws.com
Default backend: default-http-backend:80 (<none>)Rules:
Host Path Backends
---- ---- --------
*
/v2/* anchore-enterprise-api:8228 (192.168.42.122:8228) /* anchore-enterprise-ui:80 (192.168.14.212:3000)Annotations:
alb.ingress.kubernetes.io/scheme: internet-facing
kubernetes.io/ingress.class: alb
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal CREATE 14m alb-ingress-controller LoadBalancer 904f0f3b-default-anchoreen-d4c9 created, ARN: arn:aws:elasticloadbalancing:us-east-1:077257324153:loadbalancer/app/904f0f3b-default-anchoreen-d4c9/4b0e9de48f13daac
Normal CREATE 14m alb-ingress-controller rule 1 created with conditions [{ Field: "path-pattern", Values: ["/v2/*"]}] Normal CREATE 14m alb-ingress-controller rule 2 created with conditions [{ Field: "path-pattern", Values: ["/*"]}]
The output above shows that an ELB has been created. Next, try navigating to the specified URL in a browser:
Anchore Enterprise login page.
Verify Anchore Enterprise Service Status
Check the status of the system with AnchoreCTL to verify all of the Anchore Enterprise services are up:
ANCHORECTL_URL=http://xxxxxx-default-anchoreen-xxxx-xxxxxxxxxx.us-east-1.elb.amazonaws.com ANCHORECTL_USERNAME=admin ANCHORECTL_PASSWORD=<ADMIN_PASSWORD> anchorectl system status
3 - Deploying Anchore Enterprise on Google Kubernetes Engine (GKE)
Get an understanding of deploying Anchore Enterprise on a Google Kubernetes Engine (GKE) cluster and exposing it on the public internet.
When using Google Cloud, use Cloud SQL for PostgreSQL as a managed database service. Anchore Enterprise 6.x requires an external PostgreSQL 17 database with the pg_cron extension.
Prerequisites
A running GKE cluster with worker nodes launched. See GKE Documentation for more information on this setup.
An external PostgreSQL 17 database with the pg_cron extension. See Cloud SQL for PostgreSQL below.
Once you have a GKE cluster up and running with worker nodes launched, you can verify it by using the following command:
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
gke-standard-cluster-1-default-pool-c04de8f1-hpk4 Ready <none> 78s v1.30.3-gke.1639000
gke-standard-cluster-1-default-pool-c04de8f1-m03k Ready <none> 79s v1.30.3-gke.1639000
gke-standard-cluster-1-default-pool-c04de8f1-mz3q Ready <none> 78s v1.30.3-gke.1639000
Anchore Enterprise Helm Chart
Anchore maintains a Helm chart to simplify the software deployment process. An Anchore Enterprise deployment of the chart includes the following:
Anchore Enterprise software
Redis (7 or higher)
As of Anchore Enterprise 6.0, the chart no longer includes a bundled PostgreSQL database. You must provision an external PostgreSQL 17 database with the pg_cron extension. See Cloud SQL for PostgreSQL below.
To make the necessary configurations to the Helm chart, create a custom anchore_values.yaml file and reference it during deployment. There are many options for configuration with Anchore Enterprise. The following is intended to cover the minimum required changes to successfully deploy Anchore Enterprise on Google Kubernetes Engine.
For production deployments, Anchore recommends a cloud-provider managed database over running PostgreSQL in-cluster. On Google Cloud, use Cloud SQL for PostgreSQL. We suggest selecting a storage option that allows for automatic size increase and setting max_connections to at least 2,000.
Refer to the chart External Database documentation for the values-file settings needed to connect Anchore Enterprise to Cloud SQL.
Cloud SQL is a recommendation, not a requirement. You can instead run PostgreSQL in-cluster with CloudNativePG, or use any PostgreSQL 17+ instance you manage yourself — provided it has the pg_cron extension enabled and configured as described below.
Enable pg_cron
Anchore Enterprise 6.x requires the pg_cron extension. On Cloud SQL for PostgreSQL, enable it as follows:
Set the cloudsql.enable_pg_cron database flag to on. This requires an instance restart.
Make the following changes to your anchore_values.yaml.
Ingress
ingress:enabled:trueapiPaths:- /v2/*uiPath:/*
Configuring ingress is optional. It is used throughout this guide to expose the Anchore Enterprise deployment on the public internet.
If your load balancer or reverse proxy terminates TLS on behalf of Anchore Enterprise, you should set enable_ssl and enable_proxy to True in the Enterprise UI configuration. Without these settings, the UI may not correctly detect the HTTPS connection, which could result in unexpected behavior with session cookies and authentication. For more details, see Enterprise UI Configuration.
Anchore Enterprise API Service
api:replicaCount:1# kubernetes service configuration for anchore external APIservice:type:NodePortport:8228annotations:{}
Changed the service type to NodePort.
Anchore Enterprise UI
ui:# kubernetes service configuration for anchore UIservice:type:NodePortport:80annotations:{}sessionAffinity:ClientIP
Changed the service type to NodePort.
Anchore Enterprise Deployment
Create Secrets
Enterprise services require an Anchore Enterprise license, as well as credentials with permission to access the private Docker Hub repository containing the enterprise software.
Create a Kubernetes secret containing your license file:
ANCHORECTL_URL=http://34.96.64.148 ANCHORECTL_USERNAME=admin ANCHORECTL_PASSWORD=<ADMIN_PASSWORD> anchorectl system status
Anchore Enterprise Feeds
It can take some time to fetch all of the vulnerability feeds from the upstream data sources. Check on the status of feeds with AnchoreCTL:
ANCHORECTL_URL=http://34.96.64.148 ANCHORECTL_USERNAME=admin ANCHORECTL_PASSWORD=<ADMIN_PASSWORD> anchorectl feed list
It is not uncommon for the above command to return [] while the initial feed sync occurs.
Once the vulnerability feed sync is complete, Anchore Enterprise can begin to return vulnerability results on analyzed images. Please continue to the Vulnerability Management section of our documentation for more information.
4 - Deploying Anchore Enterprise on OpenShift
This document walks through the deployment of Anchore Enterprise on an OpenShift 4.x cluster and exposes it on the public internet.
An external PostgreSQL 17 database with the pg_cron extension. See Provision the Database below.
Anchore Enterprise Helm Chart
Anchore maintains a Helm chart to simplify the software deployment process. An Anchore Enterprise installation of the chart includes the following:
Anchore Enterprise software
Redis (7 or higher)
As of Anchore Enterprise 6.0, the chart no longer includes a bundled PostgreSQL database. You must provision an external PostgreSQL 17 database with the pg_cron extension. See Provision the Database below.
To make the necessary configurations to the Helm chart, create a custom anchore_values.yaml file and reference it during deployment. There are many options for configuration with Anchore Enterprise; this document is intended to cover the minimum required changes to successfully deploy Anchore Enterprise on OpenShift.
Provision the Database
Anchore Enterprise 6.x requires a PostgreSQL 17 database with the pg_cron extension. On OpenShift, provision this with either:
A cloud-provider managed database (for example, Amazon RDS if running OpenShift on AWS). See the Enable pg_cron steps in the EKS guide.
Any other PostgreSQL 17+ instance you manage yourself, provided it has the pg_cron extension enabled.
The pg_cron extension is not included in the default PostgreSQL container images. When running PostgreSQL in-cluster, you must build and host a PostgreSQL 17 image that includes it.
OpenShift Configurations
Create a New Project
Create a new project called anchore-enterprise:
oc new-project anchore-enterprise
Create Secrets
Two secrets are required for an Anchore Enterprise deployment.
Verify these secrets are in the correct namespace (anchore-enterprise):
oc describe secret <secret-name>
Link ImagePullSecret
Link the above Docker registry secret to the default service account:
oc secrets link default anchore-enterprise-pullcreds --for=pull --namespace=anchore-enterprise
Verify this by running the following:
oc describe sa
Validate your OpenShift SCC. Based on the security constraints of your environment, you may need to change the SCC: oc adm policy add-scc-to-user anyuid -z default.
Anchore Enterprise Configurations
Create a custom anchore_values.yaml file for your Anchore Enterprise deployment. Configure the connection to your external PostgreSQL 17 database, and relax the security contexts as needed for OpenShift:
# NOTE: This is not a production-ready values file for an OpenShift deployment.securityContext:fsGroup:nullrunAsGroup:nullrunAsUser:null# Connection details for your external PostgreSQL 17 (with pg_cron) databasepostgresql:externalEndpoint:<DB_HOSTNAME>auth:username:<DB_USERNAME>password:<DB_PASSWORD>database:<DB_NAME>port:5432ui-redis:master:podSecurityContext:enabled:falsecontainerSecurityContext:enabled:false
Install Software
Run the following commands to install the software:
PostgreSQL is not listed because it runs externally.
Create Route Objects
Create two route objects in the OpenShift console to expose the UI and API services on the public internet:
Route configuration is optional. It is used throughout this guide to expose the Anchore Enterprise deployment on the public internet.
If your route or reverse proxy terminates TLS on behalf of Anchore Enterprise, you should set enable_ssl and enable_proxy to True in the Enterprise UI configuration. Without these settings, the UI may not correctly detect the HTTPS connection, which could result in unexpected behavior with session cookies and authentication. For more details, see Enterprise UI Configuration.
API Route
Route configuration for the API service.
UI Route
Route configuration for the UI service.
Routes
Configured routes for the deployment.
Verify by navigating to the anchore-enterprise-ui route hostname. You should see the Anchore Enterprise login page.
Anchore Enterprise System
First, retrieve the admin password. This is stored as a secret during the helm install process:
You can customize your Helm anchore_values.yaml file to use an existing/custom secret rather than have Helm generate one for you with a generated password.
ANCHORECTL_URL=http://<anchore-api-anchore.apps.rm2.thpm.p1.openshiftapps.com> \
ANCHORECTL_USERNAME=admin \
ANCHORECTL_PASSWORD=<ADMIN_PASSWORD> \
anchorectl system status
Anchore Enterprise Vulnerability Data
Anchore Enterprise has a datasyncer service that pulls the vulnerability and other data sources, such as the ClamAV malware database, into your Anchore Enterprise deployment. You can check on the status of these feeds using AnchoreCTL:
ANCHORECTL_URL=http://<anchore-ui-anchore.apps.rm2.thpm.p1.openshiftapps.com> \
ANCHORECTL_USERNAME=admin \
ANCHORECTL_PASSWORD=<ADMIN_PASSWORD> \
anchorectl feed list
Please continue to the Vulnerability Management section of our documentation for more information about Vulnerability Management within Anchore Enterprise.
5 - Deploy Air-Gapped using Helm
Anchore Enterprise can run in an air-gapped Kubernetes cluster with no outbound internet access. The air-gapped-specific work is getting the Helm chart and container images into a registry reachable from the cluster: you pull and package them on an internet-connected system, then move the tarball to the destination network(s). Once the chart and images are in place, deployment follows the standard Kubernetes with Helm procedure.
Throughout this guide, the low side is the internet-facing system and the high side is the air-gapped cluster.
Configure Air-Gapped Feed Handling
Anchore Enterprise syncs vulnerability feed data from the Anchore Data Service automatically. In an air-gapped cluster this sync cannot reach the internet, so before deploying you must disable the Data Syncer’s automatic feed sync in your values file, and plan to download and import feed bundles manually with AnchoreCTL once the deployment is running. Both steps are described in Air-Gapped Feed Configuration.
Until you complete the air-gapped feed configuration, you will not be able to upload feed bundles into the system, and the deployment will have no vulnerability data.
Prerequisites
Low side (internet-facing) — Helm v3.8 or above and the Docker static binary, used only to pull and package the chart and images.
Low side (internet-facing) — Docker or Podman, if you are running PostgreSQL in-cluster with CloudNativePG and need to build the pg_cron-enabled image.
High side (air-gapped) — A Kubernetes cluster, kubectl, and Helm v3.8 or above, used to run Anchore Enterprise. See Prerequisites on the main Helm page for supported Kubernetes versions.
A private container registry reachable from every node in the cluster. Unlike Docker Compose, Kubernetes has no cluster-wide equivalent of docker load, so a registry is required for any deployment beyond a single-node test cluster. See Option 2 below for a node-local fallback on small clusters.
An external PostgreSQL 17 database with the pg_cron extension, provisioned as described in Provision the Database. If you are running PostgreSQL in-cluster with CloudNativePG, the custom pg_cron image you build in that section is pushed to a registry of your choosing, so that step is already air-gap-friendly.
Note the CHART VERSION column from the output — this is different from the Anchore Enterprise application version (v6.1.0) and is what helm pull expects below.
The chart’s kubectlImage (bitnamilegacy/kubectl:1.30) is only used by the osaaMigrationJob and upgradeJob during major-version upgrades, not by a fresh install. If you plan to perform a major-version upgrade later, pull and mirror this image at that time.
If you are running PostgreSQL in-cluster with CloudNativePG, the operator itself also needs mirroring — its chart and operator image are not part of the Anchore chart:
a. Add the CNPG chart repository and find its current version:
e. Save cnpg-cluster.yaml now too, using the full example in Create the PostgreSQL cluster on the main Helm page as your starting point. Leave imageName as a placeholder for now — you’ll fill in the actual <registry> reference on the high side in Install CloudNativePG and Provision the Database below, once the image has actually been pushed there.
Include the CNPG chart archive, both images, and cnpg-cluster.yaml with everything else when you save and transfer them below — there is no direct network path from the low side to the high side’s registry, so they all have to travel together.
Move the Chart and Images to the High Side
Choose one of the following. A private container registry is the recommended path for the images; use node-local import only if no registry is reachable from the cluster.
Re-tag the images for your private registry, replacing <registry> with your registry domain (for example, core.harbor.domain):
docker tag docker.io/anchore/enterprise:v6.1.0 \
<registry>/anchore/enterprise:v6.1.0
docker tag docker.io/anchore/enterprise-ui:v6.1.0 \
<registry>/anchore/enterprise-ui:v6.1.0
docker tag docker.io/redis:7.4.6 <registry>/redis:7.4.6
# If using CNPG in-cluster (step 4 above), also re-tag the operator image:docker tag ghcr.io/cloudnative-pg/cloudnative-pg:<operator-version> \
<registry>/cloudnative-pg/cloudnative-pg:<operator-version>
# If mirroring bitnamilegacy/kubectl:1.30 for a future upgrade, re-tag that too
The postgresql-pgcron image needs no separate re-tag step — build it directly against the same <registry> value you’re using here (docker build -t <registry>/postgresql-pgcron:17 .), as shown in step 4d above.
Save the tagged images to a tarball, and transfer it — along with enterprise-${CHART_VERSION}.tgz, cloudnative-pg-${CNPG_CHART_VERSION}.tgz and cnpg-cluster.yaml (if using CNPG), and your license.yaml — to the high side. There is no direct network path between the low side and the high side’s registry, so this tarball, moved across the air gap by whatever transfer process your organization uses, is how everything gets there:
# Low sidedocker save -o anchore-airgap-images.tar \
<registry>/anchore/enterprise:v6.1.0 \
<registry>/anchore/enterprise-ui:v6.1.0 \
<registry>/redis:7.4.6
# <registry>/cloudnative-pg/cloudnative-pg:<operator-version> \ # if using CNPG in-cluster# <registry>/postgresql-pgcron:17 \ # if using CNPG in-cluster# <registry>/bitnamilegacy/kubectl:1.30 # if mirroring for a future upgrade# High side, after transferring anchore-airgap-images.tar, enterprise-${CHART_VERSION}.tgz,# cloudnative-pg-${CNPG_CHART_VERSION}.tgz, and license.yaml acrossdocker load -i anchore-airgap-images.tar
Push the loaded images to your private registry from the high side:
For small or single-node clusters with no registry available, images can be imported directly into each node’s container runtime instead — for example with ctr images import (containerd), crictl on nodes where it supports import, or a distribution-specific helper such as k3s ctr images import. Save the images as in step 2 above, transfer the tarball to every node, and import it there.
This must be repeated on every node in the cluster, and again whenever a node is replaced or the cluster scales out, since the images are not shared across nodes. A private registry is strongly preferred for anything beyond a small, static cluster.
Push the Chart to an Internal Helm Repository or GitOps Source
If you use GitOps tooling (ArgoCD, Flux) or otherwise deploy from your own internal Helm repository on the high side, transferring the .tgz to a bastion host is not enough on its own — GitOps controllers pull charts from a repository URL declared in a manifest, not from a local file. Push the chart there from the low side, or from any system that can reach it:
OCI registry (Harbor, Artifactory, Amazon ECR, Azure ACR, Google Artifact Registry, and most modern registries support OCI Helm charts):
Traditional Helm chart repository (for example ChartMuseum, or a generic Artifactory Helm repo): upload enterprise-${CHART_VERSION}.tgz per that repository’s own process, then regenerate its index if required (helm repo index).
Reference oci://<registry>/charts/enterprise (or your chart repository URL) and chartVersion: ${CHART_VERSION} in your ArgoCD Application or Flux HelmRelease, alongside the image overrides described below.
Deploy on the High Side
Besides the images, the air-gapped cluster needs enterprise-${CHART_VERSION}.tgz and your license.yaml available to kubectl/helm — or, if you pushed the chart to an internal repository above, its OCI/chart-repo reference available to your GitOps controller. Create the namespace and license secret exactly as described in Install the Chart on the main Helm page.
Create the image pull secret for your private registry instead of Docker Hub:
If you are running PostgreSQL in-cluster with CloudNativePG, install the operator and create the database now, before installing Anchore Enterprise — the values file below needs the resulting database endpoint.
Install the operator from the local chart archive, pointing its image at your private registry instead of ghcr.io:
If your registry requires authentication for pulls, also create an equivalent pull secret in the cnpg-system namespace and pass –set image.pullSecrets[0].name=<secret-name> above.
Then update the imageName field in the cnpg-cluster.yaml you brought over from the low side (see step 4e in Prepare the Chart and Images), now that the image has actually been pushed to your registry:
spec:imageName:<registry>/postgresql-pgcron:17
Apply it and wait for the cluster to report ready — the anchore-pg-rw service it creates is what you’ll use as postgresql.externalEndpoint in the Anchore values file below:
Point every image at your air-gapped registry in anchore_values.yaml, in addition to the database and license/pull-secret settings described in Install the Chart on the main Helm page:
licenseSecretName:anchore-enterprise-licenseimagePullSecretName:anchore-enterprise-pullcredsimage:<registry>/anchore/enterprise:v6.1.0ui:image:<registry>/anchore/enterprise-ui:v6.1.0ui-redis:image:registry:<registry>repository:redistag:7.4.6pullSecrets:- anchore-enterprise-pullcredspostgresql:externalEndpoint:<DB_HOSTNAME> # e.g. anchore-pg-rw.anchore.svc if using CNPG above, or your managed DB endpointauth:username:<DB_USERNAME>password:<DB_PASSWORD>database:<DB_NAME>port:5432
If you plan a future major-version upgrade of this air-gapped deployment, also mirror and set kubectlImage to your registry at that time. It is not used during a fresh install.
Install from the local chart archive rather than the chart repository, since the high side cannot reach charts.anchore.io:
If you pushed the chart to an internal OCI registry or Helm repository instead, install from that reference — or configure your GitOps controller to do so — rather than the local file: