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 to400 - 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.


