Configuring lsyncd
At a glance#
- Purpose: Continuously replicate a directory from one Linux server to another as changes happen.
- Applies to: RHEL/CentOS 7+ and Ubuntu 18.04+.
- Risk: Medium — misconfigured paths can overwrite data on the target.
- Time: About 45 minutes.
Overview#
lsyncd (Live Syncing Daemon) watches a directory using the kernel's inotify interface and runs rsync whenever something changes. The result is near-real-time one-way replication without the delay of a cron job.
It is well suited to keeping a warm standby copy of web content or backups. It is not a backup on its own — deletions replicate too, so a file deleted by mistake on the source disappears from the target within seconds.
SOURCE SERVER TARGET SERVER
/backup ──inotify──> lsyncd ──rsync over SSH──> /backupWarning: Replication is one-way and destructive on the target. With delete = true (the default in most examples), anything present on the target but not the source is removed. Confirm the target directory is dedicated to this purpose before starting.
Before you start#
- Root access on both servers.
- Network connectivity from source to target on TCP 22.
- The target directory either empty or holding a known-good copy.
- Sufficient inotify watches for the number of files involved (see Troubleshooting).
The examples use:
| Role | Address | Path |
|---|---|---|
| Source | this server | /backup |
| Target | 192.168.213.80 | /backup |
Procedure#
1. Set up passwordless SSH from source to target#
lsyncd runs unattended, so it cannot answer a password prompt.
On the source server:
ssh-keygen -t ed25519 -f /root/.ssh/id_ed25519 -N ""Note:ed25519is preferred overrsaon any modern system — shorter keys, faster, and stronger. Use-t rsa -b 4096only if the target is old enough not to support it.
Copy the public key to the target:
ssh-copy-id -i /root/.ssh/id_ed25519.pub root@192.168.213.80Verify it works without prompting — do this before going further, because every later step depends on it:
ssh -i /root/.ssh/id_ed25519 root@192.168.213.80 "hostname"If that returns the target's hostname with no password prompt, continue.
2. Install lsyncd#
RHEL / CentOS 7 — lsyncd lives in EPEL, not the base repositories:
sudo yum install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
sudo yum install -y lsyncdRHEL 8/9 and Rocky/Alma:
sudo dnf install -y epel-release
sudo dnf install -y lsyncdUbuntu / Debian:
sudo apt update && sudo apt install -y lsyncdNote: On a subscription-managed RHEL system without internet access, EPEL will not be reachable. Either mirror the package internally or install it from a local repository — see Creating Local Repo for Red hat Server.
3. Create the configuration#
lsyncd is configured in Lua. Create the config directory and file:
sudo mkdir -p /etc/lsyncd
sudo nano /etc/lsyncd.confsettings {
logfile = "/var/log/lsyncd/lsyncd.log",
statusFile = "/var/log/lsyncd/lsyncd.status",
statusInterval = 20,
nodaemon = false,
}
sync {
default.rsync,
source = "/backup",
target = "192.168.213.80:/backup",
delay = 5,
delete = true,
rsync = {
archive = true,
compress = true,
rsh = "/usr/bin/ssh -l root -i /root/.ssh/id_ed25519 -o StrictHostKeyChecking=accept-new"
}
}Key settings:
| Setting | Meaning |
|---|---|
delay | Seconds to batch changes before syncing. Higher values reduce load on busy directories. |
delete | Remove files on target that no longer exist on source. Set false if the target must retain deleted files. |
archive | rsync -a — preserves permissions, ownership, timestamps and symlinks. |
compress | Compress in transit. Worth it over a WAN, unnecessary on a fast LAN. |
rsh | The SSH command, including which key to use. |
4. Create the log directory#
The package does not always create this, and lsyncd fails silently at startup if it is missing:
sudo mkdir -p /var/log/lsyncd
sudo chown root:root /var/log/lsyncd5. Validate the configuration before starting#
sudo lsyncd -nodaemon -log all /etc/lsyncd.confThis runs in the foreground with full logging. Watch for a successful initial sync, then stop it with Ctrl+C. Fix any errors before continuing — starting the service with a broken config just moves the failure somewhere less visible.
6. Start and enable the service#
sudo systemctl start lsyncd
sudo systemctl enable lsyncd
sudo systemctl status lsyncd7. Configure log rotation#
lsyncd logs grow steadily and will eventually fill the partition:
sudo nano /etc/logrotate.d/lsyncd/var/log/lsyncd/*.log {
daily
rotate 7
compress
missingok
notifempty
copytruncate
}Verification#
Confirm the service is running:
sudo systemctl status lsyncdTest replication end to end:
# On the source
echo "sync test $(date)" | sudo tee /backup/synctest.txt
# Wait a few seconds, then on the target
cat /backup/synctest.txtTest deletion propagation if delete = true:
# Source
sudo rm /backup/synctest.txt
# Target - should be gone within seconds
ls /backup/synctest.txtCheck the status file, which lsyncd rewrites periodically:
sudo cat /var/log/lsyncd/lsyncd.status
sudo tail -f /var/log/lsyncd/lsyncd.logTroubleshooting#
| Symptom | Cause and fix |
|---|---|
| Service starts then stops immediately | Log directory missing, or a Lua syntax error. Run in foreground with -log all to see the real error. |
Host key verification failed | The target key is not in known_hosts for root. Connect once manually as root to accept it. |
| Files not syncing, no errors | inotify watch limit reached. Check cat /proc/sys/fs/inotify/max_user_watches, then raise it: `echo "fs.inotify.max_user_watches=524288" |
| High CPU on the source | Too many changes with too low a delay. Increase delay to 15–30 seconds. |
| Permission denied on target | rsync runs as the SSH user. Confirm that user can write to the target path. |
| Deletions not replicating | delete = false in the configuration. |
| Sync stops after network interruption | lsyncd does not always recover cleanly. Restart the service and consider a nightly rsync as a safety net. |
Related#
- [Windows-to-Linux Rsync Sync for Nextcloud (via SSH)](Windows-to-Linux%20Rsync%20Sync%20for%20Nextcloud%20(via%20SSH%20240bf62b1b5380d3884acbf2c61e2d55.md)
- Creating Local Repo for Red hat Server