11#! /bin/bash
22set -euo pipefail
33
4+ INSTANCE_TYPE=${INSTANCE_TYPE:- c6a.4xlarge}
5+ VOLUME_SIZE=${VOLUME_SIZE:- 500}
6+
7+ # --- Xata account defaults ---------------------------------------------------
8+ # Shared org infrastructure in the Xata management account (us-east-1). These
9+ # are resource identifiers, not secrets, but they are account-specific:
10+ # override them via env when launching in a different AWS account/region, e.g.
11+ # PROFILE=myprofile REGION=eu-west-1 AMI=ami-... SUBNET=subnet-... SG=sg-... ./launch-ec2.sh
412PROFILE=${PROFILE:- management}
5- INSTANCE_TYPE=c6a.4xlarge
6- AMI=ami-04eaa218f1349d88b
13+ REGION=${REGION:- us-east-1}
14+ AMI=${AMI:- ami-04eaa218f1349d88b} # Ubuntu amd64 image used by the bench boxes
15+ SUBNET=${SUBNET:- subnet-228cc17d}
16+ SG=${SG:- sg-add473b4}
17+ # -----------------------------------------------------------------------------
18+
719# Personal key pair: no generic default exists, so it must be provided.
820# KEY_NAME=<your-ec2-key-pair> [KEY_FILE=~/.ssh/<key>.pem] ./launch-ec2.sh
921KEY_NAME=${KEY_NAME:- }
1022KEY_FILE=${KEY_FILE:- ~/ .ssh/ ${KEY_NAME} .pem}
11- SUBNET=subnet-228cc17d
12- SG=sg-add473b4
13- VOLUME_SIZE=500
1423# Track whether the name was given explicitly (env or --name): teardown
1524# refuses to run against the implicit default name.
1625NAME_EXPLICIT=false
7079# multiple people run benches in this account in parallel (e.g. tsg's
7180# long-lived clickbench/rtabench/jsonbench boxes). Launching requires a
7281# free name; explicit teardown requires --terminate-only.
73- EXISTING=$( aws ec2 describe-instances --profile " $PROFILE " \
82+ EXISTING=$( aws ec2 describe-instances --profile " $PROFILE " --region " $REGION " \
7483 --filters " Name=tag:Name,Values=$NAME " " Name=instance-state-name,Values=running,stopped,pending" \
7584 --query ' Reservations[*].Instances[*].InstanceId' --output text)
7685
7786if $TERMINATE_ONLY ; then
7887 if [ -n " $EXISTING " ]; then
7988 echo " Terminating instance(s) named '$NAME ': $EXISTING "
80- aws ec2 terminate-instances --profile " $PROFILE " --instance-ids $EXISTING --output text
81- aws ec2 wait instance-terminated --profile " $PROFILE " --instance-ids $EXISTING
89+ aws ec2 terminate-instances --profile " $PROFILE " --region " $REGION " -- instance-ids $EXISTING --output text
90+ aws ec2 wait instance-terminated --profile " $PROFILE " --region " $REGION " -- instance-ids $EXISTING
8291 echo " Terminated."
8392 else
8493 echo " No instance named '$NAME ' to terminate."
97106# Enable serial console access (idempotent, account-level setting; only
98107# needed for the launch flow's serial-console fallback)
99108echo " Ensuring serial console access is enabled..."
100- aws ec2 enable-serial-console-access --profile " $PROFILE " --region us-east-1 > /dev/null 2>&1 || true
109+ aws ec2 enable-serial-console-access --profile " $PROFILE " --region " $REGION " > /dev/null 2>&1 || true
110+
111+ # Root password for the serial-console emergency login. The serial-console
112+ # *connection* is authenticated by pushing an SSH key via ec2-instance-connect
113+ # (see the hint at the end of this script), but the getty on ttyS0 still
114+ # presents a normal login prompt, which requires a local password — so password
115+ # auth can't be dropped from this flow entirely. Instead of a fixed password
116+ # checked into git, generate a random one per launch and print it at the end.
117+ # It only grants access through the serial console, which itself requires AWS
118+ # credentials; it is not stored anywhere besides the instance's /etc/shadow.
119+ SERIAL_PW=$( openssl rand -hex 12)
101120
102121# User-data script: OOM diagnostics + serial console access
103122USER_DATA=$( cat << 'USERDATA '
104123#!/bin/bash
105124set -x
106125
107- # Set root password for serial console login
108- echo 'root:Cb3nch!s3rial#2026' | chpasswd
126+ # Set root password for serial console login (substituted at launch time;
127+ # random per launch, printed by launch-ec2.sh)
128+ echo 'root:__SERIAL_PW__' | chpasswd
109129
110130# Enable root login on serial console
111131mkdir -p /etc/systemd/system/serial-getty@ttyS0.service.d
@@ -142,10 +162,13 @@ sed -i 's/GRUB_CMDLINE_LINUX_DEFAULT=.*/GRUB_CMDLINE_LINUX_DEFAULT="console=tty0
142162update-grub 2>/dev/null || true
143163USERDATA
144164)
165+ # Inject the per-launch serial-console password (heredoc is quoted, so this is
166+ # the only substitution that happens in the user-data).
167+ USER_DATA=${USER_DATA// __SERIAL_PW__/ $SERIAL_PW }
145168
146169# Launch new instance
147170echo " Launching $INSTANCE_TYPE instance..."
148- INSTANCE_ID=$( aws ec2 run-instances --profile " $PROFILE " \
171+ INSTANCE_ID=$( aws ec2 run-instances --profile " $PROFILE " --region " $REGION " \
149172 --image-id " $AMI " \
150173 --instance-type " $INSTANCE_TYPE " \
151174 --key-name " $KEY_NAME " \
@@ -158,26 +181,42 @@ INSTANCE_ID=$(aws ec2 run-instances --profile "$PROFILE" \
158181
159182echo " Instance ID: $INSTANCE_ID "
160183echo " Waiting for instance to be running..."
161- aws ec2 wait instance-running --profile " $PROFILE " --instance-ids " $INSTANCE_ID "
184+ aws ec2 wait instance-running --profile " $PROFILE " --region " $REGION " -- instance-ids " $INSTANCE_ID "
162185
163- IP=$( aws ec2 describe-instances --profile " $PROFILE " \
186+ IP=$( aws ec2 describe-instances --profile " $PROFILE " --region " $REGION " \
164187 --instance-ids " $INSTANCE_ID " \
165188 --query ' Reservations[0].Instances[0].PublicIpAddress' --output text)
166189
167- echo " Instance ready : $IP "
190+ echo " Instance running : $IP "
168191echo " "
169192echo " ssh -i $KEY_FILE ubuntu@$IP "
170193echo " "
171194
172- # Wait for user-data to complete (cloud-init)
195+ # Wait for user-data to complete (cloud-init). Fail loudly if we never get
196+ # through — a half-initialized box must not be reported as ready.
173197echo " Waiting for cloud-init to finish..."
198+ CLOUD_INIT_OK=false
174199for i in $( seq 1 30) ; do
175200 if ssh -i " $KEY_FILE " -o StrictHostKeyChecking=no -o ConnectTimeout=5 " ubuntu@$IP " " cloud-init status --wait" 2> /dev/null; then
201+ CLOUD_INIT_OK=true
176202 break
177203 fi
178204 sleep 5
179205done
180206
207+ if ! $CLOUD_INIT_OK ; then
208+ echo " " >&2
209+ echo " ERROR: could not confirm cloud-init completion on $IP after 30 attempts." >&2
210+ echo " The instance ($INSTANCE_ID ) is still running — it was NOT terminated." >&2
211+ echo " Inspect it:" >&2
212+ echo " ssh -i $KEY_FILE ubuntu@$IP " >&2
213+ echo " ssh -i $KEY_FILE ubuntu@$IP 'cloud-init status --long'" >&2
214+ echo " Or tear it down:" >&2
215+ echo " $0 --terminate-only --name $NAME " >&2
216+ echo " Serial-console root password for this launch: $SERIAL_PW " >&2
217+ exit 1
218+ fi
219+
181220echo " "
182221echo " Instance ready. Next steps:"
183222echo " "
193232fi
194233echo " "
195234echo " Serial console (if SSH is down):"
196- echo " aws ec2-instance-connect send-serial-console-ssh-public-key --profile $PROFILE --instance-id $INSTANCE_ID --serial-port 0 --ssh-public-key file://${KEY_FILE% .pem} .pub --region us-east-1 "
197- echo " ssh -i $KEY_FILE $INSTANCE_ID .port0@serial-console.ec2-instance-connect.us-east-1 .aws"
198- echo " Login: root / Cb3nch!s3rial#2026 "
235+ echo " aws ec2-instance-connect send-serial-console-ssh-public-key --profile $PROFILE --instance-id $INSTANCE_ID --serial-port 0 --ssh-public-key file://${KEY_FILE% .pem} .pub --region $REGION "
236+ echo " ssh -i $KEY_FILE $INSTANCE_ID .port0@serial-console.ec2-instance-connect.$REGION .aws"
237+ echo " Login: root / $SERIAL_PW (random, generated for this launch only — note it down if you may need the serial console) "
0 commit comments