2014.11.20
O

PidoraでAFPファイルサーバ(Netatalk)

BitStarSSL 面倒なサーバ設定…BitStarSSLが代行します!

最近、Linuxに触れる機会も減り、家のRaspberry Piもただsambaが動いているだけのつまらない子になっていたので、sambaからnetatalk(AFP)に変え、OSも新しいのに変えちゃおう、ということで作業してみました。

今動かしている、Raspberry pi(sambaによるファイル共有サーバ)とは別にNASを買ったので、SMB/SMB2/NFSのファイル共有はそちらに任せてしまって問題ない(GbEで速いのでもうこちらしか使っていない)、というのと、そのNASでのAFP(Apple Filing Protocol)で使われているnetatalkのバージョンが古く、Spotlight検索等が使えないので、この部分をRaspberry Piにさせたい、というのが動機と目標です。

OSXにはSpotlightという強力なファイル検索機能があり、ファイルの場所がわからなくても、検索してアクセスすることができます。しかし、ファイル共有でマウントしたボリューム上のものは基本的にindexing対象外なので、探すことが出来ません。

AFPでマウントしたボリュームであればindexingの対象にすることも可能ではありますが、その場合、マウントした側にそのデータベースが作られるので、アクセスするMac毎にindexingが必要になります。

(追記(2014/12/08):AFPマウントしたもので、そのVolume下の.Spotlight-V100 を参照するものもあるようです。)

Netatalk3.1ではspotlight検索がサポートされました。これはサーバー側でGnome Trackerがindexingし、それをspotlightに渡しているようです。

なので、spotlight検索そのものではなく、強力なファイル検索とは言えませんが、サーバー側にデータベースがあるのでクライアント毎にindexingをする必要がありません。

ということで、作業始めます。OSは今まで一番おすすめっぽいNOOBSを使用していましたが、仕事で使うことがありそうなLinux distributionは大体RHEL系なので、Raspberry PiのFedora, Pidoraを選択します。趣味では基本Ubuntuですが、仕事優先で。

Pidora SD Card Installation

作業環境

  • Raspberry Pi B+
  • MacBook Pro (Retina, 13-inch, Mid 2014)
  • OSX 10.10

Download Pidora Image ZIP file

ZIPでくれ。ってことでお茶でも飲みながらダウンロード。
Downloads | Raspberry Pi

終わったらzipのSHA-1ハッシュを確認。

$ openssl sha1 Pidora-2014-R3.zip

extract archive and confirm md5 checksum.

普通に解凍してチェックサムを確認。

$ unzip Pidora-2014-R3.zip
$ cd Pidora-2014-R3
$ md5 Pidora-2014-R3.img

インストール手順を読んでおく

コマンドラインでdd書き込み、です。
よくわからないけれど、Qiitaで参考になりそうな記事もそっちを使ってるので、ALTERNATIVE METHODの方でやります。

Identify the device node of the SD card (like /dev/disk2s1).

デバイスの確認。
MacBook Pro RetinaにはSDカードリーダが付いてるので、ただ、挿す。状況によって変わるけれど僕は”/dev/disk2s1”でした。

Insert your SD/SDHC card into the MacBook pro card reader.

$ df -h

Copy the image file to the card

dd書き込み。デバイス間違えると危険なのでよく確認。
ddの方でのデバイス名は”s1”を削って、”disk”を”rdisk”に置換です。

$ diskutil unmount /dev/disk2s1
$ sudo dd bs=1m if=Pidora-2014-R3.img of=/dev/rdisk2

use headless mode

/Volumes/BOOTにマウントされているようなので、そこにheadless設定を書く。
…ディスプレイとか全部あるのだけれど…。ま、やっておきます。ipはDHCPを振る側で固定するので指定してません。

$ cat /Volumes/BOOT/headless
RESIZE
SWAP=512

Remove the card

カードが出来上がったのでアンマウントして引っこ抜く。

$ sudo diskutil eject /dev/rdisk2

Insert SD card into the Raspberry pi SD card reader, and boot it.

ラズパイにmicroSDを差して起動するだけ。
headlessでSSHで繋ぐところだけれどディスプレイあるので普通にログイン。
デフォルトのroot passwordは以下。

user password
root raspberrypi

Setup

change password

さくっとパスワード変更。

# passwd

update

まずはアップデート。

# yum -y install yum-fastestmirror
# yum -y update pidora-release
# yum -y update

check os/kernel version

os、カーネルバージョン確認。

# cat /etc/os-release 
NAME=Pidora
VERSION="2014 (Raspberry Pi Fedora Remix)"
ID=fedora
VERSION_ID=2014
PRETTY_NAME="Pidora 2014 (Raspberry Pi Fedora Remix)"
ANSI_COLOR="0;1""
CPE_NAME="cpe:/o:senecacollege:pidora-fedora-remix:20"
# uname -r
3.12.26-1.20140808git4ab8abb.rpfr20.armv6hl.bcm2708

check NIC MAC address

IP固定したいからMACアドレスを調べよ、と思ったら、
おや?ifconfigがない。

# yum provides /sbin/ifconfig
Loaded plugins: langpacks, refresh-packagekit
net-tools-2.0-0.15.20131119git.fc20.armv6hl : Basic networking tools
Repo        : pidora
Matched from:
Filename    : /sbin/ifconfig

net-toolsをyumで入れればいいのか。でも何で入ってないんだろうな。

ググると、RHEL7でnet-toolsはdeprecatedで、iproute2のipコマンド, ssコマンドを使っていけとのこと。最近のLinuxではiproute2を使うものらしい。ifconfigなんて打ってるのはロートルだったのか…。
(arpもnetstatもrouteもだ!)

対応表が出てる。ありがたや。

Deprecated Linux networking commands and their replacements | Doug Vitale Tech Blog

というわけでipコマンドを使おう.

# ip addr

DHCP Address Reservation

MACアドレスを控えてルータのDHCP割り当てでIPaddressを固定. (RaspberryPiの方にdhcpdを移すというのもいいな。そのうち考えよう)

add user, use wheel group

userの追加。なんか面倒臭くなってきたし、ディスプレイもキーボードもマウスもあるからfirstboot起動してGUIでやっちゃおうか、とか思ったけど、もともとある程度勉強目的でPidoraを選んだはずなのでコマンドで。

ユーザーを追加してパスワードを設定。

# useradd hoge
# passwd hoge

PAMでrootユーザを制限する。

PAM使えるかな?

# ls /lib/security/pam_wheel.so
(ある。ok)

ユーザをwheelグループに追加。

# gpasswd -a hoge wheel
(ユーザーhogeをwheelグループに追加)
# id hoge
(wheelに加わったことを確認)

root獲得をwheelグループのユーザに制限

# vi /etc/pam.d/su
< auth required pam_wheel.so use_uid
---
> #auth required pam_wheel.so use_uid
# visudo
("%wheel  ALL=(ALL)       ALL"はデフォルトで有効でした)

sshで追加したユーザでログインしてrootになってみる。

$ ssh hoge@ip_addr -p 22
[hoge@pidora ~] $ su -
[root@pidora ~] # 

wheelグループ以外のユーザはrootになれないことをテストユーザで確認。終わったら削除。

[root@pidora ~] # useradd testusr
[root@pidora ~] # passwd testusr
[root@pidora ~] # su testusr
[testusr@pidora ~] $ su -
su: Permission denied
[testusr@pidora ~] $ exit
[root@pidora ~]# userdel -r testusr

rootでのSSHログイン禁止

sshの設定を変更

[root@pidora ~] # vi /etc/ssh/sshd_config
< PermitRootLogin no
---
> #PermitRootLogin yes
[root@pidora ~] # sshd -t
(エラーが出なければok)

SSHの設定を反映

[root@pidora ~] # /bin/systemctl restart sshd.service

rootでのログインが弾かれればok.

SSHの鍵認証の有効化と鍵追加

sshの設定を変更・反映(デフォルトで有効だったので何もしていない)、.sshディレクトリの作成

[root@pidora ~] # vi /etc/ssh/sshd_config
("AuthorizedKeysFile      .ssh/authorized_keys"はデフォルトで有効。なのでsshdの再起動は不要)
[hoge@pidora ~] $ mkdir ~/.ssh
[hoge@pidora ~] $ chmod 700 ~/.ssh

接続元でRSA暗号鍵 (公開鍵、秘密鍵)を生成し、公開鍵をPidoraのhogeユーザーのauthorized_keysへ追加

$ ssh-keygen -t rsa
$ ls ~/.ssh
id_rsa  id_rsa.pub
(passphrase入れ忘れたので追加…。 $ ssh-keygetn -p -f ~/.ssh/id_rsa)
$ cat ~/.ssh/id_rsa.pub | ssh hoge@ip_addr "cat >>.ssh/authorized_keys && chmod 600 .ssh/authorized_keys"
$ ssh hoge@ip_addr
(鍵で入れればok)

ssh conf設定。(ほとんどデフォなので実際設定しているのアドレスとユーザだけですが。ポート番号は後で変えようか)

$ cat ~/.ssh/config
Host pidora
  Port 22
  User hoge
  HostName IP_ADDR
  IdentityFile ~/.ssh/id_rsa
$ chmod 644 ~/.ssh/config

SSHでのパスワード認証を無効化

sshの設定を変更し、反映

[root@pidora ~] #  vi /etc/ssh/sshd_config
PasswordAuthentication no
[root@pidora ~] #  sshd -t
[root@pidora ~] #  /bin/systemctl restart sshd.service

SSHのポート番号変更(そのうちやる)

sshの設定を変更し、反映

[root@pidora ~] #  vi /etc/ssh/sshd_config
Port [ポート番号]
[root@pidora ~] #  sshd -t
[root@pidora ~] #  /bin/systemctl restart sshd.service

Host名設定

$ cat /etc/hosts
133.242.17.62       localhost localhost.localdomain pidora.local
$ cat /etc/hostname
pidora

TimeZone設定

# timedatectl set-timezone Asia/Tokyo
# timedatectl set-local-rtc 0
# timedatectl status
      Local time: Tue 2014-11-02 14:42:08 JST
  Universal time: Tue 2014-11-03 05:42:08 UTC
        Timezone: Asia/Tokyo (JST, +0900)
     NTP enabled: yes
NTP synchronized: no
 RTC in local TZ: no
      DST active: n/a
# ntpdate [NTPサーバ]
# date

自動時刻合わせ(未)

まだやってません。ntpdじゃなくなったとかちらと目にしたような…。

ロケール設定

$cat /etc/locale.conf
LANG="ja_JP.UTF-8"

mail設定

sed -i '/^root:/d' /etc/aliases
echo "root: hoge@hogehoge.com" >> /etc/aliases
newaliases
echo test|mail root

Setup finished

大体準備整ったので後はsshで繋いで遊んでいきます。とりあえず適当に突っこむ。

$ sudo yum install -y vim nkf git

Netatalk

NetatalkはAFP(Apple Filing Protocol)によるファイル共有を提供するサーバのオープンソースソフトウェアです。
先に書いた様に、version3.1でspotlightがサポートされましたが、yumで入るのは2.2.3なのでソースからコンパイルします。

Instllation

ソースをとってきて解凍して中へ。

Chapter 2. Installation

$ wget https://sourceforge.net/projects/netatalk/files/netatalk/3.1.6/netatalk-3.1.6.tar.gz
$ tar zxvf netatalk-3.1.6.tar.gz
$ cd netatalk-3.1.6

依存パッケージ準備

./configure -h をみて使うオプションと依存パッケージを調べ、依存パッケージをインストール。
spotlightを使う場合、trackerをインストールし、trackerのpkg-configでのバージョンを調べておく。

$ sudo yum install -y db4-devel openssl-devel libgcrypt-devel avahi-devel avahi-glib-devel avahi-ui-devel libdb-devel libacl-devel openldap tracker-devel
$ pkg-config --list-all|grep tracker
tracker-sparql-0.14       tracker-sparql - Tracker : A library to perform SPARQL queries and updates in the              Tracker Store
tracker-miner-0.14        tracker-miner - A library to develop tracker data miners
tracker-extract-0.14      tracker-extract - Tracker : A library to develop metadata extractors for 3rd party file types.

./configure, make, make install. spotlightのためにtrackerのバージョン指定と、systemdで使えるようにオプション追加。

$ ./configure --with-tracker-pkgconfig-version=0.14 --with-init-style=redhat-systemd
    LIBEVENT:
        bundled
    TDB:
        bundled
Configure summary:
    INIT STYLE:
         redhat-systemd
    AFP:
         Extended Attributes: ad | sys
         ACL support: yes
         Spotlight: yes
    CNID:
         backends:  dbd last tdb
    UAMS:
         DHX     ( SHADOW)
         DHX2    ( SHADOW)
         RANDNUM (afppasswd)
         clrtxt  ( SHADOW)
         guest
    Options:
         Zeroconf support:        yes
         tcp wrapper support:     no
         quota support:           no
         admin group support:     yes
         valid shell check:       yes
         cracklib support:        no
         ACL support:             auto
         Kerberos support:        yes
         LDAP support:            no
         AFP stats via dbus:      yes
         dtrace probes:           no
    Paths:
         Netatalk lockfile:       /var/lock/netatalk
         init directory:          /usr/lib/systemd/syst
em
         dbus system directory:   ${sysconfdir}/dbus-1/
system.d
    Documentation:
         Docbook:                 no
$ make
$ sudo make install
$ afpd -V
afpd 3.1.6 - Apple Filing Protocol (AFP) daemon of Netatalk

This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any later
version. Please see the file COPYING for further information and details.

afpd has been compiled with support for these features:

          AFP versions: 2.2 3.0 3.1 3.2 3.3 3.4
         CNID backends: dbd last tdb
      Zeroconf support: Avahi
  TCP wrappers support: No
         Quota support: No
   Admin group support: Yes
    Valid shell checks: Yes
      cracklib support: No
            EA support: ad | sys
           ACL support: Yes
          LDAP support: No
         D-Bus support: Yes
     Spotlight support: Yes
         DTrace probes: No

              afp.conf: /usr/local/etc/afp.conf
           extmap.conf: /usr/local/etc/extmap.conf
       state directory: /usr/local/var/netatalk/
    afp_signature.conf: /usr/local/var/netatalk/afp_signature.conf
      afp_voluuid.conf: /usr/local/var/netatalk/afp_voluuid.conf
       UAM search path: /usr/local/lib/netatalk//
  Server messages path: /usr/local/var/netatalk/msg/

外付けHDDセットアップ

特に工夫なくパーティション作成してフォーマットして自動マウント設定(EA使えるように設定追加)。

fdisk (パーティション作成)

$ sudo fdisk -l
$ sudo fdisk /dev/sda
d
w
$ sudo fdisk /dev/sda
n
(return)
(return)
(return)
w
$ sudo fdisk /dev/sda
p
Device    Start          End   Size Type
/dev/sda1  2048   3907029134   1.8T Linux filesystem
q

mkfs (フォーマット)

$ sudo mkfs.ext4 /dev/sda1

マウント確認と自動マウント設定

mount test

$ sudo mkdir /media/hdd2t
$ sudo mount -t ext4 /dev/sda1 /media/hdd2t
$ sudo chmod 777 /media/hdd2t/

fstab設定 (auto mount). 拡張属性(EA)を失わないようにuser_xattrを追加しておく

$ sudo blkid /dev/sda1
/dev/sda1: UUID="837c4e28-5994-4028-976c-aab6c02bc6fc" TYPE="ext4" PARTUUID="fa4a3b40-46ca-42f1-92a9-a56010344440"
$ sudo vim /etc/fstab
UUID="837c4e28-5994-4028-976c-aab6c02bc6fc" /media/hdd2t ext4 defaults,user_xattr 0 0
$ shutdown -r now
(再起動後)
$ mount
マウントできてればok

バックアップ用HDD

バックアップにrsyncでsnapshotをとることを考えているので、もう一台HDDを設定.(sdb1を/media/rsync3tにマウント)

Neatatalk設定(conf編集, 起動, 自動起動)

とてもシンプルなconf. systemctlで起動してみて、enableで自動起動有効化.

$ cat /usr/local/etc/afp.conf
[Global]
uam list = uams_clrtxt.so uams_dhx.so uams_dhx2.so
spotlight = yes

[Homes]
basedir regex = /home

[AfpVolume]
spotlight = yes
path = /media/hdd2t
file perm = 0660
directory perm = 0770

$ sudo systemctl start netatalk.service
$ sudo systemctl status netatalk.service
$ sudo systemctl enable netatalk.service

(guest接続を有効にするならuams_guest.soを追加.)

avahi, tracker等の関連サービスも自動で起動されます。

Macからpidora.localへユーザーとしてAFP接続できればOK.

最初、Raspberry Piを再起動するとFinderからはPidoraで接続できるものの、
Bonjour(avahi)ではlinux.localになってしまって困っていたのですが、
/etc/hostnamepidoraを設定するとpidora.localで接続できるようになりました。

$ dns-sd -L "Pidora" _afpovertcp._tcp local.
Lookup Pidora._afpovertcp._tcp.local.
DATE: ---Thu 20 Nov 2014---
08:21:42.619  ...STARTING...
08:21:42.860  Pidora._afpovertcp._tcp.local. can be reached at Pidora.local.:548 (interface 4)

バックアップ(rsyncによるスナップショット)設定

RAIDやバックアップなしのストレージはゴミ箱と一緒(コストをかければ結構復旧できるということも含めて)と思っているので、rsyncでスナップショットを別のHDDに取ります。

sda1のsharedディレクトリ(/media/hdd2t/shared/)のスナップショットを
sdb1のsnapshotディレクトリ(/media/rsync3t/snapshot)に作成していきます。

rsync初回スナップショット

dry-run(-nオプション)でおためし実行.

$ rsync -av /media/hdd2t/shared/ /media/rsync3t/snapshot/shared_20141114000 -n

問題無ければ-nを外して実行.

rsyncスナップショット(1つ前のスナップショットと共通部分はハードリンク)

dry-run(-nオプション)でおためし実行.

$ rsync -av --delete --link-dest=../shared_20141114000 /media/hdd2t/shared/ /media/rsync3t/snapshot/shared_20141114001 -n

問題無ければ-nを外して実行.

いちいちパスを指定するのは面倒なので適当にpythonスクリプト作成.

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
rsyncによるスナップショット作成スクリプトとりあえず使えればいいや版
"""
import os
import glob
import subprocess
import argparse
from datetime import date

# 対象ディレクトリ
src = '/media/hdd2t/shared/'
# snapshot作成先ディレクトリ
dest = '/media/rsync3t/snapshot/'
# 連番桁数
suffixcounterlength = 3
# dry-run結果行数しきい値
dryrunlinecountthreshold = 5

if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='Take snapshot.')
    parser.add_argument(
        '-n', '--dryrun', dest='dryrun',
        action='store_true', help='dry-run.')
    args = parser.parse_args()

    src = os.path.normpath(src)
    dest = os.path.normpath(dest)
    prefix = os.path.basename(src) + '_'
    filepaths = glob.glob(dest + '/' + prefix + '*')

    filepaths.sort()
    lastsnapshot = filepaths[len(filepaths) - 1]
    head, tail = os.path.split(lastsnapshot)
    suffix = tail.lstrip(prefix)
    lastsnapshotdate = suffix[0:8]
    lastsnapshotcount = suffix[8:]
    today = date.today().strftime('%Y%m%d')
    if lastsnapshotdate == today:
        count = int(lastsnapshotcount) + 1
    else:
        count = 0

    countformat = "{0:0%d}" % suffixcounterlength
    newsnapshot = os.path.join(head, prefix + today + countformat.format(count))

    cmd = 'rsync -av --delete --link-dest=' \
        + os.path.relpath(lastsnapshot, newsnapshot) + ' ' + src + '/ ' + newsnapshot
    cmddryrun = cmd + ' -n'
    print(cmd)
    proc = subprocess.Popen(cmddryrun, stdout=subprocess.PIPE, shell=True)

    # 変更がなければsnapshot作成をスキップするのにdry-runの結果行数を判定基準にしてます
    dryrunlinecount = 0
    for line in proc.stdout:
        print(line.rstrip())
        dryrunlinecount += 1

    # dry-runオプションが指定されておらず、dry-run結果行数しきい値を超えている場合実行
    if dryrunlinecount > dryrunlinecountthreshold and not args.dryrun:
        try:
            subprocess.check_call(cmd, shell=True)
        except Exception as e:
            pass

cronなどで自動実行にしようかなーと思いつつ、とりあえず今は気が向いた時に手動実行しています。

やり残したことも多い気がしますが、AFPファイルサーバとして使えるところまではセットアップできました。

afp.confの設定を追加すればTimeMachineのバックアップ先にも指定できます。

ファイルサーバを少し使ってみた感じ、AFPマウントしたMacからのSpotlight-tracker検索はとても便利です。
本物のSpotlight程強力ではありませんが、ファイル名やexif, mp3tagのメタ情報等はindexingされるようで、十分使えます。

trackerの収集プロセスがいなくなって(tracker-control -Sで確認できます)データベース更新がされていない時は手動で終了・開始をすると直ります。

# cat ~/.tracker_profile
PREFIX="/usr/local"
export XDG_DATA_HOME="$PREFIX/var/netatalk/"
export XDG_CACHE_HOME="$PREFIX/var/netatalk/"
export DBUS_SESSION_BUS_ADDRESS="unix:path=$PREFIX/var/netatalk/spotlight.ipc"
# source ~/.tracker_profile
# tracker-control -t
# tracker-control -s
# tracker-control -S
データ格納デーモン:
20 11月 2014, 09:49:30:  ✓     Store                             - アイドル中です

収集デーモン:
20 11月 2014, 09:49:30:  ✓     ファイルシステム          - アイドル中です
20 11月 2014, 09:49:30:  ✓     アプリケーション          - アイドル中です

100BASEのせいか処理能力のせいかnetatalkのせいか、遅いな…と思うこともありますが、実用に耐えないという程ではありません。

httpでも見たいなと思い, nginx + php5-fpmでディレクトリ毎のファイル一覧を出しダウンロードできるようにしてみましたが、こちらの方が転送は速いような気がします。これにtracker-searchの検索窓とか付ければいいのかな…。

まだやりたいことはあるので、遊べそうです。

ところで、netatalkって何て読むんでしょうか。

O

一覧に戻る