An SSH command has only four visible pieces—client, key, username, and host—but EC2 adds a route, public/private addressing, security groups, network ACLs, status checks, AMI defaults, and host identity. Verify those pieces before changing sshd or opening the instance to the internet.
Quick connection command
chmod 400 ~/.ssh/my-ec2-key.pem
ssh -o IdentitiesOnly=yes -i ~/.ssh/my-ec2-key.pem ec2-user@PUBLIC_DNS_NAMEReplace every example value
my-ec2-key.pemmust be the private key matching the public key trusted by the instance; moving it under~/.sshis safer than leaving credentials in Downloads.chmod 400allows only the file owner to read the key. OpenSSH rejects private keys readable by other users.ec2-useris correct for Amazon Linux 2023 and Amazon Linux 2, but not every AMI.PUBLIC_DNS_NAMEis the instance’s current reachable DNS name, not its Name tag or an arbitrary hostname.IdentitiesOnly=yestells OpenSSH to offer the specified/configured identity instead of every key loaded in an agent.On first connection, verify the displayed host-key fingerprint through a trusted AWS/administrative path before accepting it.
Choose the access method before configuring SSH
Systems Manager Session Manager: managed Linux/Windows shell with IAM authorization and no inbound port when the SSM agent, instance profile, and network endpoints/outbound access are configured.
EC2 Instance Connect: IAM-authorized delivery of a short-lived SSH public key; a public path or EC2 Instance Connect Endpoint and supported instance configuration are still required.
OpenSSH with a static key: simple and widely compatible, but requires key custody, reachable TCP 22, host-key verification, rotation, and Linux account lifecycle.
EC2 Instance Connect Endpoint: reaches private-IP instances without assigning them public IPs; IAM, endpoint compatibility, and security-group rules govern the tunnel.
Bastion/VPN/Direct Connect: appropriate in some network designs, but introduces another system and trust boundary that must be patched, audited, and restricted.
SSH trust and network path
Your OpenSSH client
├── reads private key + local config
├── resolves public/private DNS
└── TCP connection to port 22
│ route / IGW / VPN / endpoint / bastion
│ security group + network ACL + guest firewall
▼
EC2 instance sshd
├── proves server identity with host key
├── maps requested Linux username
└── checks matching public key in authorized_keys
▼
interactive shellEach arrow can fail independently; the SSH banner is reached only after the TCP path succeeds.
Use the error phase as evidence
DNS failure occurs before a TCP attempt; verify the address and resolver path.
Timeout occurs before SSH authentication; inspect addressing, route, ingress, NACL, firewall, instance health, and listener.
Host-key warning occurs during server identity verification; investigate replacement/readdressing or possible interception before changing
known_hosts.Permission denied (publickey)means an SSH server answered but rejected the username/key/authentication configuration. Opening security groups further will not fix it.A shell that disconnects later points to keepalive, idle policy, resource pressure, reboot, network change, or session tooling—not initial key permissions.
Prerequisites
The instance is
runningand both EC2 system/instance status checks pass.You know the exact account, Region, instance ID, AMI/publisher, OS, and intended Linux login user.
The selected address is reachable from your client: public DNS/IP for direct internet SSH, or private DNS/IP through an approved private path.
The instance security group permits TCP 22 only from your actual source/path. Custom NACL and guest firewall rules also allow the connection and return traffic.
sshdis installed/running in the AMI and the matching public key is authorized for the selected user.The private key is intact, protected, not revoked, and available only to authorized operators.
You have a trusted method to verify the instance host-key fingerprint before accepting it.
1. Retrieve the authoritative instance details
aws ec2 describe-instances \
--instance-ids INSTANCE_ID \
--region REGION \
--query "Reservations[0].Instances[0].{State:State.Name,AMI:ImageId,PublicDNS:PublicDnsName,PublicIP:PublicIpAddress,PrivateDNS:PrivateDnsName,PrivateIP:PrivateIpAddress,Subnet:SubnetId,Groups:SecurityGroups[*].GroupId,Key:KeyName}" \
--output jsonWhy this is better than copying an old address
Replace
INSTANCE_IDandREGION; IDs and public DNS details are Region-scoped.A stop/start commonly changes an auto-assigned public IPv4 address and public DNS mapping. Elastic IPs/load balancers/DNS records provide different stability models.
An empty public address is expected for a private instance; use the approved private access method instead of assigning public exposure reflexively.
The EC2 key-pair name identifies launch metadata, not a downloadable copy of your private key and not necessarily later guest changes.
Inspect the returned security-group rules separately; knowing group IDs does not prove port 22 is authorized from the correct source.
2. Confirm the default username from the AMI
Amazon Linux 2023 and Amazon Linux 2 normally use
ec2-user.Ubuntu AMIs normally use
ubuntu.Debian AMIs commonly use
admin.CentOS can use
centosorec2-user; RHEL documentation can specifyec2-userorrootdepending on the image.Other marketplace/community/custom AMIs define their own account. Verify the publisher documentation or image build, and never infer the username from the instance type.
Linux users are guest OS identities. They are not IAM users, IAM roles, or the email identity used for the AWS console.
3. Protect and identify the private key
install -d -m 700 ~/.ssh
mv ~/Downloads/my-ec2-key.pem ~/.ssh/my-ec2-key.pem
chmod 400 ~/.ssh/my-ec2-key.pem
ssh-keygen -y -f ~/.ssh/my-ec2-key.pem | ssh-keygen -lf -Private-key takeaways
install -d -m 700creates a private SSH directory if absent.mvremoves the example key from Downloads; verify the source path and backup/custody policy before running it. Moving is recoverable only from the destination, not a duplicate.chmod 400is owner-read-only on POSIX filesystems. Windows OpenSSH uses Windows ACLs rather than this mode command.ssh-keygen -yderives the public key in memory/stdout; the second command prints its fingerprint without uploading the private key.A local public-key fingerprint helps inventory keys but does not prove the instance currently trusts that public key.
Never paste a private key into an online fingerprint tool, ticket, chat, source repository, user data, or shared shell history.
4. Restrict the security group
For direct SSH from one current IPv4 address, authorize TCP 22 from
YOUR_PUBLIC_IP/32. For IPv6 use the exact approved IPv6 CIDR.If your organization exits through a stable corporate/VPN CIDR, authorize that range according to policy. Residential addresses can change.
For an EC2 Instance Connect Endpoint, authorize the endpoint path according to AWS’s target security-group requirements—not the operator’s arbitrary public IP.
For a bastion, reference the bastion security group where supported rather than opening the private instance to the internet.
Review every security group attached to the ENI; AWS applies the union of their allow rules, so another broad group can defeat your narrow rule.
Security groups are stateful, while custom NACLs are stateless and must permit both connection and response traffic.
5. Verify the host key before trusting it
The private key proves your client to the server; the SSH host key proves the server to your client. On first connection, OpenSSH shows a fingerprint because no trusted mapping exists yet. Compare it with a fingerprint obtained through an independent trusted channel—such as approved EC2 console output, Session Manager, image/provisioning records, or an administrator already connected securely.
6. Connect with OpenSSH
ssh -o IdentitiesOnly=yes \
-i ~/.ssh/my-ec2-key.pem \
ec2-user@ec2-198-51-100-10.compute-1.amazonaws.comCommand semantics
-iselects the private identity file; its public half must be authorized for the remote user.IdentitiesOnly=yesprevents an SSH agent containing many keys from causing “too many authentication failures.”The example hostname uses documentation-only address space and will not reach your instance. Substitute the current verified DNS/IP.
The
user@hostvalue controls the guest account. A correct key offered to the wrong account is rejected.OpenSSH uses port 22 unless
-por configuration says otherwise; changing sshd’s port also requires matching network rules and operational documentation.
Use an SSH config for repeatable access
Host lynxbee-lab-ec2
HostName ec2-198-51-100-10.compute-1.amazonaws.com
User ec2-user
IdentityFile ~/.ssh/my-ec2-key.pem
IdentitiesOnly yes
StrictHostKeyChecking yesA named host prevents operators from repeatedly copying long commands and accidentally offering unrelated keys.
Configuration takeaways
Run
ssh lynxbee-lab-ec2after replacing the documentation hostname.StrictHostKeyChecking yesrefuses unknown/changed keys instead of training users to accept them blindly; provision verified host keys intoknown_hostsfirst.Keep
~/.ssh/configprivate (chmod 600) because hostnames and usernames reveal infrastructure metadata even though it should contain no private-key material.Use separate aliases/keys for environments and include files managed by approved tooling for larger fleets.
Static hostnames are a poor fleet-discovery system; dynamic environments should use managed access and inventory automation.
Connect to a private instance
Session Manager: no public address or inbound SSH rule; requires SSM agent, instance role permissions, and SSM network connectivity/endpoints.
EC2 Instance Connect Endpoint: creates a managed tunnel to the private address and can use AWS CLI v2/console with IAM authorization.
VPN or Direct Connect: your client routes to VPC private space; DNS, routes, security groups, NACLs, and corporate egress policy must align.
Bastion/ProxyJump: SSH first traverses a hardened jump host. Restrict source/destination and avoid copying private keys onto the bastion—agent forwarding itself has security tradeoffs.
Do not assign a public IP merely because a tutorial only shows public SSH. Private-by-default access is usually easier to defend.
EC2 Instance Connect Endpoint example
aws ec2-instance-connect ssh \
--instance-id INSTANCE_ID \
--os-user ec2-user \
--connection-type eice \
--region REGIONManaged-tunnel takeaways
This requires AWS CLI version 2, an EC2 Instance Connect Endpoint, compatible addressing, IAM authorization, and correct endpoint/instance security-group rules.
The instance must support the required SSH/Instance Connect integration for the selected connection workflow.
--connection-type eiceexplicitly selects the private endpoint path instead of relying on future-changing automatic selection order.The SSH session persists until closed even if the initiating IAM credentials later expire; apply session-duration and monitoring controls where required.
CloudTrail records Instance Connect API requests, but guest commands require separate shell/session/audit logging.
Troubleshooting by failure phase
Could not resolve hostname: wrong/stale DNS, typo, private DNS outside its resolver context, or resolver/network failure.
Connection timed out: wrong address/Region, instance not healthy, no route/public IP/IGW/VPN/endpoint, source changed, security group/NACL/firewall blocks, or sshd not listening.
Connection refused: host is reachable but port has no listener or an active reject; inspect sshd/service/firewall and custom port configuration.
UNPROTECTED PRIVATE KEY FILE: fix local ownership/permissions; do not weaken the client check.
Permission denied (publickey): wrong username, key, authorized_keys content/permissions, AMI, Instance Connect integration, or sshd authentication policy.
Too many authentication failures: too many agent identities were offered; use
IdentitiesOnly=yesand the intended-ikey.REMOTE HOST IDENTIFICATION HAS CHANGED: stop and verify instance lifecycle, address reassignment, DNS and fingerprint; do not reflexively run
ssh-keygen -R.Session drops/freezes: inspect network path, idle timeouts, client/server keepalive policy, instance resource pressure, reboot/events, and logs.
Test name resolution and TCP 22 separately
getent ahosts PUBLIC_DNS_NAME
nc -vz -w 5 PUBLIC_DNS_NAME 22Reachability-test takeaways
Replace the hostname.
getentshows addresses selected through the client’s configured name-service path.ncattempts a TCP connection without authenticating; success proves a listener/path responded, not that its SSH host key or your user/key is correct.A timeout still cannot identify which network control dropped traffic; compare route, source address, security groups, NACLs, firewall, and listener evidence.
Some environments lack netcat or block probes. OpenSSH verbose output remains the authoritative next check.
Collect verbose diagnostics safely
ssh -vvv -o IdentitiesOnly=yes \
-i ~/.ssh/my-ec2-key.pem \
ec2-user@PUBLIC_DNS_NAMEHow to read and share verbose output
Verbose output shows configuration files, DNS/address choice, connection phase, host-key algorithms, and identities offered/accepted.
It does not print the private key, but it can expose usernames, hostnames, IPs, key fingerprints, local paths, proxy commands, banners, and infrastructure policy. Redact deliberately.
Look for the last completed phase rather than searching only for the final generic error.
Use
-vvvfor a controlled reproduction, then remove it from normal workflows to avoid excessive sensitive logging.
After login
cat /etc/os-release
id
who
printf "SSH source: %s\n" "$SSH_CONNECTION"
sudo -n true && echo "passwordless sudo permitted" || echo "sudo requires interaction or is denied"Post-login verification
Confirm the OS/build and identity match the intended instance before making changes.
$SSH_CONNECTIONshows client/server addresses and ports for the current session; treat it as operational metadata.sudo -n truetests non-interactive sudo policy without prompting. A permitted result is authority, not a reason to run every command as root.Check patch state, time, disk, agents, logs, and workload health using the approved runbook.
End the session with
exit, remove temporary ingress when used, and rotate/revoke exposed keys.
Key and account lifecycle
Do not share one private key among people. Give each operator an identity and auditable authorization path.
Rotate by installing/testing a new public key or managed access route before removing the old one; keep break-glass procedures controlled and tested.
EC2 cannot re-download a generated private key. Losing it does not require exposing the instance; use an existing managed access/recovery path or approved volume-repair workflow.
Removing a key pair object from EC2 does not automatically remove public keys already written into guest
authorized_keys.Terminate access promptly when ownership changes, investigate any exposure, and keep host keys/known_hosts lifecycle aligned with instance replacement.
Related AWS guides
Create the server using the secure EC2 launch guide.
After access, deploy Apache on Amazon Linux 2023.
Troubleshoot the guest with Linux CPU and memory monitoring.
Primary references
AWS’s Linux SSH connection guide documents status, ingress, key, fingerprint, and client prerequisites.
The EC2 connection-options comparison distinguishes SSH, Session Manager, Instance Connect, and endpoints.
AWS documents EC2 Instance Connect methods and ephemeral key behavior.
The EC2 key-pair guide documents key formats, one-time private-key download, and permissions.
AWS’s Linux user guide explains AMI-dependent usernames and guest-account defaults.
Comments and corrections