/var/log/laughingman7743.log

I thought what I'd do was, I'd pretend I was one of those deaf-mutes or should I?

Navidromeとs3fsでサーバ立てた

AWSでCentOS7で立てていたSubsonicサーバを、Debian12でNavidromeと mountpoint-s3 s3fsに置き換えたときの作業ログです。

EC2インスタンスには特定のS3バケットにアクセスできる以下のような権限のロールをつけます。セキュリティグループは80、443、SSHポートを開けておきます。(SSHは自分のIPだけを許可しておくと良いでしょう)

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": [
                "s3:*"
            ],
            "Resource": [
                "arn:aws:s3:::your-s3-bucket*"
            ],
            "Effect": "Allow"
        }
    ]
}

Navidrome用のユーザを作ります。mountpoint-s3もこのユーザで動かします。(mountpoint-s3確認のためログインできるユーザを作成していますが、ログインできないユーザでもおそらく問題ないです)

$ sudo useradd -m navidrome -s /bin/bash -d /var/lib/navidrome

Navidromeをドキュメントの通りにインストールします。エディタはemacsを使います。

https://www.navidrome.org/docs/installation/linux/

$ sudo apt update
$ sudo apt upgrade
$ sudo apt install emacs ffmpeg

$ sudo install -d -o navidrome -g navidrome /opt/navidrome
$ sudo install -d -o navidrome -g navidrome /var/lib/navidrome

$ wget https://github.com/navidrome/navidrome/releases/download/v0.49.3/navidrome_0.49.3_Linux_arm64.tar.gz
$ sudo tar -xvzf navidrome_0.49.3_Linux_arm64.tar.gz -C /opt/navidrome/
$ sudo chown -R navidrome:navidrome /opt/navidrome

音楽ファイル、データファイル用のディレクトリと設定ファイルを作ります。ここで作ったディレクトリに mountpoint-s3でS3バケットをマウントします。

$ sudo mkdir /var/lib/navidrome/{music,data}
$ sudo touch /var/lib/navidrome/navidrome.toml
$ sudo chown -R navidrome:navidrome /var/lib/navidrome

navidrome.tomlはドキュメントを確認して必要な項目を設定します。

https://www.navidrome.org/docs/usage/configuration-options/

MusicFolder = "/var/lib/navidrome/music"
DataFolder = "/var/lib/navidrome/data"
LogLevel = "info"
Address = "0.0.0.0"
ScanSchedule = "0 5 * * *"

systemdのユニットファイルを作成します。

[Unit]
Description=Navidrome Music Server and Streamer compatible with Subsonic/Airsonic
After=remote-fs.target network.target
AssertPathExists=/var/lib/navidrome

[Install]
WantedBy=multi-user.target

[Service]
User=navidrome
Group=navidrome
Type=simple
ExecStart=/opt/navidrome/navidrome --configfile "/var/lib/navidrome/navidrome.toml"
WorkingDirectory=/var/lib/navidrome
TimeoutStopSec=20
KillMode=process
Restart=on-failure

# See https://www.freedesktop.org/software/systemd/man/systemd.exec.html
DevicePolicy=closed
NoNewPrivileges=yes
PrivateTmp=yes
PrivateUsers=yes
ProtectControlGroups=yes
ProtectKernelModules=yes
ProtectKernelTunables=yes
RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
RestrictNamespaces=yes
RestrictRealtime=yes
SystemCallFilter=~@clock @debug @module @mount @obsolete @reboot @setuid @swap
ReadWritePaths=/var/lib/navidrome

# You can uncomment the following line if you're not using the jukebox This
# will prevent navidrome from accessing any real (physical) devices
#PrivateDevices=yes

# You can change the following line to `strict` instead of `full` if you don't
# want navidrome to be able to write anything on your filesystem outside of
# /var/lib/navidrome.
ProtectSystem=full

# You can uncomment the following line if you don't have any media in /home/*.
# This will prevent navidrome from ever reading/writing anything there.
#ProtectHome=true

# You can customize some Navidrome config options by setting environment variables here. Ex:
#Environment=ND_BASEURL="/navidrome"

/etc/systemd/system/に放り込んで有効にします。

$ sudo systemctl daemon-reload
$ sudo systemctl start navidrome.service
$ sudo systemctl status navidrome.service
$ sudo systemctl enable navidrome.service

SSHで4533をポートフォワーディングして、NavidromeのAdminユーザを作成します。

mountpoint-s3はドキュメントの通りにインストールすれば簡単に動かせます。

https://github.com/awslabs/mountpoint-s3/blob/main/doc/INSTALL.md

$ wget https://s3.amazonaws.com/mountpoint-s3-release/1.0.1/arm64/mount-s3-1.0.1-arm64.deb
$ sudo apt-get install ./mount-s3-1.0.1-arm64.deb

適当にディレクトリを作ってマウントしてみます。

$ mkdir mount
$ mount-s3 your-s3-bucket ./mount
$ ls ./mount

普通に ls コマンドでS3のファイルが一覧表示されます。マウントできることが確認できたので、アンマウントします。

$ umount ./mount

起動時に自動的にマウントしたいので、systemdに登録します。systemdのユニットファイルはこのイシューのものを利用しました。

[Unit]
Description=Mountpoint for Amazon S3 mount
Wants=network.target
AssertPathIsDirectory=/var/lib/navidrome/music

[Service]
Type=forking
User=navidrome
Group=navidrome
ExecStart=/usr/bin/mount-s3 your-s3-bucket /var/lib/navidrome/music
ExecStop=/usr/bin/fusermount -u /var/lib/navidrome/music

[Install]
WantedBy=default.target

/etc/systemd/syste/に放り込んで有効にします。

$ sudo systemctl daemon-reload
$ sudo systemctl start mountpoint-s3.service
$ sudo systemctl status mountpoint-s3.service
$ sudo systemctl enable mountpoint-s3.service

マウントしたディレクトリはNavidromeユーザ以外からは見れないようです。

$ ls -al /var/lib/navidrome
drwxr-xr-x  3 navidrome navidrome 4096 Sep 17 15:38 data
d?????????  ? ?         ?            ?            ? music
-rw-r--r--  1 navidrome navidrome  159 Sep 17 14:44 navidrome.toml
$ sudo ls -al /var/lib/navidrome
drwxr-xr-x  3 navidrome navidrome 4096 Sep 17 15:38 data
d?????????  ? ?         ?            ?            ? music
-rw-r--r--  1 navidrome navidrome  159 Sep 17 14:44 navidrome.toml
$ sudo -u navidrome ls -al /var/lib/navidrome
drwxr-xr-x  3 navidrome navidrome 4096 Sep 17 15:38 data
drwxr-xr-x  2 navidrome navidrome    0 Sep 17 16:26 music
-rw-r--r--  1 navidrome navidrome  159 Sep 17 14:44 navidrome.toml

いくつか音楽ファイルをS3にアップロードしてNavidromeでスキャンすると、問題なくスキャンでき再生もできました。 が、SubsonicサーバのEBSで管理していたすべての音楽ファイル(1.1T 90098ファイル)をS3にアップロードし、Nvidromeでスキャンを実行してみるとマウントしたディレクトリのファイルが全て読み込まれない。。。

$ sudo du -sh /var/lib/navidrome/music/
1.1T    /var/lib/navidrome/music/
$ sudo find /var/lib/navidrome/music/ -type f -not -name cover.jpg | wc -l
90098

WARNINGメッセージがいくつか出ていましたが、原因は分からず。。。GitHubにイシュー登録できるようなログは出ていなかったです。 仕方がないので、s3fsをインストールします。

https://github.com/s3fs-fuse/s3fs-fuse

$ sudo apt install s3fs
$ echo "s3fs#your-s3-bucket /var/lib/navidrome/music fuse uid=****,gid=****,iam_role=auto,endpoint=your-region,allow_other,mp_umask=022,use_cache=/tmp,nonempty 0 0" | sudo tee -a /etc/fstab
$ sudo mount -a

s3fsでマウントしたディレクトリは、全てのファイルがNavidromeでスキャンできました。

外部に公開するためにnginxとLet's Encryptの設定をします。nginxはドキュメントの通りにインストールします。

http://nginx.org/en/linux_packages.html#Debian

$ sudo apt install curl gnupg2 ca-certificates lsb-release debian-archive-keyring
$ curl https://nginx.org/keys/nginx_signing.key | gpg --dearmor \
  | sudo tee /usr/share/keyrings/nginx-archive-keyring.gpg >/dev/null
$ gpg --dry-run --quiet --no-keyring --import --import-options import-show /usr/share/keyrings/nginx-archive-keyring.gpg
$ echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] \
  http://nginx.org/packages/debian `lsb_release -cs` nginx" \
  | sudo tee /etc/apt/sources.list.d/nginx.list
$ echo -e "Package: *\nPin: origin nginx.org\nPin: release o=nginx\nPin-Priority: 900\n" \
  | sudo tee /etc/apt/preferences.d/99nginx
$ sudo apt update
$ sudo apt install nginx

certbotをインストールして証明書を発行します。DNSで認証するのが楽です。Route53にtxtレコードを登録すれば証明書が発行されます。

$ sudo apt install certbot
$ certbot certonly --manual \
 --preferred-challenges dns-01 \
 -d foo.bar \
 -d *.foo.bar \
 -m foo@bar \
 --agree-tos

証明書は定期的に更新する必要があるので、systemdの設定をします。

$ sudo systemctl enable certbot.timer

以下のように/lib/systemd/system/certbot.serviceを少し変更して、証明書更新後にnginxをリロードするようにしています。

[Unit]
Description=Certbot
Documentation=file:///usr/share/doc/python-certbot-doc/html/index.html
Documentation=https://certbot.eff.org/docs
[Service]
Type=oneshot
ExecStart=/usr/bin/certbot -q renew --no-random-sleep-on-renew --post-hook "/usr/sbin/nginx -t && /usr/bin/systemctl reload nginx"
PrivateTmp=true

nginxで証明書の設定をして起動します。Navidromeへのproxy設定は以下のようにしています。

upstream navidrome {
    server 127.0.0.1:4533;
}

server {
    listen       80;
    server_name  foo.bar;
    rewrite ^ https://$server_name$request_uri? permanent;
}

server {
    listen       443 ssl http2;
    server_name  foo.bar;

    access_log  /var/log/nginx/foo.bar_access.log  ltsv;

    ssl_certificate /etc/letsencrypt/live/foo.bar/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/foo.bar/privkey.pem;

    location / {
        proxy_set_header       Host               $host;
        proxy_set_header       X-Real-IP          $remote_addr;
        proxy_set_header       X-Forwarded-Proto  https;
        proxy_set_header       X-Forwarded-Host   $host;
        proxy_set_header       X-Forwarded-Server $host;
        proxy_set_header       X-Forwarded-For    $proxy_add_x_forwarded_for;

        proxy_pass             http://navidrome;
        proxy_redirect         http:// https://;

        proxy_connect_timeout  30;
        proxy_send_timeout     60;
        proxy_read_timeout     60;
    }
}
$ sudo systemctl start nginx.service
$ sudo systemctl status nginx.service
$ sudo systemctl enable nginx.service

ファイアーウォールはデフォルトではインストールされていません。必要に応じてインストールして設定すると良いでしょう。

$ sudo apt install ufw
$ sudo ufw allow 22/tcp
$ sudo ufw allow 80/tcp
$ sudo ufw allow 443/tcp
$ sudo ufw allow 4533/tcp
$ sudo systemctl start ufw
$ sudo systemctl enable ufw
$ sudo ufw enable

あとはEIPを取得してインスタンスに関連付けし、Route53の設定をするだけです。

iPhoneからは以下のSubsonicクライアントで接続できました。

Subsonicサーバではsc1のEBSを1.5TB使っていたのですが、無限のストレージを手に入れることができました。mountpoint-s3は今後に期待したいと思います。

これでこれからもBandcampで音源を買いまくれますね。やったー