NextCloud on snap 外付けストレージ＋ビデオサムネイル

この記事は、[KLab Engineer Advent Calendar 2023](https://qiita.com/advent-calendar/2023/klab) の16日目の記事です。

# 概要

今年は自宅にフォト＆動画ストレージサーバを構築しました。
スマートフォンで撮影した写真や動画がスマートフォンのストレージを圧迫していたので
あえてストレージサービスを利用せず自宅にストレージサーバを用意しようと思いました。

おおよその構成はこのようになっていて
自宅の外からもアクセスができるようにしました。
ストレージの内容を同居家族以外も見ることを考慮しています。

![qiita.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311510/6e60cd65-b75b-3b89-94b1-78e6eaab8a96.png)

作った結果としてはクラウドに置いたほうがよさそうだと感じていますが
久しぶりに自宅にサーバを構築することによって勉強になったと感じています。

今回のポイントとしては下記の3つです
1. snapで構築する
2. 外付けストレージにデータを保存する
3. 動画のサムネイル生成を実現する

ざっとポイントを振り返ってから構築詳細を紹介します。

# snapで構築する
snapで構築すると依存関係や難しい設定をすべて飛ばして簡単にNextCloudサーバを構築することが可能です。
ただし、snapにはそれなりに制限があり、
- アクセスできる外部ストレージは `/mnt` または `/media` のみ
- snap管理外(つまりOS側にある)ファイルにアクセスできない

ということが自分のやりたいことにぶつかってしまいました。

# 外付けストレージにデータを保存する
NextCloudの構築後にストレージを変更するのが意図通りに動かなかったため
構築の最初から外部ストレージを組み込むことにしました
一番ハマったポイントはマウントでした。
テキトーにマウントしてもアクセスできるストレージとして認識されなかったので
ネットで複数記事を調べて動くマウントパラメーターを見つけました

# 動画のサムネイル生成を実現する
構築後、実際に写真と動画をスマホからアップロードしてみると動画のサムネイルが表示されませんでした。
色々調べてみてたどり着いたのですが `ffmpeg` がNextCloud on snapからアクセスできる場所がなくサムネイルの作成に失敗していたようでした。snapに `ffmpeg` をインストールするだけではダメで、NextCloud on snapのなかにバイナリを配置する必要がありました。

現在再確認したところ解決済みのようでした
https://github.com/alexbelgium/hassio-addons/issues/1099

# 構築詳細

## OSとsnapのインストール
今回はFedora 39を選択しました。Fedoraの理由は単に好みだからです。
Fedoraやsnap自体のインストールは記事が多数あると思うので今回は割愛します。

## ストレージの準備
まず最初にデータのストレージを準備します。
``` bash:bash
sudo mkdir /media/datadisk
sudo mkfs.ext4 -j -L DataDisk /dev/sdb
sudo blkid /dev/sdb
/dev/sdb: UUID="xxxxxxxxxxxxx" BLOCK_SIZE="4096" TYPE="ext4"
```


``` bash:/etc/fstab
/dev/disk/by-uuid/xxxxxxxxxxxxx /mnt/nextcloud auto nosuid,nodev,nofail,x-gvfs-show,x-gvfs-name=xxxxxx 0 0
```

``` bash:bash
sudo mount -a
sudo snap connect nextcloud:removable-media
```

続いてバックアップ用のストレージを準備します。
こちらのストレージはバックアップ時のみマウントするようにします。

```bash:bash
sudo mkdir /meida/usbdisk2
sudo mkfs.ext4 -j -L usbdisk2 /dev/sdc
sudo blkid /dev/sdc
/dev/sdc: UUID="xxxxxxxxxxxxx" BLOCK_SIZE="4096" TYPE="ext4"
```

```bash:/etc/auto.master
/media  /etc/auto.media
```

```bash:/etc/auto.media
usbdisk2        -fstype=ext4            :/dev/disk/by-uuid/xxxxxxxxxxxxx
```

```bash:bash
sudo systemctl start autofs.service
sudo systemctl enable autofs.service
```

バックアップのスクリプトを準備します。

```bash:nc_backup.sh
#!/bin/bash

DATA="/mnt/nextcloud/data"
DST="/media/usbdisk2/nextcloud"

# いったんNexCloudを停止
echo start at $(date)
snap stop nextcloud
echo nextcloud stopped $(date)

# データストレージからバックアップストレージにコピー
rsync -vAax /var/snap/nextcloud/current/nextcloud ${DST}/current
echo application backup is done $(date)

rsync -vAax ${DATA} ${DST}/common
echo data backup is done $(date)

# NexCloudを起動してメンテナンスモードにする
snap start nextcloud
echo nextcloud restarted $(date)
/var/lib/snapd/snap/bin/nextcloud.occ maintenance:mode --on

# mysqlのバックアップが済んだらメンテナンスモード解除
/var/lib/snapd/snap/bin/nextcloud.mysqldump > ${DST}/nc_mysqldump.bak
echo database backup is done $(date)
/var/lib/snapd/snap/bin/nextcloud.occ maintenance:mode --off

echo end at $(date)

# TODO cloud sync
```


## NexCloudの初期構築
ネットワーク周りの設定をして、スケルトン、アカウント設定をします。
```bash:bash
sudo nextcloud.occ config:system:set trusted_domains 0 --value=XXX.XXX.XXX.XXX
sudo nextcloud.occ config:system:set trusted_domains 1 --value=[独自ドメイン]
sudo mkdir -p /var/snap/nextcloud/common/skeleton
sudo nextcloud.occ config:system:set skeletondirectory --value=/var/snap/nextcloud/common/skeleton
sudo nextcloud.manual-install admin password
```

```php:/var/snap/nextcloud/current/nextcloud/config/config.php
  'datadirectory' => '/mnt/nextcloud/data',
```

## 動画サムネイル作成対応

```bash:bash
curl -OL https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-amd64-static.tar.xz
xz -d ffmpeg-release-amd64-static.tar.xz
tar -xf ffmpeg-release-amd64-static.tar
mkdir /var/snap/nextcloud/bin/
mv fmpeg-6.0-amd64-static/ffmpeg /var/snap/nextcloud/bin/
mv fmpeg-6.0-amd64-static/ffprobe /var/snap/nextcloud/bin/
```

```php:/var/snap/nextcloud/current/nextcloud/config/config.php
  'preview_ffmpeg_path' => '/var/snap/nextcloud/bin/ffmpeg',
  'memories.ffmpeg_path' => '/var/lib/snapd/snap/bin/ffmpeg',
  'memories.ffprobe_path' => '/var/lib/snapd/snap/bin/ffprobe',
  'enabledPreviewProviders' =>
  array (
    0 => 'OC\\Preview\\Image',
    1 => 'OC\\Preview\\Movie',
    2 => 'OC\\Preview\\MKV',
    3 => 'OC\\Preview\\MP4',
    4 => 'OC\\Preview\\AVI',
  ),
```

```bash:bash
snap reload nextcloud
nextcloud.occ preview:generate-all
```

## cronの設定
```cron
0 3 * * * /root/nc_backup.sh > /root/nc_backup.log 2>&1
10 * * * * /var/lib/snapd/snap/bin/nextcloud.occ preview:pre-generate > /root/preview.log 2>&1
```

# 今後の展望
今後はHDDの故障に備えてバックアップ用のHDDからさらにクラウドのストレージにバックアップすることを考えています。
バックアップ対象を写真と動画のみにすればAmazonのS3やGoogle Cloud Storageの最も安いストレージに保存することも可能なのかなと考えています。本当はそこまでやって記事化したかったのですが今回はタイムアップになってしまいました。

# 感想
snapでNextCloudを構築するのはびっくりするほど簡単でした。
TLSの証明書を取得するのもコマンド一発でできるなど実際にやってみると時代が変わった感があります。
どちらかというと自分の要求にあったサービスを何を組み合わせて構築するかを考える時代になったんだなと感じました。

# 参考記事など
- [Moving Nextcloud Data to external USB drive](https://help.nextcloud.com/t/moving-nextcloud-data-to-external-usb-drive/157830/2)
- [Video Thumbnails Failing to Generate on NextCloud Snap #1327](https://github.com/nextcloud-snap/nextcloud-snap/issues/1327#issuecomment-1671789532)
- [Nextcloudサーバのデータ自動バックアップ設定 snap版 ](https://denor.jp/nextcloud%E3%82%B5%E3%83%BC%E3%83%90%E3%81%AE%E3%83%87%E3%83%BC%E3%82%BF%E8%87%AA%E5%8B%95%E3%83%90%E3%83%83%E3%82%AF%E3%82%A2%E3%83%83%E3%83%97%E8%A8%AD%E5%AE%9A-snap%E7%89%88)
- [Ubuntu 20.04にNextcloudをインストールして設定する方法](https://www.digitalocean.com/community/tutorials/how-to-install-and-configure-nextcloud-on-ubuntu-20-04-ja)