Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
122 changes: 101 additions & 21 deletions cft-templates/ec2-dcv-claudeOnBedrock.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,14 @@ Metadata:
AWSTemplateFormatVersion: '2010-09-09'
Description: 'AWS CloudFormation Template to create an GPU based EC2 instance with NICE DCV pre installed.'
Parameters:
InstanceType:
Description: Choose the instance type from the dropdown.
Type: String
ConstraintDescription: must be a valid EC2 instance type.
EBSVolumeSize:
Description: The initial size of the volume (in GBs) EBS will use for storage.
Type: Number
Default: 70
Namespace:
Type: String
Description: An environment name that will be prefixed to resource names
Expand All @@ -17,17 +25,30 @@ Parameters:
Description: >-
An S3 URI (starting with "s3://") that specifies the location of files to be copied to
the environment instance, including any bootstrap scripts
InstanceType:
Description: Choose the instance type e.g t3.medium (2vCPU , 2GiB RAM), t3.large (2vCPU, 8GiB RAM), t3.xlarge(4vCPU, 16GiB RAM)
Type: String
ConstraintDescription: must be a valid EC2 instance type.
EBSVolumeSize:
Description: The initial size of the volume (in GBs) EBS will use for storage.
Type: Number
Default: 70

# AvailabilityZone:
# Description: Select the availability zone in which to create the instance. If you plan to attach a secondary volume to the instance, create this instance in the same AvailabilityZone as the volume you created.
# Type: AWS::EC2::AvailabilityZone::Name
# Type: AWS::EC2::AvailabilityZone::Name
ProjectId:
Type: String
Default: ''
Description: >-
RG project id. Research Gateway auto-fills this hidden parameter on every launch
(same convention used by other products). Applied as project_name tag on the
Bedrock Mantle project created by this stack.
ResearcherName:
Type: String
Default: ''
Description: >-
Researcher email. Research Gateway auto-fills this hidden parameter on every launch
(same convention used by other products). Applied as researcher_name tag on the
Bedrock Mantle project created by this stack.
CostResource:
Type: String
Default: ''
Description: >-
Cost allocation tag for this workspace. When empty, defaults to this stack's name
(same pattern as the EC2 instance cost_resource tag below).
# Password:
# Type: String
# NoEcho: True
Expand All @@ -37,8 +58,24 @@ Parameters:

Conditions:
IamPolicyEmpty: !Equals [!Ref IamPolicyDocument, '{}']
HasCostResource: !Not [!Equals [!Ref CostResource, '']]

Resources:
ClaudeMantleProject:
Type: AWS::BedrockMantle::Project
Properties:
Name: !Ref Namespace
Tags:
- Key: project_name
Value: !Ref ProjectId
- Key: researcher_name
Value: !Ref ResearcherName
- Key: cost_resource
Value: !If
- HasCostResource
- !Ref CostResource
- !Sub '${AWS::StackName}'

Resources:
SSMPolicy:
Type: AWS::IAM::ManagedPolicy
Properties:
Expand Down Expand Up @@ -92,22 +129,20 @@ Resources:
Resource: '*'
- Effect: Allow
Action:
- 'ssmmessages:*'
- 'bedrock:*'
- 'bedrock-mantle:*'
Resource: '*'
- Effect: Allow
Action:
- 'ec2messages:*'
- 'ssmmessages:*'
Resource: '*'
- Effect: Allow
Action:
- 'sns:Publish'
- 'ec2messages:*'
Resource: '*'
- Effect: Allow
Action:
- bedrock:ListInferenceProfiles
- bedrock:GetInferenceProfile
- bedrock:InvokeModel
- bedrock:InvokeModelWithResponseStream
- 'sns:Publish'
Resource: '*'
BedrockPolicy:
Type: AWS::IAM::ManagedPolicy
Expand All @@ -116,6 +151,14 @@ Resources:
PolicyDocument:
Version: "2012-10-17"
Statement:
- Sid: AllowBedrockMantleInference
Effect: Allow
Action:
- bedrock-mantle:CreateInference
- bedrock-mantle:GetProject
- bedrock-mantle:ListProjects
- bedrock-mantle:ListTagsForResources
Resource: "*"
- Sid: AllowBedrockInvoke
Effect: Allow
Action:
Expand Down Expand Up @@ -148,6 +191,7 @@ Resources:
- Ref: SSMPolicy
- Ref: BedrockPolicy
- arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
- arn:aws:iam::aws:policy/AmazonS3FilesClientFullAccess
PermissionsBoundary: !Ref InstanceRolePermissionBoundary


Expand All @@ -162,6 +206,7 @@ Resources:

EC2Instance:
Type: AWS::EC2::Instance
DependsOn: ClaudeMantleProject
CreationPolicy:
ResourceSignal:
Timeout: PT15M
Expand Down Expand Up @@ -319,6 +364,7 @@ Resources:
#!/usr/bin/env bash
exec > >(tee /var/log/user-data.log|logger -t user-data -s 2>/dev/console) 2>&1
# trap '/opt/aws/bin/cfn-signal --exit-code 1 --resource EC2Instance --region ${AWS::Region} --stack ${AWS::StackName}' ERR
sudo dnf install -y amazon-efs-utils
# Download and execute bootstrap script
aws s3 cp --region "${AWS::Region}" "${EnvironmentInstanceFiles}/get_bootstrap.sh" "/tmp"
chmod 500 "/tmp/get_bootstrap.sh"
Expand All @@ -328,17 +374,36 @@ Resources:
sudo -u ec2-user bash -lc 'curl -fsSL https://claude.ai/install.sh | bash'
[ -x /home/ec2-user/.local/bin/claude ] && ln -sf /home/ec2-user/.local/bin/claude /usr/local/bin/claude && (grep -q '.local/bin' /home/ec2-user/.bashrc || echo 'export PATH="$HOME/.local/bin:$PATH"' >> /home/ec2-user/.bashrc)

# Configure Claude Code to use Bedrock
# Configure Claude Code for Bedrock Mantle only (not Invoke API). The Mantle project
# created above (ClaudeMantleProject) is proj_... — pass both workspace headers
# (project id, not ARN) so inference is attributed to this stack's Mantle project.
MANTLE_PROJECT_ID="${ClaudeMantleProject}"
sudo -u ec2-user mkdir -p /home/ec2-user/.claude
cat >/home/ec2-user/.claude/settings.json <<EOF
{
"theme": "dark",
"env": {
"CLAUDE_CODE_USE_BEDROCK": "1",
"AWS_REGION": "${AWS::Region}"
}
"CLAUDE_CODE_USE_MANTLE": "1",
"AWS_REGION": "${AWS::Region}",
"ANTHROPIC_CUSTOM_HEADERS": "anthropic-workspace:$MANTLE_PROJECT_ID\\nanthropic-workspace-id:$MANTLE_PROJECT_ID",
"ANTHROPIC_DEFAULT_SONNET_MODEL": "anthropic.claude-sonnet-5",
"ANTHROPIC_DEFAULT_OPUS_MODEL": "anthropic.claude-opus-5",
"ANTHROPIC_DEFAULT_HAIKU_MODEL": "anthropic.claude-haiku-4-5"
},
"availableModels": [
"opus",
"sonnet",
"haiku",
"anthropic.claude-opus-5",
"anthropic.claude-sonnet-5",
"anthropic.claude-fable-5",
"anthropic.claude-opus-4-8",
"anthropic.claude-opus-4-7",
"anthropic.claude-haiku-4-5"
]
}
EOF
echo "Claude configured for Mantle endpoint with project $MANTLE_PROJECT_ID"
chown -R ec2-user:ec2-user /home/ec2-user/.claude

# Create dcv session start script (GDM must stay off; it conflicts with DCV virtual sessions)
Expand Down Expand Up @@ -500,6 +565,21 @@ Resources:
CidrIp: 0.0.0.0/0

Outputs:
MantleProjectId:
Description: Bedrock Mantle project id (proj_...) for Claude anthropic-workspace header
Value: !Ref ClaudeMantleProject
MantleProjectNameTag:
Description: 'project_name cost allocation tag (RG project id)'
Value: !Ref ProjectId
MantleResearcherNameTag:
Description: 'researcher_name cost allocation tag (researcher email)'
Value: !Ref ResearcherName
MantleCostResourceTag:
Description: 'cost_resource cost allocation tag (defaults to stack name when CostResource param is empty)'
Value: !If
- HasCostResource
- !Ref CostResource
- !Sub '${AWS::StackName}'
InstanceId:
Description: InstanceId of the newly created EC2 instance
Value: !Ref 'EC2Instance'
Expand Down
19 changes: 11 additions & 8 deletions cft-templates/ec2-dcv-codex.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,14 @@ Metadata:
AWSTemplateFormatVersion: '2010-09-09'
Description: 'AWS CloudFormation Template to create an GPU based EC2 instance with NICE DCV pre installed.'
Parameters:
InstanceType:
Description: Choose the instance type from the dropdown.
Type: String
ConstraintDescription: must be a valid EC2 instance type.
EBSVolumeSize:
Description: The initial size of the volume (in GBs) EBS will use for storage.
Type: Number
Default: 70
Namespace:
Type: String
Description: An environment name that will be prefixed to resource names
Expand All @@ -17,14 +25,7 @@ Parameters:
Description: >-
An S3 URI (starting with "s3://") that specifies the location of files to be copied to
the environment instance, including any bootstrap scripts
InstanceType:
Description: Choose the instance type e.g t3.medium (2vCPU , 2GiB RAM), t3.large (2vCPU, 8GiB RAM), t3.xlarge(4vCPU, 16GiB RAM)
Type: String
ConstraintDescription: must be a valid EC2 instance type.
EBSVolumeSize:
Description: The initial size of the volume (in GBs) EBS will use for storage.
Type: Number
Default: 70

# AvailabilityZone:
# Description: Select the availability zone in which to create the instance. If you plan to attach a secondary volume to the instance, create this instance in the same AvailabilityZone as the volume you created.
# Type: AWS::EC2::AvailabilityZone::Name
Expand Down Expand Up @@ -126,6 +127,7 @@ Resources:
ManagedPolicyArns:
- Ref: SSMPolicy
- arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
- arn:aws:iam::aws:policy/AmazonS3FilesClientFullAccess
PermissionsBoundary: !Ref InstanceRolePermissionBoundary


Expand Down Expand Up @@ -297,6 +299,7 @@ Resources:
#!/usr/bin/env bash
exec > >(tee /var/log/user-data.log|logger -t user-data -s 2>/dev/console) 2>&1
# trap '/opt/aws/bin/cfn-signal --exit-code 1 --resource EC2Instance --region ${AWS::Region} --stack ${AWS::StackName}' ERR
sudo dnf install -y amazon-efs-utils
# Download and execute bootstrap script
aws s3 cp --region "${AWS::Region}" "${EnvironmentInstanceFiles}/get_bootstrap.sh" "/tmp"
chmod 500 "/tmp/get_bootstrap.sh"
Expand Down
Loading