Last active
December 17, 2025 05:47
-
-
Save mjhong0708/c13c358a8eedabe433f8c64354657d89 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #cloud-config | |
| package_update: true | |
| package_upgrade: false | |
| packages: | |
| - ca-certificates | |
| - curl | |
| - gnupg | |
| - zip | |
| - unzip | |
| - xfsprogs | |
| - git | |
| - libssl-dev | |
| - pkg-config | |
| - build-essential | |
| - htop | |
| - tmux | |
| - jq | |
| - tree | |
| - iputils-ping | |
| - net-tools | |
| - bind9-dnsutils | |
| - nvtop | |
| write_files: | |
| # ======================= | |
| # Global config | |
| # ======================= | |
| - path: /etc/ec2-bootstrap.conf | |
| permissions: "0644" | |
| content: | | |
| REGION="ap-northeast-2" | |
| EIP_ALLOC_ID="eipalloc-00e5b714a2ebad156" | |
| VOLUME_ID="vol-0c11e130fcbe55de0" | |
| MOUNT_POINT="/data" | |
| # ======================= | |
| # AWS CLI v2 | |
| # ======================= | |
| - path: /usr/local/sbin/install-awscli-v2.sh | |
| permissions: "0755" | |
| content: | | |
| #!/bin/bash | |
| set -euo pipefail | |
| command -v aws >/dev/null 2>&1 && exit 0 | |
| curl -s https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip -o /tmp/awscliv2.zip | |
| unzip -q /tmp/awscliv2.zip -d /tmp | |
| /tmp/aws/install | |
| # ======================= | |
| # Docker | |
| # ======================= | |
| - path: /usr/local/sbin/install-docker.sh | |
| permissions: "0755" | |
| content: | | |
| #!/bin/bash | |
| set -euo pipefail | |
| command -v docker >/dev/null 2>&1 && exit 0 | |
| install -m 0755 -d /etc/apt/keyrings | |
| curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc | |
| chmod a+r /etc/apt/keyrings/docker.asc | |
| cat > /etc/apt/sources.list.d/docker.sources <<'EOF' | |
| Types: deb | |
| URIs: https://download.docker.com/linux/ubuntu | |
| Suites: noble | |
| Components: stable | |
| Signed-By: /etc/apt/keyrings/docker.asc | |
| EOF | |
| apt-get update | |
| apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin | |
| systemctl enable --now docker | |
| DEFAULT_USER=$(getent passwd 1000 | cut -d: -f1 || true) | |
| [ -n "$DEFAULT_USER" ] && usermod -aG docker "$DEFAULT_USER" | |
| runcmd: | |
| - [ bash, -lc, '/usr/local/sbin/install-awscli-v2.sh' ] | |
| - [ bash, -lc, '/usr/local/sbin/install-docker.sh' ] | |
| - [ bash, -lc, 'systemctl daemon-reload' ] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #cloud-config | |
| package_update: true | |
| package_upgrade: false | |
| write_files: | |
| # ======================= | |
| # Global config | |
| # ======================= | |
| - path: /etc/ec2-bootstrap.conf | |
| permissions: "0644" | |
| content: | | |
| REGION="ap-northeast-2" | |
| EIP_ALLOC_ID="eipalloc-00e5b714a2ebad156" | |
| VOLUME_ID="vol-0c11e130fcbe55de0" | |
| MOUNT_POINT="/data" | |
| # ======================= | |
| # Associate Elastic IP | |
| # ======================= | |
| - path: /usr/local/sbin/associate-eip.sh | |
| permissions: "0755" | |
| content: | | |
| #!/bin/bash | |
| set -euo pipefail | |
| source /etc/ec2-bootstrap.conf | |
| command -v aws >/dev/null 2>&1 || exit 1 | |
| TOKEN=$(curl -s -X PUT http://169.254.169.254/latest/api/token \ | |
| -H "X-aws-ec2-metadata-token-ttl-seconds: 21600") | |
| [ -n "$TOKEN" ] | |
| INSTANCE_ID=$(curl -s -H "X-aws-ec2-metadata-token: $TOKEN" \ | |
| http://169.254.169.254/latest/meta-data/instance-id) | |
| aws sts get-caller-identity --region "$REGION" | |
| aws ec2 associate-address \ | |
| --instance-id "$INSTANCE_ID" \ | |
| --allocation-id "$EIP_ALLOC_ID" \ | |
| --allow-reassociation \ | |
| --region "$REGION" | |
| # ======================= | |
| # EBS attach + mount | |
| # ======================= | |
| - path: /usr/local/sbin/ebs-attach-and-mount.sh | |
| permissions: "0755" | |
| content: | | |
| #!/bin/bash | |
| set -euo pipefail | |
| source /etc/ec2-bootstrap.conf | |
| command -v aws >/dev/null 2>&1 || exit 1 | |
| # ----------------------- | |
| # Metadata (IMDSv2) | |
| # ----------------------- | |
| TOKEN=$(curl -fsS -X PUT http://169.254.169.254/latest/api/token \ | |
| -H "X-aws-ec2-metadata-token-ttl-seconds: 21600") | |
| INSTANCE_ID=$(curl -fsS \ | |
| -H "X-aws-ec2-metadata-token: $TOKEN" \ | |
| http://169.254.169.254/latest/meta-data/instance-id) | |
| DEFAULT_USER=$(getent passwd 1000 | cut -d: -f1 || true) | |
| DEVICE="/dev/disk/by-id/nvme-Amazon_Elastic_Block_Store_${VOLUME_ID//-/}" | |
| STATE_FILE="/var/lib/ebs-${VOLUME_ID}.attached" | |
| # ----------------------- | |
| # One-time guard | |
| # ----------------------- | |
| if [ -f "$STATE_FILE" ]; then | |
| echo "EBS volume already processed, skipping attach" | |
| else | |
| # ----------------------- | |
| # Check attachment state | |
| # ----------------------- | |
| ATTACHED_INSTANCE=$(aws ec2 describe-volumes \ | |
| --volume-ids "$VOLUME_ID" \ | |
| --region "$REGION" \ | |
| --query 'Volumes[0].Attachments[0].InstanceId' \ | |
| --output text 2>/dev/null || true) | |
| if [ "$ATTACHED_INSTANCE" = "$INSTANCE_ID" ]; then | |
| echo "Volume already attached to this instance" | |
| elif [ "$ATTACHED_INSTANCE" = "None" ] || [ -z "$ATTACHED_INSTANCE" ]; then | |
| echo "Attaching volume $VOLUME_ID to $INSTANCE_ID" | |
| aws ec2 attach-volume \ | |
| --volume-id "$VOLUME_ID" \ | |
| --instance-id "$INSTANCE_ID" \ | |
| --device /dev/sdf \ | |
| --region "$REGION" | |
| else | |
| echo "ERROR: Volume is attached to another instance: $ATTACHED_INSTANCE" | |
| exit 1 | |
| fi | |
| # ----------------------- | |
| # Wait for NVMe device | |
| # ----------------------- | |
| echo "Waiting for device $DEVICE" | |
| for i in {1..60}; do | |
| [ -e "$DEVICE" ] && break | |
| sleep 1 | |
| done | |
| if [ ! -e "$DEVICE" ]; then | |
| echo "ERROR: Device $DEVICE did not appear" | |
| exit 1 | |
| fi | |
| touch "$STATE_FILE" | |
| fi | |
| # ----------------------- | |
| # Filesystem | |
| # ----------------------- | |
| mkdir -p "$MOUNT_POINT" | |
| if ! blkid "$DEVICE" >/dev/null 2>&1; then | |
| case "${FS_TYPE:-xfs}" in | |
| xfs) mkfs.xfs -f "$DEVICE" ;; | |
| ext4) mkfs.ext4 -F "$DEVICE" ;; | |
| *) mkfs.xfs -f "$DEVICE" ;; | |
| esac | |
| fi | |
| # ----------------------- | |
| # Mount | |
| # ----------------------- | |
| mountpoint -q "$MOUNT_POINT" || mount "$DEVICE" "$MOUNT_POINT" | |
| [ -n "$DEFAULT_USER" ] && chown "$DEFAULT_USER:$DEFAULT_USER" "$MOUNT_POINT" | |
| runcmd: | |
| - [ bash, -lc, '/usr/local/sbin/associate-eip.sh' ] | |
| - [ bash, -lc, '/usr/local/sbin/ebs-attach-and-mount.sh' ] | |
| - [ bash, -lc, 'systemctl daemon-reload' ] | |
| - | | |
| for i in {1..30}; do | |
| mountpoint -q /data && break | |
| sleep 1 | |
| done | |
| - | | |
| if systemctl is-active --quiet docker; then | |
| docker rm -f dev-container >/dev/null 2>&1 || true | |
| docker pull mjhong0708/dev-container:latest | |
| fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment