FreeNAS 11.2でJpsonicを使ってみた

# はじめに

[FreeNAS](https://freenas.org/)には[Subsonic](http://www.subsonic.org/)や[Madsonic](http://madsonic.org/)といったミュージックストリーミングサーバーのプラグインが公式で用意されています。しかし、どちらも海外製のため日本語に関する処理（ソート・分別など）はあまり強くありません。また、最新バージョンは一部機能が有償化されており、Subsonicに至ってはクローズドソース化されています。

そこで、Subsonicのオープンソース最終版からフォークした[Airsonic](https://airsonic.github.io/)に日本語まわりを強化した[Jpsonic](https://tesshu.com/jpsonic/what-is-jpsonic)を、FreeNAS Jailで動かしプラグインを自作してみます（Jpsonicのルーツの詳細は[Jpsonic Webサイト](https://tesshu.com/jpsonic/what-is-jpsonic#jpsonic-2)をご確認ください）。

# Jailの作成

FreeNAS 11.2 の新UIでJailを作成します。

- FreeNASへログインし、[Jails]を開き、```[ADD]```ボタンをクリックします。
- [Jail Name]には任意の名前を入力、[Release]は```11.2-RELEASE(fetched)```を選択し、```[NEXT]```をクリックします。
- Configure Network では各々の環境に合わせてIPアドレス等を設定し、```[NEXT]```をクリックします。
  - DHCPとDNSを連動している環境であれば、DHCPを選択するとJail名がそのままホスト名となり自動的にDNSへ登録されます。
- Confirm Options で作成するJailの設定を確認し、問題がなければ```[SUBMIT]```をクリックします。

# Mount pointの設定

すでにFreeNASのZFS PoolにMP3等の楽曲ファイルが置かれているディレクトリが用意されていることを前提に、作成したJailへディレクトリをマウントします。
配下のディレクトリ・ファイル構成は```./[アーティスト名]/[アルバム名]/[楽曲ファイル]```の構成にしておきます。

- Jail一覧より、ログインしたいJailの```[…]```ボタンをクリックし、```[Mount Point]```をクリックします。
- 右上の```[ACTIONS]```-```[Add Mount Point]```をクリックし、マウントしたいディレクトリを指定します。以下の例では、Pool内の share/media/music ディレクトリを、Jailコンテナ内の /mnt へマウントします。
- 例：
  - Source: ```/mnt/[ZFS Pool名]/share/media/music```
  - Destination: ```/mnt/[ZFS Pool名]/iocage/jails/[Jail名]/root/mnt```
- ディレクトリ内に消えては困るファイルがある場合は念のため```Read-Only```を有効にしましょう

# Jailの起動とコンソールへログイン
Jail一覧より、ログインしたいJailの```[…]```ボタンをクリックし、```[Start]```を選んで作成したJailを起動します。
起動完了後、```[Shell]```を開きコンソールへログインします。

これ以降の手順は、基本的にJpsonic作者が書かれた「[JpsonicをLinuxで動かそう](https://tesshu.com/jpsonic/how-to-run-jpsonic-on-linux)」の手順に準じて進めますが、一部FreeBSDの仕様に従い変えております。

# パッケージのインストール 

Jpsonicを起動させるのに必要なパッケージをインストールします。

なお、Windows環境のChromeでは、Shift + Ctrl + V でペーストすることができます。

```
pkg install openjdk8 ffmpeg bash wget
```

# ディレクトリ/ユーザーの作成

### jettyインストールディレクトリの作成

jettyのインストールディレクトリと、後に使用するサブディレクトリを作成します。

```bash
mkdir -p /usr/local/web/mybase /usr/local/jetty/run
```

### jettyユーザー手順

adduserコマンドでjettyユーザーを作成します。ポイントは以下のとおりです。

- シェル： /usr/local/bin/bash
- ホームディレクトリ： /usr/local/jetty/temp

```console
root@jpsonic:~ # adduser
Username: jetty
Full name: jetty
Uid (Leave empty for default):
Login group [jetty]:
Login group is jetty. Invite jetty into other groups? []:
Login class [default]:
Shell (sh csh tcsh bash rbash nologin) [sh]: /usr/local/bin/bash
Home directory [/home/jetty]: /usr/local/jetty/temp
Home directory permissions (Leave empty for default):
Use password-based authentication? [yes]:
Use an empty password? (yes/no) [no]:
Use a random password? (yes/no) [no]:
Enter password:
Enter password again:
Lock out the account after creation? [no]:
Username   : jetty
Password   : *****
Full Name  : jetty
Uid        : 1001
Class      :
Groups     : jetty
Home       : /usr/local/jetty/temp
Home Mode  :
Shell      : /usr/local/bin/bash
Locked     : no
OK? (yes/no): yes
adduser: INFO: Successfully added (jetty) to the user database.
Add another user? (yes/no): no
Goodbye!
```

### Jpsonic データディレクトリの作成

Jpsonicが使用するデータディレクトリを作成します。

```
mkdir -p /var/jpsonic/transcode
chown -R jetty:jetty /var/jpsonic
```

# Jettyのダウンロード

jettyのダウンロードと展開を行います。

```console
cd /usr/local/jetty
wget http://central.maven.org/maven2/org/eclipse/jetty/jetty-distribution/9.4.9.v20180320/jetty-distribution-9.4.9.v20180320.tar.gz
tar xzvf jetty-distribution-9.4.9.v20180320.tar.gz
rm jetty-distribution-9.4.9.v20180320.tar.gz
```

# jettyの初期設定

jettyのテンプレートファイルを生成し、ファイルを開きます。

```console
cd /usr/local/web/mybase/
java -jar /usr/local/jetty/jetty-distribution-9.4.9.v20180320/start.jar --add-to-start=deploy,http,jstl,console-capture
cp start.ini start.org

vi start.ini
```

必要に応じて以下の内容を変更しポート番号を設定します（デフォルトは8080）。

```
## Connector port to listen on
# jetty.http.port=8080
```

# jettyオーナー変更

各ファイルのオーナーを変更します。

```
chown -R jetty:wheel /usr/local/jetty
chown -R jetty:jetty /usr/local/web/mybase
```

# Jpsonicのインストール

[JpsonicのWebサイト](https://tesshu.com/jpsonic/what-is-jpsonic) へアクセスし、2.3.0 以上の jpsonic.war ファイルをダウンロードします。

（2.2.6にはバグが存在するため、jetty上で実行するにはFix版をソースからコンパイルする必要があります。）
https://github.com/tesshucom/jpsonic/issues/120

ダウンロード（またはコンパイル）したwarファイルをJailコンテナ上の /usr/local/web/mybase/webapps へ置きます。

# rcスクリプトの作成

/usr/local/etc/rc.d 配下にスクリプトファイルを作成します。

```bash:/usr/local/etc/rc.d/jpsonic
#!/usr/local/bin/bash

# jpsonic script
# insert `jpsonic_enable="YES"' in /etc/rc.conf

# PROVIDE: jpsonic
# REQUIRE: LOGIN
# KEYWORD: shutdown

. /etc/rc.subr

name="jpsonic"
rcvar="${name}_enable"

start_cmd="${name}_start"
stop_cmd="${name}_stop"

JETTY_HOME=/usr/local/jetty/jetty-distribution-9.4.9.v20180320
JETTY_BASE=/usr/local/web/mybase
JETTY_TEMP=/usr/local/jetty/temp
JETTY_JAR=/usr/local/jetty/jetty-distribution-9.4.9.v20180320/start.jar
JETTY_STATE=/usr/local/web/mybase/jetty.state
JETTY_STARTLOG="/usr/local/jetty/run/jetty-start.log"
JETTY_PID=/usr/local/jetty/run/jetty.pid

load_rc_config $name
: ${jpsonic_enable:="NO"}

jpsonic_start () {
    /usr/bin/logger Starting jpsonic...
    if [ ! -d ${JETTY_TEMP}/logs ]; then
        su -l jetty -c "mkdir ${JETTY_TEMP}/logs"
    fi
    cd ${JETTY_BASE}
    su -l jetty -c "/usr/local/bin/java -Xms128m -Xmx768m \
        -Djetty.home=${JETTY_HOME} \
        -Djetty.base=${JETTY_BASE} \
        -Djava.io.tmpdir=${JETTY_TEMP} \
        -jar ${JETTY_JAR} \
        jetty.state=${JETTY_STATE} \
        jetty-started.xml \
        start-log-file=${JETTY_STARTLOG} > /dev/null & disown $!"
    echo `pgrep -f jetty` > ${JETTY_PID}
}

jpsonic_stop () {
    /usr/bin/logger Stopping jpsonic...
    kill `cat ${JETTY_PID}`
}

run_rc_command "$1"
```

作成したスクリプトファイルに実行権を与えます。

```
chmod a+x /usr/local/etc/rc.d/jpsonic
```

# /etc/rc.conf の編集

Jail上の /etc/rc.conf を開き、以下の行を追加します。

```bash:/etc/rc.conf
（省略）
…
jpsonic_enable="YES"
```

# Jpsonicサービスの起動

Jail上で以下のコマンドを実行してJpsonicを起動してみます。

```
/usr/local/etc/rc.d/jpsonic start
```

起動には少々時間がかかります。topコマンド等でjavaプロセスのCPU使用率を確認させておき、落ちついたらWebブラウザよりアクセスしログイン画面が表示されたら成功です。

```
http://[JailのIPアドレス]:8080/jpsonic
```

最後に、Jailコンテナを再起動してJpsonicが問題なく自動起動されることを確認してください。