Deploy on AWS via the CLI
Programmatic, reproducible HailBytes SAT deployment using the AWS CLI. Designed for CI pipelines, agents, and infrastructure-as-code workflows.
Overview
HailBytes SAT publishes a hardened AMI to the AWS Marketplace (built nightly via Packer on Ubuntu 24.04). This tutorial shows how to subscribe, locate the AMI, and launch an instance entirely from the AWS CLI, with no console clicks. If you'd rather use the console, see the marketplace UI tutorial.
Prerequisites
- AWS CLI v2 configured with credentials that can call
ec2:*andaws-marketplace:Subscribe - An AWS account already subscribed to HailBytes SAT in the AWS Marketplace (one-click; required before
RunInstancessucceeds) - A VPC and public subnet, or use the default VPC
- An EC2 key pair name for SSH
Step 1: Find the Latest AMI ID
HailBytes publishes the AMI ID through SSM Parameter Store so it can be queried without hard-coding:
AMI_ID=$(aws ssm get-parameter \
--region us-east-1 \
--name /aws/service/marketplace/prod-hailbytes-sat/latest \
--query 'Parameter.Value' \
--output text)
echo "$AMI_ID"Or query the Marketplace catalog directly by owner alias and name pattern:
aws ec2 describe-images \
--region us-east-1 \
--owners aws-marketplace \
--filters "Name=name,Values=hailbytes-sat-*" \
--query 'sort_by(Images, &CreationDate)[-1].[ImageId,Name,CreationDate]' \
--output textStep 2: Create a Security Group
HailBytes SAT serves the admin UI on 3333, the phishing landing pages on 80/443, and SSH on 22. Restrict admin and SSH to your IP range.
VPC_ID=$(aws ec2 describe-vpcs --filters Name=isDefault,Values=true \
--query 'Vpcs[0].VpcId' --output text)
SG_ID=$(aws ec2 create-security-group \
--group-name hailbytes-sat-sg \
--description "HailBytes SAT inbound" \
--vpc-id "$VPC_ID" --query 'GroupId' --output text)
MY_IP=$(curl -s https://checkip.amazonaws.com)/32
# Admin UI & SSH locked to your IP
aws ec2 authorize-security-group-ingress --group-id "$SG_ID" \
--protocol tcp --port 3333 --cidr "$MY_IP"
aws ec2 authorize-security-group-ingress --group-id "$SG_ID" \
--protocol tcp --port 22 --cidr "$MY_IP"
# Phishing landing pages open to the world
aws ec2 authorize-security-group-ingress --group-id "$SG_ID" \
--protocol tcp --port 80 --cidr 0.0.0.0/0
aws ec2 authorize-security-group-ingress --group-id "$SG_ID" \
--protocol tcp --port 443 --cidr 0.0.0.0/0Step 3: Launch the Instance
Use t3.medium for trials, m6i.large for production. Pass an optional admin email through user data so first-boot emails the bootstrap credentials.
cat > user-data.yaml <<'EOF'
#cloud-config
hailbytes_sat:
admin_email: admin@your-domain.com
hostname: sat.your-domain.com
EOF
INSTANCE_ID=$(aws ec2 run-instances \
--image-id "$AMI_ID" \
--instance-type m6i.large \
--key-name YOUR_KEY_PAIR \
--security-group-ids "$SG_ID" \
--block-device-mappings 'DeviceName=/dev/sda1,Ebs={VolumeSize=50,VolumeType=gp3,Encrypted=true}' \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=hailbytes-sat},{Key=Product,Value=HailBytes-SAT}]' \
--user-data file://user-data.yaml \
--query 'Instances[0].InstanceId' --output text)
echo "Launched: $INSTANCE_ID"
aws ec2 wait instance-status-ok --instance-ids "$INSTANCE_ID"
PUBLIC_DNS=$(aws ec2 describe-instances --instance-ids "$INSTANCE_ID" \
--query 'Reservations[0].Instances[0].PublicDnsName' --output text)
echo "Open https://$PUBLIC_DNS:3333/"Step 4: First-Boot Output
First boot takes 2–3 minutes. The bootstrap admin password is written to /var/log/hailbytes-sat-first-boot.log. Pull it via SSH or the console:
aws ec2 get-console-output --instance-id "$INSTANCE_ID" \
--query 'Output' --output text | grep -A1 "ADMIN PASSWORD"
# Or via SSH:
ssh -i ~/.ssh/YOUR_KEY.pem ubuntu@$PUBLIC_DNS \
'sudo cat /var/log/hailbytes-sat-first-boot.log'Step 5: Wire DNS & TLS
Point an A record at the instance's public IP and use the built-in ACME flow to issue Let's Encrypt certs from Settings → Certificates. For production deployments use an Elastic IP so DNS doesn't drift on reboot:
EIP_ALLOC=$(aws ec2 allocate-address --domain vpc \
--query 'AllocationId' --output text)
aws ec2 associate-address \
--instance-id "$INSTANCE_ID" --allocation-id "$EIP_ALLOC"Step 6: Verify
# Liveness probe
curl -k https://$PUBLIC_DNS:3333/api/health
# Readiness (DB up)
curl -k https://$PUBLIC_DNS:3333/api/readyGovCloud Notes
For AWS GovCloud (US), swap --region us-east-1 for us-gov-west-1 or us-gov-east-1 and use the GovCloud Marketplace listing. AMI IDs differ per partition; the SSM parameter path is the same.
Teardown
aws ec2 terminate-instances --instance-ids "$INSTANCE_ID"
aws ec2 wait instance-terminated --instance-ids "$INSTANCE_ID"
aws ec2 delete-security-group --group-id "$SG_ID"
aws ec2 release-address --allocation-id "$EIP_ALLOC"Next Steps
Quickstart
Now that the instance is up, log in and run your first campaign in 10 minutes.
View Tutorial →Related Tutorials
- Programmatic Azure deploy — the same five-minute deploy on Azure with
az. - Set up SAML / OIDC SSO — hand login off to your IdP.
- REST API reference — full HTTP surface for automation.
- Browse the full tutorial library or see the HailBytes SAT product page.
Get the Free HailBytes SAT Getting Started Guide
A 7-part email series covering everything from your first deployment to advanced configuration and real-world workflows. One email per day, no spam.