
Rsync over SSH is the standard way to sync files between two servers, whether it's a one-time push from staging to production or a job that runs on a schedule for months. It transfers only the bytes that changed since the last run instead of re-copying every file, and the whole transfer travels through an encrypted SSH tunnel rather than an unencrypted protocol.
The trailing slashes matter more than they look like they should. `/home/user/apps/mysite/` with a trailing slash syncs the contents of that directory into the destination path directly, while dropping the slash syncs the directory itself into the destination, nesting everything one level deeper than intended. Get that detail wrong once on a live server and every path inside the app breaks.
Adding `--delete` turns a plain rsync into a true mirror: it removes files on the destination that no longer exist on the source, which is exactly what "keep these two servers identical" syncing requires. Without it, files deleted on the source over time just pile up and drift on the destination forever, and the two servers slowly stop matching each other even though the sync job keeps running successfully.
`--delete` is destructive by design, and a reversed source and destination or a typo in the path can wipe out files on the wrong server in seconds. Always run with `-n` first to see the exact list of what would be removed, read that list, and only drop `-n` once it matches what you expect.
A cron job is the right way to run a recurring sync instead of remembering to trigger it by hand every day. Once the rsync command is tested and safe, dropping it into crontab with a fixed interval means the destination server never falls far out of date, and every run gets logged so you can check what happened after the fact.
A 15-minute interval is a reasonable starting point for keeping a failover server's static files current without hammering either box. Tighten it if the servers can handle more frequent runs, or loosen it for large directories where a full changed-file scan every few minutes adds noticeable I/O load.
`lsyncd` triggers a sync the moment a file changes instead of waiting for the next scheduled cron run. It watches the filesystem using inotify and fires off an rsync push as soon as it sees a write, which closes the gap between a change on the source and that change reaching the destination down to seconds rather than minutes.
That kind of near-real-time behavior is worth the extra setup only when a cron interval — even a tight one — is genuinely too slow, such as keeping a hot standby server current for fast failover, or syncing an upload directory that customers are actively writing to. For most staging-to-production or periodic-backup use cases, a cron-scheduled rsync job is simpler to run and easier to reason about than a persistent inotify watcher.
A large sync job can saturate a shared network link and starve every other connection on the same server, which is why `--bwlimit` exists. Capping the transfer rate keeps a big sync from turning into an outage for anything else running on that box at the same time.
Never rsync `/var/lib/mysql` as raw files while MySQL or MariaDB has the database open. A file-level copy can capture tables mid-write and hand you a corrupted, unusable database on the other end. Use `mysqldump` for database data, or set up proper database replication, and keep rsync for static assets, uploads, and application code only.
CloudStick's Server Transfer feature moves an entire website — files and database together — between two connected servers directly from the dashboard, coordinating the database dump and restore step for you instead of requiring a hand-built rsync-plus-mysqldump pipeline. For teams running staging and production on separate CloudStick servers, that turns a multi-step manual sync into a single guided action.
Role-based team seats also mean the right person can trigger that transfer without needing SSH access to either box, which matters once more than one person is responsible for keeping servers in sync. If your workflow is a plain rsync cron job for static files and a hot standby that needs to stay current, that setup still works fine and costs nothing extra to run. When the job involves moving a full site with its database between two servers on a recurring basis, that's the point where a guided transfer beats a hand-maintained script — one less pipeline to babysit, and one less place for a stray `--delete` to do damage.

