もくじ

授業用のLinuxサーバーの構築(2012/10/08)

概要

これは授業用のLinuxサーバーの構築の解説である。Linuxクライアントからログインするユーザーに対してLDAPで認証し、ユーザホームをNFSで提供するファイルサーバーである。NFSversion4がkerberosと組み合わせることでユーザー認証を加えることができるようになったことでこの組み合わせを選んだが、残念ながらkerberosが思うように動かず、ホスト認証だけになっているのでこれは今後の課題である。

OSは Debian Gnu/Linux の Squeezeと呼ばれるバージョンである。構築の解説をすることを考えて極力Debianのデフォルト設定を活かす方向でインストールしている。その結果、次の点がユニークな点になっている。

なお、この他にもう一台のサーバーがあり、DHCP, DNS, Squid が動いているがここでは触れない

また、授業のテキスト・教材を配布するためにウェブサーバーを立てているがこれは独立性が強いので今回は触れない。

スペック

ハードウェア

グラフィックからギガのNICまでオンボードになったマザー。サーバーのために選んだものではなく2007年に購入したデスクトップ用

CPU: AMD Athlon(tm) 64 Processor 4000+
mother: ASUS M2A-VM
memory: 2GB
HDD0: 160GB システム用
HDD1: 500GB ユーザーホーム用
HDD2: 500GB ユーザーホームバックアップ用

OS

Debian GNU/Linux の安定版

Debian 6.0.5 (squeeze)
Linux amos 2.6.32-5-amd64
GNOME 2.30.2

パーティション構成

インストール時に一度自動で分けさせてその後今までのサーバーの使用状況を見て調整している。

Filesystem            Size  Used Avail Use% マウント位置
/dev/sda1             323M  154M  153M  51% /
/dev/sda5             8.3G  3.4G  4.5G  44% /usr
/dev/sda6             2.8G  450M  2.2G  17% /var  (23%)
/dev/sda8             368M   11M  339M   3% /tmp
/dev/sda9             132G  188M  125G   1% /srv  (2%)
/dev/sdb1             459G  250M  435G   1% /home  (5%)
/dev/sdc1             459G   21G  415G   1% /xhome  (5%)

dfの出力を加工したもの。( )内は現在(886人登録6ヶ月経過)の使用率。この他にスワップ領域3.6GBがsd7として取られている。

2台目のディスク(sdb)は生徒用のユーザーホームを入れるので/homeとしてマウント。別のディクスに独立させてアクセスを分散し負荷を落とすように考慮。

3台目のディスク(sdc)は /home を毎日夜にバックアップするためのもの。/xhomeとしてマウント。raid5のディスクがとても遅かったので素のディスクにして1日に一回バックアップをとることにした。raid10も考えたが分割にも重複記録にもそれなりの負荷があるしコストもかかる。授業用なので1日前の状態が確保されていれば十分ではないかと考えた。

X-windowを導入し、X なしのrunlevelの創設

サーバーにはデスクトップ環境は必要ないのでずっと入れて来なかったが、パッケージの検索や更新にsynapticが便利なこと、日本語環境のことをお任せにできること、sysv-rc-conf で簡単に X なしのrunlevelの設定ができることがわかって導入することにした。

結果としてうっかりXを起動したまま使用しても気がつくほどパフォーマンスは落ちない様だ。

sysv-rc-conf パッケージを入れて設定する。

root@amos:~# sysv-rc-conf 
| SysV Runlevel Config   -: stop service  =/+: start service  h: help  q:quit
| service      1      2      3      4      5      0      6      S        |
| ---------------------------------------------------------------------- |
| acpid       [ ]    [X]    [X]    [X]    [X]    [ ]    [ ]    [ ]       |
| alsa-utils  [ ]    [ ]    [ ]    [ ]    [ ]    [ ]    [ ]    [X]       |
| anacron     [ ]    [X]    [X]    [X]    [X]    [ ]    [ ]    [ ]       |
| apache2     [ ]    [X]    [X]    [X]    [X]    [ ]    [ ]    [ ]       |
| apcupsd     [ ]    [X]    [X]    [X]    [X]    [ ]    [ ]    [ ]       |
| atd         [ ]    [X]    [X]    [X]    [X]    [ ]    [ ]    [ ]       |
| bind9       [ ]    [X]    [X]    [X]    [X]    [ ]    [ ]    [ ]       |
| binfmt-su$  [ ]    [X]    [X]    [X]    [X]    [ ]    [ ]    [ ]       |
| bluetooth   [ ]    [X]    [X]    [X]    [X]    [ ]    [ ]    [ ]       |
| bootlogd    [ ]    [ ]    [ ]    [ ]    [ ]    [ ]    [ ]    [X]       |
| bootlogs    [X]    [X]    [X]    [X]    [X]    [ ]    [ ]    [ ]       |
| console-s$  [ ]    [ ]    [ ]    [ ]    [ ]    [ ]    [ ]    [X]       |
| cpufrequt$  [ ]    [X]    [X]    [X]    [X]    [ ]    [ ]    [ ]       |
| cron        [ ]    [X]    [X]    [X]    [X]    [ ]    [ ]    [ ]       |
| cups        [ ]    [X]    [X]    [X]    [X]    [ ]    [ ]    [ ]       |
| dbus        [ ]    [X]    [X]    [X]    [X]    [ ]    [ ]    [ ]       |
| exim4       [ ]    [X]    [X]    [X]    [X]    [ ]    [ ]    [ ]       |
| fancontrol  [ ]    [X]    [X]    [X]    [X]    [ ]    [ ]    [ ]       |
| fuse        [ ]    [ ]    [ ]    [ ]    [ ]    [ ]    [ ]    [X]       |
| gdm3        [ ]    [X]    [ ]    [X]    [X]    [ ]    [ ]    [ ]       |
| halt        [ ]    [ ]    [ ]    [ ]    [ ]    [ ]    [ ]    [ ]       |
| hdparm      [ ]    [ ]    [ ]    [ ]    [ ]    [ ]    [ ]    [X]       |
| ifupdown    [ ]    [ ]    [ ]    [ ]    [ ]    [ ]    [ ]    [X]       |
|                                                                        |
==========================================================================
| Use the arrow keys or mouse to move around.   ^n: next pg  ^p: prev pg |
|                        space: toggle service on / off                  |

Debianは2-5はすべて同じで、Xが起動するマルチユーザーモード。RedHat系とは異なる。

level2をそのままに、level3をXが起動しないマルチユーザーモードにする。考え方としてはlevel2はメンテナンスモードと考えて低い位置づけにする。

/etc/inittab の default runlevel を 3 にする。

# /etc/inittab: init(8) configuration.
# $Id: inittab,v 1.91 2002/01/25 13:35:21 miquels Exp $

# The default runlevel.
id:3:initdefault:

# Boot-time system configuration/initialization script.
# This is run first except when booting in emergency (-b) mode.
si::sysinit:/etc/init.d/rcS
..................

runlevelの確認は

root@amos:~# runlevel
2 3

これは2だったものが現在3になっているということ。起動直後は N 3 となる。

runlevelの切り替えは、initを使う(メッセージ無しで切り替わる)。基本的に生徒はサーバー機にはログインしないのでいつ切り替えても問題はない。ただデスクトップ上の端末エミュレーター上ではやらないほうがいいだろう。

[Ctrl]+[Alt]+[Fn]で別のコンソールからrootでログインするか、sshでリモートで切り替える。

root@amos:~# init 2
root@amos:~# runlevel
3 2

network-managerを削除

インストール時にデスクトップを選択すると、X-window とともに network-manager, avahi などもインストールされる。昔のたくさんのパッケージの中から自分で選択しなければならないシステムは大変だったので、自動もありがたいが、せめてサーバー用という選択肢が欲しい。デスクトップを選択しないで英語のロケールでインストールした場合はうまく行くかもしれないが日本語の扱いで苦労した過去があるのでSqueezeでは試していない。

network-manager, avahiをアンインストールすると gnome やら gnome-desktop-environment なども削除されるがこれはパッケージのグループ化したもの(仮想パッケージ)を解除するだけで全部なくなるわけではない。

Commit Log for Tue Aug  7 02:00:38 2012

以下のパッケージを完全に削除しました:
avahi-daemon
network-manager

以下のパッケージが削除されました:
gnome
gnome-desktop-environment
gnome-user-share
libapache2-mod-dnssd
libnss-mdns
network-manager-gnome
telepathy-salut

スタティックなネットワーク設定

network-managerがインストールされると /etc/network/interfaces を次のように書き換える。

root@amos:~# cat /etc/network/interfaces
# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).

# The loopback network interface
auto lo
iface lo inet loopback

# The primary network interface
allow-hotplug eth0
#NetworkManager#iface eth0 inet dhcp

アンインストールしてもこれを戻してはくれない。手で書き換える必要がある。サーバーなので固定IPにする。

/etc/network/interfaces

# The primary network interface
#allow-hotplug eth0
#iface eth0 inet dhcp
auto eth0
iface eth0 inet static
	address 10.30.30.5
	netmask 255.0.0.0
	network 10.0.0.0
	broadcast 10.255.255.255
	gateway 10.30.30.9

IPアドレスはネットワークにあわせて設定すること。数値はプライベートアドレスを使った一例。

/etc/resolv.conf

こちらはNetworkManagerが設定したままでよい。この環境ではローカルにDNSサーバーがあってDHCPで通知していたので、NetworkManagerがこれを書いた。これも環境に合わせて設定する必要がある。

# Generated by NetworkManager
search st.seiai.ed.jp
nameserver 10.30.30.9

sshの設定

サーバーをリモートから操作できると極めて便利。特に記録を取るのに好都合なのでなるべく早期に設定していた。最近のDebianではデフォルトで初期設定のユーザー,rootともにログインできるようになっている。

sshdはsshで登録されている。

root@amos~# /etc/init.d/ssh status
sshd is running.

#PasswordAuthentication yesはコメントアウトされているがデフォルトなのだろう。

root@amos:~# cat /etc/ssh/sshd_config |grep -v '^#'|grep -v '^$'
Port 22
Protocol 2
HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_dsa_key
UsePrivilegeSeparation yes
KeyRegenerationInterval 3600
ServerKeyBits 768
SyslogFacility AUTH
LogLevel INFO
LoginGraceTime 120
PermitRootLogin yes
StrictModes yes
RSAAuthentication yes
PubkeyAuthentication yes
IgnoreRhosts yes
RhostsRSAAuthentication no
HostbasedAuthentication no
PermitEmptyPasswords no
ChallengeResponseAuthentication no
#PasswordAuthentication yes
X11Forwarding yes
X11DisplayOffset 10
PrintMotd no
PrintLastLog yes
TCPKeepAlive yes
AcceptEnv LANG LC_*
Subsystem sftp /usr/lib/openssh/sftp-server
UsePAM yes

PasswordAuthenticationとUsePAM,PermitRootLoginをnoにしてRSAのみを使うことをすすめる人も多いが、ローカルなネットワークでインターネットから直接繋がらないので便利さをとる。

LDAP サーバ の利用について

なぜLDAPが必要か

ユーザー認証をして複数のユーザーがシステムを共有するのがUNIX-LINUXの基本だ。認証にはいろいろな目的があるが学校では個別なデータの保存や環境設定がユーザーごとにホストによらず有効になるようにするのが一番大きい。ウィンドウズでも最近認知されてきた「移動ユーザープロファイル」の実現である。

このためにはどのホストからでもユーザー認証ができなければならない。昔のUNIX-LINUXではNISというシステムを使って必要なユーザー名、パスワードの情報を全ホストにコピーしてホストごとに認証をしていた。

今時のLINUXではLDAPを使って認証を各ホストではなくサーバーに委託するという形をとるのが一般的。

LDAPというと巷ではLINUXの認証とSAMBAの認証の統合をするという使われ方が有名で情報も多い。本校でもwindowsMeをクライアントとしていた時には使っていた。しかしwindowsを排除してクライアントをLINUXにした今でもLINUXの認証のためにLDAPが必要なことには変わりがない。

LDAPの代わりはないのか

NISはパスワードハッシュなどの情報が暗号化されないままネットワークに流れたり、認証なしでサーバーから情報を引き出すことができたりとセキュリティの面で心配がある。

scpでパスワードファイルを全ホストにコピーすることはホストが80台程度ならそれほど不可能な話ではないし、パスワード変更をさせないのならコピーは年1回でよい。しかし、ハッシュ化されているとはいえUSB起動などでパスワードファイルが読み取られることも考えられるのでこれも問題あり。

Kerberosを使ったシステムもできそうだが、LDAPを中心にKerberosも使うという例しか聞いたことがない。

OpenLDAP サーバ (slapd) インストール

LDAPサーバのパッケージはslapdです。Squeezeのパッケージのバージョンはこちら

slapd (2.4.23-7.2)

インストール時にはひとつだけ質問してくる。以前はもっといろいろ聞いてきた。一つにしたのは英断かもしれないが、マニュアルでは説明不足だし、いくつかある解説書とあわないので苦しむ。

amos の Debconf(スーパーユーザーで) _

slapdを設定しています

管理者のパスワード

 ヘルプ(H)

パスワードの確認

 ヘルプ(H)

キャンセル(C)   戻る(B)     進む(F)  

日本語のldapの解説書は自分でコンパイルしてインストールするものが多い。ディストリビューションによりどこまで設定してあるのかがまちまちなので、どれでも共通に説明できるということなのだろう。でもやることが多く理解するのも厄介だ。

せっかくパッケージがやってくれている多くの初期設定を活かしてやろうと確認しながら読み進めると2つの壁に当たる。

slapd.confファイルがない
2.4.23-3 から /etc/ldap/slapd.d を使う設定になった。slapdを動かしたまま設定を変えられるのだそうだ。いまでもslapd.confを作ってそれを使うこともできるので書籍の改訂は遅れている。
管理者パスワードが合わない
解説書に従い ldapmodify -D cn=admin,cn=config ... などとやるとパスワードがあわないと言われる。
slapdではデータの読み書きのためのパスワードと、設定を変更するためのパスワードを別々に設定できる。これは運用の安全上望ましい。debianのパッケージがインストール時に尋ねて設定するのは前者だけ。後者は設定せずroot(linuxの管理者)が ldapmodify -Y EXTERNAL ...を使って管理をすることでパスワードを不要にしようとしているのだ。

OpenLDAP サーバ (slapd) の設定の確認

今回の方針はdebianのディストリビューションの初期設定をなるべく活かすこと。

まずどこまで設定してあるのかを調べる必要がある。

debconf-show でインストール時の値がわかる。頭に*のついたものが、入力したもの。他はdebconfが自動で設定したもの。以前のバージョン(serge)ではdomainやorganizationを入力したが、今回のSqueezeのslapdではすでに設定されているdomainからdomainを設定し、それをそのままorganizationにも利用している。

大きな会社組織でいろいろな部署があることを想定してorganizationで分けるようにしてあるのだろうが今回の場合はこれで十分。このままにする。

root@amos:/srv/www/t2012/kdchk# debconf-show slapd
* slapd/password1: (password omitted)
  slapd/internal/adminpw: (password omitted)
  slapd/internal/generated_adminpw: (password omitted)
* slapd/password2: (password omitted)
  slapd/password_mismatch:
  slapd/invalid_config: true
  shared/organization: st.seiai.ed.jp
  slapd/upgrade_slapcat_failure:
  slapd/backend: HDB
  slapd/dump_database: when needed
  slapd/allow_ldap_v2: false
  slapd/no_configuration: false
  slapd/move_old_database: true
  slapd/dump_database_destdir: /var/backups/slapd-VERSION
  slapd/purge_database: false
  slapd/domain: st.seiai.ed.jp

以前このdomainにどういうわけか最後にドットのついた st.seiai.ed.jp. が自動で設定されてしまい、起動しなくなって原因がわからないということがあった。 自動設定された値を設定し直したいときは、次のコマンドで設定のし直しができるはずである。

# dpkg-reconfigure -plow slapd

ディレクトリ構成を見る。まずは/etc/ldapディレクトリ。ldap.confはクライアント用の設定ファイル。サーバーはslapd.confが使われていたが、すでに述べたようにslapd.dに変わっている。

root@amos:~# ll /etc/ldap/
合計 4
-rw-r--r-- 1 root     root      245 2011-06-15 21:04 ldap.conf
drwxr-xr-x 2 root     root     1024 2011-06-15 21:04 sasl2
drwxr-xr-x 2 root     root     1024 2012-08-09 12:33 schema
drwxr-xr-x 3 openldap openldap 1024 2012-08-09 12:33 slapd.d

そのslapd.dの中は

root@amos:~# ll /etc/ldap/slapd.d/
合計 2
drwxr-x--- 3 openldap openldap 1024 2012-08-27 21:44 cn=config
-rw------- 1 openldap openldap  407 2012-08-09 12:33 cn=config.ldif
root@amos:~# ll /etc/ldap/slapd.d/cn\=config
合計 8
-rw------- 1 openldap openldap  383 2012-08-09 12:33 cn=module{0}.ldif
drwxr-x--- 2 openldap openldap 1024 2012-08-09 12:33 cn=schema
-rw------- 1 openldap openldap  325 2012-08-09 12:33 cn=schema.ldif
-rw------- 1 openldap openldap  343 2012-08-09 12:33 olcBackend={0}hdb.ldif
-rw------- 1 openldap openldap  586 2012-08-09 12:33 olcDatabase={-1}frontend.ldif
-rw------- 1 openldap openldap  472 2012-08-09 12:33 olcDatabase={0}config.ldif
-rw------- 1 openldap openldap 1233 2012-08-27 21:44 olcDatabase={1}hdb.ldif

ldapsearchを使うには -Y EXTERNAL オプションを使う

# ldapsearch -Y EXTERNAL -H ldapi:/// -b "cn=config" 

最後に次のような部分が出る。"olc" (OpenLDAP Configuration)だそうだ。

# {0}config, config
dn: olcDatabase={0}config,cn=config
objectClass: olcDatabaseConfig
olcDatabase: {0}config
olcAccess: {0}to * by dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth manage
    by * break
olcRootDN: cn=admin,cn=config

# {1}hdb, config
dn: olcDatabase={1}hdb,cn=config
objectClass: olcDatabaseConfig
objectClass: olcHdbConfig
olcDatabase: {1}hdb
olcDbDirectory: /var/lib/ldap
olcSuffix: dc=st,dc=seiai,dc=ed,dc=jp
olcAccess: {0}to attrs=userPassword,shadowLastChange
    by self write by anonymous auth
    by dn="cn=admin,dc=st,dc=seiai,dc=ed,dc=jp" write
    by * none
olcAccess: {1}to dn.base="" by * read
olcAccess: {2}to * by self write by dn="cn=admin,dc=st,dc=seiai,dc=ed,dc=jp" write by * read
olcLastMod: TRUE
olcRootDN: cn=admin,dc=st,dc=seiai,dc=ed,dc=jp
olcRootPW: {SSHA}XAJ**********************1FrxT9l
olcDbCheckpoint: 512 30
olcDbConfig: {0}set_cachesize 0 2097152 0
olcDbConfig: {1}set_lk_max_objects 1500
olcDbConfig: {2}set_lk_max_locks 1500
olcDbConfig: {3}set_lk_max_lockers 1500
olcDbIndex: objectClass eq

# search result
search: 2
result: 0 Success

# numResponses: 12
# numEntries: 11

Suffixの値、olcSuffix: dc=st,dc=seiai,dc=ed,dc=jp は st.seiai.ed.jp から自動生成されたもので今後ldapを利用するときに必要になる。libnss-ldapの設定では「検索ベースの識別名」でこう答えなければなせない。

最後のdnにあるデータベース{1}hdb,cn=configでは olcRootDNolcRoorPWが定義されていてこれはインストール時に入力したパスワードである。これでこのデータベースは書き込み管理ができる。

一方、一つ上のデータベース{0}config,cn=configはolcRootDNは定義されているがolcRoorPWはない。そこで認証されることができない(加えてolcAccessにもolcRootDNの項がないので駄目かもしれない)。

しかし、olcAccessには cn=External にmanage(writeより上)を許可しているので設定データベースも編集できるという事か

root@amos:~# ldapsearch -x -LLL -D 'cn=admin,cn=config' -W -b 'cn=config'
Enter LDAP Password: 
ldap_bind: Invalid credentials (49)

上でやったように -Y EXTERNAL なら実行できる

root@amos:~# ldapsearch -Y EXTERNAL -H ldapi:/// -b "cn=config" 

search なので 条件をつけて実行する。最後にdnをつけるとdnのみということらしいが。

これでスキーマはLINUXの認証をするために必要なcosine,nis,inetorgpersonのschemeの読み込みはできていることがわかる。

root@amos:~# ldapsearch -Y EXTERNAL -H ldapi:/// -b "cn=config"  dn
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
# extended LDIF
#
# LDAPv3
# base <cn=config> with scope subtree
# filter: (objectclass=*)
# requesting: dn 
#

# config
dn: cn=config

# module{0}, config
dn: cn=module{0},cn=config

# schema, config
dn: cn=schema,cn=config

# {0}core, schema, config
dn: cn={0}core,cn=schema,cn=config

# {1}cosine, schema, config
dn: cn={1}cosine,cn=schema,cn=config

# {2}nis, schema, config
dn: cn={2}nis,cn=schema,cn=config

# {3}inetorgperson, schema, config
dn: cn={3}inetorgperson,cn=schema,cn=config

# {0}hdb, config
dn: olcBackend={0}hdb,cn=config

# {-1}frontend, config
dn: olcDatabase={-1}frontend,cn=config

# {0}config, config
dn: olcDatabase={0}config,cn=config

# {1}hdb, config
dn: olcDatabase={1}hdb,cn=config

# search result
search: 2
result: 0 Success

# numResponses: 12
# numEntries: 11

同様なことがslapcatでもできる。slapcatはそもそもrootの道具なのでrootであればパスワードはそもそも不要

ただし全行ダンプされるのでgrepでフィルターにかけてdn:で始まる行だけにしている。

root@amos:~# slapcat -b cn=config |grep '^dn:'
dn: cn=config
dn: cn=module{0},cn=config
dn: cn=schema,cn=config
dn: cn={0}core,cn=schema,cn=config
dn: cn={1}cosine,cn=schema,cn=config
dn: cn={2}nis,cn=schema,cn=config
dn: cn={3}inetorgperson,cn=schema,cn=config
dn: olcBackend={0}hdb,cn=config
dn: olcDatabase={-1}frontend,cn=config
dn: olcDatabase={0}config,cn=config
dn: olcDatabase={1}hdb,cn=config

4つのschemaが入っているのがわかる。

余談だが、-bオプションはマニュアル(man)では 「-b suffix 生成する出力に対応するデータベース決定するための接尾辞 suffix を指定」と書いてあって、設定のデータベースは -b cn=config と指定。実際にこれからデータを入力して利用するデータベースは -b dc=st,dc=seiai,dc=ed,dc=jp と指定する。(もちろんドメインがst.seiai.ed.jpだったので自動でこのように登録された。自分のサーバーの設定に合わせて指定する)

root@amos:~# slapcat -b dc=st,dc=seiai,dc=ed,dc=jp |grep '^dn:'
dn: dc=st,dc=seiai,dc=ed,dc=jp
dn: cn=admin,dc=st,dc=seiai,dc=ed,dc=jp

まだ2つしかエントリーがない。

こちらのデータベースなら、ldapsearch で登録したパスワードでrootでなくても読める(そして書ける)

root@amos:~# ldapsearch -x -LLL -D 'cn=admin,dc=st,dc=seiai,dc=ed,dc=jp' -W -b 'dc=st,dc=seiai,dc=ed,dc=jp' dn
Enter LDAP Password: 
dn: dc=st,dc=seiai,dc=ed,dc=jp

dn: cn=admin,dc=st,dc=seiai,dc=ed,dc=jp

OpenLDAP サーバ (slapd) の管理方法のまとめ

ldapsearch, slpacat とデータベースが2つ。パスワードの要不要など混乱してきたのでまとめておく

もちろんdc=st,dc=seiai,dc=ed,dc=jpの部分はサーバーにより異なる。

ツール(コマンド) ユーザー -b cn=config -b dc=st,dc=seiai,dc=ed,dc=jp
slapsearch
slapadd
slapmodify
root -Y EXTERNAL
パスワード無し
-D 'cn=admin,dc=st,dc=seiai,dc=ed,dc=jp'
登録したパスワード
一般user 使用不可 -D 'cn=admin,dc=st,dc=seiai,dc=ed,dc=jp'
登録したパスワード
slapcat root パスワード不要 パスワード不要
一般user 使用不可 使用不可

slapcatが簡単に見えるがslapcatができるのはslapsearchの代わりだけ。データを追加・加工することができない。 slapcatはデータベース中のデータをダンプして書きだす(バックアップや移動のため)道具なので当然。

-b dc=st,dc=seiai,dc=ed,dc=jpデータベースのslapdsearchだけなら -D... を書かずに -x の簡易認証にすると検索できるようだ。調べが足りないが、slapaddなどを気楽に試せないので次の機会に。

root@amos:~# ldapsearch -x -b dc=st,dc=seiai,dc=ed,dc=jp uid=hoge

これでパスワードなしてhogeというユーザーのデータが表示される。ただしhogeのパスワード(のハッシュ)は表示されない

OpenLDAP サーバ (slapd) の設定の追加

スキーマまでは設定が終わっていることが確認されたのでユーザー名、グループ名などのエントリーを作ることが最初の仕事になる。

ただしsambaのスキーマは入っていないのでWindowsをクライアントにするのなら先にsambaのスキーマを入れる必要がある。本校ではLINUXしか相手にしないのでこれは必要ない。

lidfファイルに必要事項を書いて、ldapaddで登録するという手順となる。

エントリー名はLinuxのユーザー名とグループ名なので、Users,Groupsにしたいが、最初にslapdをセットした時の混乱から当時の解説本に合わせてPeople,Groupsになっている。過去のクライアントと互換をとるため今回もPeople,Groupsにする。本によってはPeople,Groupになっているのもあるので注意

Groups, People の枠組みをつくるlidf エディタで作成し、peoplegrp.lidfという名前でカレントディレクトリに保存

root@amos:~# cat peoplegrp.lidf
# Groups
dn: ou=Groups,dc=st,dc=seiai,dc=ed,dc=jp
objectClass: organizationalUnit
ou: Groups

# People
dn: ou=People,dc=st,dc=seiai,dc=ed,dc=jp
objectClass: organizationalUnit
ou: People

ldapaddで登録する

root@amos:~# ldapadd -x -D "cn=admin,dc=st,dc=seiai,dc=ed,dc=jp" -W -f peoplegrp.lidf
Enter LDAP Password: 
adding new entry "ou=Groups,dc=st,dc=seiai,dc=ed,dc=jp"

adding new entry "ou=People,dc=st,dc=seiai,dc=ed,dc=jp"

-D "cn=admin,dc=st,dc=seiai,dc=ed,dc=jp" が管理者名で登録したパスワードで認証する。一般ユーザーでも可能。

この調子で各ユーザーの設定データをlidfファイルにしてslapaddで登録してもよいが、全生徒のデータを加工するのは現実的ではない。

ldapscriptsを導入する

ldapscriptsの導入

slapdパッケージには slapdの他slapcatなどのコマンドが含まれる

ldap-utilパッケージには slapsearch, slapadd, slapmodify などのコマンドが含まれる。

今回導入するのは ldapscripts パッケージで ldapadduser, ldapaddgroup, ldapdeleteuser などLINUXにおけるユーザー登録や管理と同様の操作感でLDAPにユーザー登録などをできるようにする。

sambaが絡んでいた時代にはsmbldap-toolsという同様のスクリプトセットがあった。

/etc/ldapscripts/ldapscripts.conf の設定

結構たくさんの項目がある。でも「# DEBIAN: values from /etc/pam_ldap.conf are used.」などと他の設定を引いて使うと書いてある。楽ができるし設定が合致しない時に混乱するのでなるべく他の設定を使うことにする。

「他の設定」とは次のように大半がpam_ldapのものサーバー自身も/etc/passwdの記述は最小限なのでpam_ldapを入れることになるからこれはリーズナブル。

root@amos:~#  cat /etc/ldapscripts/ldapscripts.conf|grep DEBIAN
# Look on commented variables and description lines started with DEBIAN.
# DEBIAN: values from /etc/pam_ldap.conf are used.
# DEBIAN: /etc/pam_ldap.secret or /etc/ldap.secret are used.
# DEBIAN: values from /etc/pam_ldap.conf are used.
# DEBIAN: values from /etc/adduser.conf are used.

実はldapscripts.conf内のこの解説には間違いがあって、/etc/pam_ldap.conf ではなく /etc/libnss-ldap.confの記述が使われる。のちほど示す。

/etc/ldapscripts/ldapscripts.conf の書き換えた部分を少しずつ示す

ldapscripts.conf 1

まずpam_ldap.confの値を使うので設定しない

# DEBIAN: values from /etc/pam_ldap.conf are used.
#SERVER="ldap://localhost"
#BINDDN="cn=Manager,dc=example,dc=com"

ldapscripts.conf 2

/etc/pam_ldap.secret は pam_ldap を入れるときに作られるパスワーとファイルだが最後に改行が入っているとそれも含めてパスワードとするので正しいパスワードにならないというバグがある。これはネット検索で得られた貴重な情報。逆に改行がないことでだめなものもあるかもしれないので改行のないものを要求するldapscriptsのためにldapscripts.passwdを別に作ることにする。

このパスワードは上記のslapdのインストールの時に入力した「管理者のパスワード」。-b dc=st,dc=seiai,dc=ed,dc=jp のデータベースを検索するために必要なものである。

同じパスワードをxxxxxxxのところに入れて次のように改行なしで作り、rootだけが読み取れるようにする。

root@amos:~# echo -n xxxxxxxxxx >/etc/ldapscripts/ldapscripts.passwd
root@amos:~# chmod 600 /etc/ldapscripts/ldapscripts.passwd

/etc/ldapscripts/ldapscripts.conf にこのファイルを使うように設定する。(ファイルの作り方も書いておく)

# DEBIAN: /etc/pam_ldap.secret or /etc/ldap.secret are used.
#BINDPWDFILE="/etc/ldapscripts/ldapscripts.passwd"
#adachi made no \n file with
#   printf xxxxxxxx>ldapscripts.passwd
#or
#   echo -n xxxxxxxx>ldapscripts.passwd
#where -n means no \n !!
BINDPWDFILE="/etc/ldapscripts/ldapscripts.passwd"

ldapscripts.conf 3

これもpam_ldap.confの値を使うので設定しない

# DEBIAN: values from /etc/pam_ldap.conf are used.
#SUFFIX="dc=example,dc=com" # Global suffix
#GSUFFIX="ou=Groups"        # Groups ou (just under $SUFFIX)
#USUFFIX="ou=Users"         # Users ou (just under $SUFFIX)
#MSUFFIX="ou=Machines"      # Machines ou (just under $SUFFIX)

これがちょっと曲者。後述

ldapscripts.conf 4

/etc/adduser.conf を設定したことがないので、ここで吟味をしてセットする。以前はひな形ユーザーのホームディレクトリにいろいろな設定をしてユーザー登録の際にスクリプトでコピーしていたのでCREATEHOMESは不要だった。最近はユーザー設定の指定が面倒になってきたことでこれを使ってみることにした。

HOMEPERMS="700"はユーザーホームのファイルはデフォルトで他人に見せない設定。UNIX/LINUXの設定は伝統的に755。つまり誰でも見ることだけはできるというもの。使う人が限られて信用できた古き良き時代の習慣。プライベートグループをデフォルトにしたのなら700、または750にすべきだと思う。

これで面倒になるのがウェブページ作成実習。本人が他人に読めるようにセットしなければならなくなる。

# User properties
# DEBIAN: values from /etc/adduser.conf are used.
#USHELL="/bin/sh"
#UHOMES="/home/%u"     # You may use %u for username here
#adachi
#CREATEHOMES="no"      # Create home directories and set rights ?
CREATEHOMES="yes"      # Create home directories and set rights ?
#HOMESKEL="/etc/skel"  # Directory where the skeleton files are located. Ignored if undefined or nonexistant.
HOMESKEL="/etc/skel"  # Directory where the skeleton files are located. Ignored if undefined or nonexistant.
#HOMEPERMS="755"       # Default permissions for home directories
HOMEPERMS="700"       # Default permissions for home directories

ldapscripts.conf 5

ユーザーパスワード

# User passwords generation
# Command-line used to generate a password for added users (you may use %u for username here)
# WARNING !!!! This is evaluated, everything specified here will be run !
# Special value "<ask>" will ask for a password interactively
#adachi passwds are given in setting file
PASSWORDGEN="<ask>"

設定した<ask>はユーザー追加時にパスワードを聞いてくるもの。今回はすでに旧サーバーに登録されたユーザーを新サーバーに登録しなおす作業で、ユーザー名とパスワードの一覧ファイルを元にシェルスクリプトで登録する。すでにあるパスワードを使うには<ask>を使う必要がある。

この他、登録時にランダムなパスワードを生成してファイルに保存するという設定もある。次の新入生の登録をするときにはこれを使えばパスワードを予め生成して用意する必要がないので楽ができるかもしれない。

ユーザー登録の前に

これで ldapaddgroup や ldapadduser というコマンドが addgroup や adduser の様に使えるようになる。

ただし、pam_ldap.conf などの設定を使うのだから、libpam-ldap, libnss-ldap のインストールを済ませる必要がある。

libpam-ldap, libnss-ldap のインストール

Debianでは依存するパッケージは自動で同時にインストールされる。今回インストールされるのは3つ。最後のは認証のキャッシュ。

履歴からバージョンを記録

Commit Log for Sun Aug 12 14:43:06 2012

以下のパッケージがインストールされました:
libnss-ldap (264-2.2)
libpam-ldap (184-8.5)
nscd (2.11.3-3)

libnss-ldap

例によってインストール時にいくつか質問してくる。

LDAPサーバーのURIは自分自身なので、次のうちどちらか。

  1. 初期値 ldapi:/// のままにする。
  2. ldap://127.0.0.1/ とする。( i がないことに注意)

検索ベースの識別名 はドメイン名から作る。slapdの中ではSuffixと呼ばれているもの。それに合わせて入力する。 ここでは dc=st,dc=seiai,dc=ed,dc=jp

amos の Debconf(スーパーユーザーで) _

libnss-ldap 設定しています

LDAP サーバの URI

ldap://127.0.0.1/ ヘルプ(H)

検索ベースの識別名

dc=st,dc=seiai,dc=ed,dc=jp ヘルプ(H)

利用する LDAP バージョン

3 ヘルプ(H)

キャンセル(C)   戻る(B)     進む(F)  

root の LDAP アカウント は自動で設定された。slapdの設定でolcRootDN: cn=admin,dc=st,dc=seiai,dc=ed,dc=jp となっていたもの。cn=admin は固定だが、そのあとはFQDNから作られたもの。

パスワードは2回入力したものである。

amos の Debconf(スーパーユーザーで) _

libnss-ldap 設定しています

root の LDAP アカウント

cn=admin,dc=st,dc=seiai,dc=ed,dc=jp ヘルプ(H)

LDAP root アカウントのパスワード

●●●●●●●●● ヘルプ(H)

キャンセル(C)   戻る(B)     進む(F)  

libpam-ldap

ここはデフォルトで「LDAP 管理アカウントがローカルの root のように振る舞うことを許す」にチェックが入り、「LDAP データベースはログインを必要とする」にチェックが入っていない。このままにする。

amos の Debconf(スーパーユーザーで) _

libpam-ldap 設定しています

LDAP 管理アカウントがローカルの root のように振る舞うことを許しますか? ヘルプ(H)
  LDAP データベースはログインを必要としますか? ヘルプ(H)

キャンセル(C)   戻る(B)     進む(F)  

ここもlibnss-ldapのときと同じ管理者アカウントとパスワードを記入する。

amos の Debconf(スーパーユーザーで) _

libpam-ldap 設定しています

LDAP 管理用アカウント

cn=admin,dc=st,dc=seiai,dc=ed,dc=jp ヘルプ(H)

LDAP 管理用パスワード

●●●●●●●●● ヘルプ(H)

キャンセル(C)   戻る(B)     進む(F)  

出来上がったもの

/etc/libnss-ldap.conf

root@amos:~# cat /etc/libnss-ldap.conf |grep -v '^#' |grep -v '^$'
base dc=st,dc=seiai,dc=ed,dc=jp
uri ldapi:///
ldap_version 3
rootbinddn cn=admin,dc=st,dc=seiai,dc=ed,dc=jp

/etc/pam_ldap.conf

root@amos:~# cat /etc/pam_ldap.conf |grep -v '^#' |grep -v '^$'
base dc=st,dc=seiai,dc=ed,dc=jp
uri ldapi:///
ldap_version 3
rootbinddn cn=admin,dc=st,dc=seiai,dc=ed,dc=jp
pam_password crypt

この他に /etc/libnss-ldap.secret, /etc/pam_ldap.secret というパスワードが平文で入っているファイルができる。root所有で他には読み込み権限もない。改行が最後にあるファイルであり、ldapscripts.conf には不都合なファイルなので、改行のない/etc/ldapscripts/ldapscripts.passwdを作ってある。

ldapscripts.confからの参照のための追加

ldapscripts.confからの参照をうけるため。libnss-ldap.confは書き換えが必要。ldapscripts.confにはpam_ldap.confを参照すると書いているが参照するのはlibnss-ldap.conf。

/etc/libnss-ldap.conf

root@amos:~# cat /etc/libnss-ldap.conf |grep -v '^#' |grep -v '^$'
base dc=st,dc=seiai,dc=ed,dc=jp
uri ldapi:///
ldap_version 3
rootbinddn cn=admin,dc=st,dc=seiai,dc=ed,dc=jp
nss_base_passwd	ou=People,dc=st,dc=seiai,dc=ed,dc=jp?one
nss_base_shadow	ou=People,dc=st,dc=seiai,dc=ed,dc=jp?one
nss_base_group	ou=Groups,dc=st,dc=seiai,dc=ed,dc=jp?one

ユーザー登録

ユーザー名,パスワード,uid,名前の一覧になっているテキストファイルからperlスクリプトで登録するのが昔からの定番。uidも管理しているのはサーバーを更新したときにHDDを繋ぎ直すだけでデータをそのまま使用できるから。

登録用ファイルはスペース区切りでこんな感じ。

a2aoki ke4ouSp2 3419 aoki mai
a2azusa iwpa3Jim 3420 ishida azusa
......

perlスクリプトは

#!/usr/bin/perl
# data-file : username passwd uid sei mei
# 
# 
print "add new user\n";
$suser = "alpha";  #quota hinagata user
$filename="nampas4amos12.txt";

open(SFILE,$filename) || die "cannot open $filename";
while (<SFILE>){
   ($uname,$password,$uid,$gc,$os)=split(/\s+/);
   next if $uname eq '';
   print " - $uid  - ";
   $user_fullname = "$gc $os";
   print "$user_fullname // "; 

   #unix
   `/usr/sbin/ldapaddgroup $uname $uid`;
    print "group/ "; 
    open(pww, "| /usr/sbin/ldapadduser $uname $uname $uid >/dev/null 2>&1");
    print pww "$password\n$password\n";
    close(pww);
    print "user passwd/ "; 

   #cpquota going to  ldapscript.conf
   #`/usr/sbin/edquota  -p $suser $uname`; 
   # print "quota // "; 
    
    $ct=$ct+1;
    print "$ct\n";
}
close(SFILE);

WindowsMeがクライアントだった初期の頃はこのスクリプトはlinuxのユーザーとsambaのユーザーを両方登録するスクリプトで仕事が多かったが、NFSだけになったらとても簡単になった。quotaは今回後回しにしたのでコメントアウトしているが、将来的にはldapscript.confに設定項目があるのでldapscriptに任せることになると思う。

ユーザーの確認は

root@amos:~/# getent passwd|grep alpha
alpha:*:1110:1110:alpha:/home/alpha:/bin/bash
root@amos:~/# getent group |grep alpha
alpha:*:1110:
root@amos:~/# id alpha
uid=1110(alpha) gid=1110(alpha) 所属グループ=1110(alpha)

などで行う。うまく行かないときは nscd の可能性がある。これは認証のキャッシュで過去の認証をしばらく記憶している。いったん停止して

root@amos:~/# /etc/init.d/nscd stop
Stopping Name Service Cache Daemon: nscd.

テストが終わったらまた動かしておく

root@amos:~/# /etc/init.d/nscd start

NFS でユーザーホーム

今回のサーバーはsambaとpam-mountで運用してきたユーザーホームのローミング(移動ユーザープロファイル)を、NFS-automountとkerberos認証に変えようというものだった。しかし今回の作業ではKerberosによる認証がうまくゆかずNFS単独での使用となってしまった。継続して取り組むつもりがraid5の装置を試したことによるパフォーマンスの低下から構成を変更することに手間取ってまだ進んでいない。

ただこのままkerberosをいれると普通のSATAのHDDにしたことで一段落したパフォーマンス問題がふたたび起こることも考えられ、サーバーの役割分担も再考する必要が出てくるかもしれない。

nfsサーバーのために導入するパッケージは nfs-kernel-server です。

NFS v4 は設定が v3 とちょっと異なります。

/etc/exports にはrootとなる場所に fsid=0 と書く。別な場所をbindでmountしてexportする例が多いが普通にマウントしている/homeをexportしている。問題ない様子。今回のサーバーでは/home以下は物理的に別のハードディスクのパーティションをマウントしている。アクセスの多いウェブサーバーやLDAPサーバーと負荷を分散させるのが狙い。

root@amos:~/# cat /etc/exports
# /etc/exports: the access control list for filesystems which may be exported
#		to NFS clients.  See exports(5).
#
# Example for NFSv2 and NFSv3:
# /srv/homes       hostname1(rw,sync,no_subtree_check) hostname2(ro,sync,no_subtree_check)
#
# Example for NFSv4:
# /srv/nfs4        gss/krb5i(rw,sync,fsid=0,crossmnt,no_subtree_check)
# /srv/nfs4/homes  gss/krb5i(rw,sync,no_subtree_check)
#
/home 		10.0.0.0/8(rw,fsid=0,root_squash,no_subtree_check)
/home/nfsrc 	10.0.0.0/8(rw,no_root_squash,no_subtree_check)
#/home/partimag 	10.0.0.0/8(rw,no_root_squash,no_subtree_check)
##/home/partimag 	gss/krb5(rw,no_root_squash,no_subtree_check)

nfsrcはbindでmountしたもの。ここはログイン時にrootでログイン記録をとったりスクリプトを実行したりするのでrootでの読み書きを許可する必要があり、no_root_squash を設定している。

partimag はクライアントOSのsave,restoreに使う場所。普段は必要がない。gss/krb5の付いている部分はkerberosの動作テストの名残。

次はfstab。インストーラーが自動でUUIDを設定してくれたものに、バックアップの/xhomeとbindのnfsrcを加えたもの。

この記録を取ったのがquotaの設定後なのですでにquotaの設定が入っている。

root@amos:~/# cat /etc/fstab 
# /etc/fstab: static file system information.
#
# Use 'blkid' to print the universally unique identifier for a
# device; this may be used with UUID= as a more robust way to name devices
# that works even if disks are added and removed. See fstab(5).
#
# <file system> <mount point>   <type>  <options>       <dump>  <pass>
proc            /proc           proc    defaults        0       0
# / was on /dev/sda1 during installation
UUID=da38146c-196c-42ea-b035-5533777138a2 /               ext3    errors=remount-ro 0       1
# /home was on /dev/sdb1 during installation
UUID=077e7668-1416-4d6e-a627-286ddba57871 /home           ext3    defaults,usrjquota=aquota.user,jqfmt=vfsv0        0       2
# /srv was on /dev/sda9 during installation
UUID=97eb6f35-f7ed-46e9-9d77-ba2a5afea62a /srv            ext3    defaults        0       2
# /tmp was on /dev/sda8 during installation
UUID=e65c98ab-70e7-418d-9ced-08bf6414b295 /tmp            ext3    defaults        0       2
# /usr was on /dev/sda5 during installation
UUID=c8fd71b4-7fb2-4a2d-990c-4f25b7976143 /usr            ext3    defaults        0       2
# /var was on /dev/sda6 during installation
UUID=86ca77e7-90b9-48d7-b26d-84c5edcd2b1c /var            ext3    defaults        0       2
# swap was on /dev/sda7 during installation
UUID=9a823166-a3a7-41fc-bdfd-fda2b6698584 none            swap    sw              0       0
/dev/fd0        /media/floppy0  auto    rw,user,noauto  0       0
/dev/sdc1	/xhome		ext3    defaults        0       2
#for NFSv4
/srv/nfsrc	/home/nfsrc	none	bind	0	0
#/srv/partimag	/home/partimag	none	bind	0	0

idmapdにDomainを追加。ユーザー名は統一しているので、書くことはないが、Kerberos用にはクライアントと同じドメイン名を書く必要がある。

root@amos:~/# cat /etc/idmapd.conf
[General]
Verbosity = 0
Pipefs-Directory = /var/lib/nfs/rpc_pipefs
#adachi12-8-18
#Domain = localdomain
Domain = st.seiai.ed.jp

[Mapping]

Nobody-User = nobody
Nobody-Group = nogroup

設定の反映

root@amos:~# /etc/init.d/nfs-kernel-server reload
Re-exporting directories for NFS kernel daemon....

またはrestart

root@amos:~# /etc/init.d/nfs-kernel-server restart
Stopping NFS kernel daemon: mountd nfsd.
Unexporting directories for NFS kernel daemon....
Exporting directories for NFS kernel daemon....
Starting NFS kernel daemon: nfsd mountd.

/etc/exports を書き換えただけならば

root@amos:~# exportfs -ra
root@amos:~#

-v で現在の exportの状態を表示するる

root@amos:~# exportfs -v
/home         	10.0.0.0/8(rw,wdelay,root_squash,no_subtree_check,fsid=0)
/home/nfsrc   	10.0.0.0/8(rw,wdelay,no_root_squash,no_subtree_check)

rsyncでコピー

いままではハードウェアでミラーリングをする装置をつけてバックアップをとっていた。トラブルはなかったが時々シャットダウン中に止まってしまうクライアントがあり、アクセスが集中するときの速度に不安があったことと、シリアルATAになって今までの装置が使えなくなることで常時ミラーリングすることをやめ、毎日深夜にバックアップをとることにした。

一時期raid5の装置を試したがこれはさらにパフォーマンスが悪く悲惨な状態になった。40人の授業には耐えられるが80人の授業では実用に耐えない。教員用ならアクセスが集中することがないので多分快適だろう。

raid10にすれば緩和されたのかもしれないが、あまりの惨状に恐れをなして通常の接続にしてしまった。

毎日深夜にバックアップの道具にはrsyncを使うことにし、使用方法を確認。

home以下の全ディレクトリを同期コピーするには、

root@ezek:~/# rsync -av --delete /home/ /xhome/

以下のようにするのは間違い。/xhome/home 以下にコピーしてしまう。

root@ezek:~/# rsync -av --delete /home /xhome/  #間違い

以下だと * 部分はディレクトリだけになる。コピー元指定は / で終了するのが通常もっとも期待するバックアップになる。

root@ezek:~/# rsync -av --delete /home/zircon/* /xhome/zircon/ # *はディレクトリ

-a オプションで再帰的なコピーや更新日時を比較してのコピーなど必要なことはほとんどやってくれる。コピー元の / に注意しないと思わぬ結果になることと、--delete オプションは最後に追加することが注意点。

コピー元にないものをコピー先で削除するのが --deleteオプションだがコピー先、コピー元の指定を間違えると必要なものまで消しかねない。

何度か --delete 指定なしでチェックしてから --delete を追加した方が安心できる。

cronでrsyncそして帯域制御

cronで夜にrsyncをした所、終了できなくなったことがあった。これはかなり重症でkillできず、init0でも終了しきれず、本体リセットボタンを使用せざるを得なかった。

lsofで調べた所firefoxのキャッシュファイルのコピー先で書くか消すかしている状態で待っているらしかったが、再度rsyncすると無事に終了する。

そこで帯域制限をかけ、タイムアウトもセットした。

root@amos:~/# cat /etc/cron.d/rsynchome 
# adachi 2012-8-29 backup /home/ to /xhome/
PATH=/usr/sbin:/usr/bin:/sbin:/bin
# adachi: change at 2012-9-1 unable kill rsync!
49 20 * * * root rsync -a --delete --bwlimit=1024 --timeout=600 /home/ /xhome/

これで毎日20:49に同じホストの別のハードディスクにバックアップを取る。

帯域制限はネットワークのためにあるのかと思っていたが、sysstatの記録で見るとローカル同士でも制限はできるようだ。

cronの設定と帯域制御




quota

生徒がUSBなどで多量の画像を持ち込んだり動画を持ち込んだりする。プログラムの作成の失敗で多量のデータの入ったファイルを作ってしまう。こんなトラブルが他の生徒に影響を及ぼさなてようにデータ保存の上限を設けている。firefox(ブラウザ)のキャッシュファイルもユーザーホームに置かれるのでその容量(デフォルトで50MB)も考慮する必要がある。ひとり150MB程度でほとんど大丈夫なのだが、現在は500MBにしている。/homeに当てているHDDは500GB。

パッケージはquota

まず/etc/mounttabに設定を加える。ユーザーとグループがあるが、生徒の制限はユーザーのみでよい。バージョンが変わって書き方がちょっと変更になった。jqfmt=vfsv0はバージョンとのこと。quotaは情報が多い。

/etc/mounttabの一部

........
# /home was on /dev/sdb1 during installation
UUID=077e7668-1416-4d6e-a627-286ddba57871 /home           ext3    defaults,usrjquota=aquota.user,jqfmt=vfsv0        0       2
........

有効にするためマウントし直す。

root@amos:~/# mount -o remount /home

以前は touch /home/aquota.user などでファイルを作らなければならなかったが、今回はあると叱られた。ないままチェックをすると作成される。

root@amos:~/# quotacheck -avum /home

これでaquota.userが作成される。それからquotaを有効にする。

root@amos:~/# quotaon -a

edquota alpha で alphaというユーザーの制限を設定する。blocks, inodes が現在の使用状況、soft,hardが上限。

  GNU nano 2.2.4                File: /tmp//EdP.aJ9tVp2                                      

Disk quotas for user alpha (uid 1110):
  Filesystem                   blocks       soft       hard     inodes     soft     hard
  /dev/sdb1                     72812     500000     510000       2664    20000    21000

以前はviが起動したのだが、最近はnanoというエディタになって操作ミスをしないかとドキドキする。

一人分設定すればあとはコピーできる。

root@amos:~/# edquota -p beta alpha

上記のユーザー登録スクリプトで同時に行なってもいいし、ldapscript.conf に設定して任せてもよい。

今回はquotq設定を後回しにしたので別のスクリプトをユーザー登録スクリプトでを元に作った。

#!/usr/bin/perl
# data-file : username passwd uid sei mei
# 
# 
print "set quota\n";
$suser = "alpha";  #quota hinagata user
$filename="nampas4amos12.txt";

open(SFILE,$filename) || die "cannot open $filename";
while (<SFILE>){
   ($uname,$password,$uid,$gc,$os)=split(/\s+/);
   next if $uname eq '';
   print " - $uid  - ";
   $user_fullname = "$gc $os";
   print "$user_fullname // "; 

   #cpquota going to  ldapscript.conf
   `/usr/sbin/edquota  -p $suser $uname`; 
    
    $ct=$ct+1;
    print "$ct\n";
}
close(SFILE);

quotaの積み残し

以前は全ユーザーにメールの設定をさせていたので制限を超えたユーザーには自動でメールで通知された。最近は授業でメールの設定をさせていないのでこれができない。いまのところかなり余裕の割り当てだが、生徒に通知する方法を考えなければならない。

ldapにindexを加える

必要なインデックスをまとめる

ログにインデックスがないというメッセージがたくさん出ている。

root@amos:/var/log# cat syslog
Aug 27 10:57:07 amos slapd[2128]: <= bdb_equality_candidates: (memberUid) not indexed
Aug 27 10:57:07 amos slapd[2128]: <= bdb_equality_candidates: (memberUid) not indexed
Aug 27 10:57:07 amos slapd[2128]: <= bdb_equality_candidates: (gidNumber) not indexed
Aug 27 10:57:08 amos slapd[2128]: <= bdb_equality_candidates: (uidNumber) not indexed
........

これを次の操作で整理する

root@amos:/var/log# cat syslog|grep candidates|sort -k8 |uniq -f 5
grep candidates
candidatesを含む行だけにして(インデクスがないという報告を抜き出す)
sort -k8
8番目のキーでソートする。
uniq -f 5 -d
5番目のフィールドまでは比較しない(日付とプロセス番号?までを除外) <= 以降を比較して前の行と同じ内容の場合は表示しない。

6つであることが判明(1〜10はフィールドの番号を追記したもの)

root@amos:/var/log# cat syslog|grep candidates|sort -k8 |uniq -f 5
1   2  3        4    5            6  7                        8    9   10
Aug 27 08:54:50 amos slapd[2128]: <= bdb_equality_candidates: (cn) not indexed
Aug 27 08:54:42 amos slapd[2128]: <= bdb_equality_candidates: (gidNumber) not indexed
Aug 27 08:49:42 amos slapd[2128]: <= bdb_equality_candidates: (memberUid) not indexed
Aug 27 08:49:42 amos slapd[2128]: <= bdb_equality_candidates: (uid) not indexed
Aug 27 08:50:48 amos slapd[2128]: <= bdb_equality_candidates: (uidNumber) not indexed
Aug 27 08:54:42 amos slapd[2128]: <= bdb_equality_candidates: (uniqueMember) not indexed

connection_read(85): no connection! も結構たくさんあるが、原因はわからなかったので無視

root@amos:/var/log# cat syslog
Aug 27 10:57:07 amos slapd[2128]: <= bdb_equality_candidates: (memberUid) not indexed
Aug 27 10:57:07 amos slapd[2128]: <= bdb_equality_candidates: (memberUid) not indexed
Aug 27 10:57:07 amos slapd[2128]: <= bdb_equality_candidates: (gidNumber) not indexed
Aug 27 10:57:08 amos slapd[2128]: <= bdb_equality_candidates: (uidNumber) not indexed
Aug 27 10:57:08 amos slapd[2128]: <= bdb_equality_candidates: (gidNumber) not indexed
Aug 27 10:57:08 amos slapd[2128]: connection_read(85): no connection!
Aug 27 10:57:08 amos slapd[2128]: connection_read(85): no connection!
Aug 27 10:57:12 amos slapd[2128]: <= bdb_equality_candidates: (uidNumber) not indexed
Aug 27 10:57:12 amos slapd[2128]: <= bdb_equality_candidates: (uidNumber) not indexed
Aug 27 10:57:12 amos slapd[2128]: <= bdb_equality_candidates: (uidNumber) not indexed
Aug 27 10:57:13 amos slapd[2128]: <= bdb_equality_candidates: (uid) not indexed

インデックスを追加する

cn=configになってからのインデックス設定法についてはほとんど情報がない。http://wiki.debian.org/LDAP/OpenLDAPSetupがまとまっている唯一の情報源であった。

まずLDIFファイルを作る。

bdb_equality_candidates という言葉からeqだけでいいのではないかと少し検索で調べて、1箇所だけ言っているところがあったのでやってみた。どうせ足りなければまた促される。

dn: olcDatabase={1}hdb,cn=config
changetype: modify
add: olcDbIndex
olcDbIndex: cn eq
-
add: olcDbIndex
olcDbIndex: uid eq
-
add: olcDbIndex
olcDbIndex: uidNumber eq
-
add: olcDbIndex
olcDbIndex: gidNumber eq
-
add: olcDbIndex
olcDbIndex: memberUid eq
-
add: olcDbIndex
olcDbIndex: uniqueMember eq

-Y EXTERNAL を使ってやればパスワードは必要がない。 index.lidfという名前で保存して、

root@amos:~# ldapmodify -Y EXTERNAL -H ldapi:/// -f ./index.lidf 
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
modifying entry "olcDatabase={1}hdb,cn=config"

わからないことも多いが、rootでlocalからできることなのだと推測。

indexができたことをslapcatかldapsearch -LLLQY EXTERNALで確認

root@amos:~# slapcat -b cn=config の最後

root@amos:~# slapcat -b cn=config
dn: olcDatabase={1}hdb,cn=config
objectClass: olcDatabaseConfig
objectClass: olcHdbConfig
olcDatabase: {1}hdb
olcDbDirectory: /var/lib/ldap
olcSuffix: dc=st,dc=seiai,dc=ed,dc=jp
olcAccess: {0}to attrs=userPassword,shadowLastChange by self write by anonymous auth by dn="cn=admin,dc=st,dc=seiai,dc=ed,dc=jp" write by * none
olcAccess: {1}to dn.base="" by * read
olcAccess: {2}to * by self write by dn="cn=admin,dc=st,dc=seiai,dc=ed,dc=jp" write by * read
olcLastMod: TRUE
olcRootDN: cn=admin,dc=st,dc=seiai,dc=ed,dc=jp
olcRootPW:: e1NTSEF9W******************************GcnhUOWw=
olcDbCheckpoint: 512 30
olcDbConfig: {0}set_cachesize 0 2097152 0
olcDbConfig: {1}set_lk_max_objects 1500
olcDbConfig: {2}set_lk_max_locks 1500
olcDbConfig: {3}set_lk_max_lockers 1500
olcDbIndex: objectClass eq
olcDbIndex: cn eq
olcDbIndex: uid eq
olcDbIndex: uidNumber eq
olcDbIndex: gidNumber eq
olcDbIndex: memberUid eq
olcDbIndex: uniqueMember eq
structuralObjectClass: olcHdbConfig
entryUUID: c49bdaa4-761e-1031-9560-3b58fb4adab7
creatorsName: cn=admin,cn=config
createTimestamp: 20120809033345Z
entryCSN: 20120827124428.000883Z#000000#000#000000
modifiersName: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
modifyTimestamp: 20120827124428Z

もうひとつの情報源 http://www.rjsystems.nl/en/2100-d6-openldap-provider.php からEXERNALを使う方法。

root@amos:~# ldapsearch -LLLQY EXTERNAL -H ldapi:/// -b cn=config "(|(cn=config)(olcDatabase={1}hdb))"
dn: cn=config
objectClass: olcGlobal
cn: config
olcArgsFile: /var/run/slapd/slapd.args
olcLogLevel: none
olcPidFile: /var/run/slapd/slapd.pid
olcToolThreads: 1

dn: olcDatabase={1}hdb,cn=config
objectClass: olcDatabaseConfig
objectClass: olcHdbConfig
olcDatabase: {1}hdb
olcDbDirectory: /var/lib/ldap
olcSuffix: dc=st,dc=seiai,dc=ed,dc=jp
olcAccess: {0}to attrs=userPassword,shadowLastChange by self write by anonymous auth by dn="cn=admin,dc=st,dc=seiai,dc=ed,dc=jp" write by * none
olcAccess: {1}to dn.base="" by * read
olcAccess: {2}to * by self write by dn="cn=admin,dc=st,dc=seiai,dc=ed,dc=jp" write by * read
olcLastMod: TRUE
olcRootDN: cn=admin,dc=st,dc=seiai,dc=ed,dc=jp
olcRootPW: {SSHA}XAJ**********************1FrxT9l
olcDbCheckpoint: 512 30
olcDbConfig: {0}set_cachesize 0 2097152 0
olcDbConfig: {1}set_lk_max_objects 1500
olcDbConfig: {2}set_lk_max_locks 1500
olcDbConfig: {3}set_lk_max_lockers 1500
olcDbIndex: objectClass eq
olcDbIndex: cn eq
olcDbIndex: uid eq
olcDbIndex: uidNumber eq
olcDbIndex: gidNumber eq
olcDbIndex: memberUid eq
olcDbIndex: uniqueMember eq

ntp設定

Kerberosをつかうには時刻の同期が重要ということもあって教員系と生徒実習系と別々に上流サーバーと同期をとることにした。本来は校内でも複数サーバー内でも同期をとるようにするらしいがサーバーの更新が続いているのでとりあえず。

導入するパッケージはntp。設定は /etc/ntp.conf

セキュリティ強化の関係か面倒になってきている。notrustの意味が変わったことで古くなった情報も多い。

なるべくdebianの設定をそのまま使う方向で進める。

/etc/ntp.conf

今回はデフォルトにあったものをそのまま使う

server 0.debian.pool.ntp.org iburst
server 1.debian.pool.ntp.org iburst
server 2.debian.pool.ntp.org iburst
server 3.debian.pool.ntp.org iburst

日本のサーバーらしい名前が選択されたのでよしとした。その後も問題ないのでこのままにしている。それぞれのディストリビューションで初期値に責任を持とうと努力してくれているのだろう。ちまたでは ntpx.jst.mfeed.ad.jp(x=1,2,3) ntp.nict.jp ntp.ring.gr.jp などを勧めているところが多い。

次にサーバーとしてリクエストを受けるために、以下を加える。(これはあくまで本校の環境でのアドレスで 10.0.0.0 のクラスAのアドレスからのリクエストを受け付けるためのもの)

#adachi
restrict 10.0.0.0 mask 255.0.0.0 nomodify notrap nopeer

nomodify,notrapなどの説明は大体理解できるものの例にあるまま使っている。ただしnotrastは意味が変わったのでここに加えると参照できなくなる。

#In 4.1 (and earlier) notrust meant "Don't trust this host/subnet for time".
#In 4.2 (and later) notrust means "Ignore all NTP packets
#                   that are not cryptographically authenticated.

ntpdをリスタート(debian ではntp)

root@amos:~# /etc/init.d/ntp restart
Stopping NTP server: ntpd.
Starting NTP server: ntpd.

ntpdの動作確認。最近のリスタートの記録なので初めての時とは違うかもしれない。

root@amos:/srv/www/t2012/kdchk# ntpq -p
     remote           refid      st t when poll reach   delay   offset  jitter
==============================================================================
 E210168211231.e .INIT.          16 u    -   64    0    0.000    0.000   0.000
 103.6.16.254    10.84.87.146     2 u    1   64    1  249.405   21.765   0.002
 superluminal.sf 189.70.85.38     2 u    2   64    1   20.466    0.283   1.498
 fnttkyo043241.t 165.246.43.195   3 u    1   64    1   23.765   -0.555   0.478

少し時間が経つと次のようになって同期が始まったことがわかる。

root@amos:/srv/www/t2012/kdchk# ntpq -p
     remote           refid      st t when poll reach   delay   offset  jitter
==============================================================================
*E210168211231.e .CDMA.           1 u  248  256  377   32.937    3.910   0.961
-103.6.16.254    10.84.87.146     2 u  190  256  377  248.805   23.887   0.604
+superluminal.sf 189.70.85.38     2 u  137  256  377   20.795    5.079   0.756
+fnttkyo043241.t 165.246.43.195   3 u  118  256  377   24.639    4.254   0.578

ntpdateでアクセスするクライアント

クライアントは/etc/default/ntpdateにサーバーの名前を書いておけば、起動時に同期する。

DNSにntp.st.seiai.ed.jpを登録しておくとサーバーが交代しても記述はそのままでもよいので便利。

root@star00 # cat /etc/default/ntpdate 
# The settings in this file are used by the program ntpdate-debian, but not
# by the upstream program ntpdate.

# Set to "yes" to take the server list from /etc/ntp.conf, from package ntp,
# so you only have to keep it in one place.
#NTPDATE_USE_NTP_CONF=yes
NTPDATE_USE_NTP_CONF=no

# List of NTP servers to use  (Separate multiple servers with spaces.)
# Not used if NTPDATE_USE_NTP_CONF is yes.
#NTPSERVERS="0.debian.pool.ntp.org 1.debian.pool.ntp.org 2.debian.pool.ntp.org 3.debian.pool.ntp.org"
NTPSERVERS="ntp.st.seiai.ed.jp"

# Additional options to pass to ntpdate
NTPOPTIONS=""