Lsyncd (Live Syncing Daemon) is a free and open source we can use to keep a source and a target directory tree in sync. Written in the LUA programming language, it works by keeping track of filesystem events on the source, and replicating them on the target, typically using tools like rsync and ssh, under the hood. In this tutorial, we learn how to install lsyncd on the most used Linux distributions, and how to configure it to keep local and remote directories in sync.
In this tutorial you will learn:
- How to install lsyncd on some of the most used Linux distributions
- How to configure lsyncd to keep local and remote directories in sync

| Category | Requirements, Conventions or Software Version Used |
|---|---|
| System | Distribution-agnostic |
| Software | lsyncd |
| Other | Root privileges |
| Conventions | # – requires given linux-commands to be executed with root privileges either directly as a root user or by use of sudo command$ – requires given linux-commands to be executed as a regular non-privileged user |
Installation
Lsyncd is available in the official repositories of Fedora, Debian, and Ubuntu; installing it on those systems is just a matter of launching those distributions package managers. To perform the installation on Debian and its derivatives, Ubuntu included, we can use apt:
$ sudo apt install lsyncd
To install lsyncd on Fedora, instead, we use dnf:
$ sudo dnf install lsyncd
We can use the dnf package manager also to install lsyncd on Red Hat Enterprise Linux and its clones (Rocky Linux and AlmaLinux, for example), however, since those distributions don’t package the utility directly, we must first add the EPEL repository as a software source.
Installing lsyncd on Archlinux (AUR)
Although lsyncd is not directly available in the Archlinux official repositories, we can install it from the AUR (Arch User Repository), either using an AUR helper such as yay, or by building it manually. In this tutorial, we follow the second method.
As a first thing, we must ensure git and the base-devel packages are installed on our system:
$ sudo pacman -S install git base-devel
We also must install some build-dependencies:
$ sudo pacman -S asciidoc cmake lua53-posix
The PKGBUILD containing the package build instructions, and the other required files, are maintained in a git repository; we can clone it with the following command:
$ git clone https://aur.archlinux.org/lsyncd.git
To start building the package, we enter the git repository we just cloned, and issue the makepkg command:
$ cd lsyncd && makepkg
The process may take a while, depending on our machine resources. Once the building is complete, we should find the package in the current working directory. The package is named after the lsyncd version, which, at the moment of writing, is “2.3.1”. To install it, we run:
$ sudo pacman -U lsyncd-2.3.1-9-x86_64.pkg.tar.zst
Configuring lsyncd
To specify how lsyncd should run, we edit its main configuration file, which is itself written in LUA. On Fedora and Fedora-based distributions, the file is /etc/lsyncd.conf, while on the other distributions is: /etc/lsyncd/lsyncd.conf.lua. Notice that the file may not exist by default, therefore we may need to create it manually. Although it is possible to heavily customize the actions performed by lsyncd to keep source and target trees in sync, here we will learn to use the two main default implementations: rsync and rsync-ssh.
The rsync implementation
To start using the “rsync” implementation, we can start by copying the /usr/share/doc/lsyncd/examples/lrsync.lua example file in place, and modify it to match our use-case. On Fedora, we can run:
$ sudo cp /usr/share/doc/lsyncd/examples/lrsync.lua /etc/lsyncd.conf
On all the other distributions, instead:
$ sudo mkdir -p /etc/lsyncd/ && sudo cp /usr/share/doc/lsyncd/examples/lrsync.lua /etc/lscynd.conf.lua
Here is the content of the file:
----
-- User configuration file for lsyncd.
--
-- Simple example for default rsync.
--
settings {
▸\statusFile = "/tmp/lsyncd.stat",
▸\statusInterval = 1,
}
sync{
▸\default.rsync,
▸\source="src",
▸\target="trg",
}
The first thing we can see in the file, is the invocation of the settings function, which is used to change the daemon settings. It takes an associative array as argument, populated by configuration parameters and their values (the missing parenthesis around the argument, is just LUA syntactic sugar). In this case, for example, we can see the statusfile path is set to /tmp/lsyncd.stat (lsyncd uses this file to periodically write a status record), and statusInterval, the interval of time after lsyncd write to the status file, is set to 1 sec. We can find the complete list of the available parameters in the official documentation.
After the settings function, the sync once is called to actually sync the content of the source and the target directories. This functions also takes an associative array as its only argument: it includes the name of the implementation we want to use (default.rsync in this case), and the path of source and target directories. Supposing we wanted to keep the /var/www/html directory in sync with /opt/www/html on the same machine, we would write:
sync{
▸\default.rsync,
▸\source="/var/www/html",
▸\target="/opt/www/html",
}
Only the content of the source directory will be synchronized, not the directory itself. Furthermore, the target directory must exist for the command to be successful. To keep the target directory synchronized with a remote directory, all we have to do, is to include the host part in the target definition, just as we would do if calling rsync directly. Just as an example, to use the /opt/www/html directory as target, on a remote host with IP 192.168.122.186, connecting to it as the “vagrant” user, we would write:
sync{
▸\default.rsync,
▸\source="/var/www/html",
▸\target="vagrant@192.168.122.186:/opt/www/html",
}
It goes by itself that for this to work, an ssh connection must already be configured and authorized.
The rsyncssh implementation
The default.rsyncssh implementation differs from default.rsync, in the way it handles moving files. The latter deletes the files and re-transmits them, while the former uses ssh commands to move them locally, at the target host. When using this implementation, instead of including the remote hostname as part of the “target”, we pass it via a dedicated parameter: “host”.
As a base for this implementation, we can use the /usr/share/doc/lsyncd/examples/lrsyncssh.lua file. Here is its content:
----
-- User configuration file for lsyncd.
--
-- Simple example for default rsync, but executing moves through on the target.
--
sync{default.rsyncssh, source="src", host="localhost", targetdir="dst/"}
To synchronize the two directories we saw in the previous example using this implementation, we would write:
----
-- User configuration file for lsyncd.
--
-- Simple example for default rsync, but executing moves through on the target.
--
sync{
▸\default.rsyncssh,
▸\source="/var/www/html",
▸\host="vagrant@192.168.122.186",
▸\targetdir="/opt/www/html/"
▸\}
Passing rsync and ssh options
Both when using the default.rsync and default.rsyncssh implementations, it is possible to specify additional rsync options, via the “rsync” parameter. We can, for example, specify an alternative path for the restic binary, run rsync in archive mode (as if using the -a option), and make it read the list of files to be excluded from a file, by writing:
sync{
▸\default.rsync,
▸\source="/var/www/html",
▸\target="vagrant@192.168.122.186:/opt/www/html",
▸\rsync={
▸\▸\binary="/usr/local/bin/restic"
▸\▸\archive=true,
▸\▸\excludeFrom=/etc/rsync_excludes.txt
▸\}
}
When using the default.rsyncssh implementation, it is also possible to pass SSH options, using the “ssh” parameter. As the “rsync” one, it takes an associative array as value. By using it, just as an example, we can specify an alternative port for the ssh connection:
sync{
▸\default.rsyncssh,
▸\source="/var/www/html",·
▸\host="vagrant@192.168.122.186",·
▸\targetdir="/opt/www/html",
▸\ssh={
▸\▸\port=15400
▸\}
}
Starting and enabling the lsyncd service
Since the vast majority of Linux distributions adopted systemd as their init system, to start the lsyncd service and enable it at boot, we can use the following command:
$ sudo systemctl enable --now lsyncd.service
Conclusions
In this tutorial, we learned how to install lsyncd on some of the most used Linux distributions, and how to use it two keep two local or remote directory trees in sync. Remember that lsyncd works only in one direction, synchronizing the content of the source directory with the target. Bidirectional sync is not possible.