SSD Nodes Learn 🎉 VPS $5.50/月〜
ガイド Matt Connor著者 Matt Connor

VPSでNavidromeを運用して音楽をストリーミングする方法

VPSでNavidromeを動かし、手持ちの音楽をスマートフォンで再生する方法です。容量の見積もり、Subsonic対応アプリ、オフライン同期、TLS、安全なバックアップを解説します。

VPS で自己ホストする音楽ストリーミングの利点

VPS で自己ホストする音楽ストリーミングでは、プレーヤーを自分で運用し、音楽も自分で用意します。サーバーにはすでに所有しているファイルを保存し、通常のログインで、どのスマートフォンからでもインターネット経由でアクセスできます。始める前に、この構成のトレードオフを明確にしておく必要があります。これはストリーミングサービスのプレーヤーを置き換えるものであり、カタログを置き換えるものではありません。購入またはリッピングして、そのファイルをサーバーにコピーしない限り、ライブラリに新しい音楽は追加されません。

音声は動画よりもサーバーへの負荷がはるかに小さくなります。ファイルは小さく、スマートフォンは一般的な形式であれば追加の処理なしでデコードでき、1 人のリスナーが使用する帯域幅もビデオ通話より少なくて済みます。ここでは CPU が問題になることはほとんどありません。実際の制約はディスク容量です。これが機能するかどうかを左右するもう 2 つの要素は、タグの品質と、スマートフォンのアプリが音楽をダウンロードしてオフラインで再生できるかどうかです。

Navidrome は、音声コンテンツだけを扱う場合の標準的な選択肢です。1 つのコンテナ内で 1 つの Go バイナリとして動作し、状態を 1 つの SQLite データベースに保持します。Subsonic API に対応しているため、多数のサードパーティ製スマートフォンアプリを利用できます。2026 年 8 月時点の現行バージョンは 0.63.2 です。プロジェクトでは Raspberry Pi Zero のように小規模なハードウェアでも十分に動作すると説明されているため、費用の中心はサーバーソフトウェアではありません。

Jellyfin は、動画用に VPS 上でメディアサーバーとして Jellyfin を運用している場合に適しています。音楽ライブラリは利用でき、Finamp は Android と iOS に対応した Jellyfin 用の音楽アプリで、オフライン再生用にトラックをダウンロードできます。制限になるのは API です。Jellyfin には組み込みの Subsonic エンドポイントがなく、追加していたコミュニティプラグインも 2022 年に更新が停止しました。そのため、Subsonic アプリのエコシステムは Jellyfin では利用できません。代わりに Jellyfin 独自の API に対応したアプリを使いますが、その数は少なくなります。

Funkwhale は連合型の選択肢で、バージョン 2.0 は 2026 年 3 月にリリースされました。Funkwhale のサーバーは pod と呼ばれ、pod 同士は ActivityPub(Mastodon の基盤となるプロトコル)で連合します。ある pod のユーザーが、別の pod にある公開ライブラリをフォローすることもできます。Funkwhale は Subsonic API の一部にも対応しています。ただし、知っておくべき違いがあります。Subsonic プロトコルでは、サーバーが読み出せるパスワードが必要になるため、各ユーザーが自分の設定で Subsonic 用のパスワードを個別に設定します。Funkwhale は、Web アプリケーションに加えて PostgreSQL とタスクキューも必要になるため、インストール構成が重くなります。

連合機能が必要な場合、または Jellyfin がすでに稼働している場合を除き、Navidrome を選択してください。このガイドの残りでは、Docker を使って Navidrome を構築します。

Subsonic API が使用するスマートフォンアプリを決める仕組み

Subsonic は音楽サーバーであり、その HTTP API はセルフホスト型オーディオで共通して使われる通信仕様になりました。OpenSubsonic は、それを拡張し続けているコミュニティプロジェクトです。この経緯があるため、スマートフォンでは複数のアプリを選べます。Navidrome は独自のモバイルアプリを提供しておらず、提供する必要もありません。Subsonic クライアントは、サーバーアドレスとアカウント情報でログインできるためです。

これは、設定が日常の利用に耐えるかどうかを左右するオフライン同期で特に重要です。トンネル内のスマートフォンはサーバーに接続できません。そのため、クライアントは事前にファイルをローカルストレージへコピーしておく必要があります。すべてのクライアントはストリーミングに対応しています。ダウンロードに対応しているものは一部だけです。クライアント一覧の navidrome.org/apps では、対応状況を確認できます。Android と iOS のどちらにも選択肢があり、Android では Substreamer と Ultrasonic、iOS では Amperfy と play:Sub を利用できます。高機能なクライアントの多くは有料アプリです。Android では Symfonium が最もよく名前の挙がるアプリです。利用するアプリを決める前に2つインストールしてください。ここが、システムの中で毎日触れる部分だからです。

音楽ライブラリにはどのくらいのストレージが必要ですか?

ChartStorage per 1,000 albums by audio format
The data behind this chart
[
  {
    "label": "Opus 128k",
    "kbps": 128,
    "gb_per_1000_albums": 43
  },
  {
    "label": "MP3 320k",
    "kbps": 320,
    "gb_per_1000_albums": 108
  },
  {
    "label": "FLAC 16/44.1",
    "kbps": 900,
    "gb_per_1000_albums": 304
  },
  {
    "label": "FLAC 24/96",
    "kbps": "3,000",
    "gb_per_1000_albums": "1,013"
  }
]

これらは実際のコレクションを測定した値ではなく、ビットレートから算出した桁数の目安です。計算は簡単なので、自分のファイルと照合できます。アルバムを45分、つまり2,700秒とします。キロビット毎秒単位のビットレートに2,700を掛け、8,000で割るとメガバイトになります。320 kbpsの場合、1枚のアルバムは108 MBです。したがって、1,000枚のアルバムでは約108 GBになります。

ロスレスでは結果が変わります。CD品質のFLACは、一般的な音源で平均約900 kbpsです。そのため、同じ1,000枚のアルバムには約304 GBが必要です。24 bit、96 kHzのライブラリでは、およそ1,013 GBになります。紙に一覧を書ける程度のコレクションでも、1 TBに達します。スマートフォン向けの128 kbpsのOpusコピーなら、同じ1,000枚を43 GBに収められます。すでに所有しているライブラリでdu -sh /path/to/musicを実行してください。プランを選ぶときに重要なのは、自分の平均ビットレートだけです。

帯域幅は料金のうち、比較的小さい部分です。320 kbpsのストリームは毎秒40キロバイトなので、1時間の再生で約144 MBのデータを転送します。1か月に100時間再生しても約14 GBであり、VPSの転送量上限が問題になることはありません。例外は、スマートフォンで最初にオフライン同期を行う場合です。このときは、1晩で数十GBを転送することがあります。

ストレージ層とコンピュート層のどちらを選ぶか

音楽サーバーは、大量のコールドデータを保管し、その上で実行する処理がほとんどない構成です。40 キロバイト/秒でファイルを読み取るだけなら、どのディスクもアイドル状態のままです。CPU が動作するのは、ライブラリのスキャン中かトランスコード中だけです。しかも、トランスコードは通常ほとんど実行しません。そのため、コンピュートプランの高速な NVMe に料金を払っても、この用途ではメリットがありません。むしろ、1 GB あたりの価格が高いため、FLAC のコピーをアップロードすることをためらう原因になります。このような場合は、通常の VPS よりストレージ VPS が適しています。ストレージプランはコア数ではなく、テラバイト単位で料金が設定されているためです。

必要なメモリ容量は多くありません。Navidrome で個人用ライブラリを配信する場合、必要なメモリは数百メガバイトです。再生中ではなく、スキャン中に使用量が最大になります。サーバーには 1 GB または 2 GB の RAM を割り当て、残りの予算をディスクに充ててください。

Docker Compose で Navidrome をインストールする

まず、コンテナが実行されるユーザー ID の所有にして、ディレクトリを作成します。Compose を初めて使う場合は、VPS 上の Docker Compose で、このファイルが前提とする内容を説明しています。

sudo install -d -m 755 -o 1000 -g 1000 /srv/navidrome /srv/music

docker-compose.yml 以外はほとんど何も書かず、専用のディレクトリに配置します。

services:
  navidrome:
    image: deluan/navidrome:0.63.2
    user: "1000:1000"
    ports:
      - "127.0.0.1:4533:4533"
    restart: unless-stopped
    environment:
      ND_LOGLEVEL: "info"
      ND_SESSIONTIMEOUT: "24h"
      ND_SCANNER_SCHEDULE: "@every 24h"
      ND_BACKUP_PATH: "/data/backup"
      ND_BACKUP_SCHEDULE: "0 4 * * *"
      ND_BACKUP_COUNT: "7"
    volumes:
      - /srv/navidrome:/data
      - /srv/music:/music:ro
docker compose up -d
docker compose ps

docker compose ps で、サービスの状態が restarting ではなく running になっていることを確認します。コンテナが再起動を繰り返す場合、そのほとんどは /srv/navidrome の権限に関する問題です。docker compose logs navidrome には、書き込みに失敗したファイル名が表示されます。

このファイルでは、4 つの点を説明しておく必要があります。ポートは 127.0.0.1 のみに公開しています。そのため、サーバーにはリバースプロキシ経由でアクセスでき、インターネットに対して 4533 番ポートを直接公開しません。Docker は独自のファイアウォールルールを書き込むため、ufw がすべて拒否と報告するサーバーでも、単純な 4533:4533 ではポートが公開されたままになります。音楽のボリュームは読み取り専用です。そのため、スキャナーのバグによって唯一のコピーが削除されることを防げます。ND_SCANNER_SCHEDULE はデフォルトで無効になっています。Navidrome 0.55 より前に書かれたガイドでは、これを ND_SCANSCHEDULE と呼んでいますが、その名前は現在は存在しません。最後の 3 つのバックアップ設定により、下記のバックアップセクションで使用する組み込みデータベースバックアップを有効にします。

サーバーに音楽を配置する

rsync でライブラリをコピーします。接続が切断されても最初からやり直さずに再開できます。

rsync -av --info=progress2 ~/Music/ user@music.example.com:/srv/music/

コピー元の末尾にあるスラッシュは重要です。付けない場合は /srv/music/Music になります。コピーが完了したら、所有者を変更します。

sudo chown -R 1000:1000 /srv/music
id -u

コンテナは user id 1000 で実行され、マウントは読み取り専用です。そのため、すべてのファイルをその id で読み取れるようにする必要があります。VPS 上の SSH アカウントが uid 1000 でない場合、コピーしたファイルは別のユーザーの所有になり、スキャンでトラックが 0 件になる一方、Web インターフェースは何も表示しません。id -u で実際の id を確認できます。Docker コンテナで PUID と PGID が機能する仕組みでは、このマッピングについて詳しく説明しています。

スマートフォンでどこからでも利用できるリバースプロキシと TLS

VPS に DNS の A レコードを向け、Caddy に次の 3 行を設定します。

music.example.com {
    reverse_proxy 127.0.0.1:4533
}
sudo systemctl reload caddy

Caddy は最初のリクエスト時に証明書を取得します。ACME(自動証明書管理環境)のチャレンジにはポート 80 で応答するため、ポート 80 と 443 の両方を開放する必要があります。nginx では、location ブロックに proxy_buffering off; を追加します。Navidrome は 1 本の長時間接続を通じて Web インターフェイスに進捗イベントを送信します。バッファリングが有効だと、nginx が応答を保持し続けるため、インターフェイスは応答を待ち続けます。独自のサブドメインではなく /music のようなパスで公開する場合は、ND_BASEURL に同じパスを設定してください。設定しないと、インターフェイスが空白ページとして読み込まれます。3 つの一般的なプロキシの比較については、VPS 上の Nginx、Caddy、Traefik を参照してください。

サイトを開き、最初のアカウントを作成します。デフォルトパスワードはありません。最初の訪問者に管理者ユーザーの作成を求められるため、アドレスを他の人に知らせる前に作成してください。次に、スマートフォンのクライアントが使用する正確なパスをテストします。

SALT=$(openssl rand -hex 6)
TOKEN=$(printf '%s%s' 'YOUR_PASSWORD' "$SALT" | md5sum | cut -d' ' -f1)
curl -s "https://music.example.com/rest/ping.view?u=YOUR_USER&t=$TOKEN&s=$SALT&v=1.16.1&c=curl&f=json"

正常な応答は {"subsonic-response":{"status":"ok" で始まり、サーバーの種類として navidrome を示します。本文に "status":"failed" が含まれ、エラーコードが 40 の場合、プロキシは正常で、認証情報が誤っています。この段階で証明書エラーが発生した場合は、最初に修正してください。多くのスマートフォン用クライアントは、不正な証明書をユーザーに意味のないメッセージで拒否するためです。

初回スキャン後にライブラリの表示がおかしくなる理由

Navidrome はフォルダーではなくタグを基準にブラウズするため、表示内容はタグで決まります。アルバムアーティストタグがないトラックは、トラックアーティストの下に分類されます。そのため、各トラックのアーティストが異なるコンピレーションは、1 トラックだけのアルバムが 20 個あるように表示されます。修正する場所は Navidrome ではなくファイルです。MusicBrainz Picard と beets はどちらも MusicBrainz データベースでアルバムを検索し、標準タグを書き戻します。

Navidrome は複数アーティストのタグも個別のアーティストに分割します。そのため、名前に区切り文字を含むバンドは誤って分割されます。代表例は AC/DC です。ND_SCANNER_ARTISTSPLITEXCEPTIONS には、決して分割してはならない名前を指定します。

新しいファイルは、配置されてから数秒後に file watcher によって検出されます。file watcher はカーネルの変更通知に依存しています。しかし、別のマシンからマウントした network share に書き込まれたファイルでは、その通知が届きません。この構成では、定期的な ND_SCANNER_SCHEDULE によってライブラリを最新の状態に保ちます。full rescan ではすべてのファイルのタグを読み取るため、大規模なライブラリでは時間がかかります。これも、後述するデータベースを保護する価値がある理由の 1 つです。

ユーザー、プレイリスト、共有

管理者が Web インターフェースで他のアカウントを作成します。ユーザー自身による登録機能はありません。ユーザーごとに再生回数、プレイリスト、お気に入り、評価が分離されるため、家庭内で1つの好みのプロファイルを共有することにはなりません。

プレイリストは2つの方法で追加されます。クライアントで作成したプレイリストはデータベースに保存されます。ライブラリフォルダーに配置した .m3u ファイルはスキャン時にインポートされます。デスクトッププレーヤーからプレイリストを移行する場合に便利です。スマートプレイリストは .nsp ファイルです。小さな JSON 形式のルールファイルで、同じ方法でインポートされます。ライブラリの変更に応じて自動的に更新されます。

共有は、2026年7月にリリースされたバージョン 0.63.0 からデフォルトで有効です。ユーザーは、ログインせずに誰でも開けるアルバムの公開リンクを作成できます。ライブラリ全体を保存しているサーバーでは、望ましくない場合があります。ND_ENABLESHARINGfalse に設定すると、共有を無効にできます。

音楽ファイルとは別にデータベースをバックアップする

Navidrome 自体のバックアップ対象はデータベースだけです。ドキュメントにも明記されているとおり、バックアップ処理で保存されるのはデータベース、つまりユーザー、再生回数などであり、音楽ファイルや設定は対象外です。この分離は適切な考え方です。2 つは障害時の復旧方法が異なるためです。音楽ファイルは、リッピング元のディスクから再度コピーできます。再生回数、評価、お気に入り、プレイリストは他の場所に存在せず、再スキャンしても復元されません。

compose ファイルは毎晩 /data/backup にコピーを作成し、7 世代を保持します。アップグレード前には、手動で 1 つ作成してください。

sudo docker compose run --rm navidrome backup create

復元すると現在のデータベースが削除され、バックアップがその場所にコピーされます。復元処理は Navidrome を停止した状態で実行する必要があります。稼働中のサーバーで復元を安全に実行することはできません。

これらのファイルは同じ VPS 上にあるため、VPS の障害時には失われます。/srv/navidrome を別のマシンまたはオブジェクトストレージへ定期的に転送してください。これは restic と BorgBackup が想定している用途です。ディレクトリ全体のサイズは小さく、通常は 1 GB を大きく下回ります。そのため、毎日暗号化したコピーをサーバー外へ保存してもコストはほとんどかからず、再スキャンでは復元できないすべてのデータを取り戻せます。

FAQ

VPS で音楽をトランスコードする必要はありますか?

ほとんどの場合、必要ありません。スマートフォンやブラウザーは MP3、AAC、Opus、FLAC を自らデコードできるため、サーバーはファイルをそのまま送信し、CPU もほとんど使用しません。設定する価値があるのは、モバイルデータ通信で FLAC ライブラリをストリーミングする場合です。この場合、約 900 kbps から 128 kbps の Opus に変換すると、使用するデータ量を約 7 分の 1 に削減できます。Navidrome ではユーザーごと、プレーヤーごとに設定でき、有効にするまで無効のままです。

スマートフォンのアプリで音楽をオフライン再生用にダウンロードできないのはなぜですか?

オフライン保存はサーバーの機能ではなく、クライアントの機能だからです。Subsonic API では、どのクライアントでもファイル全体を取得できますが、スマートフォンにコピーを保持するかどうかはアプリが決定します。navidrome.org/apps のクライアント一覧を確認し、説明にオフラインダウンロードまたはキャッシュへの対応が記載されているものを選んでください。一部のクライアントは、再生済みの音楽だけをキャッシュします。これは、出発前にアルバムを同期することとは異なります。

スキャン後に 1 枚のアルバムが複数のアルバムに分かれたのはなぜですか?

アルバムアーティストタグがないか、トラック間で統一されていません。Navidrome はフォルダーではなくタグを基準にグループ化するため、12 トラックに 12 種類のアーティスト値があり、共通のアルバムアーティスト値がない場合、12 枚のアルバムとして認識されます。アルバムの全トラックにアルバムアーティストタグを設定してください。コンピレーションの場合は通常 Various Artists にします。その後、再スキャンします。MusicBrainz Picard または beets を使えば、フォルダー全体に対して一括で設定できます。

セルフホストの音楽ストリーミングで Spotify を置き換えられますか?

置き換えられるのはプレーヤーとライブラリであり、カタログではありません。すべてのデバイスで自分のコレクションを利用でき、ライセンス変更によって失われることのないプレイリストや再生回数も保持できます。一方、新しいリリースや、他の人の再生履歴を基にしたおすすめは利用できません。この環境を運用する人の多くは音楽を購入し、音楽を探すために低価格のストリーミングアカウントも維持しています。

#navidrome#music#streaming#self-hosting#media-server