Learn about deployment
Reference Architecture
Hands-on Guides
AWS Step-by-Step Guides
EC2 Deployment Guide for Oxy
Step-by-step guide for deploying Oxy on AWS EC2 with EBS storage for data persistence
Overview
The EC2 deployment provides a simple, cost-effective way to run Oxy with the following components:
- EC2 Instance: ARM64-based t4g.small instance running Ubuntu 22.04
- EBS Storage: 10GB persistent volume for application data
- Application Load Balancer: With AWS Cognito authentication
- Security Groups: Configured for web traffic and SSH access
Prerequisites
Before starting, ensure you have:
- AWS CLI configured with appropriate permissions
- SSH key pair created in AWS (or create one during setup)
- Domain name configured in Route53 (optional)
- Basic familiarity with AWS Console and CLI
Step 1: Network Infrastructure Setup
1.1 Create VPC and Subnets
Copy
Ask AI
# Create VPC
VPC_ID=$(aws ec2 create-vpc \
--cidr-block 10.0.0.0/16 \
--tag-specifications 'ResourceType=vpc,Tags=[{Key=Name,Value=oxy-playground-vpc}]' \
--query 'Vpc.VpcId' --output text)
# Enable DNS hostnames
aws ec2 modify-vpc-attribute --vpc-id $VPC_ID --enable-dns-hostnames
# Create Internet Gateway
IGW_ID=$(aws ec2 create-internet-gateway \
--tag-specifications 'ResourceType=internet-gateway,Tags=[{Key=Name,Value=oxy-playground-igw}]' \
--query 'InternetGateway.InternetGatewayId' --output text)
# Attach Internet Gateway to VPC
aws ec2 attach-internet-gateway --internet-gateway-id $IGW_ID --vpc-id $VPC_ID
# Create public subnet
SUBNET_ID=$(aws ec2 create-subnet \
--vpc-id $VPC_ID \
--cidr-block 10.0.1.0/24 \
--availability-zone us-west-2a \
--tag-specifications 'ResourceType=subnet,Tags=[{Key=Name,Value=oxy-playground-public-subnet}]' \
--query 'Subnet.SubnetId' --output text)
# Enable auto-assign public IP
aws ec2 modify-subnet-attribute --subnet-id $SUBNET_ID --map-public-ip-on-launch
# Create route table
ROUTE_TABLE_ID=$(aws ec2 create-route-table \
--vpc-id $VPC_ID \
--tag-specifications 'ResourceType=route-table,Tags=[{Key=Name,Value=oxy-playground-public-rt}]' \
--query 'RouteTable.RouteTableId' --output text)
# Add route to Internet Gateway
aws ec2 create-route --route-table-id $ROUTE_TABLE_ID --destination-cidr-block 0.0.0.0/0 --gateway-id $IGW_ID
# Associate route table with subnet
aws ec2 associate-route-table --subnet-id $SUBNET_ID --route-table-id $ROUTE_TABLE_ID
1.2 Create Security Groups
Copy
Ask AI
# Create security group for EC2 instance
EC2_SG_ID=$(aws ec2 create-security-group \
--group-name oxy-ec2-sg \
--description "Security group for Oxy EC2 instance" \
--vpc-id $VPC_ID \
--tag-specifications 'ResourceType=security-group,Tags=[{Key=Name,Value=oxy-ec2-sg}]' \
--query 'GroupId' --output text)
# Allow SSH access (port 22)
aws ec2 authorize-security-group-ingress \
--group-id $EC2_SG_ID \
--protocol tcp \
--port 22 \
--cidr 0.0.0.0/0
# Allow HTTP access (port 3000 for Oxy)
aws ec2 authorize-security-group-ingress \
--group-id $EC2_SG_ID \
--protocol tcp \
--port 3000 \
--cidr 0.0.0.0/0
# Allow MCP SSE access (port 8000)
aws ec2 authorize-security-group-ingress \
--group-id $EC2_SG_ID \
--protocol tcp \
--port 8000 \
--cidr 0.0.0.0/0
# Create security group for ALB
ALB_SG_ID=$(aws ec2 create-security-group \
--group-name oxy-alb-sg \
--description "Security group for Oxy Application Load Balancer" \
--vpc-id $VPC_ID \
--tag-specifications 'ResourceType=security-group,Tags=[{Key=Name,Value=oxy-alb-sg}]' \
--query 'GroupId' --output text)
# Allow HTTP and HTTPS for ALB
aws ec2 authorize-security-group-ingress \
--group-id $ALB_SG_ID \
--protocol tcp \
--port 80 \
--cidr 0.0.0.0/0
aws ec2 authorize-security-group-ingress \
--group-id $ALB_SG_ID \
--protocol tcp \
--port 443 \
--cidr 0.0.0.0/0
1.3 Create SSH Key Pair (if needed)
Copy
Ask AI
# Create key pair
aws ec2 create-key-pair \
--key-name oxy-keypair \
--query 'KeyMaterial' \
--output text > ~/.ssh/oxy-keypair.pem
# Set proper permissions
chmod 400 ~/.ssh/oxy-keypair.pem
Step 2: Create IAM Roles and Policies
2.1 Create IAM Role for EC2
Copy
Ask AI
# Create trust policy for EC2
cat > ec2-trust-policy.json << 'EOF'
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
EOF
# Create IAM role
aws iam create-role \
--role-name OxyEC2Role \
--assume-role-policy-document file://ec2-trust-policy.json
# Attach AWS managed policy for SSM
aws iam attach-role-policy \
--role-name OxyEC2Role \
--policy-arn arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
# Create custom policy for Parameter Store access
cat > ssm-access-policy.json << 'EOF'
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ssm:GetParameter",
"ssm:GetParameters",
"ssm:GetParametersByPath"
],
"Resource": "arn:aws:ssm:us-west-2:*:parameter/oxy-playground/*"
}
]
}
EOF
# Create and attach custom policy
aws iam create-policy \
--policy-name OxySSMAccessPolicy \
--policy-document file://ssm-access-policy.json
# Get account ID for policy ARN
ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
# Attach custom policy
aws iam attach-role-policy \
--role-name OxyEC2Role \
--policy-arn arn:aws:iam::${ACCOUNT_ID}:policy/OxySSMAccessPolicy
# Create instance profile
aws iam create-instance-profile --instance-profile-name OxyEC2InstanceProfile
# Add role to instance profile
aws iam add-role-to-instance-profile \
--instance-profile-name OxyEC2InstanceProfile \
--role-name OxyEC2Role
2.2 Create Setup Script
Create the setup script that will be executed on instance launch:
Copy
Ask AI
cat > oxy-setup.sh << 'EOF'
#!/bin/bash
set -e
# Update system
sudo apt-get update -y
sudo apt-get install -y curl wget unzip awscli
# Mount EBS volume
DEVICE="/dev/nvme1n1"
MOUNT_POINT="/mnt/data"
sudo mkdir -p $MOUNT_POINT
# Check if device exists and format if needed
if [ -b "$DEVICE" ]; then
# Check if filesystem exists
if ! sudo blkid "$DEVICE"; then
echo "Formatting $DEVICE..."
sudo mkfs.ext4 "$DEVICE"
fi
# Mount the device
sudo mount "$DEVICE" "$MOUNT_POINT"
# Add to fstab for persistence
echo "$DEVICE $MOUNT_POINT ext4 defaults,nofail 0 2" | sudo tee -a /etc/fstab
# Set permissions
sudo chown ubuntu:ubuntu "$MOUNT_POINT"
fi
# Install Oxy
curl --proto '=https' --tlsv1.2 -LsSf https://internal.oxy.tech | sudo bash
# Create directories
mkdir -p /mnt/data/oxy_data
mkdir -p /mnt/data/customer-demo
# Get environment variables from Parameter Store
aws ssm get-parameter \
--name "/oxy-playground/oxy/env" \
--region us-west-2 \
--query 'Parameter.Value' \
--output text > /mnt/data/oxy.env
# Get BigQuery credentials if they exist
if aws ssm get-parameter --name "/oxy-playground/oxy/bigquery_sample_key" --region us-west-2 --with-decryption --query 'Parameter.Value' --output text > /tmp/bigquery-key.json 2>/dev/null; then
mv /tmp/bigquery-key.json /mnt/data/customer-demo/bigquery-sample.key
fi
# Create systemd service
sudo tee /etc/systemd/system/oxy.service << 'SERVICE_EOF'
[Unit]
Description=Oxy Application
After=network.target
[Service]
Type=forking
User=ubuntu
WorkingDirectory=/mnt/data
EnvironmentFile=/mnt/data/oxy.env
ExecStart=/bin/bash -c '/usr/local/bin/oxy serve --auth-mode cognito --port 3000 & /usr/local/bin/oxy mcp-sse --port 8000 & wait'
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
SERVICE_EOF
# Enable and start service
sudo systemctl daemon-reload
sudo systemctl enable oxy
sudo systemctl start oxy
# Wait for service to be ready
sleep 10
sudo systemctl status oxy
EOF
# Make script executable
chmod +x oxy-setup.sh
Step 3: Launch EC2 Instance
3.1 Get Latest Ubuntu ARM64 AMI
Copy
Ask AI
# Get latest Ubuntu 22.04 ARM64 AMI ID
AMI_ID=$(aws ec2 describe-images \
--owners 099720109477 \
--filters "Name=name,Values=ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-arm64-server-*" \
--query 'Images | sort_by(@, &CreationDate) | [-1].ImageId' \
--output text)
echo "Using AMI: $AMI_ID"
3.2 Launch EC2 Instance
Copy
Ask AI
# Encode user data script
USER_DATA=$(base64 -i oxy-setup.sh)
# Launch instance
INSTANCE_ID=$(aws ec2 run-instances \
--image-id $AMI_ID \
--count 1 \
--instance-type t4g.small \
--key-name oxy-keypair \
--security-group-ids $EC2_SG_ID \
--subnet-id $SUBNET_ID \
--iam-instance-profile Name=OxyEC2InstanceProfile \
--user-data "$USER_DATA" \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=oxy-playground-instance}]' \
--query 'Instances[0].InstanceId' \
--output text)
echo "Launched instance: $INSTANCE_ID"
# Wait for instance to be running
aws ec2 wait instance-running --instance-ids $INSTANCE_ID
echo "Instance is now running"
3.3 Create and Attach EBS Volume
Copy
Ask AI
# Get instance availability zone
AZ=$(aws ec2 describe-instances \
--instance-ids $INSTANCE_ID \
--query 'Reservations[0].Instances[0].Placement.AvailabilityZone' \
--output text)
# Create EBS volume
VOLUME_ID=$(aws ec2 create-volume \
--size 10 \
--availability-zone $AZ \
--volume-type gp3 \
--tag-specifications 'ResourceType=volume,Tags=[{Key=Name,Value=oxy-playground-data}]' \
--query 'VolumeId' \
--output text)
# Wait for volume to be available
aws ec2 wait volume-available --volume-ids $VOLUME_ID
# Attach volume to instance
aws ec2 attach-volume \
--volume-id $VOLUME_ID \
--instance-id $INSTANCE_ID \
--device /dev/xvdf
echo "Attached volume: $VOLUME_ID"
Step 4: Configure Application Secrets
4.1 Store Environment Variables
Copy
Ask AI
# Store application environment variables
aws ssm put-parameter \
--name "/oxy-playground/oxy/env" \
--value "$(cat << 'EOF'
OXY_STATE_DIR=/mnt/data/oxy_data
AWS_REGION=us-west-2
BIGQUERY_CREDENTIALS_PATH=/mnt/data/customer-demo/bigquery-sample.key
# Add other environment variables as needed
EOF
)" \
--type "String" \
--region us-west-2
4.2 Store BigQuery Credentials
Copy
Ask AI
# Store BigQuery service account key
aws ssm put-parameter \
--name "/oxy-playground/oxy/bigquery_sample_key" \
--value "$(cat path/to/your/bigquery-key.json)" \
--type "SecureString" \
--region us-west-2
Step 5: Set Up Cognito Authentication
5.1 Create Cognito User Pool
Copy
Ask AI
# Create user pool
USER_POOL_ID=$(aws cognito-idp create-user-pool \
--pool-name oxy-users \
--policies '{
"PasswordPolicy": {
"MinimumLength": 8,
"RequireUppercase": true,
"RequireLowercase": true,
"RequireNumbers": true,
"RequireSymbols": true
}
}' \
--auto-verified-attributes email \
--username-attributes email \
--query 'UserPool.Id' \
--output text)
echo "Created User Pool: $USER_POOL_ID"
# Create user pool client
CLIENT_ID=$(aws cognito-idp create-user-pool-client \
--user-pool-id $USER_POOL_ID \
--client-name oxy-alb-client \
--generate-secret \
--supported-identity-providers COGNITO \
--callback-urls "https://your-domain.com/oauth2/idpresponse" \
--logout-urls "https://your-domain.com/logout" \
--allowed-o-auth-flows code \
--allowed-o-auth-scopes openid email profile \
--allowed-o-auth-flows-user-pool-client \
--query 'UserPoolClient.ClientId' \
--output text)
echo "Created Client: $CLIENT_ID"
# Create user pool domain
aws cognito-idp create-user-pool-domain \
--domain oxy-auth-$(date +%s) \
--user-pool-id $USER_POOL_ID
5.2 Create Application Load Balancer
Copy
Ask AI
# Create ALB
ALB_ARN=$(aws elbv2 create-load-balancer \
--name oxy-alb \
--subnets $SUBNET_ID \
--security-groups $ALB_SG_ID \
--scheme internet-facing \
--type application \
--ip-address-type ipv4 \
--tags Key=Name,Value=oxy-alb \
--query 'LoadBalancers[0].LoadBalancerArn' \
--output text)
# Create target group
TG_ARN=$(aws elbv2 create-target-group \
--name oxy-tg \
--protocol HTTP \
--port 3000 \
--vpc-id $VPC_ID \
--health-check-protocol HTTP \
--health-check-path /health \
--health-check-interval-seconds 30 \
--health-check-timeout-seconds 5 \
--healthy-threshold-count 2 \
--unhealthy-threshold-count 3 \
--query 'TargetGroups[0].TargetGroupArn' \
--output text)
# Register instance with target group
aws elbv2 register-targets \
--target-group-arn $TG_ARN \
--targets Id=$INSTANCE_ID,Port=3000
# Create ALB listener
aws elbv2 create-listener \
--load-balancer-arn $ALB_ARN \
--protocol HTTP \
--port 80 \
--default-actions Type=authenticate-cognito,AuthenticateCognitoConfig='{
"UserPoolArn":"arn:aws:cognito-idp:us-west-2:'$ACCOUNT_ID':userpool/'$USER_POOL_ID'",
"UserPoolClientId":"'$CLIENT_ID'",
"UserPoolDomain":"oxy-auth-'$(date +%s)'",
"OnUnauthenticatedRequest":"authenticate"
}',Type=forward,TargetGroupArn=$TG_ARN
Step 6: Access Your Oxy Instance
6.1 Get Instance Information
Copy
Ask AI
# Get the instance public IP
INSTANCE_IP=$(aws ec2 describe-instances \
--instance-ids $INSTANCE_ID \
--query 'Reservations[0].Instances[0].PublicIpAddress' \
--output text)
echo "Instance IP: $INSTANCE_IP"
# Get ALB DNS name
ALB_DNS=$(aws elbv2 describe-load-balancers \
--load-balancer-arns $ALB_ARN \
--query 'LoadBalancers[0].DNSName' \
--output text)
echo "ALB DNS: $ALB_DNS"
6.2 SSH Access (for debugging)
Copy
Ask AI
# Connect via SSH
ssh -i ~/.ssh/oxy-keypair.pem ubuntu@$INSTANCE_IP
6.3 Check Service Status
Copy
Ask AI
# On the EC2 instance
sudo systemctl status oxy
sudo journalctl -u oxy -f # Follow logs
Step 7: Create Cognito Users
7.1 Create Admin User
Copy
Ask AI
# Create a user in Cognito
aws cognito-idp admin-create-user \
--user-pool-id $USER_POOL_ID \
--username admin \
--user-attributes Name=email,Value=admin@your-domain.com \
--temporary-password TempPass123! \
--message-action SUPPRESS \
--region us-west-2
# Set permanent password
aws cognito-idp admin-set-user-password \
--user-pool-id $USER_POOL_ID \
--username admin \
--password SecureAdminPass123! \
--permanent \
--region us-west-2
Step 8: Monitoring and Maintenance
8.1 Monitor Instance Health
Copy
Ask AI
# Check instance status
aws ec2 describe-instance-status --instance-ids $INSTANCE_ID
# Monitor EBS volume
aws ec2 describe-volumes --volume-ids $VOLUME_ID
8.2 Application Logs
Copy
Ask AI
# SSH into instance and check logs
ssh -i ~/.ssh/oxy-keypair.pem ubuntu@$INSTANCE_IP
sudo journalctl -u oxy -f
8.3 Data Backup
Copy
Ask AI
# Create manual snapshot
SNAPSHOT_ID=$(aws ec2 create-snapshot \
--volume-id $VOLUME_ID \
--description "Oxy data backup $(date +%Y-%m-%d)" \
--query 'SnapshotId' \
--output text)
echo "Created snapshot: $SNAPSHOT_ID"
Troubleshooting
Common Issues
1. Instance fails to start Oxy service
Copy
Ask AI
# Check user data execution
ssh -i ~/.ssh/oxy-keypair.pem ubuntu@$INSTANCE_IP
sudo cat /var/log/cloud-init-output.log
sudo systemctl status oxy
sudo journalctl -u oxy
2. EBS volume not mounting
Copy
Ask AI
# Check if volume is attached
lsblk
sudo blkid /dev/nvme1n1
# Manually mount if needed
sudo mount /dev/nvme1n1 /mnt/data
3. Cannot access through ALB
Copy
Ask AI
# Check security group rules
aws ec2 describe-security-groups --group-ids $ALB_SG_ID
# Verify target group health
aws elbv2 describe-target-health --target-group-arn $TG_ARN
4. Cognito authentication issues
Copy
Ask AI
# Verify Cognito configuration
aws cognito-idp describe-user-pool --user-pool-id $USER_POOL_ID
aws cognito-idp describe-user-pool-client --user-pool-id $USER_POOL_ID --client-id $CLIENT_ID
Scaling Considerations
For the EC2 deployment:
- Vertical scaling: Increase instance size (t4g.medium, t4g.large)
- Storage scaling: Increase EBS volume size
- High availability: Consider multiple instances with a shared database
For higher scale requirements, consider the ECS deployment guide.
Cleanup
To destroy the infrastructure:
Copy
Ask AI
# Stop and delete instance
aws ec2 terminate-instances --instance-ids $INSTANCE_ID
# Wait for termination
aws ec2 wait instance-terminated --instance-ids $INSTANCE_ID
# Delete EBS volume
aws ec2 delete-volume --volume-id $VOLUME_ID
# Delete load balancer
aws elbv2 delete-load-balancer --load-balancer-arn $ALB_ARN
# Delete target group
aws elbv2 delete-target-group --target-group-arn $TG_ARN
# Delete Cognito user pool
aws cognito-idp delete-user-pool --user-pool-id $USER_POOL_ID
# Delete security groups
aws ec2 delete-security-group --group-id $EC2_SG_ID
aws ec2 delete-security-group --group-id $ALB_SG_ID
# Delete IAM resources
aws iam remove-role-from-instance-profile --instance-profile-name OxyEC2InstanceProfile --role-name OxyEC2Role
aws iam delete-instance-profile --instance-profile-name OxyEC2InstanceProfile
aws iam detach-role-policy --role-name OxyEC2Role --policy-arn arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
aws iam.detach-role-policy --role-name OxyEC2Role --policy-arn arn:aws:iam::${ACCOUNT_ID}:policy/OxySSMAccessPolicy
aws iam delete-role --role-name OxyEC2Role
aws iam delete-policy --policy-arn arn:aws:iam::${ACCOUNT_ID}:policy/OxySSMAccessPolicy
# Delete VPC resources
aws ec2 delete-route --route-table-id $ROUTE_TABLE_ID --destination-cidr-block 0.0.0.0/0
aws ec2 disassociate-route-table --association-id $(aws ec2 describe-route-tables --route-table-ids $ROUTE_TABLE_ID --query 'RouteTables[0].Associations[0].RouteTableAssociationId' --output text)
aws ec2 delete-route-table --route-table-id $ROUTE_TABLE_ID
aws ec2 delete-subnet --subnet-id $SUBNET_ID
aws ec2 detach-internet-gateway --internet-gateway-id $IGW_ID --vpc-id $VPC_ID
aws ec2 delete-internet-gateway --internet-gateway-id $IGW_ID
aws ec2 delete-vpc --vpc-id $VPC_ID
# Delete key pair
aws ec2 delete-key-pair --key-name oxy-keypair
rm ~/.ssh/oxy-keypair.pem
# Delete Parameter Store parameters
aws ssm delete-parameter --name "/oxy-playground/oxy/env"
aws ssm delete-parameter --name "/oxy-playground/oxy/bigquery_sample_key"
Security Best Practices
-
Regularly update the EC2 instance:
CopyAsk AIsudo apt update && sudo apt upgrade -y
-
Rotate SSH keys and API credentials periodically
-
Monitor CloudWatch logs for suspicious activity
-
Use VPC Flow Logs for network monitoring
-
Enable AWS Config for compliance monitoring
Next Steps
- Set up CloudWatch monitoring and alarms
- Configure automated EBS snapshots
- Implement CI/CD for application updates
- Consider migrating to ECS for production workloads
- Set up log aggregation with CloudWatch Logs or ELK stack
On this page
- Overview
- Prerequisites
- Step 1: Network Infrastructure Setup
- 1.1 Create VPC and Subnets
- 1.2 Create Security Groups
- 1.3 Create SSH Key Pair (if needed)
- Step 2: Create IAM Roles and Policies
- 2.1 Create IAM Role for EC2
- 2.2 Create Setup Script
- Step 3: Launch EC2 Instance
- 3.1 Get Latest Ubuntu ARM64 AMI
- 3.2 Launch EC2 Instance
- 3.3 Create and Attach EBS Volume
- Step 4: Configure Application Secrets
- 4.1 Store Environment Variables
- 4.2 Store BigQuery Credentials
- Step 5: Set Up Cognito Authentication
- 5.1 Create Cognito User Pool
- 5.2 Create Application Load Balancer
- Step 6: Access Your Oxy Instance
- 6.1 Get Instance Information
- 6.2 SSH Access (for debugging)
- 6.3 Check Service Status
- Step 7: Create Cognito Users
- 7.1 Create Admin User
- Step 8: Monitoring and Maintenance
- 8.1 Monitor Instance Health
- 8.2 Application Logs
- 8.3 Data Backup
- Troubleshooting
- Common Issues
- 1. Instance fails to start Oxy service
- 2. EBS volume not mounting
- 3. Cannot access through ALB
- 4. Cognito authentication issues
- Scaling Considerations
- Cleanup
- Security Best Practices
- Next Steps
Assistant
Responses are generated using AI and may contain mistakes.