Compute cheat sheet
export AWS_ACCESS_KEY_ID=… # console → Access keys, or POST /v1/access-keysexport AWS_SECRET_ACCESS_KEY=…alias sc='aws --endpoint-url https://ec2.shelfcs.com --region hel1'# ~/.aws/config — so you stop typing the flags[profile shelf]region = hel1endpoint_url = https://ec2.shelfcs.comRegion is hel1. Zone is hel1-a.
Look around
Section titled “Look around”sc ec2 describe-instance-types # shapessc ec2 describe-images # operating systemssc ec2 describe-availability-zones # hel1-asc ec2 describe-instances # what you havesc ec2 describe-volumessc ec2 describe-security-groupscurl -s https://storefront.job-rss-processor.workers.dev/v1/catalog | jq # prices + live stocksc ec2 import-key-pair --key-name mykey \ --public-key-material fileb://~/.ssh/id_ed25519.pub
sc ec2 describe-key-pairssc ec2 delete-key-pair --key-name mykeyImport your own. create-key-pair returns the private key once and never again.
Launch
Section titled “Launch”sc ec2 run-instances \ --image-id ami-… \ --instance-type cd-standard-2-4 \ --key-name mykey \ --count 1 \ --client-token "$(uuidgen)" \ --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=web}]'sc ec2 run-instances … --user-data file://cloud-init.yaml # ≤16384 bytes decodedAlways send --client-token: it makes a retry safe.
Connect
Section titled “Connect”sc ec2 describe-instances --instance-ids i-… \ --query 'Reservations[].Instances[].[InstanceId,PrivateIpAddress,PublicIpAddress,State.Name]' \ --output table
ssh debian@<address> # NOT root@ — the user is set by the image| Image | User |
|---|---|
debian-12, debian-13 | debian |
ubuntu-22.04, ubuntu-24.04 | ubuntu |
rocky-9 | rocky |
alma-9 | almalinux |
fedora-42 | fedora |
opensuse-leap-15.6 | opensuse |
arch | arch |
talos-v1.13.9 | none — no SSH |
Cannot get in? The VNC console works before the network does.
Lifecycle
Section titled “Lifecycle”sc ec2 stop-instances --instance-ids i-… # keeps the disk and the addresssc ec2 start-instances --instance-ids i-…sc ec2 reboot-instances --instance-ids i-…sc ec2 terminate-instances --instance-ids i-… # final; root disk goes with itStorage
Section titled “Storage”sc ec2 create-volume --availability-zone hel1-a --size 20 --volume-type standardsc ec2 attach-volume --volume-id vol-… --instance-id i-… --device /dev/sdfsc ec2 modify-volume --volume-id vol-… --size 40 # grows only, never shrinkssc ec2 detach-volume --volume-id vol-… # unmount inside FIRSTsc ec2 delete-volume --volume-id vol-… # destroys the datasc ec2 create-snapshot --volume-id vol-… --description "before upgrade"--volume-type standard is required — the AWS default is gp2, which is
rejected. There is one type, on 7200 rpm SATA.
Inside the guest:
lsblkmkfs.ext4 /dev/vdbblkid /dev/vdbecho 'UUID=<uuid> /data ext4 defaults,nofail 0 2' >> /etc/fstab # nofail mattersmount -a
growpart /dev/vdb 1 && resize2fs /dev/vdb1 # after modify-volumeSecurity groups
Section titled “Security groups”sc ec2 create-security-group --group-name web --description "http"sc ec2 authorize-security-group-ingress --group-id sg-… \ --protocol tcp --port 443 --cidr 0.0.0.0/0sc ec2 revoke-security-group-ingress --group-id sg-… \ --protocol tcp --port 443 --cidr 0.0.0.0/0They are the only boundary inside your account — everything you run is on one
flat 10.200.0.0/24.
Terraform
Section titled “Terraform”provider "aws" { region = "hel1" skip_credentials_validation = true skip_requesting_account_id = true skip_metadata_api_check = true endpoints { ec2 = "https://ec2.shelfcs.com" }}
resource "aws_instance" "web" { ami = data.aws_ami.debian.id instance_type = "cd-standard-2-4" # write OUR name, not m5.large key_name = aws_key_pair.mine.key_name user_data = file("cloud-init.yaml")}
resource "aws_ebs_volume" "data" { availability_zone = "hel1-a" size = 20 type = "standard" # the gp2 default is rejected}Test a call without doing it
Section titled “Test a call without doing it”sc ec2 terminate-instances --instance-ids i-… --dry-runDryRunOperation = permitted. UnauthorizedOperation = not.
The four errors you will actually hit
Section titled “The four errors you will actually hit”| Error | Fix |
|---|---|
SignatureDoesNotMatch | Region. It is hel1 |
InsufficientInstanceCapacity | Box is full. Smaller shape, or wait — quota will not help |
InstanceLimitExceeded | Your quota. Starts at 4 vCPU / 8 GB |
InvalidParameterValue on type=gp3 | One volume type, standard |
Debugging a machine that booted but does not work
Section titled “Debugging a machine that booted but does not work”cloud-init status --longsudo journalctl -u cloud-final -bsudo cat /var/log/cloud-init-output.log
# configuration is delivered on a drive, not over the networkmount /dev/disk/by-label/config-2 /mnt && cat /mnt/openstack/latest/user_dataruncmd swallows failures — a running instance is not a configured one.