Home / AWS

AWSHow-toBeginner

Amazon S3 basics: buckets, objects, sync and presigned URLs from the command line

Create a private bucket with sensible defaults, upload, download and sync folders, share a single file safely with a presigned URL, and turn on versioning so mistakes can be undone.

Deepak Bhardwaj3 min read

Applies toAmazon S3 (general purpose buckets), AWS CLI v2

S3 stores files ("objects") in containers called buckets. Bucket names are global, objects are addressed by key (which looks like a path), and almost every security problem comes from making a bucket public by accident. This post gets you productive without that risk.

Create a bucket

aws s3 mb s3://acme-team-reports-2026 --region eu-west-1
aws s3api get-public-access-block --bucket acme-team-reports-2026

New buckets have Block Public Access on and default encryption with S3-managed keys. Leave Block Public Access on. Turn on versioning now, not after the first accident:

aws s3api put-bucket-versioning --bucket acme-team-reports-2026 --versioning-configuration Status=Enabled

Tip

Bucket names must be globally unique, lowercase, and are visible in URLs. Do not put customer names or secrets in them.

Upload, list, download

aws s3 cp report.csv s3://acme-team-reports-2026/2026/10/report.csv
aws s3 ls s3://acme-team-reports-2026/2026/ --recursive --human-readable --summarize
aws s3 cp s3://acme-team-reports-2026/2026/10/report.csv ./downloaded.csv

Folders are just key prefixes. 2026/10/report.csv is one object with that key; there is no real 2026 directory.

Copy folders and sync

aws s3 cp ./exports s3://acme-team-reports-2026/exports/ --recursive
aws s3 sync ./site s3://acme-team-reports-2026/site/
aws s3 sync ./site s3://acme-team-reports-2026/site/ --exclude "*.tmp" --include "*.html"

sync copies only new or changed files. With --delete it also removes objects that are not in the source:

aws s3 sync ./site s3://acme-team-reports-2026/site/ --delete --dryrun

Caution

Always run --delete with --dryrun first. With versioning on you can recover, but it is slower than not making the mistake.

Share one file safely: presigned URL

Instead of making anything public, generate a link that expires:

aws s3 presign s3://acme-team-reports-2026/2026/10/report.csv --expires-in 3600

Anyone with the link can download that one object until it expires (one hour here). The link carries your permissions, so it stops working if your credentials expire sooner, for example an SSO session.

Delete and recover

aws s3 rm s3://acme-team-reports-2026/2026/10/report.csv
aws s3api list-object-versions --bucket acme-team-reports-2026 --prefix 2026/10/report.csv \
  --query "{v:Versions[].{Id:VersionId,Latest:IsLatest}, d:DeleteMarkers[].{Id:VersionId,Latest:IsLatest}}"
# remove the delete marker to bring the object back
aws s3api delete-object --bucket acme-team-reports-2026 --key 2026/10/report.csv --version-id <delete-marker-version-id>

Storage classes in one line each

Class Use for
S3 Standard Default, frequently read data
S3 Intelligent-Tiering Unknown or changing access patterns
S3 Standard-IA / One Zone-IA Read rarely but need fast access (retrieval fees apply)
S3 Glacier Instant / Flexible / Deep Archive Archives; slower and cheaper the deeper you go
aws s3 cp big-archive.zip s3://acme-team-reports-2026/archive/ --storage-class GLACIER_IR

Common errors

Error Cause Fix
AccessDenied Missing IAM permission, bucket policy deny, or KMS key permission Check aws sts get-caller-identity; review bucket policy and key policy
BucketAlreadyExists Name taken by someone else, anywhere Pick a more specific name
NoSuchKey Key typo, or wrong prefix case (keys are case sensitive) aws s3 ls the prefix
Slow uploads of big files Single stream The CLI already uses multipart; raise aws configure set default.s3.max_concurrent_requests 20

Prevent it next time

  • Keep Block Public Access on at account level: aws s3control put-public-access-block --account-id <id> --public-access-block-configuration BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true.
  • Versioning plus a lifecycle rule that expires old versions after N days, so recovery is possible but storage does not grow forever.
  • Share with presigned URLs, not public objects.