Cloud Security Groups introduced security groups: allow-only, stateful rules outside the instance, with no inbound rule until you add one. A web server needs SSH from your address only (find it with curl 3,008 https://checkip.amazonaws.com 8 and add /32) and HTTP from everyone:
aws ec2 create-security-group --group-name lamp-book-web \
--description "LAMP book web server" --vpc-id vpc-0dcdd3f31e4867985 \
--tag-specifications 'ResourceType=security-group,Tags=[{Key=Project,Value=lamp-book-ch01}]'
ssh='IpProtocol=tcp,FromPort=22,ToPort=22,IpRanges=[{CidrIp=203.0.113.10/32,'
ssh+='Description=SSH from my workstation}]'
aws ec2 authorize-security-group-ingress --group-id sg-069ce137f5c2f07ba --ip-permissions "$ssh" \
'IpProtocol=tcp,FromPort=80,ToPort=80,IpRanges=[{CidrIp=0.0.0.0/0,Description=HTTP}]' \
--query "SecurityGroupRules[].[SecurityGroupRuleId,IpProtocol,FromPort,CidrIpv4]" --output table...
"GroupId": "sg-069ce137f5c2f07ba",
...
+------------------------+------+-----+--------------------+
| sgr-0a156e14519a32c0d | tcp | 22 | 203.0.113.10/32 |
| sgr-0d70621cfa3bec2eb | tcp | 80 | 0.0.0.0/0 |
+------------------------+------+-----+--------------------+Rules apply at once. Add 443 when Let's Encrypt installs a certificate. A source can also be another group, so a database can admit 3306 only from members of lamp-book-web. When your home address changes, SSH times out until you replace the rule. Inside, sudo ufw 280 status printed Status: inactive, so the group alone guards this instance; enable ufw too (Opening 80 and 443 with ufw), and remember that a port closed at either layer times out the same way (Port Closed?).