自宅サーバーを構築するにあたっての備忘録

## 0.目的
 Google Cloud Platform(GCP),Microsoft AzureなどのVMでも良いのだが,やはり手元の実機環境がある方がやりやすいので構築するときの手順を備忘録として記録する。実機は Intel Xeon E5 2690 v3,ECC DDR4 8GB x 8の自作PCを使う。Xeonは発熱しないし、消費電力が思った以上に少ないので扱いやすい。またIntel CPUなので信頼性も抜群である。~~AMDのCPUは申し訳ないが信頼がない。グラフィックボードがmacOSに使えるくらいしか恩恵を感じてない。そもそもWindowsとLinuxにAMD Radeonが相性悪すぎる。~~
# 1.リモートで作業できるようにSSHのセットアップ
最近の新しいバージョンのUbuntuにはデフォルトでOpenSSHサーバーがインストールされているようなので,そのまま /etc/ssh/ディレクトリ内にあるsshd_configを編集する。このファイルでrootユーザーでのログインの許可・拒否,パスワードログインの無効化,LISTENポートの変更が出来る。

※インストールされていない場合aptコマンドを用いてインストールを行う。
```shell-session:bash or zsh
user@localhost: ~% sudo apt install openssh-server ssh -y
```
```shell:/etc/ssh/sshd_config
~~~~~~~~~~~~~~~~~
#Port 22
Port //お好きなポート番号(1-65535)
#PubkeyAuthentication yes
#AuthorizedKeysFile      .ssh/authorized_keys .ssh/authorized_keys2
・・・
#PasswordAuthentication yes
・・・
Subsystem       sftp    /usr/lib/openssh/sftp-server
~~~~~~~~~~~~~~~~~
```
:::note info
1.公開鍵認証の有効化
公開鍵を用いて接続するので＃タグを消して公開鍵認証を有効化。また,認証済みのキーの読み取りをするためにAuthorizedKeysFileの＃タグを消して有効化

2.パスワード認証の無効化
デフォルトではパスワード認証が有効になっているので＃タグを解除し,
yesをnoに書き換えてパスワード認証を無効化する

3.サブシステムの有無
sftpを使わないのであれば無効にすることもできる。Subsystemの部分に＃タグをつけるとよいだろう。
:::

:::note warn
systemctlでsshサービスを再起動しないと適用されないので,再起動をし忘れない用に注意する。以下は再起動するための一例である。
```shell-session:bash or zsh
user@localhost: ~% sudo systemctl restart ssh
```
:::
①次に公開鍵の設定を行っていく。RSA暗号方式でもよいし,楕円曲線暗号方式でも好きなものを用いるとよいだろう。今回は楕円曲線暗号の一つである**ed25519**を使うことにする。


1.``-f``オプションで生成する公開鍵のファイル名の指定ができる。
2.``-t``オプションで暗号化方式を指定することができる。指定しない場合はデフォルトのRSAが用いられる。
3.パスフレーズの入力が求められるので,パスワードを付けたければ付けれる。不要な場合は何も入力せずにReturnキーを二回連打すればよい。
```
user@localhost:~% ssh-keygen  -f {分かりやすいファイル名にする}  -t ed25519
Enter passphrase (empty for no passphrase): [Type a passphrase]
# Enter same passphrase again: [Type passphrase again]
```

4.生成が完了したら念のために,秘密鍵をchmodコマンドを使って権限を設定し直すとよいだろう。.pub拡張子のファイル(公開鍵)をsshサーバーの方に転送する。サーバーに登録するときにscp,ftpなど好きな方法で転送するとよい。
```shell-session:bash or zsh
user@localhost: ~% chmod  600 {秘密鍵のファイル名}
```
数字３桁は上の桁から順にユーザー・グループ・その他の権限設定である。読み取り権限は４，書き込み権限は２，実行権限は１であり,必要に応じてこれらの数字の足し算をして組み合わせる。600の場合はユーザーのみが読み書きができる状態である。数字でやるのが面倒な場合は別の方法でも可能である。

:::note warn
通常環境ではrootユーザーだとパスフレーズ無しの秘密鍵の中身を閲覧できてしまう。これが秘密鍵にパスワードを設定するべき理由の一つである。
:::

<※補足　別の方法>
読み取り権限(read),書き込み権限(write),実行権限(execute)のr・w・xを用いて、
```shell-session:bash or zsh
user@localhost: ~% chmod u=+rw {権限の設定したいファイル or ディレクトリ}
```
:::note
+で権限の付与, -で権限の剥奪ができる
:::

:::note
ユーザー:u= グループ:g= その他:o=
u=とするとユーザーのみの権限を設定できる。ug=だとユーザー・グループのようになる。
:::

:::note warn
あくまで一例であるので,manページで詳細を確認すると良いだろう。
:::
②公開鍵をサーバーに登録
``~/.ssh``ディレクトリ内に公開鍵の内容を貼り付ける。
``~/.ssh/authorized_keys``に公開鍵に書き込まれた情報を書き込む。``sed``コマンドなどを使って書き込んでも良いだろう。面倒な時は``cp``コマンドや``mv``コマンドで公開鍵のファイル名を``authorized_keys``にリネームすれば良いだろう。``scp``コマンドで転送するのも一つの手だ。
```shell-session:bash or zsh   (mvコマンド,cpコマンドを使う場合)
user@localhost: ~% mv -v {公開鍵のファイル名} ~/.ssh/authorized_keys
                                or
user@localhost: ~% cp -v {公開鍵のファイル名} ~/.ssh/authorized_keys
```
```shell-session:bash or zsh (scpコマンドを用いる場合)
user@localhost: ~% scp {公開鍵のファイル名} {USER}@{HOSTNAME}:/home/USER/.ssh/authorized_keys
```
③実際に接続できるかテスト
``-i``オプションを使って秘密鍵を指定してもよいし,クライアント側の.sshディレクトリ内に秘密鍵を置いて接続をしてもよい。ポート番号を22から変更している場合は``-p``オプションを用いて変更したポート番号を指定する必要がある。変更していなくても``-p 22``と指定してもよい。**以下はポート番号を20022にした例である。**
```shell-session: bash or zsh
user@localhost: ~% ssh {USER}@{HOSTNAME} -i {秘密鍵のファイル名} -p 20022
```
:::note warn
``ssh-keygen``コマンドで鍵を生成した際に,パスフレーズを入力した場合はこのコマンドを実行した後にパスフレーズの入力を求められるので,パスワードを忘れない様に注意する。
:::

:::note info
``-L``,``-R``,``-g``オプションなどを利用してポートフォワーディングを行うこともできる。ここでは説明を割愛する。
:::

# 2.Nginxを用いたWebサーバー,プロキシサーバー
:::note info
Q. Nginxとはどのようなソフトウェアなのか？
A. Webサーバーにもプロキシサーバーにもなる便利なWebアプリケーションソフトウェア。
:::
Ubuntuの公式リポジトリのNginxのバージョンは1.18.0と古いので,``git``コマンドでソースコードを取得し,ビルドするか,Nginx公式リポジトリの登録のいずれかを行う。

<手順1>Nginxのインストール
<details><summary>gitコマンドでソースコードを取得しビルドする場合</summary>

 
① ビルドツールとgitをインストールする。
```shell-session: bash or zsh
user@localhost: ~% sudo apt install git build-essential cmake -y
```
②ソースコードをクローンする。
```shell-session: bash or zsh
user@localhost: ~/nginx % git clone https://github.com/nginx/nginx.git
```
③必要なオプションを選択してビルドを行う。
 色々なオプションがあるので,好きなオプションを有効にするとよい。
```shell-session: bash or zsh
user@localhost: ~% cd nginx
user@localhost: ~/nginx % ./auto/configure  --prefix=/usr/share/nginx/prefix \
--sbin-path=/usr/sbin --modules-path=/usr/share/nginx/modules \
--conf-path=/etc/nginx/nginx.conf --error-log-path=/etc/nginx/error/error.log \
--pid-path=/var/run/nginx.pid --with-select_module --with-poll_module \ 
--with-threads --with-file-aio --with-http_ssl_module --with-http_v2_module \
--with-http_v3_module --with-http_realip_module --with-http_addition_module \
--with-http_xslt_module --with-http_xslt_module=dynamic --with-http_image_filter_module \
--with-http_image_filter_module=dynamic --with-http_sub_module --with-http_dav_module \
--with-http_flv_module --with-http_mp4_module --with-http_gunzip_module \
--with-http_gzip_static_module --with-http_auth_request_module \
--with-http_random_index_module --with-http_secure_link_module \
--with-http_degradation_module --with-http_slice_module --with-http_stub_status_module \
--http-log-path=/etc/nginx/logs/http.logs --with-mail --with-mail=dynamic \
--with-mail_ssl_module --with-stream --with-stream=dynamic --with-stream_ssl_module \
--with-stream_realip_module --with-stream_ssl_preread_module --with-cpp_test_module \
--with-compat --with-debug
```
:::note warn
こんな大量のオプションを付ける必要は無いが,筆者は付けておく。Ubuntu公式リポジトリやNginx公式リポジトリからNginxをインストールしたものがどのようなオプションが使われているか確認したい場合は以下のコマンドで確認できる。
```shell-session:bash or zsh
user@localhost: ~% nginx -V
```
:::
④ビルドして,インストールを行う。
``make``コマンドでMakeFileを作り,インストールを行う。
```shell-session:bash or zsh
user@localhost: ~/nginx % make
user@localhost: ~/nginx % sudo make install
```
</details>

<details><summary>Nginx公式リポジトリを登録する場合</summary>
①リポジトリ登録するために必要なパッケージのインストール

```shell-session:bash or zsh
user@localhost: ~% sudo apt install curl gnupg2 ca-certificates lsb-release ubuntu-keyring
```
②Nginxの署名鍵を取得して確認
```:bash or zsh
user@localhost: ~% curl https://nginx.org/keys/nginx_signing.key | gpg --dearmor \
    | sudo tee /usr/share/keyrings/nginx-archive-keyring.gpg >/dev/null
```
:::note
以下のコマンドでgpgキーの整合性を確認する。
```:bash or zsh
user@localhost: ~% gpg --dry-run --quiet --import --import-options import-show /usr/share/keyrings/nginx-archive-keyring.gpg
```
:::
*573BFD6B3D8FBC641079A6ABABF5BD827BD9BF62*という風に表示されればOK。
③リポジトリの追加と登録
リポジトリの登録ができたら``sudo apt update``を実行してキャッシュを更新する。
```:bash or zsh
user@localhost: ~% echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] \
http://nginx.org/packages/ubuntu `lsb_release -cs` nginx" \
    | sudo tee /etc/apt/sources.list.d/nginx.list
user@localhost: ~% sudo apt update
```
④パッケージのインストール
Nginxをインストールする。これでNginx公式リポジトリが参照されるようになるので,最新版のNginxがインストールされる。
```shell-session:bash or zsh
user@localhost: ~% sudo apt install nginx
```
:::note
必要な機能が入っているかを``nginx -V``を実行して確認すると良いだろう。
:::
</details>

<手順2>サーバーの起動(SSLやリバースプロキシ含む。)
①プロキシサーバーを動かすためにStreamディレクティブを``nginx.conf``に書き込む。
また,事前にStreamモジュールを読み込んでおく。
```shell:/etc/nginx/nginx.conf
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
pid        /var/run/nginx.pid;
load_module /usr/share/nginx/modules/ngx_stream_module.so;

events {
    worker_connections  1024;
}
stream {
include /etc/nginx/conf.d/*.stream;
}

http {
    include       mime.types;
    default_type  application/octet-stream;

    server_tokens off;
   
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
```
:::note
リバースプロキシの設定ファイルは拡張子を``.stream``にしておくと分かりやすい。
:::
:::note warn
ファイルの整合性を確認するために必ず以下のコマンドを実行して問題が無いかチェックする。
```shell:bash or zsh
user@localhost: ~% sudo nginx -t
```
:::
:::note alert
Streamディレクティブはhttpディレクティブより必ず前に書く必要があるので注意。
また,モジュールをロードする時は,eventディレクティブより前に入れないとエラーが出るので注意する。
:::
②SSLの設定とホスト名の解決
Cloudflareで事前に証明書を作っているのでそれを利用する。また,ホスト名の解決をするために``/etc/hosts``にドメイン名を書き込む。以下は一例であるので,参考程度に。
```shell:/etc/hosts  (ホスト名の解決)
127.0.0.1       localhost
127.0.1.1      {HOSTNAME}

127.0.0.1      {CNAME・Aレコードの設定に用いたドメイン名}

# The following lines are desirable for IPv6 capable hosts
::1     ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
```
```shell:/etc/nginx/nginx.conf (SSLの設定)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
server {
        listen       443 ssl;
        server_name  {DNSレコードの設定したドメイン名};

        charset utf-8;

        ssl_certificate      {証明書のパス}.pem;
        ssl_certificate_key  {証明書の秘密鍵のパス}.pem;

        ssl_session_cache    shared:SSL:1m;
        ssl_session_timeout  5m;

        ssl_ciphers  HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers  on;

        location / {
            root   html;
            index  index.html index.htm;
        }
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
```
:::note warn
ファイルの整合性を確認するために必ず以下のコマンドを実行して問題が無いかチェックする。
```shell:bash or zsh
user@localhost: ~% sudo nginx -t
```
:::
③リバースプロキシの設定
筆者は,友人からの依頼でマインクラフトサーバーを運営しているのだがセキュリティ対策としてプロキシサーバーを探していた所,Nginxがリバースプロキシサーバーとしても使えることを思い出して設定をした。以下は一例である。参考程度に。
```shell: /etc/nginx/conf.d/minecraft.stream (リバースプロキシなのでStreamディレクティブが適用される)
proxy_protocol on;
upstream minecraft {
#server {サーバーのipアドレス}:{PORT};
 server localhost:1201;
}
server {
        #listen {PORT};
         listen 25565;
        proxy_pass minecraft;
}
```
:::note
Serverディレクティブ内でLISTENするポートは1024-65535のウェルノウンポートではない番号を用いると良いだろう。
:::
:::note warn
ファイルの整合性を確認するために必ず以下のコマンドを実行して問題が無いかチェックする。
```shell:bash or zsh
user@localhost: ~% sudo nginx -t
```
:::
④ファイアウォールでポート開放の設定
デフォルトでインストールされている``ufw``を使って行う。デフォルトでは無効になっているので有効にし,ポート開放を行う。
```shell:bash or zsh (UFWの有効化)
user@localhost: ~% sudo ufw enable
user@localhost: ~% sudo ufw status verbose
```
:::note info
本当にシステム起動時に有効になっているか確認したい場合は``systemctl status ufw``を実行すればよい。Activeと表示されていれば問題は無い。
```shell:bash or zsh
user@localhost: ~% systemctl status ufw
```
:::
```shell:bash or zsh (ポート開放)
user@localhost: ~% sudo ufw allow from 0.0.0.0 to any port 443 proto tcp
user@localhost: ~% sudo ufw allow from 0.0.0.0 to any port 80 proto tcp
user@localhost: ~% sudo ufw allow from 0.0.0.0 to any port 25565 proto tcp
```
:::note warn
<補足>ipアドレス 0.0.0.0について
0.0.0.0というアドレスはすべてのipアドレス(グローバルとローカル両方)を指す。ローカル向けのみにポート開放したければ 192.168.1.0/24などとすると 192.168.1.1-192.168.1.255までのアドレスからのみ通信を許可することができる。
:::

ポート開放できているかを以下のコマンドで確認する。
```shell:bash or zsh (ポート開放の確認)
user@localhost: ~% sudo ufw status verbose
```
:::note warn
デフォルトではIPv6のポート開放も自動でされるので,それを無効にしたい場合は``/etc/default/ufw``ファイル内の``IPV6=YES``の記述があるのでNOに書き換えればよい。書き換え終わったら必ずファイアウォールをリロードまたは再起動する。
```shell:/etc/default/ufw
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Set to yes to apply rules to support IPv6 (no means only IPv6 on loopback
# accepted). You will need to 'disable' and then 'enable' the firewall for
# the changes to take affect.
#IPV6=YES
IPV6=no
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
```
```shell:bash or zsh (UFWの再起動)
user@localhost: ~% sudo ufw reload
                        or
user@localhost: ~% sudo systemctl restart ufw
```
:::
⑤自動起動の設定
``Systemd``に登録して終わり。ソースコードからビルドした場合は``nginx.service``が無いので自分で作る必要がある。ここでは割愛する。
```shell:bash or zsh (自動起動の有効化)
user@localhost ~% sudo systemctl enable --now nginx.service
```

# 3.マインクラフトサーバーの構築
①必要なパッケージのインストール
Javaだけでなくネットワーク系のコマンドもインストールをする。``bash``を使うとワイルドガードでパッケージ名を指定できるので便利である。``zsh``も出来たら良かったんだけどなぁ。
```shell:bash or zsh
user@localhost: ~% sudo apt update && sudo apt install openjdk-*-jdk openjdk-*-jre net-tools iperf3 curl gdebi php git ruby gpart gparted manpages-ja manpages-ja-dev zsh zsh-autosuggestions
```
②サーバーを実行するための環境を用意
サーバーやバージョンごとにディレクトリを分別しておく。サーバーの実行は割愛する。

③プロキシサーバーの設定
BungeeCord, VanillaCordとか色々あるけどMohist MCを使っているので必然的にLightfallを使う必要性が出てくる。Lightfallの``config.yml``でip forwardの設定を有効に必ずする。また,``spigot.yml``のbungeecordをfalseからtrueに書き換える。``server.properties``のprevent-proxy-connectionsをfalseからtrueにする。

# 最後に
雑な備忘録だが,筆者は割と記憶力が良いのでこの程度で大丈夫だろう。何か疑問や質問があれば,可能な範囲で答えます。正直初心者なので,こうしたほうがいいよみたいなアドバイスなどをくれるとうれしいです。また、参考になったらうれしいです。