Skip to content

EC2 Instance Connect vs Session Manager vs plain SSH: pick one access model

Compare AWS Systems Manager Session Manager, EC2 Instance Connect and plain SSH keys for reaching your EC2 servers. See what each one needs, what it records, and which one a production fleet should use by default.

For most production EC2 fleets, use Session Manager, the AWS Systems Manager feature that opens a shell from your browser or the CLI without port 22. Access is controlled by IAM, the AWS permissions service, so there are no SSH keys to track and every session can be logged. EC2 Instance Connect suits the narrower case where you truly need SSH, since it pushes a temporary key that expires after 60 seconds. Plain SSH still fits where a legacy tool demands it, or where your team runs short-lived SSH certificates across on-prem and other clouds. The choice matters most later, when you need to prove who connected, to which server, and what they did.

What you are deciding

Three access models, three trust mechanisms:

  • Plain SSH: a keypair created at launch (or distributed by hand), port 22 open to something, authorized_keys as the source of truth. Access control lives on each box; revocation means touching every box; audit is whatever the host logs and nobody ships. It works everywhere, including outside AWS, which is both its virtue and why it lingers.
  • EC2 Instance Connect (EIC): still SSH on the wire, but keys become ephemeral — aws ec2-instance-connect send-ssh-public-key pushes a public key that is valid for 60 seconds, authorized by IAM. The instance needs the EIC agent (preinstalled on Amazon Linux and Ubuntu AMIs) and reachable port 22. The EC2 Instance Connect Endpoint variant removes the public-IP requirement: it gives you a TCP tunnel into private subnets without a bastion, still IAM-gated.
  • SSM Session Manager: not SSH at all. The SSM Agent on the instance opens an outbound connection to the Systems Manager service; sessions ride that channel. No inbound ports, no keys, no bastion, works on private subnets (via NAT or VPC endpoints), IAM policies decide who reaches which instances (by tag, even), and sessions can be logged keystroke-for-keystroke to CloudWatch Logs or S3. Port forwarding and an SSH-over-SSM mode cover most “but I need scp” objections. Details live under the Systems Manager documentation.

The operational difference shows up at offboarding and audit time. With SSH keys, a departing engineer’s access dies when someone edits every authorized_keys (so, weeks later, maybe). With SSM or EIC, it dies with their IAM identity the same hour. And when a security questionnaire asks “who accessed production on June 3,” Session Manager has an answer; scattered auth.log files usually do not.

What to check first

  • Is the SSM Agent already running fleet-wide? It ships in Amazon Linux, Ubuntu, and most modern AMIs — half the migration may already be done.
  • Do instances have an instance profile with AmazonSSMManagedInstanceCore? That, plus outbound 443, is the whole server-side requirement.
  • What currently has port 22 open, and to where? 0.0.0.0/0 on 22 is the finding that sets the urgency.
  • Where do SSH private keys live today? Laptops, shared vaults, CI systems — the sprawl you are about to retire.
  • Any workflows that genuinely need SSH semantics — rsync jobs, legacy deploy scripts, developers with strong tmux opinions — that need a bridge plan rather than a decree.

How to verify

Which instances are SSM-managed and reachable right now:

aws ssm describe-instance-information \
  --query 'InstanceInformationList[].[InstanceId,PingStatus,PlatformName,AgentVersion]' \
  --output table

Instances missing from that list either lack the agent, the instance profile, or a network path to SSM endpoints. Test a session:

aws ssm start-session --target i-0123456789abcdef0

Find security groups still exposing 22 to the world:

aws ec2 describe-security-group-rules \
  --filters Name=cidr-ipv4,Values=0.0.0.0/0 \
  --query 'SecurityGroupRules[?FromPort==`22` && IsEgress==`false`].[GroupId]' --output text

In the console, Systems Manager > Fleet Manager shows managed nodes; Systems Manager > Session Manager > Session history shows who connected where — CloudTrail’s StartSession events back it up. For EIC, connection attempts appear in CloudTrail as SendSSHPublicKey.

The approach

  1. Wire the prerequisites fleet-wide: an instance profile carrying AmazonSSMManagedInstanceCore (built the way described in IAM instance profiles done right), agent present, and outbound 443 — through NAT or, cleaner for private subnets, SSM VPC endpoints.
  2. Turn on session logging before rollout, not after: Session Manager preferences → CloudWatch Logs or S3, with encryption. Audit value starts on day one.
  3. Grant access through IAM, scoped by tags. ssm:StartSession conditioned on ssm:resourceTag/Environment gives developers staging and operators production without listing instance IDs.
  4. Run both models for two or three weeks. Let people work through Session Manager (including aws ssm start-session --document-name AWS-StartPortForwardingSession for database tunnels) while port 22 still exists as the fallback.
  5. Close port 22. Delete the inbound rules, keep the keys in escrow for a quarter, and watch for whoever screams — that scream is an undocumented workflow you now get to fix properly.
  6. Keep EIC Endpoint for the exceptions. True SCP/SFTP needs and third-party tools that speak only SSH can go through an Instance Connect Endpoint with ephemeral keys — IAM-gated, no standing exposure, no bastion to patch.

When this is the wrong move

If your estate spans on-prem and other clouds and your team runs a mature certificate-based SSH setup (short-lived certs from a CA, centralized audit), SSM is a sidegrade there — though SSM Agent does support hybrid activation if you want one pane. Air-gapped or SSM-endpoint-less network designs need the VPC endpoint work first; do not ship a model people cannot reach. And keep one documented break-glass path (an EIC Endpoint, or a keypair in a sealed vault) for the day IAM, SSM, or your identity provider itself is the outage.

Common mistakes

  • Closing port 22 before verifying every instance shows Online in SSM — the unmanaged stragglers become unreachable exactly when you need them.
  • Skipping session logging and getting the security benefit but none of the audit benefit.
  • Leaving the launch-time keypairs valid forever after the migration, so the old door stays unlocked behind the new one.
  • Treating EIC and Session Manager as the same thing — EIC still requires reachable SSH and an EIC-capable distro; SSM requires neither but is not SSH.

Keeping it under control

  • An AWS Config rule or weekly script flagging any security group with 22 open beyond approved sources.
  • Alert on StartSession to production instances outside business hours, and review session history monthly.
  • Bake agent, instance profile, and logging preferences into launch templates and golden AMIs so new instances arrive compliant.
  • Re-test the break-glass path quarterly; an untested emergency door is a wall.

Pick Session Manager as the default, Instance Connect Endpoint for the SSH-shaped exceptions, and let standing SSH keys retire with honours. If nobody on your team truly owns the AWS environment end to end, that is the root of most of these problems — Stack Harbor runs AWS accounts daily under AWS Operations, and you can book an AWS review.