The Complete Guide to Moving Files Over SSH

Moving files between computers securely doesn’t have to be complicated. SSH gives you several powerful, encrypted ways to transfer data, and once you understand the basics, you’ll wonder how you ever managed without them.

Whether you’re a developer pushing code to servers, a system administrator managing backups, or just someone who needs to move files safely between machines, this guide covers everything you need to know about SSH-based file transfers.

Why SSH for File Transfers?

Unlike traditional FTP or other transfer methods, SSH encrypts everything end-to-end. Your files, passwords, and commands are all protected from prying eyes. Plus, if you’re already using SSH to manage servers, you’re using the same keys and configuration for file transfers too.

A quick note for modern systems: If you’re running OpenSSH 9.0 or later, scp now uses the SFTP protocol by default instead of the legacy scp protocol. This change fixes some old quirks, but if you specifically need the old behavior, just add the -O flag.

The Big Three: Choosing Your Tool

Think of SSH file transfer tools like different vehicles for different jobs:

SCP (Secure Copy) is like a pickup truck – simple, reliable, gets the job done for straightforward transfers. Perfect for copying individual files or directories when you just need to move something from point A to point B.

rsync is like a smart moving van – it only carries what’s changed, can resume interrupted moves, and has lots of options for complex jobs. Ideal for keeping directories in sync, backing up data, or any situation where you’re transferring the same files repeatedly.

SFTP is like having a remote file manager – interactive, great for browsing around and moving files by hand. Excellent when you need to explore what’s on a remote system and selectively transfer files.

Getting Started with SCP

SCP is the simplest way to copy files over SSH. The basic pattern is always the same: scp source destination.

Copying a file to a remote server looks like this:

scp document.pdf user@server:/home/user/docs/

Copying from a remote server to your local machine flips it around:

scp user@server:/var/log/app.log ./logs/

For directories, add the -r flag for recursive copying:

scp -r ./project_folder user@server:/var/www/

One thing to watch out for: if you use wildcards like ./folder/*, you’ll miss hidden files that start with dots. It’s usually better to copy the whole directory with the recursive flag.

Useful SCP Options

A few flags can make your SCP experience much smoother:

  • -p preserves file timestamps and permissions
  • -C compresses data during transfer (great for slow connections)
  • -v shows verbose output if you want to see what’s happening
  • -P lets you specify a different SSH port
  • -i lets you use a specific SSH key

Here’s a practical example that combines several of these:

scp -Cp -P 2222 ./big_file.zip user@server:/backups/

This command compresses the file during transfer, preserves its attributes, and connects to port 2222 instead of the default SSH port.

Copying Between Remote Servers

Sometimes you need to copy files between two remote servers. The -3 flag routes the transfer through your local machine, which is usually more reliable than trying to make the remote servers talk directly:

scp -3 user1@server1:/path/file.txt user2@server2:/dest/

Mastering rsync for Efficient Transfers

While SCP is great for simple copies, rsync shines when you need more control or efficiency. The magic of rsync is that it only transfers the parts of files that have actually changed – this can save enormous amounts of time and bandwidth.

The most common rsync pattern uses the -avz flags:

rsync -avz ./local_folder/ user@server:/remote/folder/

Here’s what those flags do:

  • -a is “archive mode” – it preserves permissions, timestamps, and other file attributes
  • -v gives you verbose output so you can see what’s happening
  • -z compresses data during transfer

The Trailing Slash Trick

Pay attention to trailing slashes with rsync – they change the behavior significantly:

  • rsync -avz source/ destination/ copies the contents of source into destination
  • rsync -avz source destination/ creates a folder called “source” inside destination

This small difference trips up a lot of people, so always double-check your slashes.

Dry Runs and Safety

Before running a complex rsync command, especially one that might delete files, use the -n flag to do a dry run:

rsync -avzn --delete ./local/ user@server:/remote/

The --delete flag makes rsync remove files from the destination that don’t exist in the source. It’s powerful but dangerous, so always test first.

Custom SSH Settings with rsync

When you need to use specific SSH settings with rsync, use the -e flag:

rsync -avz -e "ssh -p 2222 -i ~/.ssh/special_key" ./local/ user@server:/remote/

Filtering and Excluding Files

rsync has powerful filtering capabilities. You can exclude certain files or patterns:

rsync -avz --exclude="*.tmp" --exclude="logs/" ./project/ user@server:/var/www/

Or include only certain types of files:

rsync -avz --include="*.pdf" --exclude="*" ./documents/ user@server:/archives/

Interactive File Management with SFTP

SFTP gives you an interactive shell for file operations. It’s like having a file manager that works over SSH.

Start an SFTP session:

sftp user@server

Once connected, you have two sets of commands – ones that work on the remote server and ones that work on your local machine:

Remote commands:

  • pwd shows your current directory on the server
  • ls lists files on the server
  • cd changes directories on the server
  • mkdir creates directories on the server

Local commands (notice the ‘l’ prefix):

  • lpwd shows your current local directory
  • lls lists your local files
  • lcd changes your local directory

Transfer commands:

  • put local_file.txt uploads a file
  • get remote_file.txt downloads a file
  • put -r local_directory/ uploads a directory recursively
  • get -r remote_directory/ downloads a directory recursively

Resuming Interrupted Transfers

One of SFTP’s handy features is the ability to resume interrupted transfers:

  • reget filename resumes a download
  • reput filename resumes an upload

Batch Mode for Automation

You can script SFTP operations by putting commands in a file:

# Create commands.txt with:
put /local/file1.txt
put /local/file2.txt
mkdir /remote/new_folder
cd /remote/new_folder
put -r /local/directory

# Then run:
sftp -b commands.txt user@server

Making SSH Transfers Faster and Easier

SSH Configuration Files

Instead of typing long commands with ports, keys, and usernames every time, create an SSH config file at ~/.ssh/config:

Host myserver
    HostName server.example.com
    User myusername
    Port 2222
    IdentityFile ~/.ssh/my_key
    Compression yes

Host production
    HostName prod.company.com
    User deploy
    IdentityFile ~/.ssh/prod_key

Now you can simply use:

scp file.txt myserver:/path/
rsync -avz ./dir/ production:/srv/app/

Connection Multiplexing

SSH can reuse connections, which speeds up multiple transfers significantly. Add this to your SSH config:

Host *
    ControlMaster auto
    ControlPath ~/.ssh/sockets/%r@%h-%p
    ControlPersist 600

Don’t forget to create the sockets directory:

mkdir -p ~/.ssh/sockets

Jump Hosts and Bastions

If you need to go through a bastion host to reach your target server, SSH can handle that automatically:

# One-time usage
scp -J bastion user@internal-server:/path/file .

# Or in your SSH config:
Host internal-app
    HostName 10.0.0.15
    User deploy
    ProxyJump bastion

Performance Tips and Tricks

Compression

On slow connections, compression can dramatically speed up transfers. Most of the tools support it:

  • SCP: use -C
  • rsync: use -z
  • SSH config: add Compression yes

For newer versions of rsync, you can even choose your compression algorithm:

rsync -av --compress-choice=zstd --compress-level=3 ./src/ user@server:/dest/

Parallel Transfers

While rsync doesn’t have built-in multi-threading, you can run multiple rsync processes for different files or directories:

# Example using GNU parallel
find ./large_directory -maxdepth 1 -type d | parallel rsync -avz {} user@server:/dest/

Cipher Selection

Different encryption ciphers have different performance characteristics. On modern CPUs with AES acceleration, [email protected] is often fastest. On older or low-power systems, [email protected] might be better.

You can test different ciphers:

scp -c aes128-ctr large_file.zip user@server:/dest/

Troubleshooting Common Issues

Permission Problems

The most common SSH transfer problems are permission-related. Make sure your SSH directory and key files have the right permissions:

chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_*
chmod 644 ~/.ssh/id_*.pub
chmod 600 ~/.ssh/authorized_keys

Host Key Verification Failures

If you get a “host key verification failed” error, it usually means the server’s key has changed. This could be legitimate (server was rebuilt) or a sign of trouble. If you’re sure it’s legitimate:

ssh-keygen -R hostname

This removes the old key, and you’ll be prompted to accept the new one on your next connection.

Debugging Connection Issues

When things go wrong, verbose output is your friend:

scp -vvv problematic_file user@server:/dest/
ssh -vvv user@server

The triple -v gives you detailed information about what SSH is trying to do and where it’s failing.

Slow Transfer Speeds

If transfers are slower than expected:

  • Try enabling compression with -C (scp) or -z (rsync)
  • Check if your SSH config has Compression yes
  • Test different ciphers to see if one performs better on your hardware
  • Consider whether network conditions or server load might be the bottleneck

Security Best Practices

Keys Over Passwords

Always use SSH keys instead of passwords when possible. Generate a strong key:

ssh-keygen -t ed25519 -C "[email protected]"

Then copy it to your servers:

ssh-copy-id user@server

Verify Server Identity

On your first connection to a server, SSH will show you the server’s fingerprint. Don’t just hit “yes” – verify this fingerprint through another channel (like asking your system administrator or checking documentation).

Keep Things Updated

Regularly update your SSH client and server software. Security vulnerabilities are discovered and patched regularly.

Server Hardening

If you manage the servers you’re connecting to, consider these hardening steps:

  • Disable root login: PermitRootLogin no
  • Disable password authentication: PasswordAuthentication no
  • Use AllowUsers to restrict which accounts can SSH in
  • Change the default SSH port (reduces automated attacks, though it’s not a strong security measure)
  • Use fail2ban or similar tools to automatically block brute-force attempts

Putting It All Together

SSH file transfers become second nature once you understand the strengths of each tool. Use SCP for quick, one-off copies. Reach for rsync when you’re syncing directories or need efficiency. Fire up SFTP when you want to browse around and selectively move files.

Set up your SSH config file to make connections seamless, and don’t forget about useful features like connection multiplexing and jump hosts. With these tools in your toolkit, moving files securely over the network becomes as natural as copying files on your local machine.

Remember: when in doubt, use the -n flag with rsync to do a dry run, and always verify that your transfers completed successfully. Your future self will thank you for taking these small precautions.

The beauty of SSH-based file transfers is that once you’ve got your keys and configuration set up properly, everything just works. No more juggling different protocols, ports, and authentication methods – just reliable, encrypted file transfers that integrate seamlessly with your existing SSH workflow.