BLOG POSTS
How to Copy Files with rsync over SSH

How to Copy Files with rsync over SSH

Remote file synchronization is a critical skill for anyone managing servers or working with distributed systems. The rsync tool over SSH provides a secure, efficient, and flexible way to copy files between systems while preserving permissions, timestamps, and only transferring changed data. This guide will walk you through everything from basic rsync syntax to advanced scenarios, troubleshooting common issues, and optimizing performance for production environments.

How rsync over SSH Works

Rsync combines the power of remote synchronization with SSH’s security layer. Unlike simple file copy commands, rsync uses a sophisticated algorithm that compares source and destination files, transferring only the differences. When tunneled through SSH, all data transmission is encrypted and authenticated.

The process works by establishing an SSH connection to the remote host, then spawning an rsync process on both ends. These processes communicate through the encrypted tunnel, exchanging checksums and file metadata before transferring actual data. This approach makes rsync incredibly efficient for incremental backups and large file transfers.

Basic rsync Syntax and Setup

Before diving into examples, ensure both systems have rsync installed. Most Linux distributions include it by default, but you can install it using your package manager:

# Ubuntu/Debian
sudo apt-get install rsync

# CentOS/RHEL
sudo yum install rsync

# macOS
brew install rsync

The basic syntax for rsync over SSH follows this pattern:

rsync [options] source user@host:destination

Here’s a simple example copying a local directory to a remote server:

rsync -avz /local/path/ user@remote-server:/remote/path/

The most commonly used options are:

  • -a: Archive mode (preserves permissions, timestamps, symbolic links)
  • -v: Verbose output
  • -z: Compress data during transfer
  • -P: Show progress and keep partially transferred files
  • –delete: Delete files in destination that don’t exist in source

Step-by-Step Implementation Guide

Setting Up SSH Keys (Recommended)

For automated transfers and better security, configure SSH key authentication:

# Generate SSH key pair
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"

# Copy public key to remote server
ssh-copy-id user@remote-server

# Test SSH connection
ssh user@remote-server

Basic File Transfer Examples

Copy a single file to remote server:

rsync -avz /path/to/file.txt user@remote-server:/destination/

Copy directory contents (note the trailing slash):

rsync -avz /source/directory/ user@remote-server:/destination/directory/

Copy directory itself (no trailing slash):

rsync -avz /source/directory user@remote-server:/destination/

Pull files from remote to local:

rsync -avz user@remote-server:/remote/path/ /local/destination/

Advanced Options and Configurations

For production environments, you’ll often need more sophisticated options:

# Exclude specific files or patterns
rsync -avz --exclude='*.log' --exclude='cache/' /source/ user@remote:/dest/

# Use specific SSH port
rsync -avz -e "ssh -p 2222" /source/ user@remote:/dest/

# Bandwidth limiting (KB/s)
rsync -avz --bwlimit=1000 /source/ user@remote:/dest/

# Dry run to see what would be transferred
rsync -avzn /source/ user@remote:/dest/

Real-World Use Cases and Examples

Website Deployment

Deploy a website while excluding development files:

rsync -avz --delete \
  --exclude='.git/' \
  --exclude='node_modules/' \
  --exclude='*.log' \
  /local/website/ user@webserver:/var/www/html/

Database Backup Synchronization

Sync database backups to a remote backup server:

#!/bin/bash
# backup-sync.sh
BACKUP_DIR="/var/backups/mysql"
REMOTE_HOST="backup-server.example.com"
REMOTE_USER="backup"
REMOTE_PATH="/backups/mysql-primary"

rsync -avz --delete \
  --exclude='*.tmp' \
  "$BACKUP_DIR/" \
  "$REMOTE_USER@$REMOTE_HOST:$REMOTE_PATH/"

if [ $? -eq 0 ]; then
    echo "Backup sync completed successfully"
else
    echo "Backup sync failed" >&2
    exit 1
fi

Development Environment Synchronization

Keep development and staging environments in sync:

rsync -avz --delete \
  --exclude='wp-config.php' \
  --exclude='wp-content/uploads/' \
  /var/www/development/ \
  staging@staging-server:/var/www/staging/

Performance Optimization and Best Practices

Compression and Network Optimization

The effectiveness of compression depends on your data type and network speed:

Data Type Compression Benefit Recommended Option
Text files, code High (60-80% reduction) -z or –compress-level=6
Already compressed (videos, images) Minimal (may slow transfer) No compression
Mixed content Moderate (30-50% reduction) -z with selective exclusion

For high-bandwidth connections, disable compression for better CPU utilization:

rsync -av --no-compress /source/ user@remote:/dest/

SSH Connection Optimization

Configure SSH for better rsync performance in ~/.ssh/config:

Host production-server
    HostName prod.example.com
    User deploy
    Port 22
    IdentityFile ~/.ssh/deploy_key
    Compression yes
    ControlMaster auto
    ControlPath ~/.ssh/control-%h-%p-%r
    ControlPersist 600

This configuration enables SSH connection multiplexing, reusing existing connections for multiple rsync operations.

Troubleshooting Common Issues

Permission Denied Errors

When encountering permission issues:

# Check SSH connectivity first
ssh -v user@remote-server

# Verify destination directory permissions
ssh user@remote-server 'ls -la /destination/path/'

# Use sudo on remote side if needed
rsync -avz /source/ user@remote:/tmp/staging/
ssh user@remote 'sudo mv /tmp/staging/* /final/destination/'

Network Interruption Recovery

For unreliable connections, use the partial transfer and retry options:

rsync -avzP --timeout=60 --contimeout=60 /source/ user@remote:/dest/

Create a retry script for critical transfers:

#!/bin/bash
MAX_RETRIES=3
RETRY_COUNT=0

while [ $RETRY_COUNT -lt $MAX_RETRIES ]; do
    rsync -avzP /source/ user@remote:/dest/
    if [ $? -eq 0 ]; then
        echo "Transfer completed successfully"
        exit 0
    else
        RETRY_COUNT=$((RETRY_COUNT + 1))
        echo "Transfer failed, retry $RETRY_COUNT of $MAX_RETRIES"
        sleep 10
    fi
done

echo "Transfer failed after $MAX_RETRIES attempts" >&2
exit 1

Performance Issues

If transfers are slower than expected:

  • Test network bandwidth: iperf3 -c remote-server
  • Monitor disk I/O: iostat -x 1
  • Check CPU usage during compression
  • Use rsync --stats to analyze transfer statistics

Comparison with Alternative Solutions

Tool Best For Pros Cons
rsync over SSH Incremental sync, backups Delta transfer, secure, preserves metadata Learning curve, SSH dependency
scp Simple file copies Simple syntax, secure No incremental transfer, slower for large files
SFTP Interactive file management User-friendly, secure Manual process, no automation
rclone Cloud storage sync Multiple cloud providers, encryption Complex configuration, resource intensive

Security Considerations and Best Practices

Always follow security best practices when using rsync over SSH:

  • Use SSH key authentication instead of passwords
  • Implement proper firewall rules and SSH hardening
  • Use dedicated service accounts with minimal privileges
  • Enable SSH connection logging and monitoring
  • Consider using jump hosts for accessing production servers

For automated backups, create a restricted SSH key:

# Create restricted key for backup purposes
ssh-keygen -t rsa -b 4096 -f ~/.ssh/backup_key -C "backup-automation"

# Add to remote server's authorized_keys with restrictions
command="rsync --server -vlogDtpre.iLsfxC . /backup/destination/",
no-agent-forwarding,no-port-forwarding,no-pty,no-user-rc,no-X11-forwarding 
ssh-rsa AAAAB3NzaC1yc2E... backup-automation

This configuration ensures the SSH key can only be used for specific rsync operations.

Integration with Monitoring and Automation

For production environments, integrate rsync operations with monitoring systems:

#!/bin/bash
# monitored-sync.sh
LOGFILE="/var/log/rsync-sync.log"
METRIC_FILE="/var/metrics/rsync-last-run"

echo "$(date): Starting rsync operation" >> "$LOGFILE"
START_TIME=$(date +%s)

rsync -avz --stats /source/ user@remote:/dest/ 2>&1 | tee -a "$LOGFILE"
RSYNC_EXIT_CODE=${PIPESTATUS[0]}

END_TIME=$(date +%s)
DURATION=$((END_TIME - START_TIME))

# Write metrics for monitoring system
echo "rsync_duration_seconds $DURATION" > "$METRIC_FILE"
echo "rsync_exit_code $RSYNC_EXIT_CODE" >> "$METRIC_FILE"
echo "rsync_timestamp $END_TIME" >> "$METRIC_FILE"

if [ $RSYNC_EXIT_CODE -eq 0 ]; then
    echo "$(date): Rsync completed successfully in ${DURATION}s" >> "$LOGFILE"
else
    echo "$(date): Rsync failed with exit code $RSYNC_EXIT_CODE" >> "$LOGFILE"
fi

Whether you’re managing a single VPS or multiple dedicated servers, mastering rsync over SSH will significantly improve your file management capabilities. The combination of security, efficiency, and flexibility makes it an indispensable tool for system administrators and developers working with remote systems.

For additional information and advanced use cases, consult the official rsync documentation and the OpenSSH manual.



This article incorporates information and material from various online sources. We acknowledge and appreciate the work of all original authors, publishers, and websites. While every effort has been made to appropriately credit the source material, any unintentional oversight or omission does not constitute a copyright infringement. All trademarks, logos, and images mentioned are the property of their respective owners. If you believe that any content used in this article infringes upon your copyright, please contact us immediately for review and prompt action.

This article is intended for informational and educational purposes only and does not infringe on the rights of the copyright owners. If any copyrighted material has been used without proper credit or in violation of copyright laws, it is unintentional and we will rectify it promptly upon notification. Please note that the republishing, redistribution, or reproduction of part or all of the contents in any form is prohibited without express written permission from the author and website owner. For permissions or further inquiries, please contact us.

Leave a reply

Your email address will not be published. Required fields are marked