技術(tech)

Building Automated AWS EC2 Spot Instance Low-Cost Development Environment with GitHub Actions

Meta Description: Learn how to build a cost-effective development environment using GitHub Actions and AWS EC2 Spot Instances for only $3-4/month. Achieve 80% cost reduction with automated infrastructure control and detailed implementation guide.

Introduction

Learn how to build a cost-effective development environment using GitHub Actions and AWS EC2 Spot Instances for just $3-4/month, achieving 80% cost reduction.

  • Reading time: approximately 6 minutes
  • Tech stack: GitHub Actions, AWS EC2, Spot Instance
  • Cost reduction: 80% (from $15-20/month to $3-4/month)

Target Audience

  • Those with basic knowledge of AWS EC2 and GitHub Actions
  • Those interested in cloud development environment cost optimization

Technical Background and Solution

Traditional development environments run EC2 24/7, causing excessive costs for actual usage time. AWS EC2 Spot Instances offer up to 90% cost reduction but may be terminated unexpectedly. By leveraging GitHub Actions for complete automation, we can use this characteristic for temporary development environments.

Operation Challenges

  • Fixed costs: t3.micro costs $15-20/month even for minimal use
  • Manual operations: Tedious AWS Console operations
  • Environment recovery: Complex setup after Spot Instance interruptions

System Architecture and Key Features

.github/workflows/ec2-control.yml  # Main workflow
user-data.sh                       # EC2 initialization script

AWS Infrastructure
├── EC2 Spot Instance (t3.micro)
├── EBS Volume (encrypted)
└── Security Group

Key Features

  1. One-click operation: GitHub Actions UI for EC2 control
  2. Data persistence: EBS volumes retain data across instances
  3. Complete automation: Environment setup to VPN configuration

Implementation Steps

Prerequisites

1. AWS Environment Setup

Create required AWS resources:

# Create VPC with "main" tag
VPC_ID=$(aws ec2 create-vpc --cidr-block 10.0.0.0/16 --query 'Vpc.VpcId' --output text)
aws ec2 create-tags --resources $VPC_ID --tags Key=Name,Value=main

# Create public subnet with "Public" tag
SUBNET_ID=$(aws ec2 create-subnet --vpc-id $VPC_ID --cidr-block 10.0.1.0/24 --query 'Subnet.SubnetId' --output text)
aws ec2 create-tags --resources $SUBNET_ID --tags Key=Name,Value=Public

# Create security group
SG_ID=$(aws ec2 create-security-group --group-name claude-code-smartphone-sg --description "Claude Code dev env" --vpc-id $VPC_ID --query 'GroupId' --output text)
aws ec2 create-tags --resources $SG_ID --tags Key=Name,Value=claude-code-smartphone-sg

# Setup OIDC Provider (for GitHub Actions)
aws iam create-open-id-connect-provider --url https://token.actions.githubusercontent.com --thumbprint-list YOUR_THUMBPRINT --client-id-list sts.amazonaws.com

2. GitHub Secrets Setup

AWS_ROLE_ARN: arn:aws:iam::YOUR_ACCOUNT_ID:role/GitHubActionsEC2Role
GIT_TOKEN: ghp_YOUR_GITHUB_TOKEN
TAILSCALE_AUTH_KEY: tskey-auth-YOUR_KEY
GIT_USERNAME: your-github-username
GIT_EMAIL: your-email@example.com

GitHub Actions Workflow

Basic workflow configuration:

name: EC2 Instance Control

on:
  workflow_dispatch:
    inputs:
      action:
        description: 'EC2 Action'
        required: true
        default: 'status'
        type: choice
        options: [status, start, stop]

env:
  AWS_REGION: ap-northeast-1
  INSTANCE_NAME: claude-code-smartphone-server
  INSTANCE_TYPE: t3.micro
  SPOT_PRICE_MAX: "0.005"

Stop/Start/Status Implementation

Core control logic:

# Status check
get_instance_status() {
  aws ec2 describe-instances \
    --filters "Name=tag:Name,Values=$INSTANCE_NAME" \
    --query 'Reservations[0].Instances[0].State.Name' \
    --output text
}

# Create Spot Instance
create_spot_instance() {
  # Auto-detect VPC/Subnet
  VPC_ID=$(aws ec2 describe-vpcs --filters "Name=tag:Name,Values=main" --query 'Vpcs[0].VpcId' --output text)
  SUBNET_ID=$(aws ec2 describe-subnets --filters "Name=tag:Name,Values=Public" --query 'Subnets[0].SubnetId' --output text)

  # Get latest Ubuntu AMI
  AMI_ID=$(aws ec2 describe-images --owners 099720109477 \
    --filters "Name=name,Values=ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*" \
    --query 'Images | sort_by(@, &CreationDate) | [-1].ImageId' --output text)

  # Request Spot Instance
  aws ec2 request-spot-instances \
    --spot-price "$SPOT_PRICE_MAX" \
    --instance-count 1 \
    --type "one-time" \
    --launch-specification "{
      \"ImageId\": \"$AMI_ID\",
      \"InstanceType\": \"$INSTANCE_TYPE\",
      \"UserData\": \"$(base64 -i user-data.sh)\"}"
}

Data Persistence Configuration

EBS volume configuration for data retention:

"BlockDeviceMappings": [{
  "DeviceName": "/dev/sda1",
  "Ebs": {
    "VolumeSize": 20,
    "VolumeType": "gp3",
    "DeleteOnTermination": false,  // Important: Retain on instance deletion
    "Encrypted": true
  }
}]

Automated Environment Setup (user-data.sh)

Automatic setup at instance startup:

#!/bin/bash
set -euo pipefail

# System update
sudo apt-get update && sudo apt-get upgrade -y

# Git configuration
git config --global user.name "$git_username"
git config --global user.email "$git_email"
echo "https://$git_username:$github_token@github.com" > ~/.git-credentials
chmod 600 ~/.git-credentials
git config --global credential.helper store

# Tailscale VPN
curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up --authkey="$tailscale_auth_key" --ssh

# Development tools
curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker ubuntu
curl -fsSL https://claude.ai/install.sh | sh

Cost Reduction Results and Operational Impact

After 3 months of operation:

Cost Comparison

# Previous (on-demand 24/7)
t3.micro: $15/month + EBS: $2/month = ~$17-20/month

# After (Spot Instance + 4 hours/day)
Spot: $0.4/month + EBS: $2/month + Transfer: $1/month = ~$3-4/month

Reduction rate: Achieved 80% cost reduction

Operational Efficiency Improvement

  • Startup time: 5-10 minutes → 2-3 minutes
  • Operations: 10+ clicks → 1 click
  • VPN setup: Manual → Automatic

Summary

By combining GitHub Actions with EC2 Spot Instances, we achieved a flexible development environment at 1/5 the cost of traditional approaches.

Success Points

  • Complete automation: Environment setup to VPN configuration
  • Cost optimization: Spot Instance characteristics match development environment needs
  • Data protection: EBS volumes persist data after instance termination

If you’re struggling with cloud development environment costs, consider this approach.

References