AWS Run Tasks on EC2 Without SSH Using AWS Systems Manager
There are many ways to deploy your application or run commands inside an EC2 instance, but most of them lean on SSH, and that is exactly what I’d rather avoid. To keep the attack surface small, SSH should be blocked (in my opinion). Even inside a private VPC, it is always good to be careful. AWS has a tool built for this purpose, and it is called Systems Manager. It can do a lot of things besides accessing an EC2 instance and running commands on it, but this post will focus on Systems Manager Documents.
The first thing we need is to give the EC2 instances the necessary IAM policy, which is ssmfullaccess. With that in place, we can create our instance using the CLI, console, or SDK, and crucially we do not open the SSH port to anywhere on the internet or the VPC. Since I used Amazon Linux 2 here, there’s nothing extra to download or install, the Amazon ssm-agent already ships with it. That agent is what lets Systems Manager connect to the instance and execute our commands on it.

With the instance ready, the next step is defining our SSM document. Systems Manager lets us pull these from GitHub, S3, or actions defined right in the console. I went with GitHub, so I created a repo and uploaded it there.
From there we select our target instance, either by tags or manually. The last section to fill in is for SSM logs, and I pointed those at an S3 bucket. This turns out to be incredibly useful for debugging. You can also wire up SNS notifications to get alerted when commands succeed or fail.

And the command runs successfully. We stood up nginx without ever touching the instance manually or opening SSH.