If you manage a VPS, you’re moving files around constantly. We are talking about backups, deployments, 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 –partial and –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.
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/
If you’re constantly moving files between multiple VPS instances, the infrastructure itself matters. We built Virtarix for teams who spend too much time managing servers and not enough time shipping features. Reliable networking, straightforward setup, and you can focus on your work instead of debugging connection issues. Check what fits your setup at virtarix.
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.
Troubleshooting Common Transfer Issues
Here are the issues you’re most likely to run into and how to fix them quickly.
Problem: Permission Denied (publickey)
This error means SSH key authentication failed. To fix it:
- Make sure you actually copied your public key to the server:
ssh-copy-id username@server-ip
2. Check your file permissions. SSH is very strict:
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
3. Verify the authorized_keys file is owned by your user:
chown username:username ~/.ssh/authorized_keys
4. Verify your SSH agent is running and has your key loaded:
eval $(ssh-agent)
ssh-add ~/.ssh/your-private-key
Example of error logs:
bitwarden-api | [ERROR] Database connection failed
bitwarden-web | [ERROR] SSL certificate not found
This issue is almost always caused by permissions or a missed SSH-copy-id step.
Problem: Connection Timed Out
Your firewall is blocking the SSH connection. Check these one by one:
- Is SSH actually running on the server?
sudo systemctl status sshd
2. Is the firewall allowing SSH connections?
sudo ufw status
3. Can you reach the server at all?
ping your-vps-ip
- If you changed SSH to a custom port, are you specifying that port in your command?
These four checks cover most timeout issues.
Problem: Rsync Failed to Set Times or Permission Errors
This means you don’t have write permissions on the destination directory.
- Option 1: Transfer to a directory where you have write permissions (recommended).
- Option 2: Use sudo on the remote side:
rsync -avz /local/ user@server:/path/ --rsync-path="sudo rsync"
The –rsync-path flag tells rsync to run with sudo on the remote server. Use carefully, as sudo access is powerful.
Problem: SCP Works but Rsync Fails
This usually means rsync is not installed on the remote server. Install it:
ssh user@server "sudo apt install rsync"
Then re-run your rsync command.
Problem: Transfers Are Extremely Slow
Slow transfers can have several causes. Diagnose step by step:
- Are you using compression? If not, add -z to rsync or -C to scp.
- Test your network connection independently:
wget -O /dev/null http://speedtest.tele2.net/100MB.zip
3. Check if the remote disk is slow (high I/O wait times):
iostat -x 1
4. If transferring many tiny files, create a tar archive first and transfer that single file. Small files add significant overhead.
Practical Examples You Will Actually Use
Daily Automated Backups
Use rsync with a cron job to back up production servers every night at 2 AM:
rsync -avz --delete -e "ssh -i /home/user/.ssh/backup-key" prod-server:/var/www/ /backups/website/
The –delete flag keeps backups clean by removing files that were deleted from the source. This runs completely unattended.
Quick Deployment of Code Changes
When pushing code to production, sync only changed files:
rsync -avz --exclude '.git/' --exclude 'node_modules/' /local/project/ user@prod-server:/var/www/site/
This is much faster than uploading the entire project every time. Only the files you actually changed get transferred.
Grabbing Log Files for Debugging
For troubleshooting, use scp to quickly download log files:
scp admin@web-server:/var/log/app.log ~/Desktop/
Essential Commands Quick Reference
Here is a condensed cheat sheet of the commands you’ll use most often.
Rsync Commands
# Upload to server
rsync -avz /local/ user@server:/remote/
# Download from server
rsync -avz user@server:/remote/ /local/
# Mirror directories (sync + delete)
rsync -avz --delete /local/ user@server:/remote/
# Upload with progress
rsync -avzP /local/ user@server:/remote/
# Limit bandwidth
rsync -avz --bwlimit=1000 /local/ user@server:/remote/
# Exclude files
rsync -avz --exclude='*.log' /local/ user@server:/remote/
# Use SSH key
rsync -avz -e "ssh -i ~/.ssh/id_ed25519" /local/ user@server:/remote/
# Remote to remote transfer
rsync -avz user1@host1:/path/ user2@host2:/path/
SCP Commands
# Upload with SCP
scp file.txt user@server:/remote/
# Download with SCP
scp user@server:/remote/file.txt /local/
# Upload directory with SCP
scp -r /local/dir user@server:/remote/
# Download directory with SCP
scp -r user@server:/remote/dir /local/
# SCP with identity file
scp -i ~/.ssh/id_ed25519 file.txt user@server:/remote/
# Remote to remote copy with SCP
scp user1@host1:/path/file user2@host2:/path/
Rsync vs SCP Comparison
Feature | Rsync | SCP |
---|---|---|
Best For | Syncing, backups, repeated transfers | Quick one-off copies |
Delta Transfer | Yes, only sends changes | No, always full file |
Resume Capability | Yes with --partial | Limited support |
Exclude Files | Yes with --exclude | No native support |
First Transfer Speed | Similar to SCP | Similar to rsync |
Repeated Transfer Speed | Much faster (delta transfer) | Same every time |
Bandwidth Usage | Lower (only changes) | Higher (full files) |
Syntax Complexity | More flags to learn | Simpler syntax |
Final Thoughts
Rsync is objectively better for most file transfer scenarios because it only transfers what has changed. This saves time and bandwidth, especially for repeated transfers like backups and deployments. Use rsync when efficiency matters. Use scp when the speed of typing the command matters more than the speed of the transfer.
Always use SSH keys instead of passwords for security and convenience. Always keep both tools updated with the latest security patches. And always do a dry run before using –delete. That is how you efficiently transfer files on a VPS.