systemdで/var/run配下にUNIX Socket用のディレクトリを切ったら落とし穴にハマった件と対処法

## 動作確認環境

- CentOS7のサーバ

**※Ubuntu20.04も同じ実装なので同じくハマるかと思います**

## 落とし穴にハマった流れ

### やりたいこと

- `hoge`というアプリケーションのAPIサーバを建てたい
    - フロントは `nginx`でリクエストを受けてアプリケーションに渡す
    - `hoge`は `systemd`でデーモン化する
    - `hoge`は `nginx`からのリクエストを `UNIX Socket`で受け取る
        - `UNIX Socket`は `/var/run/hoge/hoge.sock`とする

### やったこと

- `/var/run/hoge`ディレクトリを作成する
    - パーミッションは `hoge:hoge`とする
- `hoge`と `nginx`の各種設定ファイルを配置してデーモンを起動する
    - この時点で動いたことは確認できた
- サーバを再起動する
- 再びAPIを叩くと `nginx`が  `Bad Gateway`のエラーを返した
    - 調べてみると`/var/run/hoge/hoge.sock`がディレクトリごと無くなっていた

### 原因

- CentOS7では `/var/run`配下が `tmpfs`になっており、サーバを再起動すると `/var/run`配下のファイルが消えてしまう

```bash
# /var/run は /run へのシンボリックリンク
$ ls -ld /var/run
lrwxrwxrwx. 1 root root 6 Jul 25  2019 /var/run -> ../run

# /run は tmpfs をマウントしている
$ mount | grep /run
tmpfs on /run type tmpfs (rw,nosuid,nodev,mode=755)
```

## 対処法

### systemdのUnitファイルに `RuntimeDirectory`の設定を追加する

`tmpfiles.d`の[MANページ](https://www.freedesktop.org/software/systemd/man/tmpfiles.d.html#Description)によると

```plaintext:原文
System daemons frequently require private runtime directories below /run to store communication sockets and similar.
For these, it is better to use RuntimeDirectory= in their unit files (see systemd.exec(5) for details), if the flexibility provided by tmpfiles.d is not required.
The advantages are that the configuration required by the unit is centralized in one place, and that the lifetime of the directory is tied to the lifetime of the service itself.
Similarly, StateDirectory=, CacheDirectory=, LogsDirectory=, and ConfigurationDirectory= should be used to create directories under /var/lib/, /var/cache/, /var/log/, and /etc/.
tmpfiles.d should be used for files whose lifetime is independent of any service or requires more complicated configuration.
```

```plaintext:日本語訳
システムデーモンは、通信ソケットなどを格納するために、/runの下にプライベートランタイムディレクトリを必要とすることがよくあります。
これらについては、tmpfiles.dによって提供される柔軟性が必要ない場合は、ユニットファイルでRuntimeDirectory =を使用することをお勧めします（詳細については、systemd.exec（5）を参照）。
利点は、ユニットに必要な構成が1か所に集中化されていること、およびディレクトリの存続期間がサービス自体の存続期間に関連付けられていることです。
同様に、/var/lib/、/var/cache/、/var/log/、および/etc/の下にディレクトリを作成するには、StateDirectory=、CacheDirectory=、LogsDirectory=、およびConfigurationDirectory=を使用する必要があります。
tmpfiles.dは、存続期間がサービスに依存しないか、より複雑な構成が必要なファイルに使用する必要があります。
```

とあるので、`RuntimeDirectory`の設定を追加します。

また、今回はパーミッションを `0755`としたいので以下の様に `RuntimeDirectoryMode`も設定します。

```plaintext:UNITファイルに追加した行
RuntimeDirectory=hoge
RuntimeDirectoryMode=0755
```

※ `systemd.exec`の[MANページ](https://www.freedesktop.org/software/systemd/man/systemd.exec.html#RuntimeDirectory=)によると `/run`が起点となるため、フルパスではなく `/run`配下に作りたいディレクトリ名を指定します

## 参考リンク

- man - tmpfiles.d
    - [https://www.freedesktop.org/software/systemd/man/tmpfiles.d.html](https://www.freedesktop.org/software/systemd/man/tmpfiles.d.html)
- man - systemd.exec(5)
    - [https://www.freedesktop.org/software/systemd/man/systemd.exec.html](https://www.freedesktop.org/software/systemd/man/systemd.exec.html#)
- Handling /var/run with systemd
    - [https://blog.hqcodeshop.fi/archives/93-Handling-varrun-with-systemd.html](https://blog.hqcodeshop.fi/archives/93-Handling-varrun-with-systemd.html)