gabriel / musehub public
aws-provision.sh bash
153 lines 6.5 KB
7f1d07e8 feat: domains, MCP expansion, MIDI player, and production hardening (#8) Gabriel Cardona <cgcardona@gmail.com> 4d ago
1 #!/usr/bin/env bash
2 # Run this locally (after installing AWS CLI and running `aws configure`).
3 # Creates an EC2 t3.small, security group, key pair, and Elastic IP for musehub.ai.
4 #
5 # Prerequisites:
6 # brew install awscli
7 # aws configure (enter your Access Key ID, Secret, region=us-east-1, output=json)
8 #
9 # Usage:
10 # chmod +x deploy/aws-provision.sh
11 # ./deploy/aws-provision.sh
12
13 set -euo pipefail
14
15 # Suppress AWS CLI pager entirely — prevents the script from blocking on `less`
16 export AWS_PAGER=""
17
18 REGION="us-east-1"
19 AMI_ID="ami-0c7217cdde317cfec" # Ubuntu 22.04 LTS (us-east-1, 2024)
20 INSTANCE_TYPE="t3.small"
21 KEY_NAME="musehub-key"
22 SG_NAME="musehub-sg"
23 SG_ID="sg-05815872537fcfe76" # Already created — skip re-creation
24 INSTANCE_NAME="musehub-prod"
25
26 # ── Key pair ──────────────────────────────────────────────────────────────────
27 if [ -f ~/.ssh/${KEY_NAME}.pem ]; then
28 echo "==> Key pair already exists at ~/.ssh/${KEY_NAME}.pem, skipping"
29 else
30 echo "==> Creating key pair: $KEY_NAME"
31 aws ec2 create-key-pair \
32 --region "$REGION" \
33 --key-name "$KEY_NAME" \
34 --query 'KeyMaterial' \
35 --output text > ~/.ssh/${KEY_NAME}.pem
36 chmod 400 ~/.ssh/${KEY_NAME}.pem
37 echo " Key saved to ~/.ssh/${KEY_NAME}.pem"
38 fi
39
40 # ── Current IP ────────────────────────────────────────────────────────────────
41 echo "==> Getting your current public IP..."
42 MY_IP=$(curl -s https://checkip.amazonaws.com)
43 echo " Your IP: $MY_IP"
44
45 # ── Security group ────────────────────────────────────────────────────────────
46 echo "==> Using existing security group: $SG_ID"
47
48 # ── Inbound rules (idempotent — ignore duplicate-rule errors) ─────────────────
49 echo "==> Adding inbound rules (SSH / HTTP / HTTPS)..."
50
51 add_rule() {
52 local port=$1 cidr=$2
53 aws ec2 authorize-security-group-ingress \
54 --region "$REGION" \
55 --group-id "$SG_ID" \
56 --protocol tcp --port "$port" --cidr "$cidr" \
57 --output text > /dev/null 2>&1 \
58 && echo " Port $port ($cidr) — added" \
59 || echo " Port $port ($cidr) — already exists, skipping"
60 }
61
62 add_rule 22 "${MY_IP}/32"
63 add_rule 80 "0.0.0.0/0"
64 add_rule 443 "0.0.0.0/0"
65
66 # ── EC2 instance ──────────────────────────────────────────────────────────────
67 # Check if instance already exists
68 EXISTING=$(aws ec2 describe-instances \
69 --region "$REGION" \
70 --filters "Name=tag:Name,Values=$INSTANCE_NAME" "Name=instance-state-name,Values=pending,running,stopped" \
71 --query 'Reservations[0].Instances[0].InstanceId' \
72 --output text)
73
74 if [ "$EXISTING" != "None" ] && [ -n "$EXISTING" ]; then
75 echo "==> Instance already exists: $EXISTING"
76 INSTANCE_ID="$EXISTING"
77 else
78 echo "==> Launching EC2 instance..."
79 INSTANCE_ID=$(aws ec2 run-instances \
80 --region "$REGION" \
81 --image-id "$AMI_ID" \
82 --instance-type "$INSTANCE_TYPE" \
83 --key-name "$KEY_NAME" \
84 --security-group-ids "$SG_ID" \
85 --block-device-mappings '[{"DeviceName":"/dev/sda1","Ebs":{"VolumeSize":20,"VolumeType":"gp3","DeleteOnTermination":true}}]' \
86 --tag-specifications "ResourceType=instance,Tags=[{Key=Name,Value=$INSTANCE_NAME}]" \
87 --query 'Instances[0].InstanceId' \
88 --output text)
89 echo " Instance ID: $INSTANCE_ID"
90 fi
91
92 echo "==> Waiting for instance to be running..."
93 aws ec2 wait instance-running --region "$REGION" --instance-ids "$INSTANCE_ID"
94 echo " Instance is running"
95
96 # ── Elastic IP ────────────────────────────────────────────────────────────────
97 # Check if already associated
98 EXISTING_EIP=$(aws ec2 describe-addresses \
99 --region "$REGION" \
100 --filters "Name=instance-id,Values=$INSTANCE_ID" \
101 --query 'Addresses[0].PublicIp' \
102 --output text)
103
104 if [ "$EXISTING_EIP" != "None" ] && [ -n "$EXISTING_EIP" ]; then
105 echo "==> Elastic IP already associated: $EXISTING_EIP"
106 PUBLIC_IP="$EXISTING_EIP"
107 else
108 echo "==> Allocating Elastic IP..."
109 ALLOC_ID=$(aws ec2 allocate-address \
110 --region "$REGION" \
111 --domain vpc \
112 --query 'AllocationId' \
113 --output text)
114 echo " Allocation ID: $ALLOC_ID"
115
116 echo "==> Associating Elastic IP with instance..."
117 aws ec2 associate-address \
118 --region "$REGION" \
119 --instance-id "$INSTANCE_ID" \
120 --allocation-id "$ALLOC_ID" \
121 --output text > /dev/null
122
123 PUBLIC_IP=$(aws ec2 describe-addresses \
124 --region "$REGION" \
125 --allocation-ids "$ALLOC_ID" \
126 --query 'Addresses[0].PublicIp' \
127 --output text)
128 fi
129
130 echo ""
131 echo "============================================================"
132 echo " DONE. Your EC2 instance is ready."
133 echo "============================================================"
134 echo " Instance ID : $INSTANCE_ID"
135 echo " Elastic IP : $PUBLIC_IP"
136 echo " Key file : ~/.ssh/${KEY_NAME}.pem"
137 echo ""
138 echo " DNS records to add at Namecheap (Advanced DNS tab):"
139 echo " ┌──────────┬──────────┬────────────────┬───────────┐"
140 echo " │ Type │ Host │ Value │ TTL │"
141 echo " ├──────────┼──────────┼────────────────┼───────────┤"
142 echo " │ A Record │ @ │ $PUBLIC_IP │ Automatic │"
143 echo " │ A Record │ www │ $PUBLIC_IP │ Automatic │"
144 echo " └──────────┴──────────┴────────────────┴───────────┘"
145 echo " Also DELETE the existing TXT record (the SPF one)."
146 echo ""
147 echo " Verify propagation: dig musehub.ai +short"
148 echo ""
149 echo " SSH into the server:"
150 echo " ssh -i ~/.ssh/${KEY_NAME}.pem ubuntu@$PUBLIC_IP"
151 echo ""
152 echo " Then run: bash /opt/musehub/deploy/setup-ec2.sh"
153 echo "============================================================"