Owntoneでファイルサーバーから音楽を配信する（ユーザーごとに）


## はじめに

### 経緯

これまでファイルサーバーから音楽を共有するのに[Jellyfin](https://jellyfin.org/)というwebアプリケーションを使っていた。スマホから簡単に操作、検索ができて非常に便利だったのだが、一つ、大きな不満があった。それはプレイリストが独自仕様でインポートやエクスポートができないということ。かつてLinuxを使い始めた頃に、それまで使っていたiTunesからメディア（特にプレイリスト）を移行するのに手間取った（というか途中で断念した）苦い経験があったので、できれば（テキストファイルベースの[`m3u`](https://ja.wikipedia.org/wiki/M3U)のような）汎用の規格でプレイリストを管理したかった。

それでもJellyfinは本当に便利だったのでなかなか踏ん切りがつかず使い続けていたのだが、最近になってファイルサーバの中身を整理し始めたついでに、改めて別のメディア配信サーバー、[OwnTone](https://owntone.github.io/owntone-server/)に移行してみることにした。

### OwnToneについて

もともとはforked-daapという名前で、この名の通りdaapという規格で音楽を共有できる。このdaapというのは、もともとiTunesの端末間での音楽共有で使われているものなので、それなりに普及しているらしく対応しているクライアントアプリも多い。また、`daap`の他にも`mpd`というプロトコルも使え、こちらも音楽共有用に昔から使われているプロトコルでクライアントも複数ある。

プレイリストは`.m3u`ファイルで管理する。今回（`jellyfin`ではなく）これを選んだ決め手がこれ。

## 今回の目的

- OwnToneを用いてNASから音楽を共有する
- OwnToneはユーザーごとに別のインスタンスで動かす[^multiuser]

## バージョン情報

```
$ uname -a
Linux fox 4.19.206-1-MANJARO #1 SMP Fri Sep 3 10:14:30 UTC 2021 x86_64 GNU/Linux
$ owntone --version
owntone 28.2
```

## インストール

本来なら[公式の手順](https://github.com/owntone/owntone-server/blob/master/INSTALL.md)に従ってやったほうが資料として残すならいいのだろうが、今回は[こちらのaur](https://aur.archlinux.org/packages/owntone-server/)でかんたんに済ませた。

```
$ cd aur
$ git clone https://aur.archlinux.org/owntone-server.git 
$ cd owntone-server
# 足りないパッケージのインストール
# 今回の自分の環境ではこれだけだったが、これ以外に必要なパッケージについては公式を参照のこと
$ sudo pacman -S mxml libantlr3c libwebsockets
$ makepkg -i
```

## 設定

諸事情によりユーザーごとにライブラリを分けたかったのだが、`daap`はもともと`iTunes`の規格だったこともあって複数ユーザーには対応していない。そのため、ユーザーごとに管理するためには別々のサービスとして起動する必要がある。

全体の設定としては以下のようにすることで、ユーザーごとにサービスを実行できるようにする。

- 再生するユーザーは共通で`owntone`
- 音楽ファイルは`/srv/owntone`ディレクトリの下にユーザーごとに置く
    - 具体的には`/srv/owntone/user`に`/home/user/Music`をバインドマウントし、グループオーナーを`owntone`にすることで、`owntone`ユーザーがアクセスできるようにする
- 設定ファイルやデータベースもユーザー別に作成する
- サービスは`systemd.service`のインスタンス機能を使い、ユーザー別に起動できるようにする
    - 具体的には `systemctl start owntone@user` でユーザーごとに起動できるようにする


### 各種ユーザー別ファイルの作成

以下のようにデフォルトの設定やデータベースのファイルをユーザーごとにコピーして用意する。

元のパス|コピー後のパス
:--|:--|
`/etc/owntone.conf`|`/etc/owntone/user1.conf`
`/var/cache/owntone/songs3.db`|`/var/cache/owntone/user1/songs3.db`
`/etc/cache/owntone/cache.db`|`/etc/cache/owntone/user1/cache.db`

適宜ディレクトリの作成やオーナーの変更も行う。


### 設定ファイルの修正

ユーザー別に作成した設定ファイルを開き、ユーザーごとに分ける必要がある箇所（データベースやポート番号など）を書き換える。


```config:/etc/owntone/user1
# ユーザー共通で使い回せる箇所は省略
general {
    # 中略
    db_path = "/var/cache/owntone/user1/songs3.db"
    db_backup_path = "/var/cache/owntone/user1/songs3.bak"
    logfile = "/var/log/owntone/user1.log"
    websocket_port = 3689
    cache_path = "/var/cache/owntone/user1/cache.db"
    #中略
}
library {
    # 中略
    port = 3688
    directories = { "/srv/owntone/user1" }
    # 中略
}
mpd {
    # 中略
    port = 6600
    # 中略
}
```

### `Music`ディレクトリの設定

共有したいメディアは`/home/user1/Music`のようにホームディレクトリ配下にあるのだが、このままだと`owntone`ユーザーからアクセスできない[^user]
ということで、まずは`/home/user1/Music`に`owntone`がアクセスできるよう、グループオーナーを`owntone`に修正する

```
$ chown -R :owntone /home/user1/Music
```

これで`owntone`ユーザーは`/home/user1/Music`の閲覧権限を得たが、その手前である`/home/user1`の権限がないためここで足止めされこれだけだとまだアクセスできない。
ホームディレクトリ自体のオーナーは変えたくないため、ホームディレクトリの外、`/srv/owntone/`経由でアクセスできるよう設定する。

以下のようにユーザーごとに`.mount`ファイルを作成し、`systemd-mountd`を使ってマウントさせる[^mount]

```config:/etc/systemd/system/srv-owntone-user1.mount
[Unit]
Description=Mount music library for owntone

[Install]
WantedBy=multi-user.target

[Mount]
What=/home/user1/Music
Where=/srv/owntone/user1
Type=none
Options=bind
```

```
$ sudo systemctl enable --now srv-owntone-user1.mount
```

### 起動

この段階で動くはずなので試してみる。

```
$ sudo /usr/bin/owntone -f -c /etc/owntone/user1.conf  
```

ブラウザで管理画面にアクセスしたり、daapクライアントで音楽を再生するなど、機能していることが確認できたら`Ctrl+c`で止めて`systemctl`で管理できるよう設定する

### Systemdの設定

デフォルトの`owntone.service`と[このsystemdインスタンスに関する記事](https://qiita.com/yasushi-jp/items/8ab68ede23b893cfdc40)を参考に、ユーザー別に起動できるよう修正する。


```config:/etc/systemd/system/owntone@.service
[Unit]

# 以下の3行はデフォルトのまま
Description=DAAP/DACP (iTunes), RSP and MPD server, supports AirPlay and Remote
Documentation=man:owntone(8)
Requires=network.target local-fs.target avahi-daemon.socket

# `/srv/owntone/`配下のマウント前に起動しないよう上で作った.mountを追記
After=network.target sound.target remote-fs.target pulseaudio.service srv-owntone-%I.mount

[Service]
# ユーザーごとのコンフィグを読むよう修正
ExecStart=/usr/bin/owntone -f -c /etc/owntone/%I.conf

[Install]
# デフォルトのまま
WantedBy=multi-user.target
```

これでユーザーごとに`systemctl`で管理できるようになった

```
$ systemctl enable owntone@user1.service
$ systemctl start owntone@user1.service
```

## 今後の課題

なぜかウェブインターフェースにアクセスできない。テストで起動した際にはアクセスできていたのだが...。
とはいえdaapサーバーとしては問題なく使えるので対応は保留にする。


[^multiuser]: 理由は一部の音楽以外の~~センシティブな~~音声ファイルを音楽と隔離したかったため。実際に複数のユーザーで使う予定はない。

[^user]: 仮に`owntone`サービスのユーザーが`user1`であればそのまま読めるのでこの工程はいらない。

[^mount]: 今更だが、`.mount`ファイルもインスタンス機能を使って一つにまとめられたりするのだろうか？