2023年12月30日土曜日

Kickstartを使ってRHEL 8やRHEL 9を自動インストールする

自宅で検証をする際に、Red Hat Enterprise Linux (RHEL) やCentOS、最近ではRocky LinuxやAlmaLinuxなど、RHEL系のディストリビューションを利用することが多く、頻繁にインストール作業を手作業で行っていた。

慣れてしまえばそこまで時間を要するものではないので、GUIを使ってせっせとインストール作業をしていたが、もっと効率よくインストールできるよう、Kickstart (キックスタート) を使ってインストールの自動化をすることにした。

環境

Kickstartの検証はESXi上に構築したRHEL 8及びRHEL9で実施した。検証完了後に同じKickstartファイルを使って、他ディストリビューションでの動作確認もしており、Rocky Linux、AlmaLinuxでもKickstartによる自動インストールが動作することを確認している。

以下に確認したディストリビューションの一覧を記載する。

  • RHEL 8.3
  • Rocky Linux 8.3
  • AlmaLinux 8.3
  • RHEL 9.2

手順

1. Kickstartファイル (ks.cfg) を作成

Kickstartは、インストール情報を定義したKickstartファイルと呼ばれるファイルを読み込ませることで自動インストールを実現する。このファイルは通常ks.cfgというファイル名で作成をするのが一般的となるが、ファイル名は任意で設定して問題ない。

Kickstartファイルは、インストール時に各種設定を定義するためのコマンドやオプションが用意されている。詳細は公式マニュアルを参照いただきたいが、最低限必要となるコマンドについては、以下表にて説明する。

なお、RHEL 8とRHEL 9で細かいところで設定方法が異なる個所があるため注意すること。

設定項目 設定コマンド 説明
インストールモード text インストールをGUIベース (graphical) にするか、CLIベース (text) にするかの設定。
利用規約 (EULA) への同意 eula --agreed 利用規約への同意を自動で行う設定。
リポジトリ repo インストールに使用するリポジトリのパスを指定。インストールイメージに応じて変更が必要。
パッケージ %packages%end 必要なパッケージを指定。最小インストールの場合は、@^minimal-environmentを指定。
インストール後のスクリプト実行 %post%end インストール後の処理として実行するコマンドを記載する。インストール中の文字化けを防止するため、このタイミングで言語設定をja_JP.UTF-8へ変更をしている。
キーボードレイアウト keyboard キーボードレイアウトを指定。
言語設定 lang システムの言語設定。ここでja_JP.UTF-8を選ぶと、インストールは進むものの画面表示が文字化けした状態となるため、あえてen_US.UTF-8を選択している。
ネットワーク network ホスト名やIPアドレスなどの設定。本設定を省略すると、DHCPによる設定が反映される。
インストールタイプ cdrom ISOイメージからのインストールを設定。
初期セットアップ firstboot 初期セットアップの処理を実行するかどうか。初期インストールであれば、有効にしておけば問題ない。
無視するディスク ignoredisk --drivesオプションにてインストールに関係ないディスクを無視するよう設定する。逆に特定のディスクのみを指定する場合は、--only-useを使用する。仮想環境の場合は、sdaのみ指定しておけば問題ない。
自動パーティション autopart 自動的にパーティションを設定する際に指定。
パーティション初期化 clearpart パーティションの初期化動作を指定。--initlabelオプションにて、対象ディスク (ignorediskで指定したディスク) をすべてフォーマットする。--noneはもしパーティションが存在する場合は削除しないためのオプション。
タイムゾーン timezone タイムゾーンを設定する。日本にする場合はAsia/Tokyoを選択する。RHEL 8の場合はここでNTPサーバを指定できる。その場合は、--ntpserversにて指定する。また、ハードウェアクロックをUTCの時刻とみなす際のオプションがRHEL 8は--isUtc、RHEL 9は--utcと異なるため注意する。
タイムソース timesource RHEL 9の場合は本設定項目にてタイムソースとするNTPサーバを指定する。--ntp-serverを用いて指定する。
rootパスワード rootpw 平文 (--plaintext) またはハッシュ化 (--iscrypted) した文字列でパスワードを指定できる。ハッシュ化したパスワードは、インストール済みの環境の/etc/shadowから抽出すると楽。
RHEL 9以降はデフォルトでrootログインが禁止されるため、もしrootログインを許可したい場合は、--allow-sshオプション(RHEL 9.1以降で使用可能)を付与する(RHEL 8の場合は特に指定しなくてもデフォルトでrootにてログイン可能)。
SELinux selinux SELinuxの有効化、無効化を設定。
ファイアウォール firewall firewalldの有効化、無効化を設定。
インストール後の動作 reboot インストール後に自動で再起動かける場合に指定。同時にDVDを取り出したい場合は、--ejectを付与する。
kdump %addon com_redhat_kdump%end kdumpの設定。
パスワードポリシー %anaconda%end パスワードの最小文字列などのパスワードポリシーの設定。RHEL 9からは本設定項目は非推奨となっている。

以下に私が実際に使用しているKickstartファイルを例として記載する。OSインストールイメージがDVD版の場合とMinimal版の場合で変更を加える箇所があり、具体的には以下2点となる。

  • レポジトリのパス
  • open-vm-toolsのインストール方式 (Minimalのイメージにはopen-vm-toolsが含まれないため、dnfを使ってインストールする必要がある)

▼【RHEL 8】OSインストールイメージがDVDの場合

#version=RHEL8
# Use text install
text

# Agree EULA
eula --agreed

# Package
repo --name="AppStream" --baseurl=file:///run/install/sources/mount-0000-cdrom/AppStream

%packages
@^minimal-environment
@guest-agents
kexec-tools

%end

# Run post script
%post --logfile=/root/ks-post.log
echo 'LANG="ja_JP.UTF-8"' > /etc/locale.conf ; cat /etc/locale.conf

%end

# Keyboard layouts
keyboard --xlayouts='jp'

# System language
lang en_US.UTF-8 --addsupport=ja_JP.UTF-8

# Network information
network  --bootproto=static --device=ens192 --gateway=192.168.11.31 --ip=192.168.11.192 --nameserver=192.168.11.61,192.168.11.62 --netmask=255.255.255.0 --noipv6 --activate
network  --hostname=localhost.localdomain

# Use CDROM installation media
cdrom

# Run the Setup Agent on first boot
firstboot --enable

ignoredisk --only-use=sda
autopart
# Partition clearing information
clearpart --none --initlabel

# System timezone
timezone Asia/Tokyo --isUtc --ntpservers=192.168.33.23

# Root password
rootpw --plaintext XXXXXXXX
#rootpw --iscrypted XXXX~(省略)~XXXX

# Disable SELinux
selinux --disabled

# Disable firewalld
firewall --disabled

# Reboot after installation
reboot

%addon com_redhat_kdump --enable --reserve-mb='auto'

%end

%anaconda
pwpolicy root --minlen=6 --minquality=1 --notstrict --nochanges --notempty
pwpolicy user --minlen=6 --minquality=1 --notstrict --nochanges --emptyok
pwpolicy luks --minlen=6 --minquality=1 --notstrict --nochanges --notempty
%end

▼【RHEL 8】OSインストールイメージがMinimalの場合

#version=RHEL8
# Use text install
text

# Agree EULA
eula --agreed

# Package
repo --name="Minimal" --baseurl=file:///run/install/sources/mount-0000-cdrom/Minimal

%packages
@^minimal-environment
kexec-tools

%end

# Run post script
%post --logfile=/root/ks-post.log
echo 'LANG="ja_JP.UTF-8"' > /etc/locale.conf ; cat /etc/locale.conf

export http_proxy=http://192.168.33.23:8080
export https_proxy=http://192.168.33.23:8080
dnf install open-vm-tools -y

%end

# Keyboard layouts
keyboard --xlayouts='jp'

# System language
lang en_US.UTF-8 --addsupport=ja_JP.UTF-8

# Network information
network  --bootproto=static --device=ens192 --gateway=192.168.11.31 --ip=192.168.11.192 --nameserver=192.168.11.61,192.168.11.62 --netmask=255.255.255.0 --noipv6 --activate
network  --hostname=localhost.localdomain

# Use CDROM installation media
cdrom

# Run the Setup Agent on first boot
firstboot --enable

ignoredisk --only-use=sda
autopart
# Partition clearing information
clearpart --none --initlabel

# System timezone
timezone Asia/Tokyo --isUtc --ntpservers=192.168.33.23

# Root password
rootpw --plaintext XXXXXXXX
#rootpw --iscrypted XXXX~(省略)~XXXX

# Disable SELinux
selinux --disabled

# Disable firewalld
firewall --disabled

# Reboot after installation
reboot

%addon com_redhat_kdump --enable --reserve-mb='auto'

%end

%anaconda
pwpolicy root --minlen=6 --minquality=1 --notstrict --nochanges --notempty
pwpolicy user --minlen=6 --minquality=1 --notstrict --nochanges --emptyok
pwpolicy luks --minlen=6 --minquality=1 --notstrict --nochanges --notempty
%end

▼【RHEL 9】OSインストールイメージがDVDの場合

#version=RHEL9
# Use text install
text

# Agree EULA
eula --agreed

# Package
repo --name="AppStream" --baseurl=file:///run/install/sources/mount-0000-cdrom/AppStream

%packages
@^minimal-environment
@guest-agents

%end

# Run post script
%post --logfile=/root/ks-post.log
echo 'LANG="ja_JP.UTF-8"' > /etc/locale.conf ; cat /etc/locale.conf

%end

# Keyboard layouts
keyboard --xlayouts='jp'

# System language
#lang ja_JP.UTF-8
lang en_US.UTF-8 --addsupport=ja_JP.UTF-8

# Network information
#network --bootproto=static --device=ens192 --gateway=192.168.11.31 --ip=192.168.11.192 --nameserver=192.168.11.61,192.168.11.62 --netmask=255.255.255.0 --noipv6 --activate
network --hostname=localhost.localdomain

# Use CDROM installation media
cdrom

# Run the Setup Agent on first boot
firstboot --enable

ignoredisk --only-use=sda
autopart
# Partition clearing information
clearpart --none --initlabel

# System timezone
timezone Asia/Tokyo --utc
timesource --ntp-server 192.168.33.23

# Root password
#rootpw --plaintext --allow-ssh XXXXXXXX
rootpw --iscrypted --allow-ssh XXXX~(省略)~XXXX

# Disable SELinux
selinux --disabled

# Disable firewalld
firewall --disabled

# Reboot after installation
reboot

%addon com_redhat_kdump --enable --reserve-mb='auto'

%end

2. NFSサーバにKickstartファイルを配置

作成したKickstartファイルは、OSインストール時に読み込ませる必要がある。いくつか方式はあるが、今回はNFSサーバにKickstartファイルを配置して、ネットワーク経由で読み込みさせることにする。

NFSサーバの構築は本題とは関係がないため割愛するが、今回はQNAP NASをNFSサーバとして使用することにした。配置パスは以下となる。

nfs:192.168.11.13:/Public2/ks/ks.cfg

3. OSインストールメディアで起動

通常通りOSインストールメディアにて起動し、最初の画面にて「Install Red Hat Enterprise Linux 8.3」を選択したのち、「e」を押し、インストールパラメータを指定する画面に遷移する。

4. インストールパラメータでkickstartファイルを指定

インストールパラメータでは、以下の通り、init.ksのパラメータを追記する。追記箇所を間違えないよう注意。

linuxefi /images/pxeboot/vmlinuz inst.stage2=hd:LABEL=RHEL-8-3-0-BaseOS-x86_64 quiet inst.ks=nfs:192.168.11.13:/Public2/ks/ks_rhel8.cfg

パラメータ追記後、「Ctrl + x」を押してインストールを開始する。

5. 自動インストール開始

Kickstartによる自動インストールが成功した場合は、以下画面のように「Starting automated install」といった表示がされ、自動的にインストールが進む。

なお、Kickstartファイルにてlang ja_JP.UTF-8を設定した場合、インストールは実行されるが、文字化けするので注意。文字化けを回避するため、前述したKickstartファイルでは、%postの処理で言語設定を変更するようにしている。

インストール完了後、自動で再起動がされ、ログインプロンプトが表示されればインストール完了となる。

6. インストール後の確認

インストール完了後、SSHでログインし以下であることを確認した。Kickstartにより問題なく初期設定がされていることが確認できた。

  • 言語設定がja_JP.UTF-8であること
  • タイムゾーンがAsia/Tokyoであること
  • Chronyにて指定したNTPサーバと同期していること
  • open-vm-toolsがインストールされ起動していること
  • SELinuxが無効化されていること
  • firewalldのサービスが停止していること
# localectl
   System Locale: LANG=ja_JP.UTF-8
       VC Keymap: jp
      X11 Layout: jp

# timedatectl
               Local time: 土 2021-05-08 17:46:57 JST
           Universal time: 土 2021-05-08 08:46:57 UTC
                 RTC time: 土 2021-05-08 08:46:57
                Time zone: Asia/Tokyo (JST, +0900)
System clock synchronized: yes
              NTP service: active
          RTC in local TZ: no

# chronyc -n sources
210 Number of sources = 1
MS Name/IP address         Stratum Poll Reach LastRx Last sample
===============================================================================
^* 192.168.33.23                 2   6   377    54   +208us[ +253us] +/- 2101us

# systemctl status vmtoolsd
● vmtoolsd.service - Service for virtual machines hosted on VMware
   Loaded: loaded (/usr/lib/systemd/system/vmtoolsd.service; enabled; vendor pr>
   Active: active (running) since Sat 2021-05-08 16:17:38 JST; 1h 29min ago
     Docs: http://github.com/vmware/open-vm-tools
 Main PID: 988 (vmtoolsd)
    Tasks: 3 (limit: 10900)
   Memory: 6.5M
   CGroup: /system.slice/vmtoolsd.service
           mq988 /usr/bin/vmtoolsd

 5月 08 16:17:38 localhost.localdomain systemd[1]: Started Service for virtual >

# getenforce
Disabled

# systemctl status firewalld
● firewalld.service - firewalld - dynamic firewall daemon
   Loaded: loaded (/usr/lib/systemd/system/firewalld.service; disabled; vendor >
   Active: inactive (dead)
     Docs: man:firewalld(1)

参考

更新履歴

  • 2021/5/8 新規作成
  • 2023/12/30 RHEL 9の情報を追記
2023年12月23日土曜日

UbuntuにZabbix Agent 2をインストールする手順

Zabbix Agentは過去のバージョンから利用されているZabbix Agentとは別に、新たにGo言語ベースで作り直されたZabbix Agent 2が存在する。

過去Windows環境にZabbix Agent 2をインストールする手順は記載した。

今回は、Ubuntuに対してZabbix Agent 2をインストールする手順を記載する。

環境

導入対象となるOSとZabbixのバージョンは以下の通り。

  • OS : Ubuntu 22.04.2 LTS
  • Zabbix Agent 2 : 6.0

Ubuntuは初期状態ではcurlコマンドが使えない場合があるので、その場合は以下の通りインストールをしておくこと。

$ sudo apt install curl

手順

1. zabbix-releaseをインストール

以下URLから最新のzabbix-releaseのパッケージファイルのURLを確認する。

バージョン URL
6.0 https://repo.zabbix.com/zabbix/6.0/ubuntu/pool/main/z/zabbix-release/
6.2 https://repo.zabbix.com/zabbix/6.2/ubuntu/pool/main/z/zabbix-release/
6.4 https://repo.zabbix.com/zabbix/6.4/ubuntu/pool/main/z/zabbix-release/

今回の場合は、Ubuntu 22.04.2 LTSに対して、Zabbix 6.0のエージェントをインストールすることから、https://repo.zabbix.com/zabbix/6.0/ubuntu/pool/main/z/zabbix-release/zabbix-release_latest%2Bubuntu22.04_all.debcurlを使ってダウンロードしてインストールする。

$ curl -LO https://repo.zabbix.com/zabbix/6.0/ubuntu/pool/main/z/zabbix-release/zabbix-release_latest%2Bubuntu22.04_all.deb
$ sudo dpkg -i zabbix-release_latest%2Bubuntu22.04_all.deb
以前に未選択のパッケージ zabbix-release を選択しています。
(データベースを読み込んでいます ... 現在 204627 個のファイルとディレクトリがインストールされています。)
zabbix-release_latest%2Bubuntu22.04_all.deb を展開する準備をしています ...
zabbix-release (1:6.0-4+ubuntu22.04) を展開しています...
zabbix-release (1:6.0-4+ubuntu22.04) を設定しています ...

$ sudo apt update

2. Zabbix Agnet 2をインストール

$ apt search zabbix-agent
ソート中... 完了
全文検索... 完了
pcp-export-zabbix-agent/jammy 5.3.6-1build1 amd64
  Module for exporting PCP metrics to Zabbix agent

zabbix-agent/jammy 1:6.0.25-1+ubuntu22.04 amd64
  Zabbix network monitoring solution - agent

zabbix-agent-dbgsym/jammy 1:6.0.25-1+ubuntu22.04 amd64
  debug symbols for zabbix-agent

zabbix-agent2/jammy 1:6.0.25-1+ubuntu22.04 amd64
  Zabbix network monitoring solution - agent

zabbix-agent2-dbgsym/jammy 1:6.0.25-1+ubuntu22.04 amd64
  debug symbols for zabbix-agent2

zabbix-agent2-plugin-mongodb/jammy 1:6.0.25-1+ubuntu22.04 amd64
  Zabbix Agent2 plugin for monitoring MongoDB installations

zabbix-agent2-plugin-postgresql/jammy 1:6.0.25-2+ubuntu22.04 amd64
  Zabbix Agent2 plugin for monitoring PostgreSQL installations
$ sudo apt install zabbix-agent2

$ systemctl status zabbix-agent2
● zabbix-agent2.service - Zabbix Agent 2
     Loaded: loaded (/lib/systemd/system/zabbix-agent2.service; enabled; vendor preset: enabled)
     Active: active (running) since Sat 2023-12-16 20:34:53 JST; 25s ago
   Main PID: 4798 (zabbix_agent2)
      Tasks: 10 (limit: 4599)
     Memory: 4.5M
        CPU: 21ms
     CGroup: /system.slice/zabbix-agent2.service
             mq4798 /usr/sbin/zabbix_agent2 -c /etc/zabbix/zabbix_agent2.conf

12月 16 20:34:53 t1082ubnt systemd[1]: Started Zabbix Agent 2.
12月 16 20:34:53 t1082ubnt zabbix_agent2[4798]: Starting Zabbix Agent 2 (6.0.25)
12月 16 20:34:53 t1082ubnt zabbix_agent2[4798]: Zabbix Agent2 hostname: [Zabbix server]
12月 16 20:34:53 t1082ubnt zabbix_agent2[4798]: Press Ctrl+C to exit.

3. 設定ファイルを修正

/etc/zabbix/zabbix_agent2.confのファイルを修正し、Zabbix Serverと疎通できるようにする。最低限以下の通り設定すれば動作する。

Server=[Zabbix ServerのIPアドレス]
ServerActive=[Zabbix ServerのIPアドレス]
Hostname=[Ubuntuのホスト名]

設定反映のため、Zabbix Agent 2を再起動する。

$ sudo systemctl restart zabbix-agent2

以上で、Ubuntuに対してZabbix Agent 2をインストールする手順は完了となる。

2023年12月16日土曜日

Kubernetesにてノードの削除・追加を行う

Kubernetesでノードの調子が悪くなったりした際に、一度ノードを削除して同じ名前で再度追加をさせたい場合がある。

簡単にノードを削除・追加するだけであればよいが、Kubernetesの場合、少し追加で必要な作業がある。本記事では、Kubernetesにてノードの削除・追加を行うために必要な手順を記載する。

環境

以下に今回構築する各種ソフトウェアのバージョンを記載する。

  • ホストOS : AlmaLinux 8.6
  • Kubernetes : v1.28.2
  • Docker : 24.0.6
  • CRI : cri-dockerd 0.3.4
  • CNI : flannel v0.22.0

今回の構成の概要図を以下に記載する。

作業前のKubernetesのノードの状態は以下の通り。3台目に存在する「t1053kube」のノードを削除したのち、追加する手順を説明する。

# kubectl get node -o=wide
NAME        STATUS   ROLES           AGE    VERSION   INTERNAL-IP     EXTERNAL-IP   OS-IMAGE                    KERNEL-VERSION              CONTAINER-RUNTIME
t1051kube   Ready    control-plane   202d   v1.28.2   192.168.11.51   <none>        AlmaLinux 8.6 (Sky Tiger)   4.18.0-372.9.1.el8.x86_64   docker://24.0.6
t1052kube   Ready    control-plane   202d   v1.28.2   192.168.11.52   <none>        AlmaLinux 8.6 (Sky Tiger)   4.18.0-372.9.1.el8.x86_64   docker://24.0.6
t1053kube   Ready    control-plane   174d   v1.28.2   192.168.11.53   <none>        AlmaLinux 8.6 (Sky Tiger)   4.18.0-372.9.1.el8.x86_64   docker://24.0.6

ノード削除手順

1. Kubernetesクラスタからノードを削除

Kubernetesクラスタからノードを削除する際は、kubectl delete node [ノード名]で行う。処理はすぐに完了する。

# kubectl delete node t1053kube
node "t1053kube" deleted

3台存在したノードが2台になったことが確認できる。

# kubectl get node -o=wide
NAME        STATUS   ROLES           AGE    VERSION   INTERNAL-IP     EXTERNAL-IP   OS-IMAGE                    KERNEL-VERSION              CONTAINER-RUNTIME
t1051kube   Ready    control-plane   202d   v1.28.2   192.168.11.51   <none>        AlmaLinux 8.6 (Sky Tiger)   4.18.0-372.9.1.el8.x86_64   docker://24.0.6
t1052kube   Ready    control-plane   202d   v1.28.2   192.168.11.52   <none>        AlmaLinux 8.6 (Sky Tiger)   4.18.0-372.9.1.el8.x86_64   docker://24.0.6

2. ノードをリセット

削除した対象のOSにログインし、kubeadm resetを用いて、一度ノードをリセットする。なお、複数のCRIがインストールされている環境の場合は、--cri-socketオプションにて使用するCRIを明記する必要がある(オプションを指定しない場合、Found multiple CRI endpoints on the host.というエラーが表示されコマンドが失敗する)。

# kubeadm reset --cri-socket=unix:///var/run/cri-dockerd.sock
[reset] Reading configuration from the cluster...
[reset] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -o yaml'
W1210 07:53:07.866239  247333 reset.go:120] [reset] Unable to fetch the kubeadm-config ConfigMap from cluster: failed to get node registration: failed to get node name from kubelet config: open /etc/kubernetes/kubelet.conf: no such file or directory
W1210 07:53:07.866312  247333 preflight.go:56] [reset] WARNING: Changes made to this host by 'kubeadm init' or 'kubeadm join' will be reverted.
[reset] Are you sure you want to proceed? [y/N]: y ★"y"を入力
[preflight] Running pre-flight checks
W1210 07:53:09.421805  247333 removeetcdmember.go:106] [reset] No kubeadm config, using etcd pod spec to get data directory
[reset] Deleted contents of the etcd data directory: /var/lib/etcd
[reset] Stopping the kubelet service
[reset] Unmounting mounted directories in "/var/lib/kubelet"
[reset] Deleting contents of directories: [/etc/kubernetes/manifests /var/lib/kubelet /etc/kubernetes/pki]
[reset] Deleting files: [/etc/kubernetes/admin.conf /etc/kubernetes/kubelet.conf /etc/kubernetes/bootstrap-kubelet.conf /etc/kubernetes/controller-manager.conf /etc/kubernetes/scheduler.conf]

The reset process does not clean CNI configuration. To do so, you must remove /etc/cni/net.d

The reset process does not reset or clean up iptables rules or IPVS tables.
If you wish to reset iptables, you must do so manually by using the "iptables" command.

If your cluster was setup to utilize IPVS, run ipvsadm --clear (or similar)
to reset your system's IPVS tables.

The reset process does not clean your kubeconfig files and you must remove them manually.
Please, check the contents of the $HOME/.kube/config file.

3. etcdからNode情報を削除

Kubernetesクラスタから削除しても、etcdからは情報が削除されない。そこで、直接etcdのPodにログインし削除作業を行う。etcdにログインすると、プロンプトがsh-5.1#に変わる。

# kubectl exec -it -n kube-system etcd-t1051kube -- sh
sh-5.1#

etcdの操作はetcdctlコマンドで実行する。オプションが多いため超絶コマンドが長いが、以下の通りetcdctl member listを実行すると、現在etcdに登録されている情報を確認することができる。先ほどKubernetesクラスタから削除した「t1053kube」のノードの情報が残っていることがわかる。

sh-5.1# ETCDCTL_API=3 etcdctl --cert=/etc/kubernetes/pki/etcd/peer.crt --key=/etc/kubernetes/pki/etcd//peer.key --cacert=/etc/kubernetes/pki/etcd/ca.crt --endpoints=https://127.0.0.1:2379 member list
391db64cfd0b76da, started, t1052kube, https://192.168.11.52:2380, https://192.168.11.52:2379, false
40f1e9f856640698, started, t1051kube, https://192.168.11.51:2380, https://192.168.11.51:2379, false
a642d0757a50ab59, started, t1053kube, https://192.168.11.53:2380, https://192.168.11.53:2379, false

テーブル形式でもう少し見やすくする場合は、etcdctl -w table member listを実行する。

sh-5.1# ETCDCTL_API=3 etcdctl --cert=/etc/kubernetes/pki/etcd/peer.crt --key=/etc/kubernetes/pki/etcd//peer.key --cacert=/etc/kubernetes/pki/etcd/ca.crt --endpoints=https://127.0.0.1:2379 -w table member list
+------------------+---------+-----------+----------------------------+----------------------------+------------+
|        ID        | STATUS  |   NAME    |         PEER ADDRS         |        CLIENT ADDRS        | IS LEARNER |
+------------------+---------+-----------+----------------------------+----------------------------+------------+
| 391db64cfd0b76da | started | t1052kube | https://192.168.11.52:2380 | https://192.168.11.52:2379 |      false |
| 40f1e9f856640698 | started | t1051kube | https://192.168.11.51:2380 | https://192.168.11.51:2379 |      false |
| a642d0757a50ab59 | started | t1053kube | https://192.168.11.53:2380 | https://192.168.11.53:2379 |      false |
+------------------+---------+-----------+----------------------------+----------------------------+------------+

削除対象の「t1053kube」のIDを引数として、etcdctl member remove [ID]を実行する。

sh-5.1# ETCDCTL_API=3 etcdctl --cert=/etc/kubernetes/pki/etcd/peer.crt --key=/etc/kubernetes/pki/etcd//peer.key --cacert=/etc/kubernetes/pki/etcd/ca.crt --endpoints=https://127.0.0.1:2379 member remove a642d0757a50ab59
Member a642d0757a50ab59 removed from cluster 786da9e9c378caa1

再度登録状況を確認すると、「t1053kube」が削除されていることが確認できる。

sh-5.1# ETCDCTL_API=3 etcdctl --cert=/etc/kubernetes/pki/etcd/peer.crt --key=/etc/kubernetes/pki/etcd//peer.key --cacert=/etc/kubernetes/pki/etcd/ca.crt --endpoints=https://127.0.0.1:2379 -w table member list
+------------------+---------+-----------+----------------------------+----------------------------+------------+
|        ID        | STATUS  |   NAME    |         PEER ADDRS         |        CLIENT ADDRS        | IS LEARNER |
+------------------+---------+-----------+----------------------------+----------------------------+------------+
| 391db64cfd0b76da | started | t1052kube | https://192.168.11.52:2380 | https://192.168.11.52:2379 |      false |
| 40f1e9f856640698 | started | t1051kube | https://192.168.11.51:2380 | https://192.168.11.51:2379 |      false |
+------------------+---------+-----------+----------------------------+----------------------------+------------+

最後にexitでetcdから抜けておく。

sh-5.1# exit

ノード参加手順

1. 参加するためのtoken作成

ノード参加のためには、tokenを作成する必要がある。現在作成されているtokenは以下コマンドで確認できる。何も表示されない場合は、未登録であることを意味する。

# kubeadm token list

tokenを作成しつつノード追加のコマンドを表示させるため、以下コマンドを実行する。

# kubeadm token create --print-join-command
kubeadm join t1041kube.intrat.local:6443 --token hqrq5b.lmlys2u5vsqmza06 --discovery-token-ca-cert-hash sha256:cd21077ae8389da3990d28424f3e8aa1fcbf5394094bcb849803b8664d700b55

また、ノード追加時に必要となる証明書の更新も実施する。

# kubeadm init phase upload-certs --upload-certs
[upload-certs] Storing the certificates in Secret "kubeadm-certs" in the "kube-system" Namespace
[upload-certs] Using certificate key:
36568d37aa84232e623cd8df34c1704c2fb16e7846e7df92b55f13072ce262f0

再度tokenを確認すると、tokenと証明書の2行が表示されていることが確認できる。

# kubeadm token list
TOKEN                     TTL         EXPIRES                USAGES                   DESCRIPTION                                                EXTRA GROUPS
hqrq5b.lmlys2u5vsqmza06   23h         2023-12-10T22:41:01Z   authentication,signing   <none>                                                     system:bootstrappers:kubeadm:default-node-token
x87o7b.ya73txnsszqsx8x5   1h          2023-12-10T00:58:59Z   <none>                   Proxy for managing TTL for the kubeadm-certs secret        <none>

2. kubectl joinコマンド実行

token作成時に生成したkubeadm joinコマンドを実行し、ノードを再参加させる。なお、コントロールプレーンとして追加する場合は、--control-plane--certificate-keyのオプション指定が追加で必要となる。--cri-socketは前述したとおり、複数のCRIがインストールされている環境の場合に必要となる。

今回の場合はコントロールプレーンとしてノードを参加させるため、コマンドは以下のようになった。

kubeadm join t1041kube.intrat.local:6443 --token hqrq5b.lmlys2u5vsqmza06 \
--discovery-token-ca-cert-hash sha256:cd21077ae8389da3990d28424f3e8aa1fcbf5394094bcb849803b8664d700b55 \
--control-plane \
--certificate-key 36568d37aa84232e623cd8df34c1704c2fb16e7846e7df92b55f13072ce262f0 \
--cri-socket=unix:///var/run/cri-dockerd.sock

実際の実行結果は以下となる。

# kubeadm join t1041kube.intrat.local:6443 --token hqrq5b.lmlys2u5vsqmza06 \
> --discovery-token-ca-cert-hash sha256:cd21077ae8389da3990d28424f3e8aa1fcbf5394094bcb849803b8664d700b55 \
> --control-plane \
> --certificate-key 36568d37aa84232e623cd8df34c1704c2fb16e7846e7df92b55f13072ce262f0 \
> --cri-socket=unix:///var/run/cri-dockerd.sock
[preflight] Running pre-flight checks
[preflight] Reading configuration from the cluster...
[preflight] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -o yaml'
[preflight] Running pre-flight checks before initializing the new control plane instance
[preflight] Pulling images required for setting up a Kubernetes cluster
[preflight] This might take a minute or two, depending on the speed of your internet connection
[preflight] You can also perform this action in beforehand using 'kubeadm config images pull'
W1210 08:16:25.328679  250776 checks.go:835] detected that the sandbox image "registry.k8s.io/pause:3.6" of the container runtime is inconsistent with that used by kubeadm. It is recommended that using "registry.k8s.io/pause:3.9" as the CRI sandbox image.
[download-certs] Downloading the certificates in Secret "kubeadm-certs" in the "kube-system" Namespace
[download-certs] Saving the certificates to the folder: "/etc/kubernetes/pki"
[certs] Using certificateDir folder "/etc/kubernetes/pki"
[certs] Generating "etcd/server" certificate and key
[certs] etcd/server serving cert is signed for DNS names [localhost t1053kube] and IPs [192.168.11.53 127.0.0.1 ::1]
[certs] Generating "etcd/peer" certificate and key
[certs] etcd/peer serving cert is signed for DNS names [localhost t1053kube] and IPs [192.168.11.53 127.0.0.1 ::1]
[certs] Generating "apiserver-etcd-client" certificate and key
[certs] Generating "etcd/healthcheck-client" certificate and key
[certs] Generating "front-proxy-client" certificate and key
[certs] Generating "apiserver" certificate and key
[certs] apiserver serving cert is signed for DNS names [kubernetes kubernetes.default kubernetes.default.svc kubernetes.default.svc.cluster.local t1041kube.intrat.local t1053kube] and IPs [10.96.0.1 192.168.11.53]
[certs] Generating "apiserver-kubelet-client" certificate and key
[certs] Valid certificates and keys now exist in "/etc/kubernetes/pki"
[certs] Using the existing "sa" key
[kubeconfig] Generating kubeconfig files
[kubeconfig] Using kubeconfig folder "/etc/kubernetes"
[kubeconfig] Writing "admin.conf" kubeconfig file
[kubeconfig] Writing "controller-manager.conf" kubeconfig file
[kubeconfig] Writing "scheduler.conf" kubeconfig file
[control-plane] Using manifest folder "/etc/kubernetes/manifests"
[control-plane] Creating static Pod manifest for "kube-apiserver"
[control-plane] Creating static Pod manifest for "kube-controller-manager"
[control-plane] Creating static Pod manifest for "kube-scheduler"
[check-etcd] Checking that the etcd cluster is healthy
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[kubelet-start] Starting the kubelet
[kubelet-start] Waiting for the kubelet to perform the TLS Bootstrap...
[etcd] Announced new etcd member joining to the existing etcd cluster
[etcd] Creating static Pod manifest for "etcd"
[etcd] Waiting for the new etcd member to join the cluster. This can take up to 40s
The 'update-status' phase is deprecated and will be removed in a future release. Currently it performs no operation
[mark-control-plane] Marking the node t1053kube as control-plane by adding the labels: [node-role.kubernetes.io/control-plane node.kubernetes.io/exclude-from-external-load-balancers]
[mark-control-plane] Marking the node t1053kube as control-plane by adding the taints [node-role.kubernetes.io/control-plane:NoSchedule]

This node has joined the cluster and a new control plane instance was created:

* Certificate signing request was sent to apiserver and approval was received.
* The Kubelet was informed of the new secure connection details.
* Control plane label and taint were applied to the new node.
* The Kubernetes control plane instances scaled up.
* A new etcd member was added to the local/stacked etcd cluster.

To start administering your cluster from this node, you need to run the following as a regular user:

        mkdir -p $HOME/.kube
        sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
        sudo chown $(id -u):$(id -g) $HOME/.kube/config

Run 'kubectl get nodes' to see this node join the cluster.

最後にノードの状態を確認すると「t1053kube」が正常に登録されステータスがReadyになっていることがわかる。

# kubectl get node -o=wide
NAME        STATUS   ROLES           AGE    VERSION   INTERNAL-IP     EXTERNAL-IP   OS-IMAGE                    KERNEL-VERSION              CONTAINER-RUNTIME
t1051kube   Ready    control-plane   202d   v1.28.2   192.168.11.51   <none>        AlmaLinux 8.6 (Sky Tiger)   4.18.0-372.9.1.el8.x86_64   docker://24.0.6
t1052kube   Ready    control-plane   202d   v1.28.2   192.168.11.52   <none>        AlmaLinux 8.6 (Sky Tiger)   4.18.0-372.9.1.el8.x86_64   docker://24.0.6
t1053kube   Ready    control-plane   17s    v1.28.2   192.168.11.53   <none>        AlmaLinux 8.6 (Sky Tiger)   4.18.0-372.9.1.el8.x86_64   docker://24.0.6

以上で、Kubernetesにてノードの削除・追加を行うために必要な手順は完了となる。

2023年12月9日土曜日

RHEL 9のsshdでPermitRootLoginなどを設定する方法

先日、RHEL 9互換OSのAlmaLinux 9を使った際に、SSHで直接rootログインを禁止しようと、PermitRootLogin noの設定を/etc/ssh/sshd_configに記載した。

しかし、記載したにも関わらずSSHでrootログインできてしまうという事象が発生した。調べてみると、RHEL 9からはsshdの設定方法が少し変更となったようだ。

本記事では、RHEL 9のsshdでPermitRootLoginなどを設定する方法を記載する。

環境

  • OS : Red Hat Enterprise Linux release 9.2

設定手順

RHEL 7や8などでは/etc/ssh/sshd_configにPermitRootLoginの設定を実施すれば問題なかったが、RHEL 9からは追加の設定は/etc/ssh/sshd_config.d/のディレクトリ内の設定ファイルに記載する方式に変わっている。

/etc/ssh/sshd_configを確認すると、以下の通りディレクトリ内の設定ファイルをIncludeする設定が記載されている。

# cat /etc/ssh/sshd_config | grep -B3 'Include'

# To modify the system-wide sshd configuration, create a  *.conf  file under
#  /etc/ssh/sshd_config.d/  which will be automatically included below
Include /etc/ssh/sshd_config.d/*.conf

実際に/etc/ssh/sshd_config.d/のディレクトリを見ると、以下の通り2つのファイルが存在した。

# ls -l /etc/ssh/sshd_config.d/
合計 8
-rw-r--r--. 1 root root 141 10月  6 20:08 01-permitrootlogin.conf
-rw-------. 1 root root 719  1月 16  2023 50-redhat.conf

今回はPermitRootLoginの設定なので、01-permitrootlogin.confのファイルを編集する。

# cat /etc/ssh/sshd_config.d/01-permitrootlogin.conf
PermitRootLogin no # noに変更しSSHによるrootログインを拒否する

設定後、sshdをリロードすれば完了となる。

# systemctl reload sshd

以上で、RHEL 9のsshdでPermitRootLoginなどを設定する方法は完了となる。

2023年12月2日土曜日

ソースからインストールしたOpenLDAPのSSL有効化手順

先日、RHEL 9にOpenLDAPをソースからインストールする手順を記載した。

上記手順ではLDAPのみ有効としており、通信が暗号化されていない。LDAPでは通信を暗号化する方法としてLDAPS (LDAP over SSL/TLS) があり、OpenLDAPにおいても設定を有効化することでLDAPS通信を利用できる。

本記事では、ソースからインストールOpenLDAPに対してSSLを有効化する手順を記載する。

環境

今回は以下のOSに対してインストールを行った。OpenLDAPは本記事作成時のLTSリリースの最新版である2.5.16をダウンロードした。

  • OS : RHEL 9
  • OpenLDAP : 2.5.16

OpenLDAPのドメイン等の情報は以下とする。

設定項目 設定値
ドメイン dc=example,dc=com
RootDN cn=Manager,dc=example,dc=com
OU ou=group,dc=example,dc=com
グループ cn=ldapgrp,ou=group,dc=example,dc=com
ユーザ1 uid=user01,ou=group,dc=example,dc=com
ユーザ2 uid=user01,ou=group,dc=example,dc=com

OpenLDAPをソースからインストール

OpenLDAPをソースからインストールする手順は、以下記事の通り実施する。

  • URL

OpenLDAP SSL有効化手順

1. 証明書作成

OpenLDAPをSSLするための公開鍵と秘密鍵を作成する。作成した鍵は/etc/openldap/certs/に配置するため、あらかじめ移動しておく。

# cd /etc/openldap/certs/

秘密鍵を作成する。

# openssl genrsa 2048 > ldaps.key

秘密鍵をもとにCSRを作成する。

# openssl req -new -key ldaps.key > ldaps.csr
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:JP
State or Province Name (full name) []:Tokyo
Locality Name (eg, city) [Default City]:
Organization Name (eg, company) [Default Company Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []:LDAPS
Email Address []:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

公開鍵に埋め込むSAN (サブジェクト代替名) の情報をテキストファイルで作成しておく。今回はOpenLDAPのドメイン (example.com) とOpenLDAPサーバのIPアドレス (192.168.11.191) で設定した。

# cat << EOF > san.txt
subjectAltName = DNS:*.example.com, IP:192.168.11.191
EOF

最後にCSRとSANの情報を用いて公開鍵を作成する。

# openssl x509 -days 3650 -req -signkey ldaps.key -in ldaps.csr -out ldaps.crt -extfile san.txt
Certificate request self-signature ok
subject=C = JP, ST = Tokyo, L = Default City, O = Default Company Ltd, CN = LDAPS

最終的に以下4つのファイルが作成される。

# ls -l
合計 16
-rw-r--r--. 1 root root 1302 10月 29 08:11 ldaps.crt
-rw-r--r--. 1 root root  997 10月 29 08:10 ldaps.csr
-rw-r--r--. 1 root root 1704 10月 29 08:10 ldaps.key
-rw-r--r--. 1 root root   54 10月 29 08:07 san.txt

2. SSL有効化用LDIFファイルを作成

OpenLDAPの設定は、LDIF (LDAP Interchange Format)と呼ばれる設定ファイルを読み込ませることで行う。

まずは、以下の通りLDIFファイルを作成する。

# cd ~
# cat << EOF > ssl.ldif
dn: cn=config
changetype: modify
replace: olcTLSCertificateFile
olcTLSCertificateFile: /etc/openldap/certs/ldaps.crt
-
replace: olcTLSCertificateKeyFile
olcTLSCertificateKeyFile: /etc/openldap/certs/ldaps.key
EOF

反映はslapmodifyコマンドで行う。

# /usr/sbin/slapmodify -v -n 0 -F /etc/openldap/slapd.d -l ssl.ldif
modify: "cn=config" (00000001)
Closing DB...

なお、ldapaddコマンドではInsufficient access (50)で失敗するため設定変更できないため注意しよう。

# ldapadd -Y EXTERNAL -H ldapi:// -f ssl.ldif
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
modifying entry "cn=config"
ldap_modify: Insufficient access (50)

3. systemdの設定を修正

systemdでOpenLDAPのサービス起動時のコマンドにおいて、LDAPSを受け付けするよう設定追加を行う。

# vi /etc/systemd/system/slapd.service
[Unit]
Description=OpenLDAP server
After=syslog.target network.target

[Service]
Type=forking
User=root
Group=root
PIDFile=/usr/var/run/slapd.pid
ExecStart=/usr/libexec/slapd -F /etc/openldap/slapd.d -h 'ldapi:/// ldap:/// ldaps:///' ←★「ldaps:///」を追加
ExecReload=/bin/kill -HUP $MAINPID
ExecStop=/bin/kill -TERM $MAINPID

[Install]
WantedBy=multi-user.target

設定を反映させる。

# systemctl daemon-reload
# systemctl restart slapd

反映後、LDAPSのポート番号である636が開放されていることを確認する。

# ss -nl | egrep '389|636'
tcp   LISTEN 0      2048        0.0.0.0:389         0.0.0.0:*
tcp   LISTEN 0      2048        0.0.0.0:636         0.0.0.0:*
tcp   LISTEN 0      2048           [::]:389            [::]:*
tcp   LISTEN 0      2048           [::]:636            [::]:*

4. LDP.exeを使った確認

実際に、外部からアクセスできることをWindows ServerのLDP.exeを利用して確認する。なお、LDP.exeは、役割管理ツールの「AD DSおよびAD LDSツール」に含まれる

なお、LDAPSはそのままではLDP.exeにて接続することができず、OpenLDAPサーバにて作成したSSLサーバ証明書の公開鍵であるldaps.crtを「信頼されたルート証明機関」として登録が必要となる。

/etc/openldap/certs/ldaps.crtLDP.exeを実行するサーバにダウンロードし、ファイルをダブルクリックすると証明書の情報を確認することができ、「証明書のインストール」を選択することで「証明書のインポートウィザード」を開始できる。

インポートウィザードでは証明書ストアにて「信頼されたルート証明機関」を選択する。

セキュリティ警告が表示される場合があるが、自己署名証明書による証明書エラーとなることから、そのまま「はい」を選択する。

証明書をインポートしたのち、再度LDP.exeにて接続すると、以下の通りSSLによる接続に成功する。

以上で、ソースからインストールOpenLDAPに対してSSLを有効化する手順は完了となる。

2023年11月25日土曜日

OpenLDAPをソースからインストールする

OpenLDAPはRHEL 7までは、リポジトリからyumコマンドを使ってインストールすることができたが、RHEL 8になってからOpenLDAPは含まれないようになってしまい、RHELのサポート範囲外のソフトウェアとなってしまった。

RHEL 8以降は、OpenLDAPからRed Hat Directory Server (RHDS) を利用することができる。しかし、RHDSは389 Directory Serverがベースとなっており、OpenLDAPや構築方法や運用方法が異なってしまう。

以上より、RHEL 8以降においてもOpenLDAPが利用するため、本記事では、RHEL 9にOpenLDAPをソースからインストールする手順を記載する。

環境

今回は以下のOSに対してインストールを行った。OpenLDAPは本記事作成時のLTSリリースの最新版である2.5.16をダウンロードした。

  • OS : RHEL 9
  • OpenLDAP : 2.5.16

OpenLDAPのドメイン等の情報は以下とする。

設定項目 設定値
ドメイン dc=example,dc=com
RootDN cn=Manager,dc=example,dc=com
OU ou=group,dc=example,dc=com
グループ cn=ldapgrp,ou=group,dc=example,dc=com
ユーザ1 uid=user01,ou=group,dc=example,dc=com
ユーザ2 uid=user01,ou=group,dc=example,dc=com

OpenLDAPインストール

1. OpenLDAPのソースを入手

OpenLDAPのソースは以下からダウンロードできる。今回はLTSリリースである2.5.16をダウンロードした。

ファイル名はopenldap-2.5.16.tgzとなる。以下の通り解凍して、解凍後のディレクトリ内に移動しておく。

# tar zxf openldap-2.5.16.tgz
# cd openldap-2.5.16

2. 前提パッケージインストール

ビルド時にエラーや警告が表示されないように、以下前提パッケージのインストールを行う。

# dnf install gcc make cyrus-sasl-devel openssl-devel systemd-devel -y

3. Makefile作成

./configureを実行してMakefileを作成する。オプションは以下の通り設定する。なお、設定可能なオプションは他にも多数あり、./configure --helpにて確認することができる。

オプション 説明
--with-tls SSL/TLSを有効化。
--with-cyrus-sasl SASLによる認証を有効化。
--enable-crypt パスワードの暗号化を有効化。
--prefix=/usr インストールディレクトリを変更。デフォルトは/usr/local/となる。
--sysconfdir=/etc 設定ファイル配置ディレクトリを変更。デフォルトは/usr/local/etcとなる。

./configureの実行結果を以下に記載する。

# ./configure --with-tls --with-cyrus-sasl --enable-crypt --with-systemd --prefix=/usr --sysconfdir=/etc
Configuring OpenLDAP 2.5.16-Release ...
checking build system type... x86_64-pc-linux-gnu
checking host system type... x86_64-pc-linux-gnu
checking target system type... x86_64-pc-linux-gnu
checking configure arguments... done
checking for cc... cc
checking for ar... ar
checking for strip... strip
checking whether make sets $(MAKE)... yes

~(中略)~

config.status: executing libtool commands
config.status: executing default commands
Making servers/slapd/backends.c
    Add config ...
    Add ldif ...
    Add monitor ...
    Add mdb ...
    Add relay ...
Making servers/slapd/overlays/statover.c
    Add syncprov ...
Please run "make depend" to build dependencies

Makefileが作成されていることを確認しておく。

# ls -l Makefile
-rw-r--r--. 1 root root 9256 10月 14 07:16 Makefile

4. 依存関係チェック

作成したMakfefileで依存関係をチェックする。特にエラーがなければ問題ない。

# make depend
Making depend in /root/openldap-2.5.16
  Entering subdirectory include
make[1]: ディレクトリ '/root/openldap-2.5.16/include' に入ります
Making ldap_config.h
make[1]: ディレクトリ '/root/openldap-2.5.16/include' から出ます

~(中略)~

  Entering subdirectory man8
make[3]: ディレクトリ '/root/openldap-2.5.16/doc/man/man8' に入ります
make[3]: 'depend' に対して行うべき事はありません.
make[3]: ディレクトリ '/root/openldap-2.5.16/doc/man/man8' から出ます

make[2]: ディレクトリ '/root/openldap-2.5.16/doc/man' から出ます

make[1]: ディレクトリ '/root/openldap-2.5.16/doc' から出ます

5. ビルド実行

ビルド実行する。1~2分程度で完了する。

#make
Making all in /root/openldap-2.5.16
  Entering subdirectory include
make[1]: ディレクトリ '/root/openldap-2.5.16/include' に入ります
make[1]: 'all' に対して行うべき事はありません.
make[1]: ディレクトリ '/root/openldap-2.5.16/include' から出ます

~(中略)~

make[3]: ディレクトリ '/root/openldap-2.5.16/doc/man/man8' から出ます

make[2]: ディレクトリ '/root/openldap-2.5.16/doc/man' から出ます

make[1]: ディレクトリ '/root/openldap-2.5.16/doc' から出ます

6. インストール

ビルド後、インストールを実行する。なお、インストール前にmake testコマンドでインストール前のテストを行うことができるので、安全にインストールを進めたい場合は実行すること。make testは数分~数十分時間を要する。

# make install
Making all in /root/openldap-2.5.16
  Entering subdirectory include
make[1]: ディレクトリ '/root/openldap-2.5.16/include' に入ります
make[1]: 'all' に対して行うべき事はありません.
make[1]: ディレクトリ '/root/openldap-2.5.16/include' から出ます

~(中略)~

installing slappasswd.8 in /usr/share/man/man8
installing slapschema.8 in /usr/share/man/man8
installing slaptest.8 in /usr/share/man/man8
make[3]: ディレクトリ '/root/openldap-2.5.16/doc/man/man8' から出ます

make[2]: ディレクトリ '/root/openldap-2.5.16/doc/man' から出ます

make[1]: ディレクトリ '/root/openldap-2.5.16/doc' から出ます

以上で、OpenLDAPのソースからのインストールは完了となる。続けて初期設定を行う。

OpenLDAP初期設定

1. 初期設定

設定ファイルをバックアップしておく。

# cd ~
# cp -R /etc/openldap ~/openldap.org
# ls -ld  ~/openldap.org
drwxr-xr-x. 4 root root 163 10月 14 07:37 /root/openldap.org

OpenLDAPの管理用ユーザーのパスワードをslappasswdを使って生成する。

# slappasswd
New password:
Re-enter new password:
{SSHA}7B1EpVxClcKpBwnlqG73YtB7IrUXhTLM

設定ファイルを以下の通り追記・変更を行う。includeではOpenLDAPで必要となるスキーマを追加している。olcSuffixolcRootDNはOpenLDAPのドメインに変更を行う。olcRootPWは先ほど生成したパスワードを指定する。

# vi /etc/openldap/slapd.ldif

~(中略)~

include: file:///etc/openldap/schema/core.ldif
include: file:///etc/openldap/schema/cosine.ldif  #<-★追記
include: file:///etc/openldap/schema/inetorgperson.ldif  #<-★追記
include: file:///etc/openldap/schema/nis.ldif  #<-★追記

~(中略)~

dn: olcDatabase=mdb,cn=config
objectClass: olcDatabaseConfig
objectClass: olcMdbConfig
olcDatabase: mdb
olcDbMaxSize: 1073741824
olcSuffix: dc=example,dc=com  #<-★変更
olcRootDN: cn=Manager,dc=example,dc=com  #<-★変更
# Cleartext passwords, especially for the rootdn, should
# be avoided.  See slappasswd(8) and slapd-config(5) for details.
# Use of strong authentication encouraged.
olcRootPW: {SSHA}7B1EpVxClcKpBwnlqG73YtB7IrUXhTLM  #<-★変更

~(以下略)~

設定ファイルの前後でdiffした結果は以下の通り。

# diff /etc/openldap/slapd.ldif{,.default}
44,46d43
< include: file:///etc/openldap/schema/cosine.ldif
< include: file:///etc/openldap/schema/inetorgperson.ldif
< include: file:///etc/openldap/schema/nis.ldif
87,88c84,85
< olcSuffix: dc=example,dc=com
< olcRootDN: cn=Manager,dc=example,dc=com
---
> olcSuffix: dc=my-domain,dc=com
> olcRootDN: cn=Manager,dc=my-domain,dc=com
92c89
< olcRootPW: {SSHA}7B1EpVxClcKpBwnlqG73YtB7IrUXhTLM
---
> olcRootPW: secret

OpenLDAPのデータ格納に必要となるディレクトリを作成する。

# mkdir /usr/var/openldap-data
# mkdir /etc/openldap/slapd.d

slapaddコマンドで設定反映を行う。

# /usr/sbin/slapadd -v -n 0 -F /etc/openldap/slapd.d -l /etc/openldap/slapd.ldif
added: "cn=config" (00000001)
added: "cn=schema,cn=config" (00000001)
added: "cn={0}core,cn=schema,cn=config" (00000001)
added: "cn={1}cosine,cn=schema,cn=config" (00000001)
added: "cn={2}inetorgperson,cn=schema,cn=config" (00000001)
added: "cn={3}nis,cn=schema,cn=config" (00000001)
added: "olcDatabase={-1}frontend,cn=config" (00000001)
added: "olcDatabase={1}mdb,cn=config" (00000001)
added: "olcDatabase={2}monitor,cn=config" (00000001)
Closing DB...

2. OpenLDAP起動確認

まずは手動でOpenLDAPを起動し、正常に起動することを確認する。

# /usr/libexec/slapd -F /etc/openldap/slapd.d -h 'ldapi:/// ldap:/// ldaps:///'

起動後に、ldapsearchで問題なく情報の参照ができるか確認する。

# ldapsearch -x -b '' -s base '(objectclass=*)' namingContexts

# extended LDIF
#
# LDAPv3
# base <> with scope baseObject
# filter: (objectclass=*)
# requesting: namingContexts
#

#
dn:
namingContexts: dc=example,dc=com ←★設定したドメインが表示されることを確認

# search result
search: 2
result: 0 Success

# numResponses: 2
# numEntries: 1

確認後、一度OpenLDAPを停止しておく。

# ps -ef | grep slapd | grep -v grep
root       69944       1  0 08:29 ?        00:00:00 /usr/libexec/slapd -F /etc/openldap/slapd.d -h ldapi:/// ldap:/// ldaps:///
# pkill slapd
# ps -ef | grep slapd | grep -v grep
#

3. systemdへ登録

RHELの場合、systemdでサービスの起動・停止を制御できた方が便利となる。以下の通り、systemdにOpenLDAPのサービスを登録するための設定ファイルを作成する。

# cat << 'EOF' > /etc/systemd/system/slapd.service
[Unit]
Description=OpenLDAP server
After=syslog.target network.target

[Service]
Type=forking
User=root
Group=root
PIDFile=/usr/var/run/slapd.pid
ExecStart=/usr/libexec/slapd -F /etc/openldap/slapd.d -h 'ldapi:/// ldap:/// ldaps:///'
ExecReload=/bin/kill -HUP $MAINPID
ExecStop=/bin/kill -TERM $MAINPID

[Install]
WantedBy=multi-user.target
EOF

上記ファイルを作成後、systemctlコマンドで起動停止が問題なくできることを確認しておく。

# systemctl daemon-reload
# systemctl start slapd
# systemctl enable slapd
# systemctl status slapd
● slapd.service - OpenLDAP server
     Loaded: loaded (/etc/systemd/system/slapd.service; enabled; preset: disabled)
     Active: active (running) since Sat 2023-10-14 08:43:52 JST; 8s ago
   Main PID: 70011 (slapd)
      Tasks: 2 (limit: 23166)
     Memory: 5.0M
        CPU: 8ms
     CGroup: /system.slice/slapd.service
             mq70011 /usr/libexec/slapd -F /etc/openldap/slapd.d -h "ldapi:/// ldap:/// ldaps:///"

10月 14 08:43:52 t1191rhel systemd[1]: Starting OpenLDAP server...
10月 14 08:43:52 t1191rhel slapd[70010]: @(#) $OpenLDAP: slapd 2.5.16 (Oct 14 2023 07:29:29) $
                                                  root@t1191rhel:/root/openldap-2.5.16/servers/slapd
10月 14 08:43:52 t1191rhel slapd[70011]: slapd starting
10月 14 08:43:52 t1191rhel systemd[1]: Started OpenLDAP server.

# systemctl stop slapd
# systemctl status slapd
○ slapd.service - OpenLDAP server
     Loaded: loaded (/etc/systemd/system/slapd.service; enabled; preset: disabled)
     Active: inactive (dead) since Sat 2023-10-14 18:28:23 JST; 1s ago
   Duration: 9h 44min 31.510s
    Process: 70408 ExecStop=/bin/kill -TERM $MAINPID (code=exited, status=0/SUCCESS)
   Main PID: 70011 (code=exited, status=0/SUCCESS)
        CPU: 14ms

10月 14 08:44:24 t1191rhel slapd[70011]: conn=1001 op=3 ADD dn="cn=ldapgrp,ou=group,dc=example,dc=com"
10月 14 08:44:24 t1191rhel slapd[70011]: conn=1001 op=3 RESULT tag=105 err=0 qtime=0.000010 etime=0.000472 text=
10月 14 08:44:24 t1191rhel slapd[70011]: conn=1001 op=4 UNBIND
10月 14 08:44:24 t1191rhel slapd[70011]: conn=1001 fd=13 closed
10月 14 18:28:23 t1191rhel systemd[1]: Stopping OpenLDAP server...
10月 14 18:28:23 t1191rhel slapd[70011]: daemon: shutdown requested and initiated.
10月 14 18:28:23 t1191rhel slapd[70011]: slapd shutdown: waiting for 0 operations/tasks to finish
10月 14 18:28:23 t1191rhel slapd[70011]: slapd stopped.
10月 14 18:28:23 t1191rhel systemd[1]: slapd.service: Deactivated successfully.
10月 14 18:28:23 t1191rhel systemd[1]: Stopped OpenLDAP server.

起動・停止が問題なくできることが確認できたら、OpenLDAPは起動させておこう。

# systemctl start slapd

4. ユーザー登録確認

ここからは実際にOpenLDAPにグループやユーザーの登録を行ってみよう。

まずは、ドメイン、OU、グループの登録を行うためのLDIFファイルを作成する。

# cat << EOF > base.ldif
dn: dc=example,dc=com
objectClass: top
objectClass: dcObject
objectClass: organization
dc: example
o: Example Inc.

dn: ou=group,dc=example,dc=com
objectClass: organizationalUnit
ou: Group

dn: cn=ldapgrp,ou=group,dc=example,dc=com
objectClass: posixGroup
gidNumber: 10000
cn: ldapgrp
EOF

ldapaddコマンドで登録を行う。パスワードは初期設定時に生成したパスワードとなる。

# ldapadd -x -D "cn=Manager,dc=example,dc=com" -W -f base.ldif
Enter LDAP Password:
adding new entry "dc=example,dc=com"

adding new entry "ou=group,dc=example,dc=com"

adding new entry "cn=ldapgrp,ou=group,dc=example,dc=com"

次にユーザー登録を行う。以下の通りLDIFファイルを作成する。

# cat << EOF > user.ldif
dn: uid=user01,ou=group,dc=example,dc=com
uid: user01
cn: Hoge Hoge
sn: user01
objectClass: posixAccount
objectClass: inetOrgPerson
userPassword: {SSHA}7B1EpVxClcKpBwnlqG73YtB7IrUXhTLM
loginShell: /bin/bash
uidNumber: 10001
gidNumber: 10000
homeDirectory: /home/user01

dn: uid=user02,ou=group,dc=example,dc=com
uid: user02
cn: Hoge Hoge
sn: user02
objectClass: posixAccount
objectClass: inetOrgPerson
userPassword: {SSHA}7B1EpVxClcKpBwnlqG73YtB7IrUXhTLM
loginShell: /bin/bash
uidNumber: 10002
gidNumber: 10000
homeDirectory: /home/user02
EOF

ldapaddコマンドで登録を行う。

# ldapadd -x -D "cn=Manager,dc=example,dc=com" -W -f user.ldif
Enter LDAP Password:
adding new entry "uid=user01,ou=group,dc=example,dc=com"

adding new entry "uid=user02,ou=group,dc=example,dc=com"

最後に、ldapsearchコマンドで登録状況を確認して完了となる。

# ldapsearch -LLL -Y EXTERNAL -H ldapi:/// -b 'dc=example,dc=com'
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
dn: dc=example,dc=com
objectClass: top
objectClass: dcObject
objectClass: organization
dc: example
o: Example Inc.

dn: ou=group,dc=example,dc=com
objectClass: organizationalUnit
ou: Group

dn: cn=ldapgrp,ou=group,dc=example,dc=com
objectClass: posixGroup
gidNumber: 10000
cn: ldapgrp

dn: uid=user01,ou=group,dc=example,dc=com
uid: user01
cn: Hoge Hoge
sn: user01
objectClass: posixAccount
objectClass: inetOrgPerson
userPassword:: e1NTSEF9WFhY772eKOecgeeVpSnvvZ5YWFg=
loginShell: /bin/bash
uidNumber: 10001
gidNumber: 10000
homeDirectory: /home/user01

dn: uid=user02,ou=group,dc=example,dc=com
uid: user02
cn: Hoge Hoge
sn: user02
objectClass: posixAccount
objectClass: inetOrgPerson
userPassword:: e1NTSEF9WFhY772eKOecgeeVpSnvvZ5YWFg=
loginShell: /bin/bash
uidNumber: 10002
gidNumber: 10000
homeDirectory: /home/user02

以上で、RHEL 9にOpenLDAPをソースからインストールする手順は完了となる。

2023年11月18日土曜日

Grafanaインストール&Zabbixの監視データを可視化する手順

Grafanaは、ログやデータなどをグラフなどに可視化する、データ可視化OSSとなる。Grafanaが可視化するデータを「データソース」と呼ぶ。データソースは、各種クラウド上に保存されている情報やDBなどに対応しており、それ以外にもプラグインを追加することでデータソースを追加することが可能となる。

本記事ではGrafanaの入門編として、GrafanaをインストールしてZabbixプラグインを追加し、Zabbixの監視データを可視化する手順を記載する。

環境

Grafanaをインストールした環境は以下の通り。

  • OS : AlmaLinux 9.2
  • Grafana : v10.0.3
  • Zabbix : 6.0.17

Grafanaインストール手順

1, Grafanaのパッケージのリポジトリ設定

Grafanaはdnfを使ってインストールすることができる。

まずは、GrafanaのリポジトリのGPGキーをダウンロードしインポートする。wgetは環境によってはインストールされていないことから、curlでダウンロードした。

# curl -LO https://rpm.grafana.com/gpg.key
# rpm --import gpg.key

以下の通りリポジトリの設定ファイルを作成する。

# cat << EOF > /etc/yum.repos.d/grafana.repo
[grafana]
name=grafana
baseurl=https://rpm.grafana.com
repo_gpgcheck=1
enabled=1
exclude=*beta*
gpgcheck=1
gpgkey=https://rpm.grafana.com/gpg.key
sslverify=1
sslcacert=/etc/pki/tls/certs/ca-bundle.crt
EOF

2. Grafanaインストール

dnfを使ってGrafanaをインストールする。

# dnf install grafana
AlmaLinux 9 - AppStream                                                                                             1.4 MB/s | 8.8 MB     00:06
AlmaLinux 9 - BaseOS                                                                                                2.4 MB/s | 2.9 MB     00:01
AlmaLinux 9 - Extras                                                                                                 19 kB/s |  17 kB     00:00
grafana                                                                                                              60 kB/s | 2.4 kB     00:00
GPG 鍵 0x2CF3C0C6 をインポート中:
 Userid     : "Grafana Labs <engineering@grafana.com>"
 Fingerprint: 0E22 EB88 E39E 1227 7A77 60AE 9E43 9B10 2CF3 C0C6
 From       : https://rpm.grafana.com/gpg.key
これでよろしいですか? [y/N]: y ★yを入力してエンター
grafana                                                                                                              10 MB/s |  37 MB     00:03
依存関係が解決しました。
====================================================================================================================================================
 パッケージ                                            アーキテクチャー        バージョン                          リポジトリー               サイズ
====================================================================================================================================================
インストール:
 grafana                                               x86_64                  10.0.3-1                            grafana                     79 M
依存関係のインストール:
 dejavu-sans-fonts                                     noarch                  2.37-18.el9                         baseos                     1.3 M
 fontconfig                                            x86_64                  2.14.0-2.el9_1                      appstream                  274 k
 fonts-filesystem                                      noarch                  1:2.0.5-7.el9.1                     baseos                     9.0 k
 freetype                                              x86_64                  2.10.4-9.el9                        baseos                     387 k
 graphite2                                             x86_64                  1.3.14-9.el9                        baseos                      94 k
 harfbuzz                                              x86_64                  2.7.4-8.el9                         baseos                     624 k
 langpacks-core-font-en                                noarch                  3.0-16.el9                          appstream                  9.4 k
 libpng                                                x86_64                  2:1.6.37-12.el9                     baseos                     116 k
 urw-base35-bookman-fonts                              noarch                  20200910-6.el9                      appstream                  846 k
 urw-base35-c059-fonts                                 noarch                  20200910-6.el9                      appstream                  873 k
 urw-base35-d050000l-fonts                             noarch                  20200910-6.el9                      appstream                   76 k
 urw-base35-fonts                                      noarch                  20200910-6.el9                      appstream                  9.8 k
 urw-base35-fonts-common                               noarch                  20200910-6.el9                      appstream                   21 k
 urw-base35-gothic-fonts                               noarch                  20200910-6.el9                      appstream                  642 k
 urw-base35-nimbus-mono-ps-fonts                       noarch                  20200910-6.el9                      appstream                  795 k
 urw-base35-nimbus-roman-fonts                         noarch                  20200910-6.el9                      appstream                  855 k
 urw-base35-nimbus-sans-fonts                          noarch                  20200910-6.el9                      appstream                  1.3 M
 urw-base35-p052-fonts                                 noarch                  20200910-6.el9                      appstream                  973 k
 urw-base35-standard-symbols-ps-fonts                  noarch                  20200910-6.el9                      appstream                   41 k
 urw-base35-z003-fonts                                 noarch                  20200910-6.el9                      appstream                  275 k
 xml-common                                            noarch                  0.6.3-58.el9                        appstream                   31 k

トランザクションの概要
====================================================================================================================================================
インストール  22 パッケージ

ダウンロードサイズの合計: 89 M
インストール後のサイズ: 312 M
これでよろしいですか? [y/N]: y ★yを入力してエンター

~(中略)~

インストール済み:
  dejavu-sans-fonts-2.37-18.el9.noarch                                  fontconfig-2.14.0-2.el9_1.x86_64
  fonts-filesystem-1:2.0.5-7.el9.1.noarch                               freetype-2.10.4-9.el9.x86_64
  grafana-10.0.3-1.x86_64                                               graphite2-1.3.14-9.el9.x86_64
  harfbuzz-2.7.4-8.el9.x86_64                                           langpacks-core-font-en-3.0-16.el9.noarch
  libpng-2:1.6.37-12.el9.x86_64                                         urw-base35-bookman-fonts-20200910-6.el9.noarch
  urw-base35-c059-fonts-20200910-6.el9.noarch                           urw-base35-d050000l-fonts-20200910-6.el9.noarch
  urw-base35-fonts-20200910-6.el9.noarch                                urw-base35-fonts-common-20200910-6.el9.noarch
  urw-base35-gothic-fonts-20200910-6.el9.noarch                         urw-base35-nimbus-mono-ps-fonts-20200910-6.el9.noarch
  urw-base35-nimbus-roman-fonts-20200910-6.el9.noarch                   urw-base35-nimbus-sans-fonts-20200910-6.el9.noarch
  urw-base35-p052-fonts-20200910-6.el9.noarch                           urw-base35-standard-symbols-ps-fonts-20200910-6.el9.noarch
  urw-base35-z003-fonts-20200910-6.el9.noarch                           xml-common-0.6.3-58.el9.noarch

完了しました!

3. Grafana起動

インポートしそのままGrafanaは起動することができるが、もしプロキシを経由してインターネット接続を行う環境の場合は、以下の通り/etc/sysconfig/grafana-serverにプロキシ関連の環境変数を記載しておく。

# vi /etc/sysconfig/grafana-server

# ↓最下行に以下を追加(記載例)
HTTP_PROXY=http://192.168.33.23:8080
HTTPS_PROXY=http://192.168.33.23:8080
NO_PROXY=localhost,127.0.0.1,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16

Grafanaを起動する。

# systemctl start grafana-server
# systemctl enable grafana-server

4. Grafanaにログイン

Grafanaは、デフォルトではHTTPの3000番ポートで待ち受ける。以下のURLをブラウザに入力するとログイン画面が表示されるはずだ。

http://[IPアドレス]:3000

ログインユーザー名、パスワードは以下を入力する。初回ログイン時はパスワード変更を求められるので、任意のパスワードに変更する。

  • ユーザー名 : admin
  • パスワード : admin

Zabbixのデータを可視化する

1. Zabbixプラグインをインストール

Zabbixの情報を可視化する場合、GrafanaにZabbixのプラグインをインストールする必要がある。プラグインのインストールはgrafana-cliコマンドで行う。

# grafana-cli plugins install alexanderzobnin-zabbix-app
? Downloaded and extracted alexanderzobnin-zabbix-app v4.3.1 zip successfully to /var/lib/grafana/plugins/alexanderzobnin-zabbix-app

Please restart Grafana after installing or removing plugins. Refer to Grafana documentation for instructions if necessary.

プラグインインストール後、Grafanaを一度再起動しておく。

# systemctl restart grafana-server

2. Zabbixプラグインを有効化

GrafanaのGUIにて[Administration]>[Plugins]に遷移し、[zabbix]で検索するとプラグインが表示されるので、表示されたZabbixのプラグインを選択する。

右上の[Enable]ボタンを選択する。

4. データソースの設定

GrafanaのGUIにて[Administration]>[Data sources]に遷移し、[Add data source]ボタンを選択する。

データソース選択画面で[zabbix]で検索すると、1件表示されるはずなので、それを選択する。

データソース設定画面では、最低限以下を設定する。

設定項目 設定値
Name Zabbix
URL http://[ZabbixサーバのIPアドレス]/zabbix/api_jsonrpc.php
Username Zabbixサーバのアクセス権限があるユーザー名
Password 上記ユーザー名のパスワード

ページ下部にある[Save & test]ボタンを選択し、エラー表示されずに接続先のZabbixのバージョンが表示されれば成功となる。

5. ダッシュボードを追加

[Dashboards]画面にてダッシュボードを作成する。

例えば以下はZabbixサーバの/領域の使用量をグラフに表示する設定となる。

設定項目 設定値
Data source Zabbix
Query type Metrics
Group Zabbix servers
Host Zabbix server
Item tag filesystem: /
Item /: Used space

以上で、GrafanaをインストールしてZabbixの監視データを可視化する手順は完了となる。

2023年11月11日土曜日

Roundcubeを使ってWebメール環境を構築する

先日、Postfix+DovecotでバーチャルドメインのIMAPメールサーバーを構築する手順を記事にした。

通常メールを確認する際は、Thunderbirdなどのメールクライアントの導入が必要となるが、メールクライアントをダウンロードしてPCにインストールしアカウントの設定を行うといった作業は、何度も実施すると結構な負荷となる。

そこで今回は、Webサーバ上で動作するメールクライアント「Roundcube」を使って、Webメール環境を構築してみることにした。

環境

Roundcubeの必要とするDBやPHPのシステム要件は、以下を参照すること。

上記を踏まえ、今回Roundcubeをインストールした環境は以下の通りとした。

  • OS : AlmaLinux 8.8
  • DB : MariaDB 10.3.35
  • Roundcube : 1.6.2
  • PHP : 7.4
  • Apache HTTP Server : 2.4.37
  • Postfix : 3.5.8
  • Dovecot : 2.3.16

以下記事の手順にて、Postfix+DovecotによるSMTP/IMAPサーバが構築済みであることが前提となる。

Roundcubeインストール手順

1. 必要パッケージのインストール

Roundcubeは必要となるパッケージが多岐にわたる。順にインストールしていこう。

まずはDBとしてMariaDBをインストールする。

dnf install httpd mariadb-server -y

次にPHPをインストールする。PHPのバージョンは7.3以上であることがシステム要件となることから、今回はPHP 7.4を選定した。また、Roundcubeは公式サイトのファイルではなく、Remiリポジトリに存在するRPMパッケージにてインストールを行う。

dnf module enable php:7.4 -y
dnf install http://rpms.remirepo.net/enterprise/remi-release-8.rpm -y
dnf --enablerepo=remi install roundcubemail -y

PHPにてMariaDBを利用するためのライブラリであるphp-mysqlnd (MySQL Native Driver) をインストールする。

dnf install php-mysqlnd -y

ImageMagicをインストールするために必要なパッケージがインストールする。gccmakeはこの後実行するpeclコマンドで必要となる。

dnf install php-devel php-pear gcc make ImageMagick ImageMagick-devel -y

単純にRPMパッケージをインストールするだけではRoundcubeからImageMagicを認識しないため、さらにpeclコマンドを実行し、ImageMagicのインストールを行う。

# pecl install imagick
WARNING: channel "pecl.php.net" has updated its protocols, use "pecl channel-update pecl.php.net" to update
downloading imagick-3.7.0.tgz ...
Starting to download imagick-3.7.0.tgz (360,138 bytes)
.........................................................................done: 360,138 bytes
33 source files, building
running: phpize
Configuring for:
PHP Api Version:         20190902
Zend Module Api No:      20190902
Zend Extension Api No:   320190902
Please provide the prefix of ImageMagick installation [autodetect] :
 ↑★そのままエンター

~(中略)~

Build process completed successfully
Installing '/usr/lib64/php/modules/imagick.so'
Installing '/usr/include/php/ext/imagick/php_imagick_shared.h'
install ok: channel://pecl.php.net/imagick-3.7.0
configuration option "php_ini" is not set to php.ini location
You should add "extension=imagick.so" to php.ini

ImageMagicのライブラリのパスを記載したPHPの設定ファイルを作成する。

# cat << EOF > /etc/php.d/20-imagick.ini
extension=/usr/lib64/php/modules/imagick.so
EOF

2. MariaDB設定

ここで一度MariaDBを起動する。

systemctl start mariadb
systemctl enable mariadb

MariaDBを起動したのちに、Roundcubeで用いるDB、ユーザ、パスワードを設定する。今回は以下の通り設定した。

  • DB : roundcubemail
  • ユーザ : roundcube
  • パスワード : password
# mysql -uroot
MariaDB [(none)]> CREATE DATABASE roundcubemail CHARACTER SET utf8 COLLATE utf8_general_ci;
MariaDB [(none)]> GRANT ALL PRIVILEGES ON roundcubemail.* TO roundcube@localhost IDENTIFIED BY 'password';
MariaDB [(none)]> FLUSH PRIVILEGES;
MariaDB [(none)]> quit

DBとDBユーザ作成後、初期設定用のSQLを流し込む。

# mysql -u roundcube roundcubemail -p < /usr/share/roundcubemail/SQL/mysql.initial.sql
Enter password: ←★先ほど作成したroundcubeユーザのパスワードを入力
# ←★エラーなくプロンプトが表示されればOK

3. Apache/PHP設定

PHPの設定ファイルであるphp.iniは最低限タイムゾーンの設定を変更しておく。

sed -i "s#;date.timezone =#date.timezone = 'Asia/Tokyo'#g" /etc/php.ini

Apacheの設定ファイルとして/etc/httpd/conf.d/roundcubemail.confがインストール時に作成されるが、そのままではローカルからのアクセスのみ許可されていることから、外部からのアクセスができるよう以下コマンドを行い設定を置換する。

sed -i 's/Require local/Require all granted/g' /etc/httpd/conf.d/roundcubemail.conf

最後にApacheを起動する。

systemctl start httpd
systemctl enable httpdd

4. インストールウィザードにアクセス

問題なくApacheが起動すれば、Roundcubeのインストールウィザード画面にアクセスできるはずだ。ブラウザから以下URLにアクセスしてみよう。

  • http://[Roundcubeのホスト名/IPアドレス]/roundcubemail/installer/

インストールウィザードでは、各種PHPのライブラリのインストール状況やDBの状況が表示される。ここでは原則すべての項目が「OK」になっていることを確認しよう(DBのみMySQLが「OK」となっていれば問題ない)。


5. config作成

インストールウィザードではRoundcubeの各種設定を行うことができる。多数の設定項目が存在するが、最低限以下表の通り設定を行えば問題ない。

設定項目 説明
Database setup > Database password (omit for sqlite) DBのroundcubeユーザのパスワードを入力する。
IMAP Settings > username_domain ここにドメインを記載すると、ログイン時にドメインを省略できる。
SMTP Settings > smtp_host 今回は同じサーバでSMTPサーバが動作していることから、localhost:25を指定する。
Display settings & user prefs > language 日本語環境にするため、ja_JPを指定する。

設定後、画面下部の「CREATE CONFIG」ボタンを選択する。

6. configをアップロード

設定した内容でconfig.inc.phpの設定ファイルが作成され表示される。

表示されたconfigの内容をブラウザ上でコピーし、/etc/roundcubemail/config.inc.phpのファイルを作成して貼り付ける。

# vi /etc/roundcubemail/config.inc.php
<?php

/* Local configuration for Roundcube Webmail */

~(中略)~

// You can connect to any other googie-compliant service by setting 'spellcheck_uri' accordingly.
$config['spellcheck_engine'] = 'enchant';

Roundcubeの設定反映のためApacheを再起動する。

systemctl restart httpd

7. ログイン確認

これでRoundcubeにログインできるはずだ。以下URLにアクセスしログイン画面が表示されることを確認しよう。

DovecotのIMAP認証に用いるものと同じユーザ (ローカルパートのみでOK) とパスワードを用いてログインできれば成功となる。

以上で、Roundcubeを使ってWebメール環境を構築する手順は完了となる。

2023年11月4日土曜日

Postfix+DovecotでバーチャルドメインのIMAPメールサーバーを構築する手順

先日、メールサーバー構築をする際の定番であるPostfixとDovecotを使ってIMAPのメールサーバーを構築した。

本記事ではその際に得られたノウハウをもとに、Postfix+DovecotでバーチャルドメインのIMAPメールサーバーを構築する手順を記載する。

環境

今回Postfix及びDovecotをインストールした環境は以下の通り。

  • OS : AlmaLinux 8.8
  • Postfix : 3.5.8
  • Dovecot : 2.3.16

共通

1. Postfix及びDovecotをインストール

Postfix及びDovecotのパッケージがインストールされていない場合は、dnfでインストールする。

dnf install postfix dovecot -y

2. バーチャルドメイン用のOSユーザ・グループの作成

バーチャルドメインの場合は、OSユーザではなくDovecot独自のユーザにてメールボックスのユーザが管理される。ただし、メールボックスへのメール配送等はOSユーザを用いる必要があることから、vmailという名前のユーザ・グループを作成する。

groupadd -g 10000 vmail
useradd -u 10000 -g vmail vmail

3. メールボックス作成

メールボックスを/var/spool/virtualというディレクトリで作成する。

mkdir /var/spool/virtual
chown -R vmail:vmail /var/spool/virtual/

上記ディレクトリの配下に、各ユーザのメールボックスが以下のディレクトリ構成で作成される。

/var/spool/virtual/[ドメイン名]/[ユーザ名]/Maildir

Postfix構築手順

1. 設定ファイルバックアップ

設定変更の前に設定ファイルをディレクトリ丸ごとバックアップする。

cp -rp /etc/postfix /root/postfix.org

2. main.cf設定

Postfixの主要な設定は/etc/postfix/main.cfに記載する。以下に主要な設定内容を記載する。

設定項目 説明
myhostname メールサーバのホスト名をFQDNで記載する。
mydomain メールサーバのドメインを記載する。今回はバーチャルドメイン環境であるため、管理対象のメールアドレスのドメインと一致しなくても問題ない。
inet_interfaces 外部からSMTPでアクセスできるようにallを指定する。
inet_protocols 今回はIPv4を指定するが、IPv4にだけでなくIPv6も使用する場合はallを指定する。
mynetworks 外部から接続可能なIPアドレスやネットワークを指定する。ここで設定したネットワークは後述するSASL認証も不要でメール送信が可能となるため、必必要以上に設定しないよう注意する。
relayhost 自ドメイン以外のメールをリレーするサーバを指定する。
home_mailbox メールボックス形式をMailbox形式(ユーザ単位で1ファイルでメールを管理)またはMaildir形式(1メールに対して1ファイルで管理)で指定する。通常はMaildir形式を指定すれば問題ない。なお、Maildir形式に場合は最後に/を付け、Maildir/で指定すること。
smtpd_banner メールヘッダー等に表示するメールサーバ情報を指定する。セキュリティの観点から、使用しているバージョン等は記載しない方針とし、ESMTPのみ設定する。
virtual_mailbox_domains バーチャルドメインで管理するドメインを記載したファイルのパスを指定する。今回は、/etc/postfix/vdomainsというファイルで管理する。
virtual_mailbox_base バーチャルドメインで管理するメールボックスのディレクトリを指定する。今回は/var/spool/virtualを指定する。
virtual_mailbox_maps バーチャルドメインで管理するユーザと、ユーザのメールボックスを紐づけするファイルのパスを指定する。今回は、/etc/postfix/vmailboxというファイルで管理する。なお、大規模環境においてはユーザを大量に管理する必要があることから、処理速度を考慮しハッシュ化したものを指定する(ハッシュ化はpostmapコマンドで行う)。
virtual_uid_maps バーチャルドメインでメール配送等の処理に使用するOSユーザを指定する。前述したvmailユーザのUIDを指定する。
virtual_gid_maps バーチャルドメインでメール配送等の処理に使用するOSグループを指定する。前述したvmailグループのGIDを指定する。
smtpd_sasl_auth_enable SASL認証を有効にする。
smtpd_sasl_type SASL認証で使用する認証先を設定する。今回はDovecotで設定するユーザ・パスワードを用いることからDovecotを指定する。なお、SASLの認証設定は、後程Dovecot側でも実施する。
smtpd_sasl_path PostfixとDovecotが同一環境で動作する環境であれば、private/authを指定すれば問題ない。これが、通信に使用するUNIXソケットファイルのパスになる。
smtpd_sasl_security_options SASL認証時のオプションを指定する。noanonymousにて匿名での認証を拒否し、noplaintextにて平文での認証を拒否する。
smtpd_recipient_restrictions メールを配送する際の制限を行う。permit_sasl_authenticatedにてSASL認証済みであれば許可し、permit_mynetworksにてmynetworksで設定したネットワークからの接続であれば許可する。最後に記載されているrejectにて、それ以外のメール配送を拒否する。
disable_vrfy_command セキュリティの観点からVRFYコマンドを禁止するため、yesで設定する。
smtpd_helo_required セキュリティの観点からSMTPコマンド接続時のHELOコマンドを必須にするため、yesで設定する。

実際のmain.cfの記載例を以下に記載する。

/etc/postfix/main.cf変更箇所抜粋

myhostname = mx01.example.com
mydomain = example.com
inet_interfaces = all
inet_protocols = ipv4
mynetworks = 10.0.0.1
relayhost = [10.0.0.1]:25
home_mailbox = Maildir/
smtpd_banner = ESMTP
virtual_mailbox_domains = /etc/postfix/vdomains
virtual_mailbox_base = /var/spool/virtual
virtual_mailbox_maps = hash:/etc/postfix/vmailbox
virtual_uid_maps = static:10000
virtual_gid_maps = static:10000
smtpd_sasl_auth_enable = yes
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
smtpd_sasl_security_options = noanonymous, noplaintext
smtpd_recipient_restrictions = permit_sasl_authenticated, permit_mynetworks, reject
disable_vrfy_command = yes
smtpd_helo_required = yes

3. バーチャルドメインの設定ファイルの作成

バーチャルドメインの設定として、以下2つのファイルを作成する。

ファイル 内容
/etc/postfix/vdomains バーチャルドメインで管理するドメインを記載したファイル。メールサーバーで管理するドメインを一覧として記載する。
/etc/postfix/vmailbox バーチャルドメインで管理するユーザと、ユーザのメールボックスを紐づけするファイル。メールアドレスとメール保存先のディレクトリを一覧として記載する。ディレクトリは、[ドメイン名]/[メールアドレスのローカルパート]/Maildir/の形式で記載する。

それぞれのファイルの記載例を以下に記載する。

/etc/postfix/vdomains

example.com
example1.com

/etc/postfix/vmailbox

ex01@example.com      example.com/ex01/Maildir/
ex02@example.com      example.com/ex02/Maildir/
ex11@example1.com     example1.com/ex11/Maildir/

/etc/postfix/vmailboxpostmapコマンドを用いてハッシュ化しておく。

postmap /etc/postfix/vmailbox

4. Postfix設定反映

設定反映前に設定ファイルのチェックを行う。

# postfix check
#  ←★エラーがなければ何も表示しない

問題がなければ、Postfixに設定を反映するため再起動する。

systemctl restart postfix
systemctl enable postfix

Dovecot構築手順

1. 設定ファイルバックアップ

設定変更の前に設定ファイルをディレクトリ丸ごとバックアップする。

cp -rp /etc/dovecot /root/dovecot.org

2. 各種設定を実施

DovecotはPostfix以上に設定ファイルが細分化されている。今回の修正対象ファイルを以下に記載する。

ファイル 内容
/etc/dovecot/dovecot.conf メインの設定ファイル。プロトコルとしてIMAPを指定する(デフォルトではPOP3、IMAPの両方が動作する)。
/etc/dovecot/conf.d/10-auth.conf 認証方式を記載する。今回は平文による認証を無効化したうえで、CRAM-MD5による認証方式を用いる。
/etc/dovecot/conf.d/auth-passwdfile.conf.ext 認証する際のパスワードファイルの指定を行う。パスワード認証情報(passdb)及びユーザ認証情報(userdb)は、後程作成する/etc/dovecot/usersファイルを参照するよう設定する。
/etc/dovecot/conf.d/10-master.conf PostfixがSASL認証で使用する際のUNIXソケットファイルのパスを指定する。

それぞれのファイルの記載例を以下に記載する。

/etc/dovecot/dovecot.conf変更箇所抜粋

protocols = imap lmtp

/etc/dovecot/conf.d/10-auth.conf変更箇所抜粋

disable_plaintext_auth = yes
auth_mechanisms = cram-md5
#!include auth-system.conf.ext
!include auth-passwdfile.conf.ext

/etc/dovecot/conf.d/auth-passwdfile.conf.ext変更箇所抜粋

passdb {
  driver = passwd-file
  args = scheme=CRAM-MD5 username_format=%u /etc/dovecot/users
}
userdb {
  driver = passwd-file
  args = username_format=%u /etc/dovecot/users
  default_fields = uid=vmail gid=vmail home=/var/spool/virtual/%d/%n/Maildir
}

/etc/dovecot/conf.d/10-master.conf変更箇所抜粋

service auth {
  unix_listener /var/spool/postfix/private/auth {
    mode = 0666
    user = postfix
    group = postfix
  }
  ~(略)~
}

3. ユーザ・パスワードファイルを作成

Dovecotのユーザ・パスワードファイルを作成する。パスワード情報は平文ではなくCRAM-MD5で暗号化されたものを記載する。CRAM-MD5の暗号化文字列の作成は以下コマンドで行う。

doveadm pw -s CRAM-MD5 -p [パスワード文字列]

上記で作成したパスワード文字列を用いて、以下書式でユーザ・パスワードファイルを作成する。行末のコロン2つ(::)は必要となるので省略しないこと。

[ユーザ名]:[暗号化パスワード文字列]::

ユーザ・パスワードファイルの記載例を以下に記載する。

/etc/dovecot/users

test01@example.com:{CRAM-MD5}dcbe8064d829ee98ad16817611150a123455fe1c9dfd79f5395be892f162bfd3::
test02@example.com:{CRAM-MD5}0a9a6905dfdefaf79e95b5a63274464123456166a2f27e593150e37ef2db952::
test11@example1.com:{CRAM-MD5}b71384fd047350e89123456a80ee9959dec89ff9766d75d45ab923792e44ea16::

4. 設定を反映

設定反映前に設定ファイルのチェックを行う。以下コマンドをすると各種設定値が羅列されるが、その際にエラーが表示されていなければ、設定値としては問題ない。

doveconf -n

Dovecotに設定を反映するため再起動する。

systemctl restart dovecot
systemctl enable dovecot

動作確認

メールクライアントを使って確認することが手っ取り早い。

Windows環境であれば、Thunderbird Portable Editionがインストール不要で使え、複数アカウント登録も簡単にできるのでお勧めとなる(ただし、容量は120MB程度あるので注意)。

今回はThunderbird Portable Editionを用いた確認手順を記載する。

1. Thunderbirdのアカウントの設定

Thunderbirdを開き、「設定」→「アカウント設定」を開き、「アカウント操作」から「メールアカウントを追加」を選択する。

でアカウント追加を行う。その際に受信サーバー(IMAP)と送信サーバー(SMTP)の設定を以下の通り行う。

受信サーバー

設定項目 設定値 説明
プロトコル IMAP -
ホスト名 構築したサーバのIPアドレス -
ポート番号 143 STARTTLSであれば143、SSL/TLSであれば993を選択する。
接続の保護 STARTTLS Dovecotの/etc/dovecot/conf.d/10-ssl.confにてssl = requiredの設定がされていることから、STARTTLSまたはSSL/TLSのどちらかを選択する。ここまでの設定で明示的に設定はしていないが、DovecotはデフォルトでIMAPSの通信が可能な構成となっている。
認証方式 暗号化されたパスワード認証 CRAM-MD5で設定されているため、「暗号化されたパスワード認証」を指定する。
ユーザー名 Dovecotで設定したユーザ名を指定 /etc/dovecot/usersに記載したユーザ名を指定する。

送信サーバー

設定項目 設定値 説明
ホスト名 構築したサーバのIPアドレス -
ポート番号 25 -
接続の保護 なし SSL/TLSの設定はしていないため、「なし」を指定する。
認証方式 暗号化されたパスワード認証 CRAM-MD5で設定されているため、「暗号化されたパスワード認証」を指定する。
ユーザー名 Dovecotで設定したユーザ名を指定 /etc/dovecot/usersに記載したユーザ名を指定する。

図13

2. 設定時の警告を承認

アカウントの作成指示に以下のセキュリティ警告が表示される。いずれも、「確認」と「セキュリティ例外を承認」を選択する。


4. アカウント作成

設定が問題なければ「アカウント作成が完了しました」の画面が表示される。

3. メール送受信テスト

同様の手順で複数アカウントを作成し、お互いでメールを送受信できることを確認できれば動作確認完了となる。

以上で、Postfix+DovecotでバーチャルドメインのIMAPメールサーバーを構築する手順は完了となる。

人気の投稿