How to Copy Files to Amazon EC2 Ubuntu Instance Using Rsync

3 min read

Rsync is the fastest way to copy files between your local machine and an EC2 instance. Unlike scp, rsync only transfers files that have changed, which makes repeated syncs much faster. This guide covers how to use rsync to copy files to EC2 Ubuntu, pull files back, and filter what gets transferred.

The examples here are run on WSL2 Ubuntu in Windows, but they work the same on any Linux or macOS system.

Prerequisites

  • An EC2 instance running Ubuntu — follow How to deploy EC2 Ubuntu 22.04 LTS on AWS if you need one
  • Your EC2 key pair file (.pem) with permissions set to 400
  • Port 22 (SSH) open in the EC2 Security Group
  • Rsync installed on both machines (Ubuntu includes it by default)

If rsync isn’t installed:

sudo apt update && sudo apt install -y rsync

Push Files: Local to EC2

Copy a local directory to your EC2 instance:

rsync -avz -e "ssh -i ~/.ssh/your-key.pem" ./my-project/ ubuntu@203.0.113.10:/home/ubuntu/my-project/
  • -a — archive mode: preserves permissions, timestamps, symlinks, and ownership
  • -v — verbose: shows which files are being transferred
  • -z — compress data during transfer (faster over slow connections)
  • -e "ssh -i ..." — tells rsync to use SSH with your PEM key for the connection

Trailing slash matters

This is the most common rsync mistake. A trailing / on the source means “copy the contents of this directory.” No trailing slash means “copy the directory itself.”

Command Result on remote
rsync ./my-project/ remote:/dest/ Files land directly in /dest/
rsync ./my-project remote:/dest/ Creates /dest/my-project/ containing the files

Pull Files: EC2 to Local

Copy files from EC2 back to your local machine — just swap the source and destination:

rsync -avz -e "ssh -i ~/.ssh/your-key.pem" ubuntu@203.0.113.10:/home/ubuntu/my-project/ ./my-project/

Dry Run First

Before running any rsync command on production files, add -n (or --dry-run) to see what would happen without actually transferring anything:

rsync -avzn -e "ssh -i ~/.ssh/your-key.pem" ./my-project/ ubuntu@203.0.113.10:/home/ubuntu/my-project/

Review the file list in the output. If it looks right, remove -n and run it for real.

Exclude Files and Directories

Use --exclude to skip specific files or directories:

rsync -avz -e "ssh -i ~/.ssh/your-key.pem" \
  --exclude '.git' \
  --exclude 'node_modules' \
  --exclude '.env' \
  ./my-project/ ubuntu@203.0.113.10:/home/ubuntu/my-project/

Use an exclude file for longer lists

If you have many patterns to exclude, put them in a file:

.git
node_modules
.env
*.log
__pycache__
.DS_Store

Save this as .rsync-exclude in your project root, then reference it:

rsync -avz -e "ssh -i ~/.ssh/your-key.pem" \
  --exclude-from '.rsync-exclude' \
  ./my-project/ ubuntu@203.0.113.10:/home/ubuntu/my-project/

Sync Only Specific File Types

To transfer only certain file types, combine --include with --exclude '*':

rsync -avz -e "ssh -i ~/.ssh/your-key.pem" \
  --include '*.php' \
  --include '*.html' \
  --include '*/' \
  --exclude '*' \
  ./my-project/ ubuntu@203.0.113.10:/var/www/html/
  • --include '*/' — required so rsync traverses subdirectories (without it, it only checks the top level)
  • --exclude '*' — excludes everything not matched by the include rules

Delete Remote Files Not in Source

If you want the remote directory to be an exact mirror of your local directory — including deleting files that no longer exist locally — add --delete:

rsync -avz --delete -e "ssh -i ~/.ssh/your-key.pem" \
  ./my-project/ ubuntu@203.0.113.10:/home/ubuntu/my-project/

Use this carefully. Always do a dry run with -n first to confirm which files will be deleted.

Using Rsync with Passwordless SSH

If you’ve set up passwordless SSH on your EC2 instance, you can drop the -e "ssh -i ..." flag entirely:

rsync -avz ./my-project/ ubuntu@203.0.113.10:/home/ubuntu/my-project/

Quick Reference

Flag Purpose
-a Archive mode (preserves everything)
-v Verbose output
-z Compress during transfer
-n Dry run (show what would happen)
--progress Show transfer progress per file
--delete Remove remote files not in source
--exclude Skip matching files/directories
--exclude-from Read exclude patterns from a file
--include Force-include matching patterns
-e "ssh -i ..." Use SSH with a specific key

Conclusion

Rsync is faster than scp for repeated transfers because it only sends what’s changed. Combined with exclude patterns and dry runs, it’s a reliable way to keep files in sync between your local machine and EC2.

For persistent file sharing across multiple EC2 instances, you might want to mount an Amazon EFS volume instead. Or if you need to push files to S3, check out mounting an S3 bucket with S3FS.