Self-Hosted Deployment Guide¶
Overview¶
Deploy CloudAEye Code Review in your AWS account with the CloudAEye Terraform configuration. The stack creates the network, ECS Managed Instances cluster, application services, data services, user pool, queues, and logging required for a self-hosted deployment.
Prerequisites¶
Before you deploy, confirm you have:
- Terminal.
- Terraform
1.15.5installation guide. - AWS CLI configured for the customer AWS account.
- AWS permissions to create VPC, EC2, ECS, Elastic Load Balancing, IAM, EBS, SQS, Cognito, CloudWatch Logs, Cloud Map, and related resources.
- Tenant admin details for the first admin user.
- A GitHub App for the self-hosted Code Review integration. Follow Create The GitHub App before filling in the
github_*Terraform values. - LLM provider details. Follow LLM Model Configuration.
- License key. You will receive it in your email.
What Gets Created¶
| Resource | Purpose |
|---|---|
| VPC, public subnet, private subnet | Isolated network for the deployment |
| Internet gateway and NAT gateway | Public load balancer access and private ECS outbound access |
| Application Load Balancer | Public entry point for CloudAEye routes |
| ECS cluster with ECS Managed Instances | Runtime for application containers and data services |
| MongoDB ECS service | Internal database for CloudAEye application data |
| ChromaDB ECS service | Internal vector database |
| ECS managed EBS volumes | Persistent storage for MongoDB and ChromaDB |
| Cloud Map private DNS | Internal service discovery for MongoDB and ChromaDB |
| SQS queues | cloudaeye-indexing-queue for indexing work and cloudaeye-review-queue for asynchronous review work |
| Cognito user pool and identity resources | Tenant user authentication and bootstrap setup |
| CloudWatch log groups | Logs for application, data, and bootstrap tasks |
MongoDB and ChromaDB are private services and are not exposed through the public load balancer.
Terraform Bundle Files¶
CloudAEye provides the Terraform configuration as a zip file. The configuration includes only the deployable Terraform configuration and example input files.
| File | What it contains |
|---|---|
providers.tf |
AWS provider configuration. |
terraform.tf |
Terraform and provider version constraints. |
variables.tf |
Input variables for AWS region, networking, tenant bootstrap, GitHub App values, LLM settings, ECS sizing, data volumes, and autoscaling. |
terraform.tfvars.example |
Example customer input file to copy to terraform.tfvars locally. |
locals.tf |
Derived names, default ECS service definitions, task counts from deployment_user_count, environment variables, service routes, and shared tags. |
main.tf |
Core infrastructure: VPC, public/private subnets, internet gateway, NAT gateway, route tables, security groups, SQS queues, Cognito CloudFormation stack, Cloud Map private DNS, and load balancer routing. |
ecs.tf |
ECS cluster, ECS Managed Instances capacity providers, CloudWatch log groups, task definitions, ECS services, MongoDB and ChromaDB volumes, bootstrap task, and worker autoscaling. |
iam.tf |
IAM roles and policies for ECS task execution, application tasks, ECS infrastructure, managed instances, SQS access, Cognito bootstrap, and ECS managed EBS volumes. |
outputs.tf |
Deployment outputs such as ECS cluster name, ALB DNS name, app URL, service routes, internal data service DNS names, queue URLs. |
NewTenantPoolONLY.template |
CloudFormation template used by Terraform to create the Cognito user pool, app client, identity pool, groups, and Cognito IAM roles. |
Step 1: Prepare The Terraform Bundle¶
Go to the Terraform deployment bundle:
cd /path/to/on-prem-deployment
Create your local variables file:
cp terraform.tfvars.example terraform.tfvars
Step 2: Configure Terraform Variables¶
Edit terraform.tfvars and set the exact values:
Understanding the source labels¶
The Source column identifies who chooses, provides, or creates each value:
| Source | What it means |
|---|---|
| CloudAEye | CloudAEye provides the value. Contact CloudAEye if you have not received it. |
| Generate | You create a new strong random value. Generate a separate value for every secret. |
| AWS | Obtain the value from your AWS account. |
| GitHub | Obtain the value from the GitHub App settings or installation details. |
| LLM provider | Obtain the value from the selected model provider's console, such as OpenAI, Anthropic, AWS, Google Cloud, or Azure. |
| Customer | The customer chooses or supplies the value based on their deployment, organization, or initial admin user. |
AWS and deployment basics¶
| Variable | Source | How to obtain the value | Example |
|---|---|---|---|
aws_region |
Customer | Choose the AWS region where you want to deploy. | us-east-2 |
aws_profile |
Customer | Use the profile configured by aws configure. Use default if you configured the default profile. |
default |
app_name |
Customer | Choose a prefix for the resources created by this deployment. | cloudaeye |
allowed_app_cidr |
Customer | Use your public IP address with a /32 suffix. |
203.0.113.10/32 |
Generated secrets¶
Generate a different strong random value for each secret.
| Variable | Source | How to obtain the value | Example format |
|---|---|---|---|
mongodb_password |
Generate | Generate a strong random password for the private MongoDB service. | <64-character-random-hex-string> |
server_x_api_key |
Generate | Generate a strong random API key for communication with the CloudAEye application containers. | <64-character-random-hex-string> |
github_webhook_secret |
Generate | Generate a strong random secret. Enter this exact value in both terraform.tfvars and the GitHub App webhook configuration. |
<64-character-random-hex-string> |
AWS credentials for the application runtime¶
These credentials are used by the deployed CloudAEye services. They are separate from the local aws_profile that Terraform uses during deployment.
| Variable | Source | How to obtain the value | Example format |
|---|---|---|---|
server_aws_access_key_id |
AWS | In the AWS console, open IAM > Users > your application user > Security credentials, then create an access key. | <AWS-access-key-id> |
server_aws_secret_access_key |
AWS | Copy the secret access key when AWS displays it after creating the access key. AWS displays this value only once. | <AWS-secret-access-key> |
LLM configuration¶
| Variable | Source | How to obtain the value | Example |
|---|---|---|---|
llm_host_type |
Customer | Choose cloudaeye for CloudAEye-hosted models, which is the default, or your_own when supplying your own provider credentials. |
cloudaeye |
llm_provider |
Customer | Choose one of OpenAI, Anthropic, AWS_Bedrock, GCP_Vertex, or Azure. |
OpenAI |
llm_model |
Customer | Enter a model supported by the selected provider. | gpt-5.4 |
llm_* provider settings |
LLM provider | Required only with llm_host_type = "your_own". Obtain the API key, credentials, endpoint, region, or service account details from your provider console. |
<OpenAI-key> |
Tenant and initial admin¶
| Variable | Source | How to obtain the value | Example |
|---|---|---|---|
tenant_key |
CloudAEye | Assigned by CloudAEye during tenant and license provisioning. | 12345 |
tenant_identifier |
CloudAEye | Assigned by CloudAEye during tenant and license provisioning. | acme-corp |
tenant_admin_email |
Customer | Enter the email address of the customer's first admin user. Use this when logging into CloudAEye console. | admin@example.com |
tenant_admin_password |
Customer | It must include uppercase and lowercase letters, a number, and a symbol, and be at least 8 characters long. Use this when logging into CloudAEye console. | <strong-admin-password> |
tenant_admin_company |
Customer | Enter your company name. | Acme Corporation |
tenant_admin_first_name, tenant_admin_last_name |
Customer | Enter the first and last name of the initial user. | John, Smith |
License¶
| Variable | Source | How to obtain the value | Example format |
|---|---|---|---|
license_token |
CloudAEye | Use the token emailed to you by CloudAEye. Production tokens start with cla_live_. |
<issued-token> |
GitHub App¶
| Variable | Source | How to obtain the value | Example |
|---|---|---|---|
github_app_id |
GitHub | Open the GitHub App settings page and copy App ID. | 123456 |
github_app_key |
GitHub | Use a random generated value. | cloudaeye-code-review-acme |
github_installation_id |
GitHub | Copy the numeric ID from the installation URL: .../settings/installations/<ID>. |
6666666 |
github_user |
GitHub | For a personal-account installation, enter the account username. Set exactly github_user. |
octocat |
github_organization |
GitHub | For an organization installation, enter the organization name. Set exactly github_organization. |
acme-corp |
github_private_key |
GitHub | In the GitHub App settings, select Private keys > Generate a private key. Paste the complete contents of the downloaded .pem file. |
-----BEGIN RSA PRIVATE KEY-----... |
github_webhook_secret |
GitHub | Use the same generated random secret that you entered in the GitHub App webhook configuration. | <64-character-random-hex-string> |
Optional Cognito email settings¶
Set both values to send Cognito email through a verified Amazon SES identity, or leave both commented out to use the default Cognito no-reply sender.
| Variable | Source | How to obtain the value | Example |
|---|---|---|---|
cognito_ses_identity_arn |
AWS | Copy the ARN of the verified identity from Amazon SES in the deployment region. | arn:aws:ses:us-east-2:123456789012:identity/example.com |
cognito_email_from |
Customer / AWS | Enter the sender name and an email address allowed by that SES identity. | <no-reply@example.com> |
Step 3: Deploy¶
Run Terraform:
terraform init
terraform validate
terraform plan
terraform apply
Review the plan before applying. On the first apply, Terraform creates the infrastructure, starts the ECS services, and runs a one-time auth bootstrap task after Cognito and ECS are ready.
The bootstrap task creates or updates the on-prem tenant, admin user, Cognito admin user, and LLM details inside the deployed MongoDB service.
Step 4: Access CloudAEye¶
After terraform apply completes, get the application URL:
terraform output app_base_url
Open the CloudAEye UI at <app_base_url>/ui.
You can also inspect the load balancer DNS name and public routes:
terraform output alb_dns_name
terraform output service_routes
Public paths:
| Route | Service |
|---|---|
/ui/* |
cloudaeye-web |
/code-review/* |
cloudaeye-reviews |
/rca/test/* |
cloudaeye-api |
/rca/code-repository-integration/* |
cloudaeye-repositories |
/external-service/* |
cloudaeye-indexer-api |
/secret-scanner/* |
cloudaeye-secrets |
/sso/* |
cloudaeye-auth |
/github-app/webhook |
cloudaeye-webhook |
The cloudaeye-indexer-worker, MongoDB, and ChromaDB services are private and are not exposed through the load balancer.
Configuration¶
Most customer-specific configuration is handled through terraform.tfvars.
To restrict access to the public application, set allowed_app_cidr to your office or CIDR:
allowed_app_cidr = "203.0.113.10/32"
For advanced deployments, the ecs_services map can override service images, CPU, memory, desired count, commands, route paths, and health check paths. Use this only after consulting CloudAEye.
Operations¶
List ECS services:
aws ecs list-services \
--cluster "$(terraform output -raw ecs_cluster_name)"
Describe a service:
aws ecs describe-services \
--cluster "$(terraform output -raw ecs_cluster_name)" \
--services <service-name>
CloudWatch log groups are created under:
/ecs/<app_name>-<environment>/<service-name>
Destroy¶
To remove the deployment:
terraform destroy
This deletes the infrastructure created by the stack, including ECS services and the EBS data volumes. Export or back up any required data before destroying the deployment.