GoogleドライブとCRYPTOMATORを組み合わせて大容量暗号化ストレージの中にDockerでJellyfinとcloudflaredコンテナを立ててプライベートな音楽配信サービスを作る
システム開発部の前野です。いつもウェブネーションのコーポレートサイトへご訪問頂きありがとうございます。暖冬と言われて11月に入ってもなかなか気温が下がりませんでしたが、ようやく寒い冬が到来しました!
なんでそんなに嬉しそうかというと、寒いと山で焚き火をする気分になるから!ということで、週末は久々に山籠りをして鍋パーティでも開催したいと思います。
今日のお題はJellyfin!
少し前からredditというソーシャルサービスに加入して通勤時間によく見ているのですが、私が参加しているコミュニティのメインは「r/selfhosted」「r/opensource」の2つ。はい、完全に技術者向けのコミュニティです。
これらのコミュニティでは様々なオープンソースソフトウェアが議題になりますが、例えば写真管理のソフトウェアってどれがおすすめ?(Googleフォトが嫌ならImmichでも使っとけという定番コメント多数)とか、ドキュメント管理に何を使っている?(定番はPaperless-ngx)が多いのですが、ふと「個人契約しているGoogle Oneが無駄に容量空いているなんか使えないかな?」ということで、コミュニティで見つけた自分で配信サービスが作れるJellyfinを使って無駄データを突っ込んでみましたというのが今回のお題です。
動画は普段から「NetflixかAmazon Prime Video」でしか見ず、プライベート動画だと子供の動画がGoogle フォトにあるだけでプライベートな動画をストリーミングするようなニーズがないので、今回は音楽ストリーミング配信のみの紹介となります。
音楽も個人的には買った音楽や昔のCDとかはGoogle Play Musicを使っていた名残で「Youtube Musicにアップロードする派」なので、今回はGoogle Takeoutを使ってYoutube Musicから音楽を引き出してからGoogleドライブに放り込むことにします。
そもそもなんで暗号化?
「GoogleドライブとCRYPTOMATORを組み合わせて大容量暗号化ストレージの中にDockerでJellyfinとcloudflaredコンテナを立ててプライベートな音楽配信サービスを作る」と冒頭からいきなり情報過多の呪文を唱えていますが、まずは前半の暗号化ストレージについてです。
ストレージを暗号化すること自体は今回の記事で特段重要な部分ではないのですが、少し前にGoogleアカウントを誤BANされた記事(突然YouTubeやグーグルのアカウントBAN問題…不明確な基準の実態 – Business Journal)を見てから、なるべく自分の管理外ストレージは暗号化(ベンダーに鍵を管理させない)する癖が付いたせいもあり、特に見られて困るようなファイルはないものの、今回は普段使いしているCRYPTOMATORも合わせて紹介します。
CRYPTOMATORはGoogleドライブを始めとするクラウドストレージ等を暗号化するソフトウェアで、オープンソースで提供されています。仕組みとしてはソフトウェアを導入することで、暗号化されたフォルダが作成され、そのフォルダにファイルを放り込むことによって、透過的にファイルの暗号化を実現しています。
この組み合わせによりクラウドへのファイル保存と同時に自動で暗号化され、ベンダーを含め鍵を持たない第三者が中身を見ることは事実上不可能となりますので、今回はGoogleドライブを導入すると共に、暗号化ソフトウェアのCRYPTOMATORと合わせて導入することをおすすめします。
DockerでJellyfinを導入する
GoogleドライブとCRYPTOMATORの導入が終わったらいよいよ本番のJellyfinについてです。今回はお手軽にDockerからJellyfinを導入したいと思います。
version: '3.5'
services:
jellyfin:
image: jellyfin/jellyfin
container_name: jellyfin
user: uid:gid
network_mode: 'host'
volumes:
- /path/to/config:/config
- /path/to/cache:/cache
- /path/to/media:/media
- /path/to/media2:/media2:ro
restart: 'unless-stopped'
# Optional - alternative address used for autodiscovery
environment:
- JELLYFIN_PublishedServerUrl=http://example.com
# Optional - may be necessary for docker healthcheck to pass if running in host network mode
extra_hosts:
- "host.docker.internal:host-gateway"
本家ドキュメントでは上記のようにdocker-compose.ymlが用意されていますので、参考にしたいと思います。
version: '3.5'
services:
jellyfin:
image: jellyfin/jellyfin
container_name: jellyfin
volumes:
- /Volumes/cryptomator/jellyfin/config:/config
- /Volumes/cryptomator/jellyfin/cache:/cache
- /Volumes/cryptomator/jellyfin/media:/media
restart: 'unless-stopped'
# Optional - alternative address used for autodiscovery
environment:
- JELLYFIN_PublishedServerUrl=http://example.com
# Optional - may be necessary for docker healthcheck to pass if running in host network mode
extra_hosts:
- "host.docker.internal:host-gateway"
ports:
- 8096:8096
修正後は上記の赤色部分となりました。今回は最終的に外部へ公開するため、ネットワークモードはホストではなくブリッジにするため削除を、ボリュームは暗号化されたフォルダをコンテナにアタッチさせたいと思います。
docker-compose.ymlの変更後に行う内容としては以下の通りです。
1. Docker環境にアタッチされた暗号化ボリュームが/Volumes/cryptomator/というフォルダになりますので、その中にjellyfinという空のフォルダを作成します。
2. 次にdocker-compose -up dでDockerコンテナを立ち上げます。
3. 少し待ってからhttp://localhost:8096/にアクセスするとログイン画面(初回はアカウント設定)が表示されます。
4. 1で作成した空のフォルダはdocker-compose -up dの実行によって設定ファイル等が自動生成されます。
ログイン後はJellyfinから操作をすることになりますが、まだ音楽フォルダの中身が空のため何もすることができません。
上記docker-compose.ymlでvolumesを設定したことで、ホストで指定したフォルダに音楽を入れることで、コンテナからもアクセスができるようになっています。
1. まずはホストで/Volumes/cryptomator/jellyfin/media/musicというフォルダを作成します。
2. 次にホストで配信したい音楽を上記フォルダへ入れます。暗号化に時間がかかるので、気長に待ちます。
3. コンテナに共有したいファイルの保存が終わったらJellyfinにログインし、管理画面→設定→ダッシュボードの順に遷移します。
ダッシュボードでは音楽のメタデータをJellyfinへ取り込むように設定を行います。
まずは左メニューのライブラリより、メディアライブラリを追加を選択します。
ここでは音楽を追加しますのでミュージックを選びます。
次にどのフォルダを追加するかを選ぶため、フォルダの右にあるプラスアイコンから、上記画面を表示し、/mediaを選択→次に先ほどファイルを保存した/media/musicを選びます。
ローカルフォルダではないので、少し読み込みの際は待たされるかと思いますが、気長に待ちます。
最後に「すべてのライブラリをスキャン」を押下して待ちます。スキャンは音楽データのメタデータの取得等を裏で行い、最終的にライブラリに表示されて再生が可能となります。
これでJellyfinの設定は完了しました。スマホアプリ(iOS、Android)も公開されていますので、スマホからの再生も簡単です。
cloudflaredを使って外からでも再生できるようにする
この流れは以前の記事が参考になりますが、今回はDockerを使ってもっと簡単に実現したいと思います。
まずは以前の記事の2番(トークンの取得)までをダッシュボードから行います。
以前の記事から抜粋しましたが、ここで取得したトークンをDockerコンテナに入れてしまおうと思います。
version: '3.5'
services:
jellyfin:
image: jellyfin/jellyfin
container_name: jellyfin
volumes:
- /Volumes/cryptomator/jellyfin/config:/config
- /Volumes/cryptomator/jellyfin/cache:/cache
- /Volumes/cryptomator/jellyfin/media:/media
restart: 'unless-stopped'
# Optional - alternative address used for autodiscovery
environment:
- JELLYFIN_PublishedServerUrl=http://example.com
# Optional - may be necessary for docker healthcheck to pass if running in host network mode
extra_hosts:
- "host.docker.internal:host-gateway"
ports:
- 8096:8096
cloudflared:
image: cloudflare/cloudflared:latest
container_name: cloudflared
command: tunnel --no-autoupdate run --token {{cloudflareで取得したトークン}}
restart: unless-stopped
変更後のdocker-compose.ymlは上記となり、cloudflaredから下の合計5行が追加されました。
commandにトークンを追加することで、コンテナの起動と同時にcloudflareとのトンネルセッションがcloudflaredコンテナで開始され、docker-composeによりこの2コンテナしか通信できない専用のネットワークが構築されますので、コンテナが大量にある環境でも余計なことをしない省力設計です。
あとは以前の記事の3番をダッシュボードから行い完成です。これで出先からIDとパスワードでログインできるようになりました。
ここで設定するServiceはDockerコンテナ間の通信ですので、localhostではなくhttp://jellyfin:8096となる点に注意ください。
また以前の記事の4番をダッシュボードから行うと、限定されたメールアドレスでの2段階認証が付加され第三者からはどのようなサービスが公開されているのかが分かりにくくなり、よりセキュアな接続が可能となります。
JellyfinはDockerに限らず各種OSに対応していますので、自宅で使わなくなったPCにインストールし、2段階認証によってセキュアに公開することで自分だけのストリーミングサーバーを無料で実現できます!