If you manage a VPS, you're moving files around constantly. We are talking about backups, deployments, and migrations—these tasks happen daily. And if you're doing it wrong, you're wasting both time and bandwidth. Two tools handle this work: rsync for syncing directories and large transfers, and scp for quick one-off file copies.
Starting with OpenSSH 9.0, the scp command still looks and feels the same, but under the hood, it now relies on the SFTP protocol by default instead of the legacy SCP protocol. This change was introduced because the older protocol had security flaws like CVE-2019-6111. If you really need the old behavior, you can force it with the -O flag, but in almost every case, it is better to use the new default for security reasons.
We will show you exactly how to use both tools. By the end of this guide, you’ll know which commands to use, when to use them, and how to avoid the most common mistakes.
Understanding Rsync vs SCP
Before jumping into commands, you need to understand what makes these tools different.
Rsync: the smart file syncing tool
Rsync (Remote Sync) only transfers what has changed. It uses a delta transfer algorithm that compares files and sends only the differences. If you sync a 10GB directory and only 50MB has changed, Rsync will transfer just 50MB instead of the full 10GB.
This makes Rsync ideal for backups that run repeatedly, deployments where only a few files change, and any situation where you’re syncing the same directories multiple times. The first sync takes longer because everything needs to be copied, but every sync after that is significantly faster.
SCP: the quick copy command
SCP (Secure Copy Protocol) is much simpler. You tell it to copy a file from point A to point B, and it copies the entire file. There is no comparison process, no delta transfer, just a straightforward copy operation.
This makes SCP the right choice for one-time transfers when you just need to grab a log file or copy a configuration file quickly. The syntax is simple, and you don’t need to worry about additional flags or options.
The key difference is this: Rsync becomes more efficient with repeated use, while SCP remains the same speed every time because it always copies the entire file.
Basic rsync usage: syncing files
Start with the most common Rsync operations you’ll use daily.
Upload local files to your VPS
rsync -avz /local/directory/ username@your-vps-ip:/remote/directory/
Same flags, same logic, just a different direction.
Sync and delete files (mirror directories)
Sometimes you want the destination to exactly match the source, including deleting files that no longer exist in the source. This is called mirroring.
rsync -avz --delete /local/directory/ user@server:/remote/directory/
The --delete flag removes any files from the destination that don’t exist in the source. This keeps your backups clean and prevents old files from piling up.
Critical warning: This permanently deletes files. If you accidentally swap your source and destination, you could wipe out important data. Always double-check your paths before using --delete.
Test with dry run before executing
Before running any rsync command that modifies files, especially one using --delete, test it first with a dry run.
rsync -avz --delete --dry-run /local/ user@server:/remote/
The --dry-run flag shows you exactly what would happen without actually doing it. Rsync prints every action it would take. If something looks wrong, you catch it before any damage happens.
Always use a dry run before major syncs. This simple habit has saved teams from accidentally deleting production data many times.
Exclude files and directories
You may not always want to sync everything. For example, you might want to skip log files, temporary directories, or dependency folders.
Exclude specific patterns
rsync -avz --exclude '*.log' --exclude 'temp/' --exclude 'cache/' /local/ user@server:/remote/
Exclude using a file for cleaner commands
Create a text file called exclude-list.txt with your patterns:
*.log
*.tmp
node_modules/
.git/
temp/
cache/
Then reference that file:
rsync -avz --exclude-from='exclude-list.txt' /local/ user@server:/remote/
This approach is cleaner when you have many exclusions. You maintain the list in a file and reuse it across different Rsync commands.
Resume interrupted transfers
Your internet connection might drop halfway through transferring a 50GB file. Frustrating, but with Rsync, you don’t start over from the beginning.
rsync -avz --partial --progress /local/large-file.tar.gz user@server:/remote/
-
--partial: Keeps partially transferred files so Rsync can resume them. -
--progress: Shows transfer progress in real time so you know how much is complete and how much remains.
When you run the command again after your connection is restored, Rsync picks up where it left off instead of starting from zero.
Show detailed transfer statistics with --info=progress2:
rsync -avz --info=progress2 /local/ user@server:/remote/
The --info=progress2 flag shows overall transfer statistics instead of per-file updates. When syncing thousands of files, this prevents the screen from filling with line-by-line updates and gives you a much clearer ETA for the entire operation.
Pro tip: Use -P as a shorthand for --partial --progress.
rsync -avzP /local/file user@server:/remote/
-
-P: Combines--partialand--progress. Keeps partial files and shows progress in real time.
Advanced rsync techniques
Atomic transfers
Atomic transfers prevent partially uploaded files from being visible during a sync. This is important when deploying to a live server so visitors don’t access incomplete files.
rsync -avz --temp-dir=/tmp --delay-updates /local/ user@server:/remote/
This command writes files to /tmp first, then with --delay-updates, rsync moves all completed files to their final locations at the end of the sync (not during). This ensures files appear atomically: they are either fully present or not present at all.
rsync:// protocol
In addition to rsync over SSH, rsync can also connect using the native rsync:// protocol. This is mainly used for accessing public mirrors (for example, downloading Linux distributions).
Example:
rsync rsync://mirror.example.com/repo/ /local/repo/
For most production use cases, SSH is recommended because it is more secure and flexible.
Basic SCP usage: quick file copies
SCP is simpler than rsync. You tell it what to copy and where to put it; that is it.
Upload a single file:
scp /local/file.txt username@your-vps-ip:/remote/path/
Download a single file:
scp username@your-vps-ip:/remote/file.txt /local/path/
To copy entire directories (with all subdirectories and files), add the -r flag:
scp -r /local/directory username@your-vps-ip:/remote/path/
For faster transfers of text files, source code, and uncompressed data, use the -C flag:
scp -C /local/file.txt user@server:/remote/
-
-C(compression): Compresses data during transfer. - Best for text files, source code, and other uncompressed data.
- Not useful for already-compressed files like .zip, .tar.gz, or .jpg.
We typically use scp when we need to quickly grab a log file or a small config file:
scp admin@web-server:/var/log/nginx/error.log ~/Desktop/
Fast, simple, done. For repeated or large transfers, rsync is the better option.
Common transfer operations
Transferring files between remote servers
Sometimes you need to move files directly between two VPS instances.
With scp:
scp username1@source-server:/path/to/file username2@destination-server:/path/
Your local machine acts as the intermediary – data flows through your SSH connection.
With rsync:
rsync -avz username1@source-server:/path/ username2@destination-server:/path/
For large transfers, SSH into one server first and run rsync from there (avoids routing through your home internet):
ssh username1@source-server
rsync -avz /path/ username2@destination-server:/path/
Using SSH keys instead of passwords
Typing passwords for every transfer wastes time. SSH keys solve this problem.
Generate a key pair:
ssh-keygen -t ed25519 -C "your-email@example.com"
This command generates two files:
-
id_ed25519→ your private key (keep this secret) -
id_ed25519.pub→ your public key (share this with servers).
Never share your private key (id_ed25519) with anyone. Treat it like your password. Only the .pub file is safe to upload to servers.
Copy the public key to your server:
ssh-copy-id username@your-vps-ip
Now you can SSH and transfer files without typing passwords.
Use keys with rsync:
rsync -avz -e "ssh -i /path/to/private-key" /local/ user@server:/remote/
Use keys with scp:
scp -i /path/to/private-key /local/file user@server:/remote/
SSH keys are essential for automated scripts and scheduled backups, since scripts cannot enter passwords interactively.
Working with custom SSH ports
Many people change SSH from the default port 22 to a custom port to reduce automated attack attempts. If your server uses a custom port, you need to specify it in your commands.
With rsync:
rsync -avz -e "ssh -p 2222" /local/ user@server:/remote/
You specify the port inside the -e flag as part of the SSH command.
With scp:
scp -P 2222 /local/file user@server:/remote/
Notice that rsync uses lowercase -p inside the SSH command, but scp uses uppercase -P directly. This inconsistency can be annoying, but that is just how these tools work.
Limiting bandwidth to avoid network saturation
If you’re on a shared network and don’t want your file transfer to consume all available bandwidth, you can limit the transfer speed.
With rsync:
rsync -avz --bwlimit=1000 /local/ user@server:/remote/
The –bwlimit flag limits speed in kilobytes per second (KBps). For example, –bwlimit=1000 means 1000 KBps (roughly 1 MB/s or 8 Mbps).
This is especially useful when running backups during business hours, as it prevents slowing down everyone else on the network.