The AWS Command Line Interface lets you manage every AWS service from a terminal and from scripts, which is the first step toward automating infrastructure. Version 2 became generally available on 10 February 2020 and is the version AWS recommends for new installs.
Versions in use on this date. AWS CLI 2.0.x on Ubuntu 20.04 LTS. v2 ships its own Python, so it no longer depends on the system Python (useful now that Python 2 is retired). It adds SSO login support, a default pager, and better installers; v1 remains available through pip and from the distribution package, but receives fewer new features.
How the CLI finds credentials
flowchart TB
CMD[aws s3 ls] --> C1{Command line options?}
C1 -->|no| C2{Environment variables<br/>AWS_ACCESS_KEY_ID}
C2 -->|no| C3{Profile in ~/.aws/credentials<br/>or SSO session}
C3 -->|no| C4{Container or EC2 instance role}
C4 -->|yes| ROLE[Temporary credentials from metadata service]
C3 -->|yes| PROF[Static keys or SSO token]
C2 -->|yes| ENV[Use env credentials]
C1 -->|yes| OPT[Use options]
ROLE --> CALL[Signed API request to AWS]
PROF --> CALL
ENV --> CALL
OPT --> CALL
The order matters when debugging: an old AWS_ACCESS_KEY_ID in your shell silently overrides the profile you think you are using.
Install on Ubuntu 20.04
sudo apt install -y unzip curl
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o awscliv2.zip
unzip -q awscliv2.zip
sudo ./aws/install
aws --version # aws-cli/2.0.x Python/3.7.x Linux/5.4...
AWS publishes the installer’s signature (a PGP signature file next to the download) if you want to verify it before running. Upgrade later with sudo ./aws/install --update. For ARM servers use the aarch64 zip. Add shell completion with complete -C '/usr/local/bin/aws_completer' aws in ~/.bashrc.
Configure credentials
aws configure --profile dev
# AWS Access Key ID, Secret Access Key, default region (ap-south-1), output format (json)
aws sts get-caller-identity --profile dev # who am I, which account
This writes two files: ~/.aws/credentials (keys) and ~/.aws/config (region, output, role settings). Protect them (chmod 600), never commit them, and use named profiles so you never run a command in the wrong account by accident.
# ~/.aws/config
[default]
region = ap-south-1
output = json
[profile prod-readonly]
role_arn = arn:aws:iam::222222222222:role/ReadOnly
source_profile = dev
mfa_serial = arn:aws:iam::111111111111:mfa/ravi
region = ap-south-1
Role assumption with MFA (source_profile and mfa_serial) gives short-lived credentials and is much safer than long-lived keys for production. AWS CLI v2 can also sign in through AWS Single Sign-On (aws configure sso) where your organisation uses it.
export AWS_PROFILE=prod-readonly
aws sts get-caller-identity
On EC2, ECS and Lambda, attach an IAM role instead of configuring keys at all.
Everyday use
aws s3 ls
aws ec2 describe-instances --query 'Reservations[].Instances[].[InstanceId,State.Name,Tags[?Key==`Name`]|[0].Value]' --output table
aws ec2 describe-instances --filters Name=instance-state-name,Values=running --output json | jq -r '.Reservations[].Instances[].InstanceId'
aws ec2 wait instance-running --instance-ids i-0abc123
aws ec2 describe-regions --query 'Regions[].RegionName' --output text
aws help; aws ec2 help; aws ec2 run-instances help
--queryuses JMESPath to filter output on the client;--filtersfilters on the server (faster for large results).--output table|text|json|yaml; v2 addsyaml.aws <service> wait ...pauses until a resource reaches a state, which makes scripts reliable.--dry-run(on EC2 commands) checks permissions without making changes.- v2 pipes long output into a pager; disable with
export AWS_PAGER=""in scripts.
Troubleshooting
| Symptom | Likely cause |
|---|---|
Unable to locate credentials |
No profile or environment set, or no instance role |
InvalidClientTokenId / SignatureDoesNotMatch |
Wrong or expired keys; clock skew on the server |
AccessDenied / UnauthorizedOperation |
IAM policy lacks the action; decode with aws sts decode-authorization-message |
| Works in console, not CLI | Different account or region; check sts get-caller-identity and aws configure list |
| Slow or timeouts | Proxy settings, or the wrong region endpoint |
aws configure list shows where each value came from, and --debug prints the full request flow.
Safe habits
- Rotate access keys regularly and delete unused ones (
aws iam list-access-keys). - Never put keys in scripts, AMIs, containers or Git.
- Use least-privilege policies per profile.
- Keep CLI v2 updated; new services and flags arrive constantly.