Blog · WebJi® India

Rsync Files to a Server

Quick answer: Copy files to a server with rsync -avz /local/path/ user@host:/remote/path/. The trailing slash copies the folder's contents; leave it off and you get an extra nesting level. Run with -n first, use --delete only for a true mirror, and use an SSH key so cron can run it without a password.
✓ In business since 2005✓ INR + GST billing✓ 24/7 Email Support — avg reply < 60 min
Stacked hard drives in a secure storage room with one drive glowing, symbolising safe data backups — rsync files to server

The rsync command that copies files to a server

Rsync sends only the parts of a file that changed, over SSH, which is why a second copy of a 2 GB site takes seconds. The whole syntax hangs on which side the remote host sits.

DirectionCommandUse it for
Pushrsync -avz ./site/ user@203.0.113.10:/var/www/site/Laptop or build server to the live server
Pullrsync -avz user@203.0.113.10:/var/www/site/ ./site-copy/Backup, or copying production down to test
Through a portrsync -avz -e "ssh -p 2222" ./site/ user@host:/var/www/site/Any server that is not on port 22

The remote side needs rsync installed as well, even for a pull. On Debian or Ubuntu the package is rsync; on RHEL and its clones it is also rsync, from the base repository.

The trailing slash decides what gets copied

This is the rule that catches everyone once. /var/www/site/ means the contents of that folder. /var/www/site means the folder itself.

  • rsync -av ./site/ host:/var/www/site/ puts index.php at /var/www/site/index.php. Correct for a deploy.
  • rsync -av ./site host:/var/www/site/ puts it at /var/www/site/site/index.php. The site disappears behind a folder.
  • A trailing slash on the destination changes nothing. Only the source matters.

Which flags matter on a web server

-avz is the default most people type. Two of those three letters do real work, and one is often a waste.

FlagWhat it doesWhen to keep it
-aArchive mode: recursive, keeps permissions, timestamps, links and ownershipAlmost always, for a site deploy
-zCompresses during transferSlow or metered links. Drop it for JPEGs, video and zips, which are already compressed
-PProgress plus resumable partial filesLarge uploads on a connection that drops
--checksumCompares content instead of size and mtimeVerifying a backup, not routine syncs
--bwlimit=8000Caps transfer at about 8 MB/sA daytime sync that must not saturate the link
-e "ssh -p 2222"Passes options to SSHNon-standard port or a specific identity file

Exclude the files that should never be copied

A raw copy of a project folder carries things the server does not need and should not serve: version history, build caches, logs and local environment files.

  1. Start with the obvious four: --exclude='.git/' --exclude='node_modules/' --exclude='*.log' --exclude='.env'
  2. Move the list into a file once it passes three entries: --exclude-from=/etc/rsync-excludes.txt
  3. Keep .well-known/ and any upload folder out of the exclude file. Both are needed on the live server.
  4. Check the paths rsync actually sees with -v. Patterns match from the source root, so cache/ will not match wp-content/cache/.

Dry run, then mirror with --delete

--delete removes anything on the server that is not in the source. That is what makes a mirror a mirror, and it is also how a wrong source path empties a live site. Never run it first.

  1. Dry run with the exact command you intend to use, plus -n: rsync -avzn --delete ./site/ user@host:/var/www/site/
  2. Read the deletions in the output line by line. A wall of deleting lines usually means a wrong source path or a missing trailing slash.
  3. Take a server-side copy before the first real run: ssh user@host "cp -a /var/www/site /var/www/site.bak"
  4. Drop the -n and run again. Keep -v for the first run, then remove it.

If the site writes uploads or cache files on the server, exclude those folders instead of using --delete. A mirror will delete every file a visitor created since the last sync.

Run the sync from cron with an SSH key

A sync that needs a typed password cannot run on a schedule. Generate a key for this job alone, copy the public half to the server, then test the login before you touch cron.

  1. ssh-keygen -t ed25519 -f ~/.ssh/deploy_key -C "deploy" and leave the passphrase empty for a cron job, or load it into an agent.
  2. ssh-copy-id -i ~/.ssh/deploy_key.pub user@203.0.113.10
  3. Add the host to ~/.ssh/config so the command stays short and cron does not parse quotes badly: Host live, then HostName, User, Port and IdentityFile.
  4. Write the job as a script with absolute paths: /usr/bin/rsync -az --delete -e "ssh -i /home/deploy/.ssh/deploy_key" /var/www/build/ deploy@live:/var/www/site/
  5. Add the log redirect so a failure is visible: 0 2 * * * /usr/local/bin/deploy.sh >> /var/log/deploy.log 2>&1

Fix ownership after the files land

Rsync with -a keeps the numeric owner and group from the source machine. If your laptop user is 501 and the web user is 1001, Apache or PHP will return 403 on files it cannot read.

Set ownership to the web user after the transfer: chown -R www-data:www-data /var/www/site on Debian and Ubuntu, or the account user on a cPanel or DirectAdmin server. Files go to 644 and folders to 755, never 777. On a WordPress site the uploads folder usually needs to stay writable by the web user, which chown already handles.

If you sync as a non-root deploy user, add --no-o --no-g so rsync stops trying to set ownership it is not allowed to set. The transfer stops reporting errors, and the chown step becomes the only place ownership is set.

Rsync exit codes and common failures

SymptomCauseFix
Exit code 23, "some files could not be transferred"Usually a permission error, or a file that changed while being readRead the list above the code, fix ownership, re-run. Code 23 on a live site is normal and harmless
Exit code 24, "some files vanished"A file was deleted during the transfer, often a cache fileRe-run once. If it repeats every time, exclude that folder
Permission denied (publickey)The key is not offered to the host, or ~/.ssh is 755 instead of 700Test with ssh -v host, fix the permissions, confirm the key is in authorized_keys
rsync: command not foundrsync is missing on the remote end, even for a pullInstall the package on both machines
Files transfer again on every runTimestamps are not preserved on the destination filesystemAdd --checksum once to confirm, then fix the mount or use a filesystem that keeps mtime

Rsync on a WebJi® VPS

Rsync over SSH needs a server where you have a shell account and a key of your own. A WebJi® VPS gives you root access from the first boot, so the deploy user, the key and the cron job are yours to create.

VPS plans start at ₹499 a month, before 18% GST, with the configuration quoted by email at support@webji.services before you pay. If you are moving an account rather than a folder, the DirectAdmin restore guide covers archives and databases.

Frequently Asked Questions

How do I copy files to a server with rsync?

Run rsync -avz /local/path/ user@server:/remote/path/. The local path comes first for a push. Put the remote host first to pull files down. The trailing slash on the source copies the folder's contents rather than the folder itself.

What does the trailing slash in rsync do?

It changes the source from the folder to its contents. With the slash, files land directly in the destination. Without it, rsync creates one more folder level, which is the usual reason a deploy shows an empty site.

Is rsync --delete safe?

Only after a dry run. Add -n to the exact command and read the deletion list before running it for real. Keep a server-side copy of the site, and never point --delete at a source path you have not checked.

How do I run rsync from cron without a password?

Use an SSH key with no passphrase, or load the key into an agent. Copy the public key with ssh-copy-id, use absolute paths inside the script, and redirect stdout and stderr to a log so a failed run is visible.

Why do files get 403 after an rsync deploy?

Rsync with -a copies numeric ownership from the source machine, so the web server may not be able to read the files. Run chown -R www-data:www-data on the site folder, set files to 644 and folders to 755.

Can I use rsync on shared hosting?

Only if your host gives you SSH and rsync on the account. On shared hosting you usually deploy through the file manager, SFTP or git. Rsync needs a shell account, which is what a VPS or a dedicated server provides.

Need help with this?

WebJi® support does it for you — free. Talk to our Jaipur team →