Install

Steps to install Protegrity Anonymization.

This project deploys the Anonymization service on Amazon EKS as part of the AI Team Edition.

Install order: prerequisites → OpenTofu infrastructure configuration → Helm deployment.

OCI registry authentication

OpenTofu OCI modules and Helm charts may require authentication. If the registry requires a login, authenticate before running tofu init or helm upgrade --install:

echo "<password>" | helm registry login <Container_Registry_Path> --username "<username>" --password-stdin

Note:

  • Set registry_auth_enabled = true for Protegrity container registry. Set it to false only for a public or pre-authenticated registry.
  • If deploying from the Protegrity Container Registry, use registry.protegrity.com:9443. Specify the local registry endpoint if a local registry is used.
  • Verify that you are logged in to the registry before proceeding.

Deployment Steps

Step 1 - Provision cloud resources with OpenTofu

The anonymization OpenTofu module provisions all cloud prerequisites and writes an anonymization-values.yaml file with cloud-specific Helm overrides.

AWS (EKS)

The module creates:

  • S3 bucket (name provided via bucket_name variable — must be globally unique)
  • IAM role + Pod Identity association → anon-service-account ServiceAccount
  • EC2NodeClass and NodePool (Bottlerocket FIPS, isolated nodes)
  • anonymization-values.yaml — Helm overrides file
Azure (AKS)

The module creates:

  • Storage Account + blob container for model storage
  • Managed Identity + Workload Identity federated credential → anon-service-account ServiceAccount
  • anonymization-values.yaml — Helm overrides file
You do not have a root module

Create a new directory with a single main.tf:

Note: If deploying from the Protegrity Container Registry, use registry.protegrity.com:9443. Specify the local registry endpoint if a local registry is used.

mkdir anon-install && cd anon-install
cat > main.tf <<'EOF'
terraform {
  required_version = "~> 1.10"
  required_providers {
    aws        = { source = "registry.opentofu.org/hashicorp/aws", version = "~> 5.0" }
    kubernetes = { source = "registry.opentofu.org/hashicorp/kubernetes", version = "~> 2.35" }
  }
}

variable "cluster_name" {
  type = string
}
variable "bucket_name" {
  type = string
}
variable "chart_version" {
  type    = string
  default = ""
}

data "aws_eks_cluster" "this" { name = var.cluster_name }
data "aws_eks_cluster_auth" "this" { name = var.cluster_name }

provider "kubernetes" {
  host                   = data.aws_eks_cluster.this.endpoint
  cluster_ca_certificate = base64decode(data.aws_eks_cluster.this.certificate_authority[0].data)
  token                  = data.aws_eks_cluster_auth.this.token
}

module "anonymization" {
  source = "oci://<Container_Registry_Path>/anonymization/anonymization-server/opentofu/anonymization?tag=aws-2.1.0"

  cluster_name          = var.cluster_name
  oci_host              = "<Container_Registry_Path>"
  bucket_name           = var.bucket_name
  chart_version         = var.chart_version
  registry_auth_enabled = true  # required for registry.protegrity.com; set false only for public/pre-authenticated registries
}

output "helm_install" { value = module.anonymization.helm_install }
output "helm_values" { value = module.anonymization.helm_values }
EOF

tofu init
tofu apply \
  -var="cluster_name=<your-cluster-name>" \
  -var="bucket_name=<globally-unique-bucket>" \
  -var="chart_version=2.1.0"

This writes anonymization-values.yaml (S3, IAM/Pod Identity, Karpenter node isolation, affinity/tolerations already filled in).

Display both generated outputs:

tofu output

Create a new directory with a single main.tf:

Note: If deploying from the Protegrity Container Registry, use registry.protegrity.com:9443. Specify the local registry endpoint if a local registry is used.

mkdir anon-install && cd anon-install
cat > main.tf <<'EOF'
terraform {
  required_version = "~> 1.10"
  required_providers {
    azurerm = {
      source  = "registry.opentofu.org/hashicorp/azurerm"
      version = "~> 5.7"
    }
    kubernetes = {
      source  = "registry.opentofu.org/hashicorp/kubernetes"
      version = "~> 2.35"
    }
  }
}

variable "cluster_name" {
  type = string
}
variable "resource_group_name" {
  type = string
}
variable "storage_account_name" {
  type = string
}
variable "chart_version" {
  type    = string
  default = ""
}
variable "environment" {
  type    = string
  default = "production"
}

provider "azurerm" {
  features {}
  resource_provider_registrations = "none"
}

data "azurerm_kubernetes_cluster" "this" {
  name                = var.cluster_name
  resource_group_name = var.resource_group_name
}

provider "kubernetes" {
  host                   = data.azurerm_kubernetes_cluster.this.kube_config[0].host
  client_certificate     = base64decode(data.azurerm_kubernetes_cluster.this.kube_config[0].client_certificate)
  client_key             = base64decode(data.azurerm_kubernetes_cluster.this.kube_config[0].client_key)
  cluster_ca_certificate = base64decode(data.azurerm_kubernetes_cluster.this.kube_config[0].cluster_ca_certificate)
}

module "anonymization" {
  source = "oci://<Container_Registry_Path>/anonymization/anonymization-server/opentofu/anonymization?tag=azure-2.1.0"

  cluster_name          = var.cluster_name
  oci_host              = "<Container_Registry_Path>"
  resource_group_name   = var.resource_group_name
  storage_account_name  = var.storage_account_name
  chart_version         = var.chart_version
  registry_auth_enabled = true  # required for registry.protegrity.com; set false only for public/pre-authenticated registries
}

output "helm_install" { value = module.anonymization.helm_install }
output "helm_values" { value = module.anonymization.helm_values }
EOF

tofu init
tofu apply \
  -var="cluster_name=<cluster>" \
  -var="resource_group_name=<rg>" \
  -var="storage_account_name=<globally-unique-name>" \
  -var="chart_version=2.1.0"

This writes anonymization-values.yaml (Storage Account, Managed/Workload Identity, affinity/tolerations already filled in).

Display both generated outputs:

tofu output
Module variables
VariableRequiredDefaultDescription
cluster_nameyes—EKS cluster name
bucket_nameyes—S3 bucket name for model storage (must be globally unique across all AWS accounts)
oci_hostno<Container_Registry_Path>OCI registry hostname
Note: If deploying from the Protegrity Container Registry, use registry.protegrity.com:9443. Specify the local registry endpoint if a local registry is used.
environmentnoproductionEnvironment tag and S3 bucket prefix (staging or production)
namespacenoanon-nsKubernetes namespace
registry_typenoartifactoryProtegrity container registry or Local registry
chart_versionno""Helm chart version. When set, tofu output -raw helm_install prints a ready-to-run command.
karpenter.enablednotrueCreate Karpenter NodePool + EC2NodeClass
karpenter.node_class.ami_familynoBottlerocketAMI family. Bottlerocket selects FIPS AMI automatically.
karpenter.node_class.ami_idno""Explicit AMI ID override. When set, overrides ami_family-based selection.
karpenter.node_pool.instance_typesno["c5.large", ...]EC2 instance types for Karpenter NodePool
archnoamd64CPU architecture: amd64
fipsnotrueUse FIPS-validated Bottlerocket AMI. Set false to use the standard (non-FIPS) AMI.
ami_idno""Explicit AMI ID override (highest priority). When set, bypasses both ami_family and fips selection.

AMI selection priority:

PriorityConditionAMI Selected
1ami_id is setExact AMI by ID (e.g. ami-0123456789abcdef0)
2fips = true (default)Latest bottlerocket-aws-k8s-<K8S_VER>-fips-<ARCH>-*
3fips = falseLatest bottlerocket-aws-k8s-<K8S_VER>-<ARCH>-*

Note: If you use ami_id, the ami_family value must match the image that the AMI ID points to. The default value of ami_family is Bottlerocket.

Examples:

# Use a specific AMI (bypasses all auto-selection)
module "anonymization" {
  source = "oci://..."
  # ...
  ami_id = "ami-0123456789abcdef0"
}

# Disable FIPS (use standard Bottlerocket AMI)
module "anonymization" {
  source = "oci://..."
  # ...
  fips = false
}
VariableRequiredDefaultDescription
cluster_nameyes—AKS cluster name
resource_group_nameyes—Azure resource group for the Managed Identity and Storage Account
storage_account_nameyes—Azure Storage Account name (must be globally unique, 3-24 lowercase alphanumeric chars)
environmentnoproductionEnvironment tag and storage account name prefix
namespacenoanon-nsKubernetes namespace
oci_hostno<Container_Registry_Path>OCI registry hostname
Note: If deploying from the Protegrity Container Registry, use registry.protegrity.com:9443. Specify the local registry endpoint if a local registry is used.
registry_typenoartifactoryProtegrity container registry or Local registry
chart_versionno""Helm chart version. When set, tofu output -raw helm_install prints a ready-to-run command.
instance_typesno["Standard_D4as_v5", ...]VM instance types for NodePool

Note:

  • Running tofu plan is optional. It lets you review the planned changes before they are applied.
  • tofu output -raw helm_install prints a ready-to-run Helm command with the correct version and namespace.
  • bucket_name is a new S3 bucket name and it is created as part of this deployment.

Step2 - Deploy with Helm

The OpenTofu module writes an anonymization-values.yaml file in your working directory. Pass it to Helm with --values. Passwords are required on first install only — they are preserved automatically on subsequent upgrades.

Tip: tofu output -raw helm_install prints a ready-to-run Helm command with the correct version and namespace pre-filled.

Note: If deploying from the Protegrity Container Registry, use registry.protegrity.com:9443. Specify the local registry endpoint if a local registry is used. Ensure harbor-secret exists in the default namespace.

export MLOPS_PASSWORD=<your-mlops-password>
export JOBSTATE_PASSWORD=<your-jobstate-password>

helm upgrade --install anonymization \
  oci://<Container_Registry_Path>/anonymization/anonymization-server/helm/anonymization \
  --version 2.1.0 \
  --namespace anon-ns --create-namespace \
  --values anonymization-values.yaml \
  --set-string database.auth.mlopsPassword=$MLOPS_PASSWORD \
  --set-string database.auth.jobstatePassword=$JOBSTATE_PASSWORD

On upgrade (passwords already stored in the cluster secret — omit --set):

helm upgrade anonymization \
  oci://<Container_Registry_Path>/anonymization/anonymization-server/helm/anonymization \
  --version <new-version> \
  --namespace anon-ns \
  --values anonymization-values.yaml

To rotate a password during upgrade:

helm upgrade anonymization ... \
  --set-string database.auth.mlopsPassword=$NEW_MLOPS_PASSWORD

For more information about the Python SDK, refer to Python SDK Reference.

Validate installation

Note: Before proceeding, ensure your kubectl context is set to the target cluster kubectl config current-context.

kubectl get pods -n anon-ns          # All pods should be Running
kubectl get statefulset -n anon-ns   # PostgreSQL, 1/1 ready
kubectl get deployment -n anon-ns    # app, dask-scheduler, dask-worker
kubectl get hpa -n anon-ns
kubectl get nodes -l anonymization.protegrity.com/deployment=true   # AWS: Karpenter nodes (if enabled) should be Ready.
kubectl get pods -n anon-ns          # All pods should be Running
kubectl get statefulset -n anon-ns   # PostgreSQL, 1/1 ready
kubectl get deployment -n anon-ns    # app, dask-scheduler, dask-worker
kubectl get hpa -n anon-ns

Standalone Helm Install (No OpenTofu)

Use this when cloud infrastructure already exists or is managed separately.

Step 1 - Verify prerequisites
# StorageClass
kubectl get storageclass ebs-sc               # AWS

# Pod Identity Agent (AWS)
kubectl get daemonset -n kube-system eks-pod-identity-agent

# Karpenter NodePool (if using node isolation)
kubectl get nodepool anonymization-cpu
kubectl get ec2nodeclass anonymization-cpu
# StorageClass
kubectl get storageclass managed-csi-premium  # Azure

kubectl get nodepool anonymization-cpu
kubectl get aksnodeclass anonymization-cpu
Step 2 - Create a values override file

AWS example (my-values.yaml):

cloudProvider: aws

serviceaccount:
  name: anon-service-account
  annotations:
    eks.amazonaws.com/role-arn: "arn:aws:iam::<ACCOUNT_ID>:role/<ROLE_NAME>"

storage:
  enabled: true
  bucketName: <your-globally-unique-bucket-name>
  region: us-east-1

database:
  persistence:
    storageClass: ebs-sc
    size: 20Gi

karpenter:
  enabled: true   # set false if NOT using Karpenter isolation

Azure example (my-values.yaml):

cloudProvider: azure

serviceaccount:
  name: anon-service-account
  annotations:
    azure.workload.identity/client-id: "<MANAGED_IDENTITY_CLIENT_ID>"

storage:
  enabled: true
  dsn: "abfss://models@<storage_account>.dfs.core.windows.net/"

database:
  persistence:
    storageClass: managed-csi-premium
    size: 20Gi

karpenter:
  enabled: false
Step 3 - Install

Note: If deploying from the Protegrity Container Registry, use registry.protegrity.com:9443. Specify the local registry endpoint if a local registry is used. Ensure harbor-secret exists in the default namespace.

export MLOPS_PASSWORD=<your-mlops-password>
export JOBSTATE_PASSWORD=<your-jobstate-password>

helm upgrade --install anonymization \
  oci://<Container_Registry_Path>/anonymization/anonymization-server/helm/anonymization \
  --version 2.1.0 \
  --namespace anon-ns --create-namespace \
  --values my-values.yaml \
  --set-string database.auth.mlopsPassword=$MLOPS_PASSWORD \
  --set-string database.auth.jobstatePassword=$JOBSTATE_PASSWORD

Next Steps

For more information about the Python SDK, refer to Python SDK Reference.

If you encounter any error during or after installation, refer to Troubleshooting.

Last modified : November 03, 2026