Automated setup of a cheap AWS EC2 instance running Claude Code with a web UI.
Prompt:
create the cheapest instance on aws with 8gb of ram (arm is okay) and use ssh (razer.pem) to get there and install claude there, copy the same config as you use now and make claude available via web
| Property | Value |
|---|---|
| Instance Type | t4g.medium (4GB RAM, ARM64) |
| AMI | Ubuntu 22.04 LTS (ARM64) |
| Region | eu-west-1 |
ssh -i ~/.ssh/razer.pem ubuntu@public-dsn- Node.js v24 - JavaScript runtime
- Claude Code CLI -
@anthropic-ai/claude-code(v2.0.76) - Claude Code UI - Web interface by siteboon (v1.12.0) on port 8080
- ttyd - Web terminal (v1.7.7) on port 8081 with password auth
- Build tools - cmake, gcc, etc. for building dependencies
Use the same config (location: ~/.claude/settings.json) on the instance.
Both services run as systemd:
# Claude Web UI (port 8080)
sudo systemctl status claude-web
sudo systemctl restart claude-web
journalctl -u claude-web -f
# Web Terminal (port 8081)
sudo systemctl status ttyd
sudo systemctl restart ttyd
journalctl -u ttyd -fWhen you stop the instance, the public IP changes on restart. To start and get the new IP:
# Start the instance
aws ec2 start-instances --instance-ids i-0856daa3bc7c14cb5
# Wait for it to be running, then get the new public IP
aws ec2 describe-instances --instance-ids i-0856daa3bc7c14cb5 \
--query "Reservations[0].Instances[0].PublicIpAddress" --output textThen update secret.md with the new IP and access via:
- Claude Web UI:
http://<NEW-IP>:8080 - Web Terminal:
http://<NEW-IP>:8081 - SSH:
ssh -i ~/.ssh/razer.pem ubuntu@<NEW-IP>
# Stop instance (stops billing)
aws ec2 stop-instances --instance-ids i-0856daa3bc7c14cb5
# Start instance
aws ec2 start-instances --instance-ids i-0856daa3bc7c14cb5
# Terminate (delete instance)
aws ec2 terminate-instances --instance-ids i-0856daa3bc7c14cb5
# Check instance state
aws ec2 describe-instances --instance-ids i-0856daa3bc7c14cb5 \
--query "Reservations[0].Instances[0].State.Name" --output textSecurity Group: claude-web-sg (sg-0b5dcc5f6e6674dc7)
| Port | Service | Access |
|---|---|---|
| 22 | SSH | 0.0.0.0/0 |
| 8080 | Claude Web UI | 0.0.0.0/0 |
| 8081 | Web Terminal (ttyd) | 0.0.0.0/0 (password protected) |
- On-demand: ~$15-20/month (t4g.medium in eu-west-1)
- Spot: ~$5-8/month (if switched to spot instances)
# 1. Find latest Ubuntu ARM64 AMI
aws ec2 describe-images \
--owners 099720109477 \
--filters "Name=name,Values=ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-arm64-server-*" "Name=state,Values=available" \
--query "sort_by(Images, &CreationDate)[-1].ImageId" \
--output text
# 2. Create security group
aws ec2 create-security-group --group-name claude-web-sg --description "Security group for Claude web access"
# 3. Add rules
aws ec2 authorize-security-group-ingress --group-name claude-web-sg --protocol tcp --port 22 --cidr 0.0.0.0/0
aws ec2 authorize-security-group-ingress --group-name claude-web-sg --protocol tcp --port 8080 --cidr 0.0.0.0/0
aws ec2 authorize-security-group-ingress --group-name claude-web-sg --protocol tcp --port 8081 --cidr 0.0.0.0/0
# 4. Launch instance
aws ec2 run-instances \
--image-id ami-01b277d8dbe41e3de \
--instance-type t4g.medium \
--key-name razer \
--security-groups claude-web-sg \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=claude-web}]'
# 5. On instance (after SSH):
# Install Node.js
curl -fsSL https://deb.nodesource.com/setup_lts.x | sudo -S bash -
sudo apt-get install -y nodejs
# Install Claude Code
sudo npm install -g @anthropic-ai/claude-code
# Clone and setup web UI
git clone https://github.com/siteboon/claudecodeui.git
cd claudecodeui
npm install
npm run build
# Create .env
cat > .env << EOF
ANTHROPIC_AUTH_TOKEN=<token>
ANTHROPIC_BASE_URL=https://api.z.ai/api/anthropic
HOST=0.0.0.0
PORT=8080
EOF
# Create systemd service
sudo tee /etc/systemd/system/claude-web.service << EOF
[Unit]
Description=Claude Web UI
After=network.target
[Service]
Type=simple
User=ubuntu
WorkingDirectory=/home/ubuntu/claudecodeui
ExecStart=/usr/bin/node server/index.js
Restart=always
RestartSec=3
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable claude-web
sudo systemctl start claude-web
# Install ttyd (web terminal)
sudo apt-get install -y build-essential cmake git libjson-c-dev libwebsockets-dev
cd /tmp
git clone https://github.com/tsl0922/ttyd.git
cd ttyd
mkdir build && cd build
cmake ..
make -j$(nproc)
sudo make install
# Create ttyd systemd service
sudo tee /etc/systemd/system/ttyd.service << EOF
[Unit]
Description=Ttyd Web Terminal
After=network.target
[Service]
Type=simple
User=ubuntu
ExecStart=/usr/local/bin/ttyd -p 8081 -i 0.0.0.0 -c admin:claude123 -W bash
Restart=always
RestartSec=3
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable ttyd
sudo systemctl start ttyd