Bali, Indonesia
Insights

Thinking Replication to a Second Server Is a Backup, Until It Syncs Encrypted Files

November 3, 2026
0:00
A common setup looks responsible on paper: production on one server, a second server receiving a mirror via rsync, lsyncd, or database replication, and a note in the runbook that says disaster recovery is covered. Then ransomware runs on production, or someone deletes the wrong directory, and the second server ends up holding the same encrypted or missing files a few seconds or minutes later. The mirror did exactly what it was built to do. It just was never a backup. The difference comes down to one property. A backup keeps history, so you can go back to how things looked before the damage. A replica keeps the present, so it always looks like the source, including the source's mistakes. Looking at how each replication method actually moves data makes it clear why encrypted files travel across so reliably.
Replication answers one question: if the primary machine disappears right now, is there another machine with nearly the same data? That is a hardware-failure question. Dead disk, failed RAID controller, a host that will not boot, a datacenter network outage. For those, a replica is excellent, because the data on the second server is recent and often ready to serve. It does not answer the other question: if the data on the primary becomes wrong, is there a copy of the data from before it went wrong? Ransomware, a bad deploy that truncates files, a plugin update that corrupts a database, an rm -rf in the wrong path. These are logical failures. The hardware is fine, the filesystem is consistent, and every write is a perfectly valid write. Replication has no way to tell an encrypting process apart from an editor saving a file, so it copies both. This is also what tends to confuse site owners when they ask support to restore from the mirror. The mirror exists, it is reachable, and it is up to date. That is precisely the problem.
Scheduled rsync is the simplest case. On each run, rsync builds a file list on both ends and, by default, uses a quick check: if a file's size or modification time differs, it is treated as changed. Encrypted files almost always differ in both. rsync then transfers the changes, writes the new content to a temporary file on the receiver, and renames it over the old one. Once that rename completes, the previous version on the mirror is gone. There is no older copy kept unless you ask for one with options like --backup and --backup-dir. The deletion side is worse. Many ransomware families do not overwrite in place. They read the original, write an encrypted copy under a new name (often with an added extension), then unlink the original. From rsync's point of view, the source now has new files and is missing the old ones. If the job runs with --delete, which mirror setups usually do so the copy stays clean, rsync removes the clean originals from the mirror and uploads the encrypted ones. The cron job finishes with exit code 0 and nothing looks unusual in its log. Before trusting any mirror job, it helps to see what it would do right now. A dry run lists changes and deletions without touching the destination:
BASH
# -n is a dry run: nothing is transferred or deleted
# --itemize-changes shows why each file would be updated
rsync -avn --delete --itemize-changes /var/www/ backup-host:/srv/mirror/www/
Lines starting with *deleting are files the mirror would lose on the next real run. On a healthy server this list is short. After an encryption run it would be most of the site. lsyncd removes even the delay that a cron schedule gives you. It uses inotify, the Linux kernel interface that reports filesystem events on watched directories. When a process closes a file it wrote, the kernel emits IN_CLOSE_WRITE. When a file is renamed, it emits IN_MOVED_FROM and IN_MOVED_TO. When a file is unlinked, it emits IN_DELETE. lsyncd collects these events for a short window, then spawns rsync for the affected paths. An encryption run produces a dense stream of exactly these events, so lsyncd dutifully batches them and pushes the result to the second server. The faster your sync, the faster the damage arrives.
Block-level replication such as DRBD sits below the filesystem. It sees write requests to the block device, not files. Every block the filesystem writes on the primary is sent to the secondary, and in synchronous mode the write is not acknowledged to the filesystem until the peer confirms it has the data too. That is what makes it valuable for hardware failover: the secondary is byte-identical. It is also why it offers no protection here. When ransomware writes encrypted blocks, DRBD replicates encrypted blocks. When a file is deleted and the filesystem marks blocks as free, those metadata writes are replicated as well. There is no file-level history to fall back on. Database replication follows the same logic at a different layer. In MySQL, the source records changes in the binary log, and replicas read that log and apply each event. A DROP TABLE, a mass UPDATE without a WHERE clause, or a compromised application rewriting rows all become binlog events. The replica applies them in order, usually within seconds. If the attacker encrypts the data directory files directly instead of going through SQL, the replica may keep its own copy intact, but it is still connected to the same source, so any later damage through SQL lands on it too. One useful variation is a delayed replica, which applies events only after a fixed lag. That turns replication into a short rewind window for SQL-level mistakes:
SQL
-- MySQL 8.0.23+ syntax; older versions use CHANGE MASTER TO ... MASTER_DELAY
STOP REPLICA;
CHANGE REPLICATION SOURCE TO SOURCE_DELAY = 3600; -- illustrative example: one hour
START REPLICA;
If someone drops a table, you have up to the delay window to stop the replica before it applies the event. It is helpful, but it is still not a backup. It only covers SQL changes, the window is short, and it does nothing for files on disk.
Recovery Point Objective (RPO) is how much data you can afford to lose, measured as time. If your RPO is one hour, you need a copy that is never more than an hour old. Replication makes RPO look close to zero, and for hardware failure it really is. For logical damage, the useful measure is different: how far back is the last copy that is still good? With a pure mirror, the answer is often never, because the mirror has already been overwritten with the bad state. The effective RPO becomes whatever older copy you happen to have elsewhere, which is sometimes nothing at all. The June 2024 ransomware attack on Indonesia's Temporary National Data Center 2 (PDNS 2) in Surabaya is a reminder of how large the impact can be. Public reporting described 282 government tenants disrupted, a USD 8 million ransom demand, and malware identified as Brain Cipher, a variant linked to LockBit 3.0. In incidents like that, what matters during recovery is not how many copies of the data exist, but how many copies the attacker could not reach or change.
You do not have to throw the replica away. Keep it for failover, and add something that holds history and resists change from production. A few approaches work well together. Versioned snapshots keep multiple restore points. A simple pattern with plain rsync uses --link-dest: each run creates a new dated directory, and files unchanged since the previous run are hard-linked instead of copied, so many versions cost little extra space. Running it from the backup server, pulling from production, matters as much as the versioning:
BASH
# Run on the backup server, not on production
set -e
today=$(date +%F)
base=/srv/backups/site
rsync -a --link-dest="base/latest" backup-ro@prod-host:/var/www/ "base/$today/"
ln -sfn "base/today" "$base/latest"
Note that this snapshot will still copy encrypted files on the day of the attack. The protection is that yesterday's directory is untouched, as long as you prune old snapshots on a schedule you control and production has no way to reach the backup server. Pull-based access is the key part. If production holds an SSH key or storage credentials that can write to the backup target, ransomware running as root on production can use them to delete or encrypt the backups too. Reversing the direction, so the backup server connects to production with a read-only account, removes that path. The same idea applies to offsite storage, which is covered in more detail in checking that offsite backups don't get deleted along with the server. Append-only or immutable storage helps when you need to push from production. Tools like borg and restic can run their server side in an append-only mode, so a client can add new archives but not remove existing ones. Many object storage providers offer object lock or retention settings that block deletion until a set date. Behavior differs between providers, so check the documentation of the one you use and test that a delete actually fails. Offline copies are the last layer: a copy on media or an account that is disconnected from both servers most of the time. It is slower to restore, but nothing running on production can touch it. Whatever mix you choose, test a restore from an older version, not just the latest. A backup set where only the newest point has ever been tested can hide the exact problem this article describes. The practical rule is simple. Keep replication for what it is good at, staying online when hardware fails, and put a separate, versioned copy somewhere production cannot write to or delete from. Then ask one question of every copy you have: if the primary were encrypted ten minutes ago, would this copy still hold yesterday's files? If the answer is no, it is a replica, not a backup.