Daydreaming in Boston

N150のMini PCでホームラボ始めました

1. Acemagic Mini PC V1

2025年のsummer projectとして、N150 Mini PCでホームラボサーバーをたてました。

GMKtec Mini PC N150 (メモリ16GB, ストレージ1TB) $194を狙っていたのですが、よく見たらプライムメンバー向けの特別価格でした。。。

仕方なく同等品を探したところ、Acemagicとかいう会社のMini PC V1 (16GB, 1TB)が200ドル以下(今なら$189;更にプロモコードあり)であるのを見つけたので、これを買いました。512GBモデルだと更に安いのですが、家族のスマホ写真全てを集約するつもりなので、1TBのモデルにしました。GMKtecと違ってストレージが高速なNVMeではなくS-ATAなところが残念ですが、プラス50ドルは予算オーバーです。

IntelのN150プロセッサーは6-7年くらい前のミドルレンジCPUと同等の性能で非力です。N150のすごいところは、非常に低消費電力(アイドル時6W)なところです。これを使ったMini PCは負荷をかけない限りファンの音がほとんどしないのでベッドルームに置いても気になりません。サーバーとして24時間稼働させても家計に優しい。

2. Proxmoxを試してみる

ホームラボなので色々と試したりして環境をうっかり壊してしまうリスクが常にあります。そこで、Linuxを直接インストールするのではなくハイパーバイザー上で動かすことにしました。壊してしまってもスナップショットがとってあればその状態に戻すことができます。

VMwareがBroadcomに買収されてESXiを有償化したり、無料に戻したり迷走しています。今後のリスクを考えてESXiは避け、評判の良いProxmoxを試すことにしました。オープンソース万歳。Mini PCに最初から入っているWindows 11 Proは即消しです。

2.1. インストール

Proxmoxのインストールはえらく簡単でした。手順は、

  • ここからインストーラーISOをダウンロードする
  • MacBook上でUSBメモリに書き込む
diskutil list
# USBメモリを挿す
diskutil list # 新たに増えた分(/dev/diskNとする)がUSBメモリ
diskutil unmountDisk /dev/diskN
sudo dd if=/path-to.iso of=/dev/rdiskN bs=1m # rdiskの'r'を忘れないように
diskutil eject /dev/diskN
# USBメモリを抜く
  • Mini PCにUSBマウスとキーボードを付け、HDMIケーブルでテレビにつなげる。Etherケーブルもつなげておく
  • USBメモリをMini PCに挿して電源ボタンを押す
  • ESC/Deleteキー押しっぱなしにするとBIOSに入るので、USBメモリからブートできるように設定し、起動する
  • 画面の指示に従う。IPアドレスは固定で与える。

これでProxmoxが起動してきます。最初にrootユーザーを登録したらhttp://<IPアドレス>:8006 で管理できるようになるので、マウス、キーボード、テレビは不要になります。あまりに簡単なので拍子抜けです。

3. Linuxを入れる

次にLinuxを入れます。職場ではRocky Linuxを使っているのですが、将来性が微妙そうなのでUbuntuを選びました。RedHatはすごい会社と思いますが、IBMに買収されてからやはり迷走しています。資本主義の行き過ぎを実感している今日このごろです。

まず、UbuntuインストーラーISOへのURLを用意します。今だと最新の長期サポート版24.04.2 LTSは ここ です。

3.1. VMを作る

  • Proxmoxの管理画面にログイン > local(ディスク) > ISO Images > Download from URL > ISOへのURLを指定する > Download
  • Create VM > Name: (入れる) > Next > ISO image: ダウンロードしたインストーラーを指定 > Next > Next > Disk size: 820GB > Next > Cores: 4 > Memory: 12GB > Next > Next > Finish

Proxmox+CT用にメモリ4GB、ストレージ100GB+アルファを残しています。ディスクサイズの820GBはほぼ最大です。

3.2. Ubuntuインストール

普通にインストールするだけ。サーバーにするのでIPアドレスを固定で与えます。あとはapt update&upgradeしたり、opensshサーバーをインストールしたり。

sudo apt update -y
sudo apt upgrade -y
# opensshサーバーインストール
sudo apt install openssh-server openssh-client

いつもVMを入れるとやるように、MacBookからsshできるようにする。MacBookから

ssh <user>@<Ubuntu VM IP> # sshできることを確認
# パスワード入力する
exit # MacBookに戻る
cd ~/.ssh
ssh-copy-id -i <id_rsa> <user>@<Ubuntu VM IP>
# パスワード入力する
ssh <user>@<Ubuntu VM IP> # パスワード無しでsshできることを確認

4. Dockerを入れる

アプリケーションを楽にデプロイ、運用するためにDockerを入れます。docker-composeによるデプロイはあまりに簡単です。ここ を参考にインストールします。

sudo apt install apt-transport-https ca-certificates curl software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu focal stable"
apt-cache policy docker-ce # to check
sudo apt install docker-ce
sudo systemctl status docker
sudo usermod -aG docker ${USER}
(reboot)
docker run hello-world

5. サーバーアプリ(コンテナ)を入れる

docker-composeが本領を発揮します。以下のアプリを入れることにしました。

  • Immich - スマホ写真をホストする。Google Photosを置き換え予定
  • Pi-hole - ネットワークレベルの広告ブロッカー
  • RomM - レトロゲームのROMマネージャー

5.1. Immich

immich はすごいです。Google Photosと比べてほとんど違和感がありません。写真や動画の圧縮に対応していないことと、スマホからの最初のアップロードが重いことが難点なくらいで、使い勝手はGoogle Photosそのまま。写真の顔認識も(勝手に)してくれます。

写真はPC上のブラウザーやスマホの専用アプリから見られます。インターネットを経由しないので、動作はGoogle Photos等よりも軽快です。

wget -O docker-compose.yml https://github.com/immich-app/immich/releases/latest/download/docker-compose.yml
wget -O .env https://github.com/immich-app/immich/releases/latest/download/example.env
# .env をエディットしてタイムゾーン(TZ)や写真アップロード場所を指定する。
docker compose up -d

インストールはこれだけ。拍子抜けな簡単さです。docker-composeすごいよ!

5.2. Pi-hole

広告ブロッカーって便利ですよね。一度使ってしまうと、これなしではいられなくなります。鬱陶しいWeb広告を見なくて済むことって、こんなにも精神衛生上良いことだとは。。。

Pi-hole はネットワーク(DNS)レベルで広告をブロックします。WifiルーターDHCPのDNSサーバーをこれに設定しておくと、PCやスマホでは広告が表示されなくなります。スマホでも有効なところが素晴らしい。

なお、ローカルのホストネームはpi-holeコンテナのコンソールに入って/etc/hostsに追記し、コンテナを再起動します。

5.2.1. VMのDocker上にデプロイする(旧)

(この方法はやめました)

簡単にデプロイできたimmichと比べて、pi-holeには少々苦戦しました。Ubuntuではsystemd-resolvedが有効になっているため、これをなんとかしてやる必要がありました。

sudo sed -r -i.orig 's/#?DNSStubListener=yes/DNSStubListener=no/g' /etc/systemd/resolved.conf
sudo sh -c 'rm /etc/resolv.conf && ln -s /run/systemd/resolve/resolv.conf /etc/resolv.conf'
systemctl restart systemd-resolved

最初これに試行錯誤して、早速Proxmoxのスナップショットのお世話になりました。Ubuntu上で危険なことをやるときには、事前にスナップショットをとっておくと安心です。

  • docker-compose.yamlを作る。
version: "3"

 # More info at https://github.com/pi-hole/docker-pi-hole/ and https://docs.pi-hole.net/
services:
  pihole:
    container_name: pihole
    image: pihole/pihole:latest
    # For DHCP it is recommended to remove these ports and instead add: network_mode: "host"
    ports:
      - "53:53/tcp"
      - "53:53/udp"
      - "67:67/udp"
      - "8081:80/tcp"  # ポート8081を指定しています。
    environment:
      TZ: 'America/New_York'  # タイムゾーン
      WEBPASSWORD: '<some password>'  # パスワード。。。のはず
      PIHOLE_DNS_: '1.1.1.1;8.8.8.8'
    # Volumes store your data between container upgrades
    volumes:
      - './etc-pihole:/etc/pihole'
      - './etc-dnsmasq.d:/etc/dnsmasq.d'
    #   https://github.com/pi-hole/docker-pi-hole#note-on-capabilities
    cap_add:
      - NET_ADMIN # Required if you are using Pi-hole as your DHCP server, else not needed
    restart: unless-stopped
  • タイムゾーンTZ, WEBPASSWORD, volumesあたりを変えました。そして、
docker compose up -d

するだけ。

ここで問題が。http://<IP>:8081/admin でログインしようとすると、何故かパスワードが違うと言ってきます。仕方がないので無理やりパスワードリセットします。

docker ps  # Pi-holeのコンテナIDをメモする
docker exec -it <pi-holeのコンテナID> bash # pi-holeコンテナのシェルが開きます
pihole setpassword

5.2.2. ProxmoxにCTとしてデプロイする(新; 追記)

Pi-holeをUbuntu VM上のDockerコンテナとしてしばらく使っていたのですが、このVM上でWebサイトをブラウズする時には広告が表示されてしまうというしょうもない問題に気が付きました。ProxmoxのCTはセキュリティー上あまり好ましくないようなことを読んだので使うのを避けていましたが、背に腹は代えられないので、Pi-holeをCTに外だしすることにしました。

Proxmox VEのヘルパースクリプトが用意されているのでデプロイは非常に簡単でした。最初からこちらを選べばよかった。

Proxmoxのコンソールを開いて

bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/ct/pihole.sh)"

を実行するだけ。Create CTボタンを押す必要もありません。sshからやろうとすると、やめた方が良いと言われます。途中でunboundを入れるか聞かれるので、ついでに入れておきました。

新たに作成されたCTのNetworkを固定IPに変更して(CT > Networkからできます)、Pi-holeの管理者パスワードを設定します(CT > Consoleから)。

/usr/local/bin/pihole setpassword

最初、CTのコンソールの開き方がわからなかったので、Proxmoxのコンソールから

pct enter 101 # 101はコンテナ番号

でやってしまいました。まあ、結果は同じです。

あとは、ルーターのDHCPが指定するDNSまたはデバイスのDNSにPi-hole CTのIPアドレスを設定するだけ。広告の無い世界をお楽しみください。

5.2.3. ChromeがPi-holeをバイパスする

と、ここで問題が。ChromeがPi-holeを無視して勝手にDNS解決するのです。広告が消えないのであせりました。まったくGoogleってやつは。。。

ここに解決策がありました。ChromeのURL/検索バーで

chrome://settings/security?search=dns

を実行して"Use secure DNS"を無効にします。

5.3. RomM

RomMはレトロゲームのROMマネージャーです。PCやスマホのブラウザー(Chrome推奨)からゲームがプレイできます。ゲームは端末上のJavaScriptで動くため、サーバーへの負荷は最小限です。スーファミのゲームなら、うちにある2013年のMacBook Proでもサクサク動きます。これはすごい。もちろん、ROMはご自分で用意ください。

なお、ブラウザーとしてFirefoxを使うと、何故か音が割れまくりです。

RomMはクイックスタートガイドに従って悩むことなくデプロイできました。

RomMはIGDBというネット上のゲームデータベースからAPIを使ってゲーム写真などを持ってくることができます。これをやらないと見た目が寂しいですが、APIキーを入手するのが一苦労です。ここ にやり方が詳しく書いてあります。

Pro tip: ROMがたくさんあるとRomMのUIから全部アップロードすると大変なので、scpを使って一気に転送したいところです。しかし、ディレクトリ配置に厳密に従わないと認識してくれないので、最初の1個だけUIからアップロードし、それで作成されたディレクトリにscpで転送してやるとよいと思います。

6. その他

以前のエントリーを参考に、emacsやら何やらをセットアップしています。

まあ、デスクトップとしてはあまり使わないので、それほど頑張ってはいません。emacsも基本はtrampで使いますし。

現在困っているのは、Mac上のX2Go Clientとしてブラウザーを飛ばした時に日本語入力ができないこと。Mac上の日本語入力は無視されます。何かいい解決方法は無いものか。。。

7. 終わりに

今回はホームラボサーバーをたてました。写真などの重要なデータはここに集約予定なので、これが動かなくなったりデータが失われると困ります。次回はホームラボサーバーのバックアップについて考えます。

Tech Tech