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

はじめに

経緯

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

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

OwnToneについて

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

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

今回の目的

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

バージョン情報

$ 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

インストール

本来なら公式の手順に従ってやったほうが資料として残すならいいのだろうが、今回はこちらのaurでかんたんに済ませた。

$ 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

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

設定ファイルの修正

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

# ユーザー共通で使い回せる箇所は省略
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ユーザーからアクセスできない2 ということで、まずは/home/user1/Musicowntoneがアクセスできるよう、グループオーナーをowntoneに修正する

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

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

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

[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インスタンスに関する記事を参考に、ユーザー別に起動できるよう修正する。

[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サーバーとしては問題なく使えるので対応は保留にする。

1

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

2

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

3

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