MiniPCで自宅サーバーを構築する ~ 購入からLinuxインストール編 ~

# はじまり
最近、Rustでデータ分析アプリの開発だったりとプログラミングで遊んでいるとローカルPCに限界を感じてきました。
今僕が使っているメインPCは3年前くらいに買ったM1 Pro Macbook Pro なのですが、当時はそこまでデータ関連の開発をすることはなくてWebなどばかりだったので、RAM16GBにしてしまったのが良くなかったのです。
少し大きなデータを使おうとするとすぐにスワップが発生してしまったり、場合によってはOOMが発生する始末。。。
とはいえ、新しいMacbook Proを買おうとすればRAM36GBで40万をゆうに超えてしまう。![スクリーンショット 2024-08-03 13.06.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3570569/50e5719d-4b71-145c-710a-9c3718c93b3e.png)
流石にこんなお金は払えません。
そんなことを考えながら悶々としていると、Amazonであるものを見つけました。
![スクリーンショット 2024-08-03 13.15.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3570569/da491547-bf52-64bc-3f93-9d3f9abf31f3.png)
ミニPCでありながら、Ryzen 6900HXでRAM 64GBという脅威の性能。そして、それが86980円という値段だったのです。
ここで僕は考えました。同等のAWS EC2を開発環境に使ったらどれくらいになるのだろうと。
16C-64GBのインスタンスとしてm6a.4xlargeというサイズが存在します。aということでAMDなのでちょうど良いでしょう。
こちらは $0.8928/hという料金になっています。
1日6時間くらいは使うとして、0.8928 * 6 * 30 = 160.xxくらいでしょう。現在のレートで150円/$として24000円。
これが1年で288000円。
(こう見るとMacBook Proは絶望的に高いですね。円安のせいなのか、りんごの悪戯のせいなのか。。。)
そう考えると、1年でも保ってくれれば御の字であると言えそうだと考えて即座にポチッとしました。
(後になってS版じゃなくてPro版が3000円差だったので、UM690 Proを購入しました。)
![スクリーンショット 2024-08-03 13.36.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3570569/18fc581e-ac1e-accb-0c22-ee7a59102dba.png)


# サーバー(になる予定のPC)到着
Amazonで注文して15時間後、購入したMiniPCが到着しました。（今更ですが、Amazonの配送ってやっぱ尋常じゃなく早いですよね。）
![IMG_0177.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3570569/dc72f1ac-cfd9-7066-353e-5b7a068cb9a3.jpeg)
買ってしまってから「本当に64GBも積んでるのか？騙されてるんじゃ？」と不安になってきました。
とはいえ、MINISFORUMというメーカー、現在はTSUKUMOやヨドバシカメラ、ビックカメラでも扱っているくらいメジャーなメーカーなので多分大丈夫だと思っていますが。
ということでタスクマネージャを見てみました。改めて、手のひらサイズのミニPCで16coreってすごく違和感がありますね。
見えにくいですが、メモリは61.8GBということで嘘ではないようです。
![IMG_0181.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3570569/e1960445-5d1b-114d-6d5f-2c18f0228f85.jpeg)
サーバー化する際にWindowsは消してしまうので、先にcinebenchを回しておきましょう。
![IMG_0182.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3570569/5e728134-23b4-59af-266e-4ad75d372c21.jpeg)
さすが、ラップトップ版とはいえRyzen9です。Apple M1 Maxに近い性能(Armとx64なんで比較していいかは別ですが)を示しています。また、ミニPCで不安な排熱面も10分間のCINEBENCH 2024で84℃なら、GUIを使わないLinuxに換装すれば排熱に困ることもなさそうです。
今回はサーバー化するのが目的ですから、これ以上の詳しいベンチマーク結果などは専門の人たちに任せるとして、早速サーバー化を進めていきましょう。

# Linuxへの換装
サーバーとして使うには選択肢は  

 - Windows Server
 - Linux

に基本的にはなってきますが、Windows Serverはいかんせん、ライセンス費用がクソ高いです。
正直個人向けではまっっっっっっっっっったくないので、まぁ必然的にLinuxになりますね。
次にどのディストリビューションを使うかですが、

 - Rocky Linux
 - Ubuntu
 - Debian
 - OpenSUSE
 - Linux Mint
 - ...

といろいろありますが、個人的にRockyかUbuntuのどちらかな、というのが考えるまでもなく最初の段階での考えでした。(エンジニアっぽさを出すためにいろいろ出しましたが。)
Ubuntuは今年、LTSの2024をリリースしていますし、当然kernelバージョン的にも新しいです。
ただ、これまで人生で扱ってきたサーバーはRedHat系が大半だったこともあってRockyの方が躓かない気がします。
悩みましたが、Ubuntu24.04を使ってみたい想いもありますし、今時躓いてもネット情報でどうにでもなるので今回はUbuntu24.04 LTSを利用することに決めました。

## Ubuntu24.04のインストールメディアの作成
今回は [Ubuntu 24.04](https://jp.ubuntu.com/download)を使ってインストールメディアを作っていきます。
GUIは今回は不要なのでUbuntu Serverを選択してダウンロードしていきます。
もし、これを見ながらやっている方がいれば、Ubuntu ServerはGUIがなくとも2.6GBもありますのでゆっくりとココアでも飲みながら待ちましょう。僕はココア作ってきます。
... 数分後
![スクリーンショット 2024-08-03 14.27.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3570569/3a45c96b-c0ab-5e25-12ce-b02839fa727b.png)
ダウンロードが完了しましたね。では、これをUSBに入れてミニPCに...と簡単にはいかないんですね。
インストールメディアを作る必要があります。今回はMacで作成します。(Unix系だけあってほぼLinuxと変わりません。)
もしWindowsしか持ってないよ〜(涙)という場合は以下のような記事があるので、こちらを参照してください。

https://diagnose-fix.com/topic2-003/

さて、手順はLinuxに馴染みのある方ならご存知のddコマンドを使って書き込むのですが、その前にUSBをフォーマットしていきます。

### USBをフォーマット
Macをご利用の方はdiskutilというものを使っていきます。(Linuxの`fdisk`とか`unmount`とかのディスク関連のコマンドをまとめてくれてる感じかな？)

1. USB記憶装置の番号を確認する
    ```
    diskutil list
    ```
    を実行すると以下のように表示されます。
    ```
    ...
    /dev/disk5 (synthesized):
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:      APFS Container Scheme -                      +17.1 GB    disk5
                                 Physical Store disk4s1
   1:                APFS Volume iOS 17.0.1 21A342 Si... 16.6 GB    disk5s1

    /dev/disk6 (external, physical):
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:                            Rocky-9-3-x86_64       *7.9 GB     disk6
    ```
    Macではデバイスを`/dev/diskX`という形で管理しています。今回の目的のUSBは`/dev/disk6`です。
    (このUSBは過去にゲームサーバーを構築した際にRocky9のインストールメディアにしたものですね。)
2. USBメモリをフォーマットする
    ```
    diskutil eraseDisk MS-DOS UNTITLE /dev/disk6
    ```
    を実行します。これは、diskutilのeraseDiskというフォーマットツールを使って、MS-DOSフォーマットに初期化します。
    MS-DOSはいわゆるFAT32と呼ばれる形式です。現代では別のものでも良いのかもしれませんが、FAT32が一番安心なイメージがあるんですよね。
    UNTITLEは別に別の名前でもいいですよ。お好きに。
    実行すると以下のように表示されます。
    ```
    /disk6
    Started erase on disk6 (Rocky-9-3-x86_64)
    Unmounting disk
    Creating the partition map
    Waiting for partitions to activate
    Formatting disk6s2 as MS-DOS (FAT) with name UNTITLE
    512 bytes per physical sector
    /dev/rdisk6s2: 14958016 sectors in 1869752 FAT32 clusters (4096 bytes/cluster)
    bps=512 spc=8 res=32 nft=2 mid=0xf8 spt=32 hds=255 hid=411648 drv=0x80 bsec=14987264 bspf=14608 rdcl=2 infs=1 bkbs=6
    Mounting disk
    Finished erase on disk6
    ```
    完了するとFinderでもUNTITLEと表示されます。
    ![スクリーンショット 2024-08-03 14.49.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3570569/91f93ba0-ab88-7644-f5ea-7f235ea0f21a.png)
3. USBをアンマウントする
    基本的にddコマンドで書き込む場合にはデータの一貫性、安全性の観点から排他的書き込みにする方が良いです。
    さらにそもそもbusyとして書き込めないこともあるので書き込みする前にアンマウントしましょう。
    ```
    diskutil unmountDisk /dev/disk6
    ```
    `Unmount of all volumes on disk6 was successful`と表示されればOKです。
4. isoファイルからデータをUSBに書き込む
    いよいよ、書き込んでいきます。とは言ってもddコマンドを使って簡単にデータを書き込めてしまいます。
    以下のコマンドを実行します。このisoファイルのパスは各自で合わせてください。
    ```
    sudo dd if=./Downloads/ubuntu-24.04-live-server-amd64.iso of=/dev/disk6 bs=1m
    ```
    bsはブロックサイズです。1MBにしていますが、別に指定しなくても多分大丈夫です。ただ、ddコマンドはbsが小さい方がスループットが良いことも多いのでこうしています。
    この作業には時間がかかることがあるので気長に待ちましょう。先ほどダウンロード時間で飲んだココアのカップを洗って待つのが良いですね。
    ```
    2627+1 records in
    2627+1 records out
    2754981888 bytes transferred in 396.904916 secs (6941163 bytes/sec)
    ```
    と表示されたらOKです！
5. USBを取り出す
    ```
    diskutil eject /dev/disk6
    ```
    `Disk /dev/disk6 ejected`と表示されたらUSBを取り出しましょう。

お疲れ様です。これでインストールメディアは完成ですね。

# Ubuntu 24.04のインストール
ではでは、先ほど作ったUSBをMiniPCに差し込んで再起動しましょう。
再起動時にキーボードのDELボタンをひたすら叩きまくりましょう。すると、Windowsが起動せずに以下のような画面が表示されます。
(ここからはスクリーンショットが物理的に使えないので画面の写真を貼ります。)
![IMG_0183.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3570569/57beeb96-ac7b-9a0b-1672-ae13b02ab8d0.jpeg)

Setupをクリックすると以下の画面になります。そしてBootを選択して、Boot Option #1を先ほどのインストールメディアにします。
![IMG_0184.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3570569/faa10ba1-c7bd-5c4f-6506-24e24d64499d.jpeg)
そしてSave & Exitを開いて　`Save Changes and Exit`を選択して設定を保存の上で再起動します。
![IMG_0185.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3570569/43a43d9c-a558-a00a-ee23-05b02378dc0d.jpeg)
すると、Windowsではない画面が表示されます。
あとはインストールするだけなのですが、この流れは少し複雑なので以下の公式ドキュメントを参考にインストールまで完了してしまってください。
英語が苦手〜という人はとりあえずkeyboardレイアウトの画面とインストール先のメディア選択以外はそのままで大丈夫です。
keyboardとインストール先はちゃんと見た方が幸せになれます多分。

https://ubuntu.com/tutorials/install-ubuntu-server#1-overview

(ほぼ22.04から手順は変わってないのでこちらが参考になるかも？　https://zenn.dev/mesgory/articles/ffe5cc73fe5650)

ちなみに途中でインストールに際してLVMを使うか？という選択を行うことが可能になっていますが、KVMを使いたい場合にはLVMの方が後々楽かもしれません。

何はともあれ、以下のような表示になればインストールは完了です。画面下のボタンから再起動します。なお、この時にインストールメディアを取り外すように表示されるので、表示されたら取り外してEnterをおすと良いです。
![IMG_0187.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3570569/f6b2379e-2729-8d72-217f-7690e5a82d80.jpeg)

あとは起動に少し時間がかかりますが、しばらく待って、
```
[ OK ] Finished cloud-final.service - Execute cloud user/final scripts.
```
のように表示されて停止したら、Enterを押すと
```
<Server name> login: 
```
という表示になります。Server nameはインストール時に入力したserver nameです。
ここでユーザ名を入力してEnter、Passwordを求められるのでパスワードを入力してEnterするとよく見るLinuxのCLIが表示されます。
```
<username>@<server name>:~$ 
```
という画面になれば、あとはいつも通りコマンドが使えます。
お疲れ様でした！

# SSH設定
:::note info
Ubuntuのインストール内でSSH設定を自動で実施するようにしていた場合は不要です。サーバーを楽しんでください！
:::
ローカルでのコマンドも可能になってサーバーのインストールが終わりましたね。
でも、サーバーを直接キーボードでしか操作できないのは不便ですよね。SSHアクセスをしたいところです。

1. パッケージリストとパッケージをアップデートする
    ```
    sudo apt update -y && sudo apt upgrade -y
    ```
    これはもう手慣れたものですよね。まぁ、ほとんどの人にとっていつものやつです。
2. opensshのインストール
    ```
    sudo apt install -y openssh-client openssh-server
    ```
    これによってSSHを行うために必要なパッケージをインストールします。
3. 設定ファイルの編集
    `/etc/ssh/sshd_config`を編集してSSHでのアクセス目指します。
    まず、`Port 22`と`PubkeyAuthentication yes`のコメントアウトを外します。
    ```
    ...
    #Port 22
    #AddressFamily any
    ...

    #PobkeyAuthentication yes
    
    ...
    ```
    の先頭の`#`を外します。いちいち探すの面倒だな、という人は以下のコマンドを実行するだけでも同じことができます。
    ```
    sudo sed -i -e 's/^#Port 22/Port 22/' -e 's/^#PubkeyAuthentication yes/PubkeyAuthentication yes/' /etc/ssh/sshd_config
    ```
    変更を適用するためにsshを再起動します。
    ```
    sudo systemctl restart ssh
    ```
4. IPアドレスを確認し、SSHでアクセスする
    IPアドレスと言っても自宅内のローカルIPですが、確認します。
    ```
    ip a
    ```
    を実行するとネットワークカードの一覧が表示されます。このうち、`inet`が表示されているもので `127.0.0.1`以外のものがあなたのマシンの自宅内のIPです。
    (基本的に一つしか繋いでいなければ一つしかないですが、複数あってサブネットが異なる場合はご自宅のネットワーク責任者に確認してください(笑))
    そのIPを使って他のPCからSSHを接続してみましょう。usernameはインストール時の設定したものです。
    ```
    ssh <username>@<local ip>
    ```
    パスワードが求められたら入力してください。これも先ほどのインストール時に入力したパスワードです。
    
    :::note warn
    
    SSHの失敗
    `Too many authentication failures`が表示されてしまうことがありますが、これはパスワード認証であるにもかかわらず、Authkeyで認証しようとするためです。これに関する素晴らしい記事があったので https://qiita.com/kiyodori/items/971ef06969bbb2b50aaa をご確認くださいな。
    
5. Pubkeyを設定する
    さて、これでリモートから環境を利用できるようになりましたね。ですが、SSHをパスワードでできる状況というのはあまり望ましくないです。もちろんローカル環境でしか今後ずっと使わない、というのであればそのままでも良いかもしれませんが。(その場合はこれで終わりなのでこの後のステップはSkipしてください)
    
    個人的にはそもそも僕自身SSHキーはパスワードマネージャに管理させていて、パスワード認証の方が面倒、というのもあるので認証を鍵だけにしていきます。
    まずはSSHキーを作成します。
    ```
    ssh-keygen -t ed25519
    ```
    パスフレーズを聞かれるので自身で設定してください。パスフレーズまではいらない、という場合は何も入力せずにエンターをするので良いです。
    そして、この公開鍵を`authorized_keys`に設定していきます。
    ```
    cat ~/.ssh/id_ed25519.pub >> ~/.ssh/authorized_keys
    ```
    秘密鍵は `~/.ssh/id_ed25519` に配置されているのでこれをローカルにscpなりクリップボードなりで取得して保存してください。
    秘密鍵でログインできることを確認しましょう。ここで確認を忘れて後でできない、となるとサーバーに物理的にアクセスして設定し直す必要が出てくるので気をつけてくださいね。
    ```
    ssh <username>@<local ip> -i <保存した秘密鍵>
    ```
    これでパスワードが聞かれずにログインができればOKです。
    そしたら秘密鍵についてはサーバーから削除しておきましょう。秘密鍵は**絶対に**流出してはいけない情報です。
    ```
    rm ~/.ssh/id_ed25519
    ```
6. パスワードでのログインをブロックする
    `/etc/ssh/sshd_config`の `#PasswordAuthentication yes` を `PasswordAuthentication no`に修正します。
    viコマンドを使っても良いですが、
    ```
    sudo sed -i 's/^#PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config
    ```
    で一発で修正できます。
    適用するために ssh を再起動します。
    ```
    sudo systemctl restart ssh
    ```
    サーバーを抜けて以下のコマンドを実行します。(usernameとhostは適宜置き換えてください)
    ```
    ssh <username>@<host> -o PreferredAuthentications=password
    ```
    このsshではパスワード認証を指定しています。これで
    ```
    Permission denied (publickey)
    ```
    が返ってくれば、パスワード認証がブロックされるようになったことがわかります。

お疲れ様でした！これでサーバーにSSHでも接続できるようになりました。
あとは開発環境として使うなら普通に使っていけますね。例えば、あまりオススメしませんが開発環境ということで外部アクセスがない前提ならばユーザに対してパスワードなしでsudoを実行できるようにしたり、Dockerを入れてコンテナを使ったり、いろんなことができると思います。

# 終わりに
これでAmazonで購入したWindows ミニPCをUbuntuサーバーにすることができました。
今回は`購入からLinuxインストール編`ということで目標が達成できました。ただ折角ある程度大きなリソースを持つサーバーを作ったので、次はKVMを入れて仮想マシンを利用できるようにしていこうと考えています。
ベアサーバーをそのまま使うのも良いのですが、開発サーバーとして使う場合、環境を破壊する可能性も否定できないので仮想マシンを利用したい、というのが個人的な思いだったりします。
何はともあれ、ここまで読んでくださった方がいたらこんな駄文を読んでくださりありがとうございます。また次のKVMインストール編(予定)も興味があれば是非！
ではでは、よき自宅開発サーバーライフを！