VPS で動かしている Ubuntu や Debian のバージョンアップのブロッカーになっていた OpenLDAP (slapd) のバックエンドデータベースをやっと hdb から mdb に移行しました。

対象環境

  • Ubuntu 20.04.6 LTS (focal)
    • slapd 2.4.49+dfsg-2ubuntu1.10
  • Debian GNU/Linux 11 (bullseye)
    • slapd 2.4.57+dfsg-3+deb11u1

移行手順の概要

まず slapcat で LDAP データベースのバックアップをとって、 hdb のデータベースは削除します。

そして https://github.com/DSI-Universite-Rennes2/openldap-migrate-backend を参考にして、 /etc/ldap/slapd.d/# AUTO-GENERATED FILE - DO NOT EDIT!! Use ldapmodify. と書いてあるファイルの内容を直接書き換えて、 CRC32 がずれるのは https://gogs.zionetrix.net/bn8/check_slapdd_crc32 で修正します。

slapadd で mdb としてデータベースを復元して動作確認ができれば終了です。

バックアップ

まず slapcat を使って適当なファイル名でバックアップをとっておきます。

0 は cn=config なので、 /etc/ldap/slapd.d を直接バックアップした方が良さそうです。 etckeeper を使っているので、そこのバックアップはしていません。

1 がメインのデータベースなので、後で使います。

2 は accesslog で使う設定にしていますが、設定がちゃんとできていなかったらしく、 トップレベルの dn: cn=accesslog だけで他に何もデータが入っていませんでした。

普通は 1 だけとっておけばいいと思います。

sudo slapcat -n 0 -l slapcat.0.$(date -I).ldif
sudo slapcat -n 1 -l slapcat.1.$(date -I).ldif
sudo slapcat -n 2 -l slapcat.2.$(date -I).ldif
sudo chmod 640 slapcat.*.ldif

移行対象を停止

syncrepl で 2 台体制で動かしているので、1台止めて移行します。

止めても getent passwd などがちゃんと動くのを確認しておきます。

sudo systemctl stop slapd.service
getent passwd

olcDbDirectory

olcDbDirectory を確認して削除して空ディレクトリを作りなおしておきます。 sudo slapadd で root 所有のファイルができるので、後でまとめて chown するので、 空ディレクトリは root 所有のままにしました。

ディレクトリがないと sudo slaptest -u -F /etc/ldap/slapd.d でエラーになります。

空ディレクトリの作成は普通は sudo mkdir -p /var/lib/ldap でいいと思います。

$ cd /etc/ldap
$ sudo grep -r olcDbDirectory
slapd.d/cn=config/olcDatabase={1}hdb.ldif:olcDbDirectory: /var/lib/ldap
slapd.d/cn=config/olcDatabase={2}hdb.ldif:olcDbDirectory: /var/lib/ldap/accesslog
$ ls -al /var/lib/ldap/
合計 11212
drwxr-xr-x  3 openldap openldap     4096 12月 31 18:06 .
drwxr-xr-x 56 root     root         4096 11月 20  2024 ..
-rw-r--r--  1 openldap openldap       96  8月  2  2014 DB_CONFIG
-rw-------  1 openldap openldap   532479 12月 31 18:06 __db.001
-rw-------  1 openldap openldap   139263 12月 31 18:06 __db.002
-rw-------  1 openldap openldap   286719 12月 31 18:06 __db.003
drwxr-xr-x  2 openldap openldap     4096 12月 31 18:06 accesslog
-rw-r--r--  1 openldap openldap     4096 12月 31 18:06 alock
-rw-------  1 openldap openldap    28672  3月 21  2016 cn.bdb
-rw-------  1 openldap openldap     8192  3月 21  2016 displayName.bdb
-rw-------  1 openldap openldap    24576  3月 21  2016 dn2id.bdb
-rw-------  1 openldap openldap     8192  3月 21  2016 entryCSN.bdb
-rw-------  1 openldap openldap     8192  3月 21  2016 entryUUID.bdb
-rw-------  1 openldap openldap     8192  3月 21  2016 gidNumber.bdb
-rw-------  1 openldap openldap    16384  3月 21  2016 givenName.bdb
-rw-------  1 openldap openldap    81920  3月 21  2016 id2entry.bdb
-rw-------  1 openldap openldap 10485759 12月 31 17:59 log.0000000001
-rw-------  1 openldap openldap     8192  3月 21  2016 loginShell.bdb
-rw-------  1 openldap openldap     8192  3月 21  2016 member.bdb
-rw-------  1 openldap openldap    16384  3月 21  2016 memberUid.bdb
-rw-------  1 openldap openldap     8192  3月 21  2016 objectClass.bdb
-rw-------  1 openldap openldap     8192  3月 21  2016 ou.bdb
-rw-------  1 openldap openldap     8192  3月 21  2016 sambaDomainName.bdb
-rw-------  1 openldap openldap     8192  3月 21  2016 sambaGroupType.bdb
-rw-------  1 openldap openldap     8192  3月 21  2016 sambaPrimaryGroupSID.bdb
-rw-------  1 openldap openldap     8192  3月 21  2016 sambaSID.bdb
-rw-------  1 openldap openldap    16384  3月 21  2016 sn.bdb
-rw-------  1 openldap openldap    16384  3月 21  2016 uid.bdb
-rw-------  1 openldap openldap     8192  3月 21  2016 uidNumber.bdb
$ ls -al /var/lib/ldap/accesslog/
合計 10828
drwxr-xr-x 2 openldap openldap     4096 12月 31 18:06 .
drwxr-xr-x 3 openldap openldap     4096 12月 31 18:06 ..
-rw-r--r-- 1 openldap openldap       96  8月  2  2014 DB_CONFIG
-rw------- 1 openldap openldap   532479 12月 31 18:06 __db.001
-rw------- 1 openldap openldap   139263 12月 31 18:06 __db.002
-rw------- 1 openldap openldap   114687 12月 31 18:06 __db.003
-rw-r--r-- 1 openldap openldap     4096 12月 31 18:06 alock
-rw------- 1 openldap openldap     8192  3月 21  2016 dn2id.bdb
-rw------- 1 openldap openldap     8192  3月 21  2016 entryCSN.bdb
-rw------- 1 openldap openldap    32768  3月 21  2016 id2entry.bdb
-rw------- 1 openldap openldap 10485759 12月 31 17:59 log.0000000001
-rw------- 1 openldap openldap     8192  3月 21  2016 objectClass.bdb
-rw------- 1 openldap openldap     8192  3月 21  2016 reqStart.bdb
$  sudo rm -rf /var/lib/ldap/
$  sudo mkdir -p /var/lib/ldap/accesslog

check_slapdd_crc32 を用意

CRC32 修正用のコマンドを用意しておきます。

$ git clone https://gogs.zionetrix.net/bn8/check_slapdd_crc32
Cloning into 'check_slapdd_crc32'...
warning: redirecting to https://gitea.zionetrix.net/bn8/check_slapdd_crc32/
remote: Enumerating objects: 61, done.
remote: Counting objects: 100% (61/61), done.
remote: Compressing objects: 100% (51/51), done.
remote: Total 61 (delta 22), reused 0 (delta 0), pack-reused 0
Receiving objects: 100% (61/61), 12.16 KiB | 47.00 KiB/s, done.
Resolving deltas: 100% (22/22), done.

書き換え

https://github.com/DSI-Universite-Rennes2/openldap-migrate-backend の手順を参考にして手で書き換えました。 シェルスクリプトの内容を確認して、直接実行でも良いと思います。

$ sudo grep -ri hdb
slapd.d/cn=config/olcDatabase={1}hdb.ldif:dn: olcDatabase={1}hdb
slapd.d/cn=config/olcDatabase={1}hdb.ldif:objectClass: olcHdbConfig
slapd.d/cn=config/olcDatabase={1}hdb.ldif:olcDatabase: {1}hdb
slapd.d/cn=config/olcDatabase={1}hdb.ldif:structuralObjectClass: olcHdbConfig
slapd.d/cn=config/cn=module{0}.ldif:olcModuleLoad: {0}back_hdb
slapd.d/cn=config/olcBackend={0}hdb.ldif:dn: olcBackend={0}hdb
slapd.d/cn=config/olcBackend={0}hdb.ldif:olcBackend: {0}hdb
slapd.d/cn=config/olcDatabase={2}hdb.ldif:dn: olcDatabase={2}hdb
slapd.d/cn=config/olcDatabase={2}hdb.ldif:objectClass: olcHdbConfig
slapd.d/cn=config/olcDatabase={2}hdb.ldif:olcDatabase: {2}hdb
slapd.d/cn=config/olcDatabase={2}hdb.ldif:structuralObjectClass: olcHdbConfig
$  sudo mv -vi slapd.d/cn\=config/olcBackend\=\{0\}hdb.ldif slapd.d/cn\=config/olcBackend\=\{0\}mdb.ldif
renamed 'slapd.d/cn=config/olcBackend={0}hdb.ldif' -> 'slapd.d/cn=config/olcBackend={0}mdb.ldif'
$  sudo mv -vi slapd.d/cn\=config/olcDatabase\=\{1\}hdb.ldif slapd.d/cn\=config/olcDatabase\=\{1\}mdb.ldif
renamed 'slapd.d/cn=config/olcDatabase={1}hdb.ldif' -> 'slapd.d/cn=config/olcDatabase={1}mdb.ldif'
$  sudo mv -vi slapd.d/cn\=config/olcDatabase\=\{2\}hdb.ldif slapd.d/cn\=config/olcDatabase\=\{2\}mdb.ldif
renamed 'slapd.d/cn=config/olcDatabase={2}hdb.ldif' -> 'slapd.d/cn=config/olcDatabase={2}mdb.ldif'
$  sudo mv -vi slapd.d/cn\=config/olcDatabase\=\{1\}hdb slapd.d/cn\=config/olcDatabase\=\{1\}mdb
renamed 'slapd.d/cn=config/olcDatabase={1}hdb' -> 'slapd.d/cn=config/olcDatabase={1}mdb'
$  sudo mv -vi slapd.d/cn\=config/olcDatabase\=\{2\}hdb slapd.d/cn\=config/olcDatabase\=\{2\}mdb
renamed 'slapd.d/cn=config/olcDatabase={2}hdb' -> 'slapd.d/cn=config/olcDatabase={2}mdb'
$  sudo sed -i 's/back_hdb/back_mdb/' slapd.d/cn=config/cn\=module\{0\}.ldif
$  sudo sed -i 's/hdb/mdb/' slapd.d/cn\=config/olcBackend\=\{0\}mdb.ldif slapd.d/cn\=config/olcDatabase\=\{1\}mdb.ldif slapd.d/cn\=config/olcDatabase\=\{2\}mdb.ldif
$  sudo sed -i 's/Hdb/Mdb/' slapd.d/cn\=config/olcDatabase\=\{1\}mdb.ldif slapd.d/cn\=config/olcDatabase\=\{2\}mdb.ldif
$  for attr in olcDbCacheFree olcDbCacheSize olcDbChecksum olcDbConfig olcDbCryptFile olcDbCryptKey olcDbDNcacheSize olcDbDirtyRead olcDbIDLcacheSize olcDbLinearIndex olcDbLockDetect olcDbPageSize olcDbShmKey; do sudo sed -i "/^$attr:/d" slapd.d/cn\=config/olcDatabase\=\{1\}mdb.ldif; done
$  sudo sed -i '/^olcAccess: {0}/i olcDbMaxSize: 1000000000' slapd.d/cn\=config/olcDatabase\=\{1\}mdb.ldif
$  sudo ~/check_slapdd_crc32/check_slapdd_crc32 --fix
2025-12-31 18:11:21,901 - check_slapdd_crc32 - WARNING - /etc/ldap/slapd.d/cn=config/olcDatabase={0}config.ldif: no CRC32 value found. Correct CRC32 value is "47dba06d".
2025-12-31 18:11:21,902 - check_slapdd_crc32 - WARNING - /etc/ldap/slapd.d/cn=config/olcBackend={0}mdb.ldif: invalid CRC32 value found (f6ccc16c != 1918d801)
2025-12-31 18:11:21,902 - check_slapdd_crc32 - WARNING - /etc/ldap/slapd.d/cn=config/cn=module{0}.ldif: invalid CRC32 value found (bc225411 != f86810e2)
2025-12-31 18:11:21,902 - check_slapdd_crc32 - WARNING - /etc/ldap/slapd.d/cn=config/olcDatabase={1}mdb.ldif: invalid CRC32 value found (4b81209f != 7623f07e)
2025-12-31 18:11:21,903 - check_slapdd_crc32 - WARNING - /etc/ldap/slapd.d/cn=config/olcDatabase={2}mdb.ldif: invalid CRC32 value found (09c73f52 != 6c208dd4)
$  sudo slaptest -u -F /etc/ldap/slapd.d
config file testing succeeded
$  sudo slapschema -F /etc/ldap/slapd.d -b 'cn=config'
$

DB 移行

mdb にバックアップしておいたデータベースを取り込んで、ファイルのオーナーなどを修正します。

$  sudo slapadd -n 1 -l ~/slapcat.1.2025-12-31.ldif
_#################### 100.00% eta   none elapsed            none fast!
Closing DB...
$  sudo slapadd -n 2 -l ~/slapcat.2.2025-12-31.ldif
_#################### 100.00% eta   none elapsed            none fast!
Closing DB...
$  sudo chown -R openldap:openldap /var/lib/ldap
$

作業対象サーバーの入れ替え

同時に起動すると syncrepl で問題が起きそうなので、 残っていた1台を sudo systemctl stop slapd.service で止めて、 一瞬 LDAP サーバーがなくなった状態になった後、 移行した方を sudo systemctl start slapd.service で起動しました。

getent passwd などで問題がないことを確認して、次のサーバーも同様に作業しました。

もう1台も移行

もう1台の方も sudo systemctl start slapd.service で起動して、 syncrepl などの状態を確認できたら移行完了です。

最後に

以前に移行作業しようとしたときは、全然具体的な情報がなくて諦めていましたが、 さすがに Debian で hdb 対応が消えた bookworm が oldstable になっていたり、 Ubuntu でも hdb が消えた jammy (22.04) の次の LTS の noble (24.04) が出ていたりするので、 具体的な移行方法もみつけられました。

focal も bullseye もまだ完全な EOL ではないものの、 いろんなツールなどの対応が終わってきているので、 slapd の hdb が原因でまだ上げられていない人がいれば参考にしてみてください。

Disqus Comments

Kazuhiro NISHIYAMA

Ruby のコミッターとかやってます。 フルスタックエンジニア(って何?)かもしれません。 About znzに主なアカウントをまとめました。

znz znz


Published