お金をかけずにサーバーの勉強をしよう

2つのサーバー間でファイルの同期をする

2025年10月19日

メニューへ戻る

1つのサーバーでファイルが変更されたら2つ目のサーバーに同期をします。

システムサーバー構成設計における考え方のお勉強の一環のネタになります。

あるサーバーで結構重要な情報を持つファイルを扱っているとして、このファイルがそこそこの頻度(ファイルサーバーのファイル程ではないという程度)で変更されるものとします。

その「あるサーバー」が障害を起こして当該ファイルの参照ができなくなると業務的にチトまずいという事情があるとして、ではどうするか?のお話。

こういうケースで、他のサーバーに「あるサーバー」でのファイル変更を反映させる「ファイル同期」という手法があります。

「あるサーバー」と「他のサーバー」間でファイル変更の若干のタイムラグは発生しますが、こういうシンプルな構造はいつだって非常に有用なソリューションゆえ、古から利用されているものなので、ここではその環境を作ってみます。


1.環境

以下の構成でいきます。

用途OSマシン名IPアドレス
あるサーバーUbuntu Server 24.04aru192.168.1.103
他のサーバーUbuntu Server 24.04hoka192.168.1.104

Ubuntu Serverのインストールについては「Ubuntu 24.04 Server インストール」に書いています。

ここに「lsyncd] というプログラムのサービスを介在させてファイル同期を実現します。

絵にするとこんな感じです。
構成図 1
実際にファイルの同期をしてくれるのは rsync(と ssh)というプログラムなんですが、これらは Ubuntu Serverをミニマムじゃない形でインストールすると最初から入っていますので、ここではインストールはしません。

なお [aru]サーバーから [hoka]サーバーへのアクセスのために [aru]サーバーの
[/etc/hosts]ファイルには予め以下の行を追加して名前解決できるようにしてあります。

hoka 192.168.1.104


また [aru]サーバー・[hoka]サーバーの両方で [/data]ディレクトリが作ってあるものとします。


2.ファイル同期機能用の専用ユーザーを作る

後述の lsyncdインストールの際に分かるのですが、[aru]サーバーでは lsyncd と rsync を実行するのは [root]ユーザーになります。

[aru]サーバーでは複数のユーザーが [/data]ディレクトリにファイルを作ったりすると仮定して、それぞれにオーナー・グループのパーミッションを持つので、lsyncdや rsyncがそれらを読むのに root権限が必要なので理にかなっているとは言えます。

※できれば [aru]サーバーでも一般ユーザーで運用したいところなんですが、lsyncdの実行ユーザーを変更するのは結構面倒なので [root]ユーザーでの実行に甘んじることにしました。

一方 [hoka]サーバーでも受信したファイルの属性(オーナー・グループ・パーミッションなど)を同期元と同じに設定するために root権限が必要なのですが、こちらは一般ユーザーに sudoを使わせてやるよう設定すれば良さそうですので [lsyncd]という一般ユーザー(とグループ)を作ろうと思います。

subro@hoka:~$ sudo adduser lsyncd
info: ユーザ `lsyncd' を追加しています...
info: 1000 から 59999 の範囲でUID/GID を選択しています...
info: 新しいグループ `lsyncd' (1001) を追加しています...
info: 新しいユーザ `lsyncd' (1001) をグループ `lsyncd (1001)' として追加しています...
info: ホームディレクトリ `/home/lsyncd' を作成しています...
info: `/etc/skel' からファイルをコピーしています...
新しいパスワード: [lsyncd]ユーザーの新規パスワード
新しいパスワードを再入力してください: [lsyncd]ユーザーの新規パスワードをもう一回
passwd: パスワードは正しく更新されました
lsyncd のユーザ情報を変更中
新しい値を入力してください。標準設定値を使うならリターンを押してください
        フルネーム []:Enterキー
        部屋番号 []:Enterキー
        職場電話番号 []:Enterキー
        自宅電話番号 []:Enterキー
        その他 []:Enterキー
以上でよろしいですか? [Y/n] Y
info: 追加のグループに新しいユーザ 'lsyncd' を追加しています 'users' ...
info: ユーザ `lsyncd' をグループ `users' に追加しています...

できました。


3.公開鍵方式で通信できるようにする

[aru]サーバーの [root]ユーザーが [hoka]サーバーの [lsyncd]ユーザーとしてパスワードを使わずに公開鍵方式で sshログインできるようにします。

公開鍵を使った sshログインについては「Ubuntu Serverへの SSH接続とファイルコピー 3」に細かく書いていてそれと同じことをやっています。

以下、[aru]サーバーでの作業になります。

まず [root]ユーザーにスイッチしましょう。

subro@aru:~$ sudo su -

root@aru:~#

コマンドプロンプトが変って [root]ユーザーになれた事が分かります。

公開鍵と秘密鍵のセットを作ります。
(私は ED25519形式の暗号を好んで使っています。)

root@aru:~# ssh-keygen -t ed25519
Generating public/private ed25519 key pair.
Enter file in which to save the key (/root/.ssh/id_ed25519):Enterキー
Enter passphrase (empty for no passphrase):Enterキー
Enter same passphrase again:Enterキー
Your identification has been saved in /root/.ssh/id_ed25519
Your public key has been saved in /root/.ssh/id_ed25519.pub
The key fingerprint is:
SHA256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx lsyncd@aru
The key's randomart image is:
+--[ED25519 256]--+
|xxxxxxxxxxxxxxxxx|
|xxxxxxxxxxxxxxxxx|
|xxxxxxxxxxxxxxxxx|
|xxxxxxxxxxxxxxxxx|
|xxxxxxxxxxxxxxxxx|
|xxxxxxxxxxxxxxxxx|
|xxxxxxxxxxxxxxxxx|
|xxxxxxxxxxxxxxxxx|
|xxxxxxxxxxxxxxxxx|
+----[SHA256]-----+

root@aru:~# ls -l ~/.ssh
合計 8
-rw------- 1 root root   0  4月 26  2024 authorized_keys
-rw------- 1 root root 399 10月 19 05:58 id_ed25519 ←秘密鍵
-rw-r--r-- 1 root root  90 10月 19 05:58 id_ed25519.pub ←公開鍵

できました。

公開鍵ファイルを [hoka]サーバーの [lsyncd]ユーザーのホームディレクトリに配置します。

root@aru:~# ssh-copy-id -i ~/.ssh/id_ed25519 lsyncd@hoka
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_ed25519.pub"
The authenticity of host 'hoka (192.168.1.104)' can't be established.
ED25519 key fingerprint is SHA256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
lsyncd@hoka's password:

Number of key(s) added: 1

Now try logging into the machine, with:   "ssh 'lsyncd@hoka'"
and check to make sure that only the key(s) you wanted were added.

配置できました。


4.lsyncdインストール

[aru]サーバーでの作業です。

上の作業で [lsyncd]ユーザーにスイッチしていますが、ここではまた管理者権限ユーザーである [subro] に戻っています。

lsyncdをインストールします。

subro@aru:~$ sudo apt -y install lsyncd
〜〜〜 省略 〜〜〜

特に問題なくインストールできたんですが、ちょっとここで知っておくことが。

インストールした lsyncdのパッケージの中身をみてみます。

subro@aru:~$ dpkg -L lsyncd
/.
/etc
/etc/init.d
/etc/init.d/lsyncd
/usr
/usr/bin
/usr/bin/lsyncd
/usr/share
/usr/share/doc
/usr/share/doc/lsyncd
/usr/share/doc/lsyncd/README.Debian
/usr/share/doc/lsyncd/README.md
/usr/share/doc/lsyncd/changelog.Debian.gz
/usr/share/doc/lsyncd/copyright
/usr/share/doc/lsyncd/examples
/usr/share/doc/lsyncd/examples/lalarm.lua
/usr/share/doc/lsyncd/examples/lbash.lua
/usr/share/doc/lsyncd/examples/lecho.lua
/usr/share/doc/lsyncd/examples/lftp.lua
/usr/share/doc/lsyncd/examples/lgforce.lua
/usr/share/doc/lsyncd/examples/limagemagic.lua
/usr/share/doc/lsyncd/examples/lpostcmd.lua
/usr/share/doc/lsyncd/examples/lrsync.lua
/usr/share/doc/lsyncd/examples/lrsyncssh.lua
/usr/share/doc/lsyncd/examples/ls3.lua.gz
/usr/share/doc/lsyncd/examples/lsayirc.lua
/usr/share/doc/lsyncd/lsyncd.1.txt
/usr/share/man
/usr/share/man/man1
/usr/share/man/man1/lsyncd.1.gz

プログラム本体は [/usr/bin/lsyncd] として、おやっ? [/etc/init.d/lsyncd] とは何か。

これは現在主流の systemd の前の仕組みの initd用のサービス起動ファイルです。

systemdは古いものの互換性のために initdの対応をしていて、自動的に systemd用のサービスファイルに書き換えてくれてるんですね。

その結果 [/var/run/systemd/generator.late/]ディレクトリ下に systemd用に書き換えられたサービスユニットファイルが作られています。

subro@aru:~$ ls -l /var/run/systemd/generator.late/
合計 4
drwxr-xr-x 2 root root  60 10月 17 21:42 graphical.target.wants
-rw-r--r-- 1 root root 510 10月 17 21:42 lsyncd.service
drwxr-xr-x 2 root root  60 10月 17 21:42 multi-user.target.wants

[lsyncd.service]ファイルが自動生成されていました。

この中身はこうなっています。

# Automatically generated by systemd-sysv-generator

[Unit]
Documentation=man:systemd-sysv-generator(8)
SourcePath=/etc/init.d/lsyncd
Description=LSB: lsyncd daemon init script
Before=multi-user.target
Before=multi-user.target
Before=multi-user.target
Before=graphical.target
After=remote-fs.target

[Service]
Type=forking
Restart=no
TimeoutSec=5min
IgnoreSIGPIPE=no
KillMode=process
GuessMainPID=no
RemainAfterExit=yes
SuccessExitStatus=5 6
ExecStart=/etc/init.d/lsyncd start
ExecStop=/etc/init.d/lsyncd stop

これを見る限り、サービスの開始は [/etc/init.d/lsyncd start] としているようです。

じゃ [/etc/init.d/lsyncd]ファイルは何者かというと lsyncd起動用シェルスクリプトです。

抜粋しますとこんな内容なんですが

PATH=/sbin:/usr/sbin:/bin:/usr/bin
DESC="synchronization daemon"
NAME=lsyncd
DAEMON=/usr/bin/$NAME
CONFIG=/etc/lsyncd/lsyncd.conf.lua
PIDFILE=/var/run/$NAME.pid
DAEMON_ARGS="-pidfile ${PIDFILE} ${CONFIG}"
SCRIPTNAME=/etc/init.d/$NAME
NICELEVEL=10

# Exit if the package is not installed
[ -x "$DAEMON" ] || exit 0

# Exit if config file does not exist
[ -r "$CONFIG" ] || exit 0

〜〜〜 以下略 〜〜〜

[/etc/lsyncd/lsyncd.conf.lua] が設定ファイルで、これがないと何もしないで終わってしまう仕組みだと分かりました。

なお、このファイルもディレクトリもインストールでは作られていません。


5.lsyncd設定

先にディレクトリを作っておきましょう。

subro@aru:~$ sudo mkdir /etc/lsyncd

設定ファイルを作りますが、どうにも情報が少ない…。

以下のリンクの「default.rsync」を参照しましたけど、イマイチハッキリしませんでした。
Config Layer 4: Default Config

結局色々なブログの情報を頼りにしましたけど、皆どこで情報を拾っているのか。

[/etc/lsyncd/lsyncd.conf.lua]ファイルを以下の内容で作成しました。
(当然ながら実ファイルからは黄色い文字は除外願います。)

settings {
    logfile = "/var/log/lsyncd/lsyncd.log",
    statusFile = "/var/log/lsyncd/lsyncd.status",
    statusInterval = 5, ←5秒おきに同期する
    insist = 1, ←転送先が停止していても動くようになるまでリトライする
}
sync {
    default.rsync,
    delay = 5,
    source = "/data/",
    target = "lsyncd@hoka:/data/",
    rsync = { ↓以下 rsyncコマンドに渡すオプションが記載されている
        rsync_path = "sudo /usr/bin/rsync", ←[hoka]サーバーで実行するrsyncコマンドのパス。sudoをつけているのはファイル属性も同期元と同じにするため。
        archive = true, ←オーナー・グループ・パーミッションやらなるべく同期元と同期先を同じにする
    }
}

ブログなどでは他に「転送時にデータ圧縮する」「ファイルの削除は同期しない」オプションを付けてるところが多かったですが、ここではシンプルにするため外しています。

設定ファイルの上の方でログディレクトリを指定していますが、これもインストール時に作られてはいませんので作ります。

subro@aru:~$ sudo mkdir /var/log/lsyncd


設定ファイルを書き換えましたので、[lsyncd]サービスを再起動します。

subro@aru:~$ sudo systectl restart lsyncd

subro@aru:~$ systemctl status lsyncd
● lsyncd.service - LSB: lsyncd daemon init script
     Loaded: loaded (/etc/init.d/lsyncd; generated)
     Active: active (running) since Sun 2025-10-19 07:04:23 JST; 4s ago
       Docs: man:systemd-sysv-generator(8)
    Process: 2161 ExecStart=/etc/init.d/lsyncd start (code=exited, status=0/SUCCESS)
      Tasks: 1 (limit: 9379)
     Memory: 584.0K (peak: 3.4M)
        CPU: 150ms
     CGroup: /system.slice/lsyncd.service
             └─2167 /usr/bin/lsyncd -pidfile /var/run/lsyncd.pid /etc/lsyncd/lsyncd.conf.lua

10月 19 07:04:23 aru systemd[1]: Starting lsyncd.service - LSB: lsyncd daemon init script...
10月 19 07:04:23 aru lsyncd[2161]:  * Starting synchronization daemon lsyncd
10月 19 07:04:23 aru lsyncd[2166]: 07:04:23 Normal: --- Startup, daemonizing ---
10月 19 07:04:23 aru lsyncd[2161]:    ...done.
10月 19 07:04:23 aru systemd[1]: Started lsyncd.service - LSB: lsyncd daemon init script.

良さげです。


6.同期先で同期元のファイル属性を再現する

[hoka]サーバーでの作業です。

段落タイトルがやや意味不明ですが…。

同期先の [hoka]サーバーで受信したファイルを作るのは一般ユーザーの [lsyncd]です。

一般ユーザーですので、少なくともファイルのオーナー・グループを自分以外に変える権限がなく、受信元のファイル属性と同じに設定できないことを意味します。

具体的には以下をやらないと全ファイルのオーナー・グループが [lsyncd:lsyncd]になります。

逆に言うと「単にバックアップだから」とそれで良いならやらなくて良い設定作業になります。

sudoersの設定で、[lsyncd]ユーザーに対して、rsyncコマンド実行時のみ sudoして root権限を使えるようにします。

[/etc/sudoers.d]ディレクトリに以下の内容で [lsyncd] というファイルを作りました。
ファイルのパーミッションは [-rw-r-----](640) が良いですね。
(作成には root権限が必要です。)

lsyncd ALL=NOPASSWD: /usr/bin/rsync



7.動作確認

やっと実際にファイル同期をやれるようになりました。

同期元の [aru]サーバーの [/data]ディレクトリにファイルを作ってみました。
[subro]ユーザーで作成しているのがキモです。

subro@aru:/data$ touch aaa

subro@aru:/data$ ls -l
合計 0
-rw-rw-r-- 1 subro subro 0 10月 19 07:08 aaa


同期先の [hoka]サーバーの [/data]ディレクトリを見てみます。

subro@hoka:/data$ ls -l
合計 0
-rw-rw-r-- 1 subro subro 0 10月 19 07:08 aaa

ファイルが出来ていました。\(^o^)/
オーナー・グループも [subro] になっていて、属性も同期されてることが分かります。

※ [hoka]サーバーにも同じユーザーID:グループIDで [subro:subro] が存在しているので [subro]と表示されているのだと思います。
同期先サーバーに同じユーザーID:グループIDがない場合や別な名前のID:グループが存在する場合はそちらのユーザー名:グループ名が表示されるのでしょう。
違うのが嫌な場合は、同期元と同じユーザー:グループを作っておく必要がありそうです。
もしかすると rsyncコマンドがお利口で、ちゃんとそこまで考えて同期してくれるのかも知れません。
ここの動作について私が確認までをする気がないので想定だけで書いています。


==========
シンプルなようでいて、lsyncdの設定に関する情報の少なさのせいか、参考にしたサイトやブログそれぞれで好きにやっていて「これかな〜」ってセッティングを煮詰めるのに苦労しました。

でも構成はシンプルであって、Ubuntu Serverを使う限りにおいてはインストールするものも 1つだけでしたし、一度セッティングが出来てしまえばデータ圧縮をしたいとか、同期間隔を延ばしたいって変更は簡単だと思いました。

実際の運用環境では cronで rsyncを定期実行する更にシンプルな構成を見ますね。
これは設計者・運用者の好みで選べばよいかと思います。

このお勉強の副産物として、init.dのスクリプトを systemdが拾って自動でサービスユニットファイルを作るって機能を知りました。

「systemd-sysv-generator」と言うのですが「は〜よくやってくれるな…」という印象で、Ubuntuの lsyncdパッケージは早い所 systemdに以降して欲しいですが、lsyncdの大元がメンテナンスされてないのかも知れません。

「systemd-sysv-generator」はこの本でも言及されていました。
やはり必携。買うしか無い。 (私は持っています)