Skip to content

🧠 Lightweight Bash tool to create, connect, and manage AWS EC2 development environments directly from your Mac

Notifications You must be signed in to change notification settings

gracaninja/ec2-dev-helper

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

2 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

🧠 EC2 Dev Machine Helper

A lightweight Bash tool to create, connect, and manage AWS EC2 development environments directly from your Mac.
Perfect for Cursor, VS Code Remote-SSH, or any cloud-based development workflow.

This script automates EC2 creation, locale configuration, and connectivity (via Mosh + SSH) β€” letting you spin up a full dev server in seconds and tear it down when done.


🧭 Architecture Overview

         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
         β”‚          Your Mac            β”‚
         β”‚ (Cursor / VS Code / CLI)     β”‚
         β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                        β”‚ SSH + Mosh
                        β–Ό
         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
         β”‚     EC2 Dev Instance         β”‚
         β”‚ Ubuntu 24.04 (x86/ARM)       β”‚
         β”‚ β”œβ”€ Python + uv               β”‚
         β”‚ β”œβ”€ Node 20 LTS               β”‚
         β”‚ β”œβ”€ Claude Code (AI agent)    β”‚
         β”‚ └─ tmux / mosh / git / htop  β”‚
         β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                        β”‚
                        β–Ό
         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
         β”‚         AWS Cloud            β”‚
         β”‚ EC2 + Elastic IP + SG rules  β”‚
         β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Your Mac runs the control script (ec2-dev.sh) which:

  1. Creates and configures the EC2 instance
  2. Opens required ports (SSH 22, Mosh UDP 60000–61000)
  3. Bootstraps tools and UTF-8 locales
  4. Connects you via mosh (auto-reconnects, fast typing latency)

🧰 Mac & AWS Setup (first-time developers)

Follow these steps once β€” after that, the script handles everything.

1️⃣ Install prerequisites on your Mac

# Homebrew (if not already installed)
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

# CLI tools
brew install awscli mosh jq

2️⃣ Configure your AWS credentials

Ask your IT manager to create an IAM user for you (e.g. dev-yourname) with EC2 permissions.
They’ll give you:

  • Access Key ID (starts with AKIA…)
  • Secret Access Key

Then configure AWS CLI:

aws configure

Enter:

AWS Access Key ID [None]: AKIA...
AWS Secret Access Key [None]: your-secret
Default region name [None]: eu-west-1
Default output format [None]: json

3️⃣ Create or import your SSH key pair

Either import your local public key:

aws ec2 import-key-pair   --region eu-west-1   --key-name mac-key   --public-key-material fileb://$HOME/.ssh/id_ed25519.pub

Or generate one from AWS:

aws ec2 create-key-pair   --region eu-west-1   --key-name mac-key   --query 'KeyMaterial' --output text > ~/.ssh/mac-key.pem
chmod 600 ~/.ssh/mac-key.pem

4️⃣ Verify everything works

aws sts get-caller-identity
aws ec2 describe-key-pairs --region eu-west-1

πŸš€ Quick Usage

1️⃣ Create your Free-Tier test machine

# x86 (Intel) Free Tier
INSTANCE_TYPE=t3.micro ./ec2-dev.sh create

# or ARM (Graviton) Free Tier
ARCH=arm64 INSTANCE_TYPE=t4g.micro ./ec2-dev.sh create

2️⃣ Bootstrap the environment

./ec2-dev.sh bootstrap

This installs:

  • mosh, tmux, htop, uv, git, node 20
  • claude (Claude Code CLI)
  • Sets UTF-8 locales for Mosh

3️⃣ Configure your API keys (one-time)

# Copy the example file
cp env.example .env

# Edit with your actual keys
nano .env

# Secure it
chmod 600 .env

# Transfer to remote instance
./ec2-dev.sh setup-secrets

4️⃣ Connect

./ec2-dev.sh connect

πŸ’‘ Install Mosh locally: brew install mosh


βš™οΈ Common Commands

Action Command Notes
Create instance ./ec2-dev.sh create Auto-creates SG + optional Elastic IP
Check status ./ec2-dev.sh status Shows ID, state, public IP
Connect (Mosh/SSH) ./ec2-dev.sh connect Uses alias or current IP
Bootstrap ./ec2-dev.sh bootstrap Installs mosh/tmux/uv/node/claude
Setup secrets ./ec2-dev.sh setup-secrets Transfer API keys from .env (secure)
Stop instance ./ec2-dev.sh stop Suspends compute billing
Start instance ./ec2-dev.sh start Resumes a stopped VM
Terminate completely ./ec2-dev.sh terminate Deletes instance, EIP, and SG
Allocate Elastic IP ./ec2-dev.sh eip-allocate Creates stable IP
Associate Elastic IP ./ec2-dev.sh eip-associate Attaches to instance
Release Elastic IP ./ec2-dev.sh eip-release Frees unused IP
Get public IP ./ec2-dev.sh ip Prints IP
Get instance ID ./ec2-dev.sh id Prints instance ID

🧹 Terminate a Machine Completely

When you're done testing (to avoid charges):

./ec2-dev.sh terminate

This single command will:

  • Release the Elastic IP (if allocated)
  • Terminate the EC2 instance
  • Delete the security group

The instance will vanish from AWS after 1–2 minutes.


🧩 Moving from Free Tier β†’ Paid Instance

When ready for a faster dev box:

Type Arch vCPU / RAM Monthly (approx.) Command
t4g.large ARM 2 / 8 GB €45 ARCH=arm64 INSTANCE_TYPE=t4g.large ./ec2-dev.sh create
m7i-flex.large x86 2 / 8 GB €75 INSTANCE_TYPE=m7i-flex.large ./ec2-dev.sh create
m7i-flex.xlarge x86 4 / 16 GB €150 INSTANCE_TYPE=m7i-flex.xlarge ./ec2-dev.sh create

Then:

./ec2-dev.sh bootstrap
./ec2-dev.sh connect

πŸ’» Using Cursor with Your EC2 Dev Instance

Cursor works seamlessly with remote EC2 instances via SSH. Here's the complete guide to get you coding in the cloud.

πŸ”§ Initial Setup

1️⃣ Create and bootstrap your EC2 instance

# Create a dev instance (Free Tier or larger)
INSTANCE_TYPE=t3.micro ./ec2-dev.sh create

# Install essential development tools
./ec2-dev.sh bootstrap

# Check it's running
./ec2-dev.sh status

2️⃣ Configure SSH access

Get your instance's public IP:

./ec2-dev.sh ip

Create or edit your SSH config:

nano ~/.ssh/config

Add this entry (replace <YOUR_IP> with your actual IP or Elastic IP):

Host heyl
  HostName <YOUR_IP>
  User ubuntu
  IdentityFile ~/.ssh/id_ed25519   # or ~/.ssh/mac-key.pem
  ServerAliveInterval 60
  ServerAliveCountMax 5
  TCPKeepAlive yes

πŸ’‘ Pro Tip: Use an Elastic IP so this config never changes:

./ec2-dev.sh eip-allocate
./ec2-dev.sh eip-associate

3️⃣ Test the SSH connection

ssh heyl

If it connects successfully, type exit to return to your Mac.


πŸš€ Connecting Cursor

πŸ“¦ First-Time Setup: When you connect for the first time, Cursor will prompt you to install the Cursor Remote - SSH extension. Click Install - this is required for remote development and is a one-time setup.

Method 1: Using the Command Palette (Recommended)

  1. Open Cursor
  2. Press Cmd+Shift+P (Mac) or Ctrl+Shift+P (Windows/Linux)
  3. Type: Remote-SSH: Connect to Host…
  4. Select your host: heyl
  5. If prompted, install the Cursor Remote - SSH extension (first time only)
  6. Cursor will then:
    • Install the Cursor Server on your EC2 instance (first time only)
    • Connect your local Cursor UI to the remote environment
    • Open a remote workspace

Method 2: Using the Remote Explorer

  1. Click the Remote Explorer icon in the left sidebar (looks like a computer monitor)
  2. Under "SSH Targets", find heyl
  3. Click the β†’ (connect) icon
  4. Cursor connects and opens a new window

πŸ“‚ Opening Your Project

Once connected to your EC2 instance:

  1. Open a remote folder:

    • File β†’ Open Folder…
    • Navigate to your project (e.g., /home/ubuntu/my-project)
    • Click OK
  2. Clone a repository:

    # In Cursor's integrated terminal
    cd ~
    git clone https://github.com/yourname/your-repo.git
    cd your-repo
  3. Reopen the folder:

    • File β†’ Open Folder… β†’ Select the cloned repo

🎯 Best Practices for Remote Development

βœ… Use tmux for Persistent Sessions

Even if your Cursor connection drops, tmux keeps your work running:

# Start a named session
tmux new -s dev

# Run long-running processes (servers, builds, etc.)
npm run dev
# or
uv run python main.py

# Detach: Ctrl+B, then D
# Reattach later: tmux attach -t dev

βœ… Optimize File Watching

For large projects, disable file watchers to save resources:

In Cursor settings (Cmd+,):

{
  "files.watcherExclude": {
    "**/.git/objects/**": true,
    "**/node_modules/**": true,
    "**/.venv/**": true,
    "**/dist/**": true,
    "**/build/**": true
  }
}

βœ… Enable Auto-Save

To prevent losing work due to connection issues:

{
  "files.autoSave": "afterDelay",
  "files.autoSaveDelay": 1000
}

βœ… Use Remote Extensions

Install extensions on the remote instance (not locally). Cursor will prompt you:

  • Click Install in SSH: heyl when installing extensions
  • Your extensions install directly on the EC2 instance

πŸ”„ Typical Development Workflow

# Morning: Start your instance
./ec2-dev.sh start

# Connect with Cursor
# (Use Command Palette β†’ Remote-SSH: Connect to Host β†’ heyl)

# Inside Cursor's terminal:
tmux attach -t dev || tmux new -s dev

# Start your dev server
cd ~/my-project
npm run dev
# or
uv run uvicorn app.main:app --reload

# Code all day with Claude/AI assistance...

# Evening: Stop the instance to save costs
./ec2-dev.sh stop

πŸ› οΈ Troubleshooting

Connection Hangs or Times Out

# Check instance is running
./ec2-dev.sh status

# Test SSH manually
ssh -v heyl

# If stopped, start it
./ec2-dev.sh start

"Could not establish connection"

  1. Verify security group allows SSH (port 22):

    aws ec2 describe-security-groups \
      --region eu-west-1 \
      --filters "Name=group-name,Values=heyl-dev-sg"
  2. Check your IP didn't change (if not using Elastic IP):

    ./ec2-dev.sh ip
    # Update ~/.ssh/config with new IP

Cursor Server Installation Fails

# SSH in and check disk space
ssh heyl
df -h

# If low on space, clean up:
sudo apt clean
docker system prune -af  # if using Docker

Slow Performance

  1. Upgrade instance type:

    ./ec2-dev.sh stop
    # Manually change instance type in AWS Console
    ./ec2-dev.sh start
  2. Or create a larger instance:

    ./ec2-dev.sh terminate
    INSTANCE_TYPE=t4g.large ./ec2-dev.sh create
    ./ec2-dev.sh bootstrap

🌟 Advanced Tips

Port Forwarding

Forward remote ports to your Mac (e.g., for web apps):

Add to ~/.ssh/config:

Host heyl
  HostName <YOUR_IP>
  User ubuntu
  IdentityFile ~/.ssh/id_ed25519
  ServerAliveInterval 60
  LocalForward 3000 localhost:3000    # Forward port 3000
  LocalForward 8000 localhost:8000    # Forward port 8000

Now http://localhost:3000 on your Mac shows your EC2 server!

Multi-Instance Workflow

Manage multiple projects with different configs:

# Project 1: Small dev box
EC2_NAME_TAG=project1 INSTANCE_TYPE=t3.micro ./ec2-dev.sh create

# Project 2: ML workload
EC2_NAME_TAG=project2 INSTANCE_TYPE=g4dn.xlarge ./ec2-dev.sh create

Add separate SSH configs for each:

Host project1
  HostName <IP_1>
  User ubuntu

Host project2
  HostName <IP_2>
  User ubuntu

Using with GitHub Copilot / Cursor AI

Both work normally on remote instances! The AI features run on your Mac, but file access is over SSH.


πŸ“Š Cost Optimization

  • Stop instances when not coding (evenings/weekends):

    ./ec2-dev.sh stop  # Pays only for storage (~$0.08/day for 60GB)
  • Use Free Tier for learning (750 hours/month):

    INSTANCE_TYPE=t3.micro ./ec2-dev.sh create
  • Terminate test instances when done:

    ./ec2-dev.sh terminate

πŸ’‘ Quick Reference: Once set up, your daily workflow is simply:
./ec2-dev.sh start β†’ Open Cursor β†’ Connect to heyl β†’ Code β†’ ./ec2-dev.sh stop


πŸ€– Using Claude Code (AI Agent)

Your EC2 instance comes with Claude Code pre-installed - an AI-powered coding agent that can help with development tasks.

πŸ”‘ Setup Your API Key

After bootstrapping, you need to configure your Anthropic API key. Two secure methods:

Method 1: Automated Setup (Recommended)

Create a local .env file with your secrets (this file stays on your Mac):

# Create .env with your API keys
cat > .env <<EOF
ANTHROPIC_API_KEY=sk-ant-your-key-here
EOF

# Secure the file (important!)
chmod 600 .env

# Add to .gitignore (prevent accidental commits)
echo ".env" >> .gitignore

# Transfer secrets securely to your EC2 instance
./ec2-dev.sh setup-secrets

This command:

  • βœ… Reads your local .env file
  • βœ… Transfers only API keys via encrypted SSH
  • βœ… Never stores secrets in cloud-init or AWS metadata
  • βœ… Automatically configures ~/.profile on the remote instance

Method 2: Manual Setup

# SSH to your instance
ssh ubuntu@$(./ec2-dev.sh ip)

# Set your API key (get one at https://console.anthropic.com/)
echo 'export ANTHROPIC_API_KEY=sk-ant-...' >> ~/.profile
source ~/.profile

# Verify installation
claude --version

πŸ”’ Security Best Practices

βœ… DO:

  • Store API keys in local .env with chmod 600
  • Add .env to .gitignore
  • Use setup-secrets to transfer keys securely
  • Keep your local .env backed up (encrypted)

❌ DON'T:

  • Never commit .env to git
  • Never put API keys in cloud-init user-data
  • Never store secrets in AWS EC2 metadata
  • Don't share your .env file

πŸ” Supported Keys in setup-secrets

The setup-secrets command safely transfers these environment variables:

  • ANTHROPIC_API_KEY (Claude Code)
  • OPENAI_API_KEY (OpenAI APIs)
  • GITHUB_TOKEN (GitHub API access)
  • HUGGING_FACE_TOKEN (HuggingFace models)

Other variables in your .env are ignored for safety (like AWS credentials).

πŸ’‘ Using Claude Code

Claude Code can help with various development tasks:

# Get help
claude --help

# Ask Claude to create files
claude "Create a FastAPI hello world app in main.py"

# Ask Claude to debug code
claude "Why is my app.py throwing a 500 error?"

# Ask Claude to refactor
claude "Refactor database.py to use async/await"

# Ask Claude to write tests
claude "Write pytest tests for my user authentication module"

πŸ”„ Working with Cursor + Claude Code

You can use both tools together:

  • Cursor AI: For interactive coding in your IDE with inline suggestions
  • Claude Code CLI: For automated tasks, scripts, and batch operations

Example workflow:

# In terminal: Use Claude Code for setup
claude "Create a new FastAPI project with poetry"

# In Cursor IDE: Continue development with AI assistance
# Code with Cursor's inline AI help...

# In terminal: Use Claude Code for testing
claude "Run all tests and fix any failures"

πŸ’° API Key Best Practices

  1. Never commit your API key to git
  2. Set it in ~/.profile (already done by bootstrap)
  3. Monitor usage at https://console.anthropic.com/
  4. Consider a separate key for dev vs production

🧠 Everyday Usage

# One-time setup
INSTANCE_TYPE=t3.micro ./ec2-dev.sh create
./ec2-dev.sh bootstrap

# Create .env with your API keys (one-time)
echo 'ANTHROPIC_API_KEY=sk-ant-...' > .env
chmod 600 .env
echo '.env' >> .gitignore

# Transfer secrets to remote instance
./ec2-dev.sh setup-secrets

# Connect (via mosh)
./ec2-dev.sh connect

# Work inside tmux for persistent sessions
tmux new -s dev
# detach: Ctrl+B then D

# Stop when done
./ec2-dev.sh stop

# Restart next day
./ec2-dev.sh start
# Re-run setup-secrets if you rotated keys
./ec2-dev.sh setup-secrets

# Terminate when finished
./ec2-dev.sh terminate

βš™οΈ Requirements

  • macOS or Linux with:
    • AWS CLI (brew install awscli)
    • Homebrew (brew install mosh jq)
    • SSH key pair (mac-key or equivalent)
  • IAM user with EC2 permissions
  • AWS region set (default: eu-west-1)

🧱 Notes

  • Security group opens SSH (22) and Mosh UDP (60000–61000).
  • Locale is pre-set to en_US.UTF-8 for Mosh compatibility.
  • Cloud-init automatically installs essential dev tooling.
  • Elastic IP is optional but recommended for stable connections.
  • All instances are Ubuntu 24.04 LTS (Canonical official AMIs via SSM).

🧩 Example Workflow (Summary)

# Free Tier setup
INSTANCE_TYPE=t3.micro ./ec2-dev.sh create
./ec2-dev.sh bootstrap

# Configure secrets (one-time)
echo 'ANTHROPIC_API_KEY=sk-ant-...' > .env && chmod 600 .env
./ec2-dev.sh setup-secrets

# Connect and work
./ec2-dev.sh connect

# Work, test, build
# ...

# Stop when idle
./ec2-dev.sh stop

# Terminate after testing
./ec2-dev.sh terminate

Built for rapid, clean, and reproducible EC2 dev environments.

About

🧠 Lightweight Bash tool to create, connect, and manage AWS EC2 development environments directly from your Mac

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages