概要
Windows11にwsl2+Dockerで自宅用Nextcloudを構築する手順です。
インターネットには公開せず、自宅LAN内での稼働を想定しています。
きっかけ
子どもが生まれ、増え続ける写真データを家族で共有する方法を探していました。
Googleフォトを有料プランにするのも、NASを購入するのも、結構お金がかかるので、自宅に転がっている機器を使って、ファイルサーバを構築すればタダじゃん楽しそうと考えたのがきっかけです。
イメージ図
使用したもの
・HeroBox2023 Mini PC (OS:Windows11 home)
・Crucial X9 外付け SSD 1TB
1. WSL2(Ubuntu)の導入
1.1. WSL2をインストールする
管理者権限でPowerShellを起動して、以下のコマンドを実行する。
wsl --install
※--distribution:というオプションをつけると、インストールするLinuxディストリビューションを指定することが可能ですが、指定しない場合は、デフォルトのLinuxディストリビューションであるUbuntuがインストールされます。
再起動を求められたら再起動します。
WindowsにUbuntuアプリがインストールされます。
Ubuntu初回起動時にユーザ名・パスワードを入力します。
1.2. Windows起動時にWSL2が起動するようにする
・以下のバッチファイルを用意する
wsl
・スタートアップフォルダに配置する
C:\Users\(Username)\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup
※「Windowsキー+R」を押して「ファイル名を指定して実行」のダイアログボックスに「shell:startup」と入力して実行することでもスタートアップフォルダを開くことが可能。
2. USB外付けSSDのマウント
2.1. USB外付けSSDをext4にフォーマットする
私はLinuxがインストールされたノートPCが手元にあったので、それにUSB外付けSSDを接続して、mkfs.ext4コマンドでフォーマットしました。
[別の手段の候補]
・USB外付けSSDをWSL2にマウント(手順2.2.)した後に、WSL2からmkfs.ext4コマンドを実行してもできそうです。(先にe4fsprogsパッケージをインストールする必要あり)
・Windowsでもフリーソフトを使ってext4にフォーマットできそうです。
[フォーマットが必要な理由]
フォーマットせずにNextcloudを構築した場合、初めにブラウザからNextcloudを開いた画面で[インストール]ボタンを押すと、「エラー あなたのデータディレクトリは他の人が読み取ることができます ディレクトリが他人から見えないように、パーミッションを 0770 に変更してください。」と表示されます。
これは、USB外付けSSDのファイルシステムが、購入時の状態ではFAT32だったためです。パーミッションが755になっていて、FAT32はLinuxのパーミッションの概念がなくchmodすることもできません。
別の回避方法として、Nextcloudのインストール時にパーミッションのチェックをしないようにする方法もあるようですが、ここは素直にext4にフォーマットしました。
2.2. USB外付けSSDをWSL2(Ubuntu)にマウントする
・WSL2側からデバイスを見る
Ubuntuを起動してlsblk
を実行
jo@herobox:~/docker-nextcloud$ lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
sda 8:0 0 388.6M 1 disk
sdb 8:16 0 1T 0 disk /var/lib/docker
/snap
/mnt/wslg/distro
/
→ディスクを認識する前の状態を確認しておく。
・Windowsで使用可能なディスクの一覧を表示する
Powershellで以下のコマンドを実行する。
GET-CimInstance -query "SELECT * from Win32_DiskDrive"
PS C:\Windows\system32> GET-CimInstance -query "SELECT * from Win32_DiskDrive"
DeviceID Caption Partitions Size Model
-------- ------- ---------- ---- -----
\\.\PHYSICALDRIVE0 AirDisk 256GB SSD 3 256052966400 AirDisk 256GB SSD
\\.\PHYSICALDRIVE1 Micron CT1000X9SSD9 SCSI Disk Device 1 1000202273280 Micron CT1000X9SSD9 SCSI Disk Device
→USB外付けSSDのDeviceIDとPartitionsを控えておく。
DeviceID:\\\.\PHYSICALDRIVE1
Partitions:1
・ディスクを認識させる
Powershellで以下のコマンドを実行
Partitionsが0の場合:wsl --mount <DiskPath>
Partitionsが1以上の場合:wsl --mount <DiskPath> --bare
※<DiskPath>は先ほど控えたDeviceID(今回は\\\.\PHYSICALDRIVE1)
PS C:\Windows\system32> wsl --mount \\.\PHYSICALDRIVE1 --bare
この操作を正しく終了しました。
・WSL2側からデバイスを見る
Ubuntuを起動してlsblk
を実行
jo@herobox:~/docker-nextcloud$ lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
sda 8:0 0 388.6M 1 disk
sdb 8:16 0 1T 0 disk /var/lib/docker
/snap
/mnt/wslg/distro
/
sdc 8:32 0 931.5G 0 disk
├─sdc1 8:33 0 128M 0 part
└─sdc2 8:34 0 931.4G 0 part
→新たにディスクが認識されたことを確認。今回マウントしたいのはsdcのパーティション番号2である。
・パーティションをマウントする
Powershellで以下のコマンドを実行
wsl --mount <DiskPath> --partition <PartitionNumber>
PS C:\Windows\system32> wsl --mount \\.\PHYSICALDRIVE1 --partition 2
ディスクは '/mnt/wsl/PHYSICALDRIVE1p2' として正常にマウントされました。
注: /etc/wsl.conf で automount.root 設定を変更した場合、場所は異なります。
ディスクのマウントを解除してデタッチするには、'wsl.exe --unmount \\.\PHYSICALDRIVE1' を実行してください。
→/mnt/wsl/PHYSICALDRIVE1p2にマウントされたと出力されている。
・WSL2側からデバイスを見る
Ubuntuを起動してlsblk
を実行
jo@herobox:~/docker-nextcloud$ lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
sda 8:0 0 388.6M 1 disk
sdb 8:16 0 1T 0 disk /var/lib/docker
/snap
/mnt/wslg/distro
/
sdc 8:32 0 931.5G 0 disk
├─sdc1 8:33 0 128M 0 part
└─sdc2 8:34 0 931.4G 0 part /mnt/wsl/PHYSICALDRIVE1p2
→/mnt/wsl/PHYSICALDRIVE1p2にマウントされていることを確認。後でcompose.ymlに書くので控えておく。
・Windows起動時にマウントされるようにする
ディスクをマウントするには管理者権限が必要なため、タスクスケジューラを設定します。
- [全般]タブ
名前:USB外付けSSDマウント
「ユーザーがログオンしているかどうかにかかわらず実行する」のラジオボタンをON
「最上位の特権で実行する」のチェックをON - [トリガー]タブ-[新規]→
タスクの開始:スタートアップ時 - [操作]タブ-[新規]→
操作:プログラムの開始
プログラム/スクリプト:wsl
引数の追加:--mount \.\PHYSICALDRIVE1 --partition 2
参考
3. WSL2(Ubuntu)にDocker CEをインストール
3.1. Ubuntuを起動して、以下の手順通りコマンドを実行する
参考
1. Set up Docker's apt repository.
# Add Docker's official GPG key:
sudo apt-get update
sudo apt-get install ca-certificates curl gnupg ##すでにインストール済みなので不要
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg
# Add the repository to Apt sources:
echo \
"deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
"$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
2. Install the Docker packages.
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
3. Verify that the Docker Engine installation is successful by running the hello-world image.
sudo docker run hello-world
4. Dockerコンテナの作成と実行
4.1. WSL2(Ubuntu)にDocker composeをインストールする
Ubuntuを起動して、以下のコマンドを実行
jo@herobox:~$ sudo apt install docker-compose
4.2. Nextcloud用のディレクトリを作成する
jo@herobox:~$ mkdir docker-nextcloud
4.3. compose.ymlファイルを作成する
jo@herobox:~$ cd docker-nextcloud/
jo@herobox:~/docker-nextcloud$ vi compose.yml
以下の内容を記述する。
services:
db:
image: mariadb:10.6
container_name: nextcloud_db
restart: always
command: --transaction-isolation=READ-COMMITTED --log-bin=binlog --binlog-format=ROW
volumes:
- /mnt/wsl/PHYSICALDRIVE1p2/nextcloud/db:/var/lib/mysql #'/mnt/wsl/PHYSICALDRIVE1p2'の部分はWSL2にマウントしたパスを記述する。
environment:
MYSQL_ROOT_PASSWORD: P@ssw0rd #任意のパスワードを記述する。
MYSQL_PASSWORD: P@ssw0rd #任意のパスワードを記述する。
MYSQL_DATABASE: nextcloud
MYSQL_USER: nextcloud
TZ: Asia/Tokyo
nextcloud:
image: nextcloud
container_name: nextcloud_app
restart: always
ports:
- 8686:80 #他のWebアプリで8080ポートを使うつもりなので、今回は8686ポートにした。
depends_on:
- db
volumes:
- /mnt/wsl/PHYSICALDRIVE1p2/nextcloud/data:/var/www/html/data #'/mnt/wsl/PHYSICALDRIVE1p2'の部分はWSL2にマウントしたパスを記述する。
- /mnt/wsl/PHYSICALDRIVE1p2/nextcloud/config:/var/www/html/config #'/mnt/wsl/PHYSICALDRIVE1p2'の部分はWSL2にマウントしたパスを記述する。
environment:
MYSQL_PASSWORD: P@ssw0rd #任意のパスワードを記述する。
MYSQL_DATABASE: nextcloud
MYSQL_USER: nextcloud
MYSQL_HOST: db
TZ: Asia/Tokyo
[補足]
volumes:の記述によって、WSL2(Ubuntu)でマウントしたUSB外付けSSDのパスを、Dockerコンテナにバインドマウントします。これにより、コンテナを削除しても写真データは消えない状態(永続化)になります。
4.4. コンテナを作成・起動する
jo@herobox:~$ cd docker-nextcloud/
jo@herobox:~/docker-nextcloud$ sudo docker compose up -d
4.5. コンテナができたか確認する
jo@herobox:~/docker-nextcloud$ sudo docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
15fa22bb3b8a nextcloud "/entrypoint.sh apac…" 2 minutes ago Up 2 minutes 0.0.0.0:8686->80/tcp, :::8686->80/tcp nextcloud_app
5f7ed9bae989 mariadb:10.6 "docker-entrypoint.s…" 2 minutes ago Up 2 minutes 3306/tcp nextcloud_db
4.6. ブラウザからnextcloudの起動を確認する
ブラウザ上で以下のアドレスを入力する。
http://localhost:8686/
4.7. Nextcloudの管理者アカウントを作成する
「管理者アカウントを作成してください」という画面が表示されているはずです。
管理者アカウントとなるユーザ名・パスワードを入力して、[インストール]ボタンを押します。
その後、推奨アプリを入れるか聞いてきますが、必要なければスキップでOK.
5. ネットワーク周りの設定
5.1. Windowsファイアウォールでポートを解放する
[コントロールパネル]-[システムとセキュリティ]-[Windows Defender ファイアウォール]-[詳細設定]-[受信の規則]
→ポート8686を解放
5.2. Port Forwardingを設定する
ホストOSのIPアドレス宛ての通信をWSL2(Ubuntu)にポートフォワーディングする設定を行っていきます。
・ホストOSのIPアドレスを固定化する
192.168.0.100
・UbuntuのIPアドレスを確認する
Ubuntuを起動して、以下のコマンドを実行
ip a show dev eth0
→192.168.204.7
・ポートフォワーディングを設定する
管理者権限でPowerShellを起動して、以下のコマンドを実行する
PS C:\Windows\system32> netsh interface portproxy add v4tov4 listenaddress=* listenport=8686 connectaddress=192.168.204.7 connectport=8686
設定できたか確認する
PS C:\Windows\system32> netsh interface portproxy show all
ipv4 をリッスンする: ipv4 に接続する:
Address Port Address Port
--------------- ---------- --------------- ----------
* 8686 192.168.204.7 8686
5.3. 他端末のブラウザからNextcloudが開けるか確認する
他端末のブラウザから http://192.168.0.100:8686/ を開く
参考
6. 動画のサムネイル生成
画像のサムネイルは何もしなくても生成されるのですが、動画のサムネイル生成は一手間加える必要があります。
6.1. ffmpegをインストールする
・docker composeで立てたコンテナの中にログインする
Ubuntuを起動して、以下のコマンドを実行
docker compose exec (サービス名) /bin/bash
sudo docker compose exec nextcloud /bin/bash
・apt-get updateして、ffmpegとviをインストールする
root@15fa22bb3b8a:/var/www/html# apt-get update
root@15fa22bb3b8a:/var/www/html# apt-get install ffmpeg
root@15fa22bb3b8a:/var/www/html# apt-get install vi
・config.phpを修正する
vi config/config.php
以下を追記する
'enabledPreviewProviders' =>
array (
0 => 'OC\\Preview\\TXT',
1 => 'OC\\Preview\\MarkDown',
2 => 'OC\\Preview\\OpenDocument',
3 => 'OC\\Preview\\PDF',
4 => 'OC\\Preview\\MSOffice2003',
5 => 'OC\\Preview\\MSOfficeDoc',
6 => 'OC\\Preview\\Image',
7 => 'OC\\Preview\\Photoshop',
8 => 'OC\\Preview\\TIFF',
9 => 'OC\\Preview\\SVG',
10 => 'OC\\Preview\\Font',
11 => 'OC\\Preview\\MP3',
12 => 'OC\\Preview\\Movie',
13 => 'OC\\Preview\\MKV',
14 => 'OC\\Preview\\MP4',
15 => 'OC\\Preview\\AVI',
)
参考
7. バックグラウンドジョブを「Cron(推奨)」に変更
7.1. バックグラウンドジョブの設定を変更する
ブラウザでNextcloudを開き、管理者アカウントでログインし、
[管理者設定]-[基本設定]-[バックグラウンドジョブ]→「Cron(推奨)」を選択する。
→[バックグラウンドジョブ]画面に「最終ジョブ実行は xx時間前 です。何か問題が発生しています。」と表示される。
7.2. 対策を講じる
・試行1
www-data 権限 #33 でコンテナに入って、cron.phpを実行する。
jo@herobox:~/docker-nextcloud$ sudo docker compose exec -u 33 nextcloud /bin/bash
www-data@15fa22bb3b8a:~/html$ php cron.php
www-data@15fa22bb3b8a:~/html$
→直後、[バックグラウンドジョブ]画面に「最終ジョブ実行は 数秒前 です。」と表示されたので、成功したと思われる。
・試行2
WSL2(Ubuntu)からcron.phpを実行する。
jo@herobox:~/docker-nextcloud$ sudo docker compose exec -u 33 nextcloud php /var/www/html/cron.php
jo@herobox:~/docker-nextcloud$
→直後、[バックグラウンドジョブ]画面に「最終ジョブ実行は 数秒前 です。」と表示されたので、成功したと思われる。
・WSL2(Ubuntu)のrootにて、cronを設定する
cronの設定を実施
sudo crontab -e
以下を追加
*/5 * * * * cd /home/jo/docker-nextcloud && docker compose exec -u 33 nextcloud php /var/www/html/cron.php
→以降、[バックグラウンドジョブ]画面に「最終ジョブ実行は x分前 です。」と常に5分以内の時間が表示されるようになった。
参考
8. 【おまけ】バックアップ運用
ちょっと変わったバックアップの取り方をしています。
まず、バックアップ対象は、Nextcloud上に保存されたデータのみ(写真データ等)です。
もっと正確に言うと、以下の図の、My PCに同期されたデータのみをUSB外付けHDDにバックアップしています。
Nextclud自体のバックアップは取っていません。
なぜこのようなバックアップ体制になっているかというと、理由は2つあります。
- もしハード故障などでNextcloudが動かなくなってしまっても、我が家ではそんなに困らないので、のんびり復旧or再構築するつもり。
- 以前からMy PCのデータをUSB外付けHDDにバックアップしていたので、運用負荷は変わらない。
メリットとしては、NextcloudとMy PCの間でデータを同期しているため、どちらかのディスクが壊れてもデータが失われない冗長構成になっている点が挙げられます。
8.1. 自動アップロード
スマホにNextcloudアプリをインストールして設定すればOK.
以下のNextcloudの公式サイトからダウンロード可能。
8.2. 自動同期
パソコンにNextcloudデスクトップクライアントをインストールして設定すればOK.
こちらも以下のNextcloudの公式サイトからダウンロード可能。
8.3. バックアップ
My PCの内蔵HDD(F:)にあるデータをUSB外付けHDD(X:)にバックアップする方法をご紹介します。
Windowsのrobocopyコマンドを以下のようにバッチファイル化して、My PCから実行しています。
src,dst,logfileの値を適宜修正すれば使い回せます。
robocopyの結果がログファイルに出力されるようにしています。出力先のフォルダはあらかじめ作っておく必要があります。
@echo off
set src="F:\Nextcloud"
set dst="X:\Nextcloud_BAK_X"
set logfile="C:\log\robocopy_nextcloud_F_to_X_%date:/=%.log"
robocopy %src% %dst% /COPYALL /E /NP /V /R:1 /W:1 /LOG+:%logfile%
rem robocopy %src% %dst% /COPYALL /MIR /NP /V /R:1 /W:1 /LOG+:%logfile%
警告
robocopyコマンドに、/MIR
オプションをつけて実行する際は注意してください。
/MIR
はディレクトリツリーをミラー化するオプションです。したがって、コピー元に存在しないディレクトリ及びファイルは、コピー先から削除されます。
万が一、コピー元やコピー先のパスを間違えていた場合、必要なデータが削除されてしまう可能性があります。
繰り返しますが、/MIR
オプションは非常に危険です。これからバックアップを取ろうという時に、誤ってデータを削除してしまっては絶望するしかありません。
そこで、初めてrobocopyを実行する時は/MIR
をつけずに、代わりに/E
をつけて実行するのが安全です。そうすることで、コピー元からコピー先へのコピーは行われますが、コピー先からデータが削除されることはありません。
上記のバッチファイル例では、/MIR
をつけたコマンドの行をrem
でコメントアウトしてあります。
1度目は/E
で実行し、コピー元とコピー先が間違っていないことを確認した後、2度目以降は/MIR
で実行すると良いでしょう。
その他のオプションの説明については、Microsoftのドキュメントをご参照ください。
以上