電子趣味の部屋

電子系のガジェットやアプリ開発等の趣味の話題を書いてます

UbuntuでNAS環境構築

現在Beelink U59でNASを構築してして運用していますが、このときに行ったセットアップ内容をまとめておきたいと思います。

自分へのメモも兼ねて一通り書いたので、長文になります。

ディスク構成

デバイス 種類 用途
/dev/sda 2.5インチHDD 2TB NAS領域のデータ用
/dev/sdb M.2 SATA SSD 128GB OS含むシステム用

Beelink U59の2.5インチスロットは厚さ7mmまで対応してます。9.5mmのものは入りませんので注意してください

導入

Ubuntuのインストールとディスク構築方法はここでは省略します。
また、Ubuntu以外でもDebian系のディストリビューションなら同じ手順で構築できると思います。

OSインストール後初期ディスク構成

Ubuntuインストール時に"ディスクを削除してUbuntuをインストール"を選択したので、/dev/sdbは自動で設定されました。
/dev/sdaはディスク全体をNAS用としてExt4でフォーマットして、/nasディレクトリを作りそこにマウントしてます。
フォーマットとマウント定義はUbuntu標準の"ディスク"アプリで行いました。

デバイス マウントポイント フォーマット サイズ
/dev/sdb1 /boot/efi FAT32 537MB
/dev/sdb2 / Ext4 128GB
/dev/sda1 /nas Ext4 2TB

/nasディレクトリはrootで作成

sudo mkdir /nas

Samba

インストール

sudo apt install samba

サービス開始、自動起動設定

sudo systemctl start smbd
sudo systemctl enable smbd

アクセスユーザ設定

SambaにアクセスしたいユーザがUNIXユーザにいない場合は作成。
ここでは仮にユーザ名をuser1とする。

sudo adduser user1

Sambaパスワード設定

sudo pdbedit -a user1

Sambaのパスワードは独自に管理しているため、すでに存在するUNIXユーザでもパスワード設定が必要。

共有フォルダ用のディレクトリ作成。

ゲスト等だれてもアクセスできる共有フォルダ

ディレクトリの所有者をroot、権限を777とする。
ここでは仮に共有フォルダ名をshareとする。

sudo mkdir /nas/share
sudo chmod 777 /nas/share
特定のユーザがアクセスできる共有フォルダ

ディレクトリの所有者をアクセスユーザ、権限を700とする。
ここでは仮にアクセスユーザをuser1、共有フォルダ名をprivate_user1とする。

sudo mkdir /nas/private_user1
sudo chown user1 /nas/private_user1
sudo chmod 777 /nas/private_user1

ワークグループ設定

Sambaの設定でワークグループはWORKGROUP
これを変更する場合は設定ファイル /etc/samba/smb.conf の以下の行を変更する

workgroup = WORKGROUP

共有フォルダ設定

/etc/samba/smb.conf に共有フォルダ毎の設定を追加する
詳細な説明は省略するが、基本的に[]内に共有フォルダ名、pathにサーバ内のディレクトリを設定する

ゲスト等だれてもアクセスできる共有フォルダ

ここでは仮に共有フォルダ名をshareとする。

/etc/samba/smb.conf の最後に追加。

[share]
comment = share folder
path = /nas/share
writable = yes
guest ok = yes
guest only = yes

guest only = yes を設定することによって、すべてのアクセスがnobody:nogroupになり、ファイルを作成した他のユーザが更新や削除ができないといったことがなくなる。

特定のユーザのみアクセスできる共有フォルダ

ここでは仮に共有フォルダ名をprivate_user1、アクセス可能なユーザをuser1とする。

/etc/samba/smb.conf の最後に追加。

[private_user1]
comment = only user1
path = /nas/private_user1
writable = yes
valid users = user1
設定後Samba再起動
sudo systemctl restart smbd

転送速度チューニング

デフォルト状態では転送速度が遅いので少しチューニングしてみた。
ここの設定は環境によるので各項目の説明は省略して参考程度に書いておく。

以下の設定を /etc/samba/smb.conf の[global]セクションに追加

[global]

unix charset = UTF-8
dos charset = CP932

client min protocol = SMB2

log level = 1

socket options = TCP_NODELAY

wsdd

Windows10でデフォルトでSMB1.0のプロトコルが無効化され、Web Service Discoveryを使用するようになり、このままではWindowsのネットワーク共有に表示されなくなった。
これを解決するために Web Service Discovery host daemon (wsdd) を導入する。

/etc/apt/sources.list.d/wsdd.list作成
↓内容

deb https://pkg.ltec.ch/public/ bullseye main

pgpキーを登録してインストール

sudo apt-key adv --fetch-keys https://pkg.ltec.ch/public/conf/ltec-ag.gpg.key
sudo apt update
sudo apt install wsdd

サービススタート、自動起動

sudo systemctl start wsdd
sudo systemctl enable wsdd

NAS基本機能構築完了

ここまででNASとしての基本機能は完了。
以降の項目は個人的にやりたいことをやったので、付加機能として書いておく。

bcache導入

システム部分は128GBのSSDを使用しているが、この段階で10GBほどしか使用していない。
今後多少のサーバ機能を追加してもそんなに急激に増えるとは考えられない。
これでは非常にもったいないので、半分の64GBをHDDのキャッシュとしてSSHD的な動作を行えるbcacheを導入することにした。

まずはインストールメディアとして使用したUSBメモリからライブブートし、"ディスク"アプリを使用して/dev/sda1を64GBに縮小し、新たに64GBのExt4でフォーマットした領域を確保した。

このディスク構成からの設定を行う。

デバイス マウントポイント フォーマット サイズ
/dev/sdb1 /boot/efi FAT32 537MB
/dev/sdb2 / Ext4 64GB
/dev/sdb3 未割当て Ext4 64GB
/dev/sda1 /nas Ext4 2TB

この構成で /dev/sda1 をバックディスク、/dev/sdb3 をキャッシュディスクとして扱う

インストール

sudo apt install bcache-tools

ファイルシステムのメタデータをクリア

sudo wipefs -a /dev/sda1
sudo wipefs -a /dev/sdb3

bcache作成

sudo make-bcache -B /dev/sda1 -C /dev/sdb3

正常に作成できた場合はデバイスファイル /dev/bcache0 が作られている。(0の部分は連番)

マウント定義

まず/dev/bcache0のuuidを取得

blkid /dev/bcache0

/etc/fstabを編集
元々/nasのマウント定義のデバイス部分が "/dev/disk/by-uuid/(UUID)"の形式だったのでこのUUIDを書き換えるだけにして他のパラメータはそのまま使うことにした

仮に/dev/bcache0のUUIDを14bb71b8-a012-47fb-8290-XXXXとする

/dev/disk/by-uuid/14bb71b8-a012-47fb-8290-XXXX /nas auto nosuid,nodev,nofail,x-gvfs-show 0 0

/nasをアンマウント、マウントするのも良いが、一旦再起動

sudo reboot

再起動したらマウント確認

mount | grep nas

/dev/bcache0 on /nas type ext4 (rw,nosuid,nodev,relatime,x-gvfs-show)

キャッシュモード

cat /sys/block/bcache0/bcache/cache_mode

現在は[writethrough]となっていた。
電源切断時のデータ損失が怖いので、そのままとする。(writethroughはファイル更新時に遅延なしにHDDも更新される)

評価

まだキャッシュにあるデータが少ないせいか、そんなに変わらないが多少早くなった気がする。
PC無線LAN-NAS有線LANの環境で試したので、ディスクアクセス速度より転送速度のほうがネックになってそう。
小さいファイルの連続アクセスは快適になった気がする。

バックアップ

外付けHDDにNAS領域をバックアップすることにした。
HDDはWindowsでも読めるように、Windows上でNTFSでフォーマットしたものを使用。

マウント

/media/backupにマウントするように定義

マウントポイント作成
sudo mkdir /media/backup
uuidを取得

USBディスクを接続して"ディスク"アプリで確認したところ/dev/sdd1と判明したので、これのUUIDを取得

blkid /dev/sdd1

接続する際にデバイス名が変わる可能性があるので、UUIDでマウント定義をする

/etc/fstabに追加
仮に/dev/sdd1のUUIDをB6149A52149AXXXXとする

UUID=B6149A52149AXXXX /media/backup/ ntfs auto,nosuid,nofail,user_id=0,group_id=0,default_permissions,allow_other 0 0

USBを接続して起動すると認識されるが、起動中に接続してマウントされない場合はマウントコマンドを実行

sudo mount /media/backup

バックアップスクリプト

Sambaでシェルを編集できるように定義

管理系のファイルを置くディレクトリを作成

sudo mkdir /nas/admin_tools
sudo chmod 777 /nas/admin_tools

とりあえず誰でもアクセスできる共有フォルダとする
/etc/samba/smb.conf の最後に追加。

[admin_tools]
comment = admin tools
path = /nas/admin_tools
writable = yes
guest ok = yes
guest only = yes
設定後Samba再起動
sudo systemctl restart smbd
バックアップスクリプト作成

今回作成したPythonのスクリプトを書いておきます。
ソースの始めの方にあるfoldersの配列定義部分にバックアップ対象の/nas以下のディレクトリ名を書いてください。

folders = [
	"share",
	"private_user1",
]


この部分


バックアップスクリプトのソースファイル
ファイル名は"/nas/admin_tools/daily_backup.py"で保存してください。

import datetime
import subprocess
import os

# バックアップする対象
folders = [
	"share",
	"private_user1",
]

# logsフォルダを除外するバックアップする対象
exclude_log_folders = [
	"admin_tools",
]

dt = datetime.datetime.now()
d = dt.strftime('%Y%m%d_%H%M%S')

backup_tool_dir = "/nas/admin_tools"
nas_dir = "/nas"
dist_dir = "/media/backup/nas"
backup_delete_dir = "/media/backup/backupfiles/backup_" + d
log_dir = backup_tool_dir + "/logs/" + d[:6] + "/" + d[:8]

os.makedirs(log_dir, exist_ok=True)

# mountチェック
check = subprocess.run("mount | grep backup", shell=True, capture_output=True, text=True)
if "media" not in check.stdout:
	log_file = log_dir + "/" + d + "_error.log"
	command = "echo \"disk mount error\" > " + log_file
	subprocess.run(command, shell=True)
	exit()

# 続行

# folders
for f in folders:
	target_dir = nas_dir + "/" + f
	log_file = log_dir + "/" + d + "_" + f + ".log"
	command = "rsync -avh --delete --exclude=\"*.DS_Store\" --exclude=\"._*\" --backup --backup-dir=\"" + backup_delete_dir + "\" --log-file=\"" + log_file + "\" " + target_dir + " " + dist_dir
	subprocess.run(command, shell=True)

# exclude_log_folders
for f in exclude_log_folders:
	target_dir = nas_dir + "/" + f
	log_file = log_dir + "/" + d + "_" + f + ".log"
	command = "rsync -avh --delete --exclude=\"*.DS_Store\" --exclude=\"._*\" --exclude=\"logs\" --backup --backup-dir=\"" + backup_delete_dir + "\" --log-file=\"" + log_file + "\" " + target_dir + " " + dist_dir
	subprocess.run(command, shell=True)

command = "chmod -R a+rw " + backup_tool_dir + "/logs/" + d[:6]
subprocess.run(command, shell=True)

更新や削除されたファイルは/media/backup/backupfiles以下の日時別ディレクトリに保存される。
この処理が不要な場合は、rsyncコマンドを定義している箇所(command = "rsync〜の部分)から"--backup"を削除する。

ubuntu上で作成した場合は権限変更をする

chmod 777 /nas/admin_tools/daily_backup.py

cron登録

バックアップスクリプトの実行をcronに登録する。
毎日4時に実行するように登録した場合を書く。
cronはrootで実行するようにする。

sudo crontab -e

↓追加する内容

# backup daily
0 4 * * * /usr/bin/python3 /nas/admin_tools/daily_backup.py

ログファイル

バックアップスクリプトが実行されるとログが/nas/admin_tools/logs/(日時)に保存される。

Netatalkサーバ

MacのTimeMachineのバックアップ先として使用できるようにnetatalkを導入
最大500GBを使用できるように設定

インストール

sudo apt install netatalk

メディアファイルを置くディレクトリ

/nas/timecapsuleに置くとする

sudo mkdir /nas/timecapsule
sudo chmod 777 /nas/timecapsule

設定ファイル編集

/etc/netatalk/afp.conf を編集
割と短いので全文載せます

;
; Netatalk 3.x configuration file
;

[Global]
; Global server settings
 mimic model = TimeCapsule6,106
 mac charset = MAC_JAPANESE

; [Homes]
; basedir regex = /xxxx

; [My AFP Volume]
; path = /path/to/volume

[nas timecapsule]
 path = /media/timecapsule
 time machine = yes
 vol size limit= 500000
 valid users = user1
 unix priv = yes

サービス開始、自動起動設定

sudo systemctl start netatalk
sudo systemctl enable netatalk

DLNAサーバ

NAS製品によくあるDLNAサーバの機能も欲しので、手軽なminidlnaを導入

インストール

sudo apt install minidlna

サービス開始、自動起動設定

sudo systemctl start minidlna
sudo systemctl enable minidlna

メディアファイルを置くディレクトリ

/nas/dlnaに置くとする
今回は動画、画像、音楽ファイルの置く場所を区別しない

sudo mkdir /nas/dlna
sudo chmod 777 /nas/dlna

とりあえず誰てもアクセスできる共有フォルダとする
/etc/samba/smb.conf の最後に追加。

[admin_tool]
comment = dlna
path = /nas/dlna
writable = yes
guest ok = yes
guest only = yes

設定後Samba再起動

sudo systemctl restart smbd

DLNA設定

/etc/minidlna.conf を編集する

media_dirを変更

media_dir=/nas/dlna

リストの自動更新を有効

inotify=yes

(コメントの#を削除するだけ)

自動更新時間を1分毎に変更

notify_interval=60

(コメントの#を削除して値を変更)

設定後minidlna再起動

sudo systemctl restart minidlna

WEBサーバ

ちょっとしたメモをウェブ上におけると便利だと思い、WEBサーバを導入
始めは慣れているApacheと思ったが、少しでも軽量にしたくてnginxを使うことにした

インストール

sudo apt install nginx

サービス開始、自動起動設定

sudo systemctl start nginx
sudo systemctl enable nginx

ファイルを置くディレクトリ

/nas/wwwに置くとする

sudo mkdir /nas/www
sudo chmod 777 /nas/www

とりあえず誰てもアクセスできる共有フォルダとする
/etc/samba/smb.conf の最後に追加。

[www]
comment = www
path = /nas/www
writable = yes
guest ok = yes
guest only = yes

設定後Samba再起動

sudo systemctl restart smbd

nginx設定

/etc/nginx/sites-available/default を編集
serverブロックにある root を /nas/www に変更する

        root /nas/www;

ついでにPHPインストール

sudo apt install php php-fpm php-common php-gd php-mbstring php-json php-xml

/etc/nginx/sites-available/default にPHPの定義があるので、下のようにコメントを外して編集する

        # pass PHP scripts to FastCGI server
        #
        location ~ \.php$ {
                include snippets/fastcgi-php.conf;

                # With php-fpm (or other unix sockets):
                fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
        #       # With php-cgi (or other tcp sockets):
        #       fastcgi_pass 127.0.0.1:9000;
        }

設定後nginx再起動

sudo systemctl restart nginx