Skip to content

Deploy AI Security to the cloud

The CAI-Deploy script helps you automate installation of the AI Security platform and manage its state over time.

You can use CAI-Deploy in different ways:

  • Provision cloud resources end to end.
  • Install the platform into an existing cloud Kubernetes environment.

CAI-Deploy supports deployments for all F5 AI Security products.

Here's a link to the script.

It's configured to deploy on AWS, Azure, and GCP. It assumes you're using Ubuntu Linux 24.04.

If this is your first time using the script, read through this document. Otherwise, jump to Before you deploy.

Assumptions

Before you continue, verify that you have:

  • An AWS, Azure, Google Cloud Platform (GCP), or Oracle Cloud Infrastructure (OCI) cloud account, or a Kubernetes cluster
  • Access to your cloud environment, including Kubernetes access
  • Admin access to your cloud environment (if you want the installer to create cloud resources)
  • Internet access from the Kubernetes cluster (to pull containers and Helm charts)
  • Harbor credentials for required images and Helm charts
  • Sufficient resources to meet quotas for instances:
    • Guardrails: CUDA-compatible GPU with minimum memory of 24GB
    • Red Team:: CUDA-compatible GPU with minimum memory of 48GB
  • A valid SSL certificate
  • At least 200 GB of disk space on the Red Team worker node (to download the model)
  • A license from AI Security
  • An installation host with the required tools to run the installer, such as Helm, kubectl, AWS CLI, Azure SDK, or GCP SDK

Supported cloud environments

We support:

AWS CLI

If you create a new Amazon Elastic Kubernetes Service (EKS) cluster, install the AWS Command Line Interface (AWS CLI). Set it up with credentials that can create the required AWS resources, such as the EKS cluster. Install the AWS CLI using the official installer.

AWS required permissions

To run the installer and deploy AWS resources, the AWS user or role must have the IAM permissions shown in the policies below. The IAM policies are split because they exceed the maximum character limit per policy.

These policies work for:

  • The default EKS cluster name cai-cluster
  • A custom cluster name that starts with cai-cluster*

If you use a different cluster name, update the policies to match.

If you store remote state in Amazon S3, update the bucket name to the state bucket in your AWS account.

With these policies, you can set up permissions to:

  • Create and manage an EKS cluster and related components
  • Provision and tear down full VPC networking infrastructure
  • Launch and configure EC2 instances and launch templates
  • Create, manage, and clean up IAM roles, policies, and instance profiles
  • Manage Auto Scaling Groups and scaling behavior
  • Deploy and manage Application Load Balancers and listeners
  • Import and manage ACM certificates for ALBs
  • Provision and manage EBS volumes
  • Access and modify data in a specific S3 bucket
  • Query service quotas and account limits
  • Look up EC2 instance types and availability zones
  • Create and manage RDS (Aurora) clusters and related DB components

Policy #1

If you use this policy, be sure to replace:

  • YOUR-BUCKET-NAME-HERE

You may also want to specify a specific AWS region and account ID where appplicable, such as for arn:aws:eks:*:*:cluster/cai-cluster

To view the policy, select here:
json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "ec2:DeleteVpc",
        "ec2:DeleteSubnet",
        "ec2:AttachInternetGateway",
        "ec2:DetachInternetGateway",
        "ec2:DeleteInternetGateway",
        "ec2:ReleaseAddress",
        "ec2:DeleteNatGateway",
        "ec2:DeleteRouteTable",
        "ec2:DisassociateRouteTable",
        "ec2:DeleteRoute",
        "ec2:DeleteTags",
        "ec2:ModifyVpcAttribute",
        "ec2:ModifySubnetAttribute"
      ],
      "Resource": "*",
      "Condition": {
        "StringLike": {
          "ec2:ResourceTag/Name": "cai-cluster*"
        }
      }
    },
    {
      "Effect": "Allow",
      "Action": [
        "ec2:DescribeImages",
        "ec2:DescribeVpcAttribute",
        "ec2:DescribeVpcs",
        "ec2:DescribeSubnets",
        "ec2:DescribeInternetGateways",
        "ec2:DescribeAddresses",
        "ec2:DescribeNatGateways",
        "ec2:DescribeRouteTables",
        "ec2:DescribeSecurityGroups",
        "ec2:DescribeNetworkInterfaces",
        "ec2:DescribeSecurityGroupRules",
        "ec2:CreateVpc",
        "ec2:CreateSubnet",
        "ec2:CreateInternetGateway",
        "ec2:AllocateAddress",
        "ec2:CreateNatGateway",
        "ec2:CreateRouteTable",
        "ec2:AssociateRouteTable",
        "ec2:CreateRoute",
        "ec2:ReplaceRoute",
        "ec2:CreateSecurityGroup",
        "ec2:CreateTags",
        "ec2:RunInstances",
        "ec2:RevokeSecurityGroupEgress",
        "ec2:AuthorizeSecurityGroupIngress",
        "ec2:RevokeSecurityGroupIngress",
        "ec2:AuthorizeSecurityGroupEgress",
        "ec2:DescribeAddressesAttribute",
        "ec2:DisassociateAddress",
        "ec2:DeleteSecurityGroup"
      ],
      "Resource": "*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "iam:GetPolicy",
        "iam:ListAttachedRolePolicies"
      ],
      "Resource": "*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "eks:CreateCluster",
        "eks:DeleteCluster",
        "eks:DescribeCluster",
        "eks:UpdateClusterVersion",
        "eks:UpdateClusterConfig",
        "eks:CreateNodegroup",
        "eks:DeleteNodegroup",
        "eks:DescribeNodegroup",
        "eks:ListClusters",
        "eks:TagResource",
        "eks:UntagResource",
        "eks:CreatePodIdentityAssociation",
        "eks:DeletePodIdentityAssociation"
      ],
      "Resource": "arn:aws:eks:*:*:cluster/cai-cluster*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "eks:DeletePodIdentityAssociation"
      ],
      "Resource": "arn:aws:eks:*:*:podidentityassociation/cai-cluster*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "eks:CreateAddon",
        "eks:DeleteAddon",
        "eks:UpdateAddon",
        "eks:DescribeAddon",
        "eks:DescribeAddonVersions",
        "eks:ListAddons",
        "eks:DescribePodIdentityAssociation"
      ],
      "Resource": "*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "eks:DeleteAccessEntry",
        "eks:UpdateAccessEntry"
      ],
      "Resource": [
        "arn:aws:eks:*:*:access-entry/cai-cluster*",
        "arn:aws:eks:*:*:cluster/cai-cluster*"
      ]
    },
    {
      "Effect": "Allow",
      "Action": [
        "eks:CreateAccessEntry",
        "eks:DescribeAccessEntry",
        "eks:ListAccessEntries"
      ],
      "Resource": [
        "*"
      ]
    },
    {
      "Effect": "Allow",
      "Action": [
        "ssm:GetParameter",
        "ssm:GetParameters",
        "ssm:GetParameterHistory"
      ],
      "Resource": "*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "autoscaling:UpdateAutoScalingGroup",
        "autoscaling:DeleteAutoScalingGroup",
        "autoscaling:SetDesiredCapacity",
        "autoscaling:TerminateInstanceInAutoScalingGroup"
      ],
      "Resource": "*",
      "Condition": {
        "StringLike": {
          "autoscaling:ResourceTag/Name": "cai-cluster*"
        }
      }
    },
    {
      "Effect": "Allow",
      "Action": [
        "autoscaling:CreateAutoScalingGroup",
        "autoscaling:DescribeScalingActivities",
        "autoscaling:DescribeAutoScalingGroups"
      ],
      "Resource": "*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "ec2:CreateLaunchTemplate",
        "ec2:DeleteLaunchTemplate",
        "ec2:DescribeLaunchTemplates",
        "ec2:DescribeLaunchTemplateVersions"
      ],
      "Resource": "*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "elasticloadbalancing:DeleteLoadBalancer",
        "elasticloadbalancing:DeleteTargetGroup"
      ],
      "Resource": "*",
      "Condition": {
        "StringLike": {
          "elasticloadbalancing:ResourceTag/Name": "cai-cluster*"
        }
      }
    },
    {
      "Effect": "Allow",
      "Action": [
        "elasticloadbalancing:CreateLoadBalancer",
        "elasticloadbalancing:CreateTargetGroup"
      ],
      "Resource": "*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "elasticloadbalancing:CreateListener",
        "elasticloadbalancing:DeleteListener",
        "elasticloadbalancing:RegisterTargets",
        "elasticloadbalancing:DeregisterTargets"
      ],
      "Resource": "*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "elasticloadbalancing:Describe*"
      ],
      "Resource": "*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "acm:ImportCertificate",
        "acm:AddTagsToCertificate",
        "acm:RemoveTagsFromCertificate",
        "acm:DeleteCertificate"
      ],
      "Resource": "arn:aws:acm:*:*:certificate/cai-cluster*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "acm:ListCertificates",
        "acm:DescribeCertificate"
      ],
      "Resource": "*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "ec2:CreateVolume",
        "ec2:AttachVolume",
        "ec2:DeleteVolume",
        "ec2:DescribeVolumes"
      ],
      "Resource": "*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "s3:GetObject",
        "s3:PutObject",
        "s3:DeleteObject"
      ],
      "Resource": [
        "arn:aws:s3:::YOUR-BUCKET-NAME-HERE/*"
      ]
    },
    {
      "Effect": "Allow",
      "Action": [
        "s3:ListBucket"
      ],
      "Resource": [
        "arn:aws:s3:::YOUR-BUCKET-NAME-HERE"
      ]
    },
    {
      "Effect": "Allow",
      "Action": [
        "sts:GetCallerIdentity"
      ],
      "Resource": "*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "servicequotas:GetServiceQuota",
        "servicequotas:ListServiceQuotas",
        "servicequotas:ListServices",
        "servicequotas:GetAWSDefaultServiceQuota",
        "cloudwatch:GetMetricData"
      ],
      "Resource": "*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "ec2:DescribeAccountAttributes",
        "ec2:DescribeInstanceTypeOfferings",
        "ec2:DescribeInstanceTypes",
        "ec2:DescribeAvailabilityZones"
      ],
      "Resource": "*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "rds:CreateDBCluster",
        "rds:CreateDBClusterSnapshot"
      ],
      "Resource": [
        "arn:aws:rds:*:*:cluster:cai-cluster*",
        "arn:aws:rds:*:*:subgrp:cai-cluster*",
        "arn:aws:rds:*:*:cluster-snapshot:cai-cluster*"
      ]
    },
    {
      "Effect": "Allow",
      "Action": [
        "rds:DeleteDBCluster",
        "rds:ModifyDBCluster",
        "rds:DescribeDBClusters",
        "rds:CreateDBInstance",
        "rds:DeleteDBInstance",
        "rds:ModifyDBInstance",
        "rds:DescribeDBInstances"
      ],
      "Resource": [
        "arn:aws:rds:*:*:cluster:cai-cluster*",
        "arn:aws:rds:*:*:db:cai-cluster*"
      ]
    },
    {
      "Effect": "Allow",
      "Action": [
        "rds:CreateDBSubnetGroup",
        "rds:DeleteDBSubnetGroup",
        "rds:ModifyDBSubnetGroup"
      ],
      "Resource": [
        "arn:aws:rds:*:*:subgrp:cai-cluster*"
      ]
    },
    {
      "Effect": "Allow",
      "Action": [
        "rds:CreateDBParameterGroup",
        "rds:DeleteDBParameterGroup",
        "rds:ModifyDBParameterGroup"
      ],
      "Resource": [
        "arn:aws:rds:*:*:pg:cai-cluster*"
      ]
    },
    {
      "Effect": "Allow",
      "Action": [
        "rds:ListTagsForResource",
        "rds:DescribeDBSubnetGroups",
        "rds:DescribeDBParameterGroups",
        "rds:DescribeDBParameters",
        "rds:AddTagsToResource",
        "rds:RemoveTagsFromResource",
        "rds:ListTagsForResource",
        "rds:DescribeGlobalClusters"
      ],
      "Resource": [
        "*"
      ]
    }
  ]
}

Policy #2

If you use this policy, you may want to include your AWS account ID:

To view the policy, select here:

{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "eks:CreateAccessEntry", "Resource": [ "arn:aws:eks:::cluster/cai-cluster*", "arn:aws:iam:::role/cai-cluster" ] }, { "Effect": "Allow", "Action": [ "iam:DeleteRole", "iam:CreateRole", "iam:PassRole", "iam:AttachRolePolicy", "iam:DetachRolePolicy", "iam:PutRolePolicy", "iam:TagRole", "iam:DeleteRolePolicy", "iam:ListInstanceProfilesForRole" ], "Resource": [ "arn:aws:iam:::role/cai-cluster", "arn:aws:iam:::role/lb-controller" ]

    },
            {
        "Effect": "Allow",
        "Action": [
            "iam:ListPolicyVersions",
            "iam:DeletePolicy",
            "iam:CreatePolicy"

        ],
        "Resource": 
        [
        "arn:aws:iam::*:policy/cai-cluster*",
        "arn:aws:iam::*:policy/lb-controller*"
        ]
    },
    {
        "Effect": "Allow",
        "Action": [
            "iam:ListRolePolicies",
            "iam:GetRolePolicy",
            "iam:GetUserPolicy",
            "iam:ListAttachedUserPolicies",
            "iam:GetPolicyVersion",
            "iam:GetRole"
        ],
        "Resource": "*"
    },
    {
        "Effect": "Allow",
        "Action": [
            "iam:CreateInstanceProfile",
            "iam:AddRoleToInstanceProfile",
            "iam:RemoveRoleFromInstanceProfile",
            "iam:DeleteInstanceProfile",
            "iam:GetInstanceProfile"
        ],
        "Resource": "arn:aws:iam::*:instance-profile/cai-cluster*"
    }
]

}

Azure CLI

If you create a new Azure Kubernetes Service (AKS) cluster, install and set up the Azure command-line interface. Pulumi uses the Azure CLI to authenticate to your account and create resources.

Install Azure CLI on Linux

The following command sets up the Azure CLI with a .deb package, which works with Ubuntu. You can set this up on Ubuntu 24.04 LTS.

shell
curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash

Before you can store the Pulumi state in Azure, you need to set the following permissions the user in Azure, on the Storage Container:

  • Storage Blob Data Contributor
  • Storage Queue Data Contributor

GCP CLI

Before you create a new Google Kubernetes Engine (GKE) cluster, install and set up the Google Cloud CLI. Next, run the following commands to authenticate.

bash
gcloud auth login
gcloud auth application-default login

Now install the GKE authorization plugin. The following command applies to Debian-based linux systems:

bash
sudo apt-get install google-cloud-sdk-gke-gcloud-auth-plugin

Next, to run the installer and deploy all GCP resources, you need to assign permissions / roles to the appropriate GCP user or service accounts. For more information, see the Google Cloud documentation on how to manage access.

You need to set up these accounts to:

  • Create and manage a GKE cluster
  • Create Cloud SQL instance and networks
  • Manage service accounts
  • Configure IAM bindings
  • Deploy Kubernetes resources
  • Configure load balancer and firewall rules
  • Read and write to GCS buckets
  • Validate required quotas

For this purpose, set up the following roles:

Role NameRole ID
Cloud SQL Adminroles/cloudsql.admin
Compute Adminroles/compute.admin
Compute Load Balancer Adminroles/compute.loadBalancerAdmin
Compute Security Adminroles/compute.securityAdmin
Kubernetes Engine Adminroles/container.admin
Project IAM Adminroles/resourcemanager.projectIamAdmin
Service Account Adminroles/iam.serviceAccountAdmin
Service Account Userroles/iam.serviceAccountUser
Service Networking Adminroles/servicenetworking.admin
Storage Object Adminroles/storage.objectAdmin
Viewerroles/viewer

As listed in assumptions, we assume that you have kubectl installed, configured, and connected to your existing GCP cluster. This allows you to use Pulumi to authenticate to your cluster and create new Kubernetes resources.

Before you deploy

To ensure the smoothest installation process possible, ensure you have all information required by the installer, as well as permissions to create needed resources.

Here's a link to the script.

  • After you download the script, remember to make it executable (chmod u+x /path/to/script).

As shown in the script, it downloads a text-based wizard with the following filename: cai-deploy-latest-linux-x86_64. The options shown on this page reflect the options from that wizard.

The installer can set up a new network. If you plan on using an existing cloud network, be prepared with your VPC ID and subnet IDs.

If you plan on creating a new Kubernetes cluster with the installer and wish for the installer to create a load balancer and Ingress controller, be prepared with a SSL certificate signed by a certificate authority. Do not use self-signed certificates.

If you have an existing cluster

If you deploy the platform into an existing cluster, review these options:

  • Install the Nvidia GPU Operator into the system
  • Use one of the following labels on the node groups that you plan to use for the AI Security platform:
    • moderator
    • cai-scanner
    • redteam

This depends on the pod that you plan to run on that node. You'll need to run additional commands to include:

Preparation and installation

The installation script requires some information. As shown in the first few lines of the script, you need to:

  1. Set cloud_provider to aws, azure, or gcp.
  2. Enter the relvant configuration variables for the cloud provider you are launching to.
  3. Log in to your cloud provider through its CLI.
  4. Make sure the script file is executable, and then Run this script.
  5. Connect to the instance with the provided SSH command.
  6. Run the command "calypsoai-installer" to run the installer.

Script details

Given the options, the script includes a large number of prompts. For a full list, see our page on Installer prompts.

Set up DNS and Ingress

After you run the installation script, you'll need to also do the following:

  • Set up DNS. Make sure the DNS record points to the URL of your installation.
  • If you have an existing cluster, set up the Ingress controller and DNS as needed for your environment.

Final steps

During the deployment process, the installer runs through health checks to ensure that each pod is up and running.

If you're setting up a Red Team deployment, the worker may show an error due to the size of the model downloaded to the container.

Cost estimate (AWS)

For guidance only, we've set up a cost estimate for deploying on AWS.

The following is an estimate. Actual costs will vary based on the specific configuration choices you make during the interactive setup, your usage patterns (traffic, data storage, etc.), and current AWS pricing in your selected region. All prices are based on the us-west-2 (Oregon) region and are subject to change (Pricing per 07/14/2025).

Core Infrastructure

ServiceEstimated HourlyEstimated MonthlyNotes
EKS Control Plane0.10 USD73.00 USD• Fixed cost for AWS Kubernetes control plane
EC2 (EKS Worker Nodes) incl. EBS Storage (Defend)2.225 USD1610 USD• Based on default instance types and counts (1x t3.xlarge, 1x c7a.4xlarge, 1x m7a.xlarge, 1x g5.xlarge)
• Each of the 3 nodes is configured with a 100 GB gp3 root volume
EC2 (EKS Worker Nodes) incl. EBS Storage (Red Team)2.093 USD1532.96 USD• Based on default instance types and counts (1x g6e.xlarge, 1x m7a.xlarge)
• Each of the 3 nodes is configured with a 200 GB gp3 root volume
Core Infrastructure Total4.418 USD3208.96 USD

Optional Resources

ServiceEstimated HourlyEstimated MonthlyNotes
NAT Gateway0.05 USD37.35 USD• Allowing private subnets to access the internet, e.g. pulling images and installing updates
• Assumes 100 GB of data processed per month
Application Load Balancer (Ingress)0.03 USD18.77 USD• Assumes light traffic
External Database (RDS Aurora PostgreSQL)0.61 USD446.04 USD• 2x db.r7g.large Aurora PostgreSQL DB instances
• Assumes 50 GB of storage
Optional Resources Total0.69 USD502.16 USD

All Resources Total

Estimated HourlyEstimated Monthly
All Resources Total3.22 USD3,711.12 USD

Other Potential Costs to Consider

  • Data Transfer: Data transfer out from AWS to the internet is not free (beyond the first 100GB/month). Costs also apply for data transferred between Availability Zones, which this architecture uses for high availability. This cost is highly dependent on application traffic.
  • CloudWatch: While there is a generous free tier, extensive custom metrics or very high-volume logging could result in charges.
  • ACM Certificate: The code can import a certificate into AWS Certificate Manager (ACM). If you use an ACM-provided public certificate, it is free.
  • GPU: Additional GPU node for Red Team to run the Red Team worker.

Updated at: