NucBox5にAlpine Linuxをインストールして自宅サーバ構築

May 15, 2023

linuxAlpineLinux

目次

はじめに

AmazonのタイムセールでGMKtec NucBox5を15,881円で購入。ずいぶん安価になったものだ。そこそこハイスペックなPCなので、そのままWindows11Proで使用してもストレスなく使えそうではあるが、Alpine Linuxを入れて自宅サーバーとして使用することに。

筆者宅ではCHUWI LarkBoxにAlpine Linuxを入れて自宅サーバーを構築していた。LarkBoxサーバーは導入から3年問題なく稼働し続けてきたが、そもそもLarkBoxには有線LANポートが無く、無線LANが1ポートだけで騙し騙し使ってきたこともあり、この際NucBox5にリプレイスすることにした。

LarkBoxと比較すると、CPUは第8世代Celeron J4115から第11世代N5105へ、ストレージはeMMCからESATAへとアップグレードし、有線LANポートも付いているので性能アップが期待できる。とはいっても自宅サーバーの用途ではLarkBoxで性能不足を感じることはほとんどなかったのだけど。nodeを使うような大規模なdockerイメージをビルドするときとかはだいぶ高速になりそうな予感。

NucBox5のスペックは以下。

Device Spec
CPU Intel Celeron N5105
RAM 8GB 2933MHz
ストレージ 128GB SATA M2.SSD
Ethernet Giga LAN(RJ45)
Wi-Fi Wi-Fi 6
Bluetooth 5.2

ストレージは2242サイズで換装可能。 TDP 10Wなので、発熱も消費電力も極小でサーバ向きだと思う。ラズパイ4なんかよりもだいぶハイスペックで、Webアプリをガンガン動かすことも可能な、いけてるサーバが構築できよう。

自宅サーバの基本コンセプトとして、

  • 母艦OSはdockerを動かす最小限の機能だけにする
  • 母艦OSに直接インストールするのはdockerなど最小限のツールのみ
  • 必要なアプリは全てdocker composeで動かす

という方針を掲げて臨んでみた。 docker composeを使う理由は、お手軽な点ももちろんなのですが、Linuxの場合、アプリのインストールは簡単にできるものの、uninstallをきれいに(完全に)行うことがなかなか難しいので、インストールとアンインストールを繰り返していくうちにシステムが汚れていくのを避けるためです。アプリをdocker composeでインストールすれば、不要になったアプリは

docker comppose down -v

だけで一掃でき、その後docker imageを削除すれば、完全になかったことにできます。

母艦OSの選択肢はAlpine Linux一択です。これは異論の余地はないでしょう。

本記事には、GMKtec NucBox5にAlpine Linuxを入れて、dockerを入れるところまでの手順を掲載しています。その後の自宅サーバ構築手順は、以下の記事にまとめています。

本サイトに、NucBox5にAlpine Linuxを入れて自宅サーバを構築した手順についての、以下の記事を掲載します。

以下はAlpine Linuxにapkで直インストール

以下はdocker composeでインストール

写真上げときます。単3乾電池4本と比べても小ささがわかる。

nucbox5.png

NucBox5のセットアップ

自宅サーバでは、Macのバックアップ用のTimeCapsuleも稼働させたいので、ストレージ128GBでは不足。 そこで、ストレージを1TB M2.SSDに換装する。2242サイズのものしか使えない。

換装の前にWindows11のプロダクトキーをサルベージしておく。一度Windows11で起動し、マイクロソフトアカウントでログインしておくと、マイクロソフトアカウントとプロダクトキーが紐付けられて、Windows11を削除しても再インストールして再アクティベーションが可能になるので安心。

それでも不安なら、cmdから

C:\> wmic path SoftwareLicensingService get OA3xOriginalProductKey

でプロダクトキーを表示させて控えておく。

プロダクトキーをサルベージしたら、電源を切り、裏蓋を開けて、SSDをスロットに挿されたSSDを交換してセットアップ完了。

nucbox5_bottom.png

BIOSへの入り方は、電源ボタンを押下後、エスケープキーを連打する。

BIOSの設定をUSBメモリから起動するようにしておく。

Alpine Linuxのインストール

Alpine Linuxのダウンロード

Alpine LinuxのサイトからEXTENDEDパッケージをダウンロードし、インストールします。はじめは、STANDARDパッケージをインストールしようとしたのだけど、STANDARDパッケージは最小限すぎてpingすら入っていない状態であまりにも使いにくい。Alpine Linuxに対して、NucBox5のストレージはあまりにも広大なので、ここはEXTENDEDパッケージのほうがいいと思う。

alpine_linux_downloads.png

USBメモリからブート

ダウンロードしたISOファイルalpine-extended-3.17.3-x86_64.isoをUSBメモリに焼いて、そこからブートします。

Windows上でISOファイルをUSBメモリに焼くには、Rufusなどのツールを使用すればよい。

ブートしたら、rootでログインします。(rootのパスワードは無し)

Welcome to Alpine Linux 3.17
Kernel 5.15.104-0-lts on an x86_64 (/dev/tty1)

localhost login: root

Alpine Linuxのインストーラは、メジャーなデストリビューションのインストーラのようにいけてない。1つ1つ対話的に設問に応答していく必要があります。 インストールを開始は、

# setup-alpine

なんだけど、Alpine Linuxのインストーラではディスクのパーティションを切るオプションが無い!システム全体が1つのパーティションにインストールされてしまう。そこで、インストールスクリプトを書き換えて、ルートパーティションを必要な分だけ確保してそこにインストールするようにし、後で、残った領域にパーティションを追加することにする。

1TB SSDを次のようにパーティションを切ることにする。

/      16GB
/var  150GB
/home 834GB

SSDに余裕があったのでルートパーティションを16GB確保したが、Alpine Linuxでは4GBもあれば十分だとは思う。

dockerでWebアプリをガンガンインストールする予定なのでコンテナが使用する/varは余裕の大きさを確保する。ただ150GBはやりすぎかも。

残りの領域が/home。

ルートパーティションを必要な分だけ確保する方法は、以下の記事を参考にした。

【参考】
https://qiita.com/soprano1125/items/cf0585eaf563f4b79305
「実機に Alpine Linux をインストールするときパーティション分けてぇよなぁ」と思ってやったこと

ディスク設定用のインストールスクリプトを編集

# vi /sbin/setup-disk

スクリプト中の

local root_size=${ROOT_SIZE}

local root_size=${ROOT_SIZE:-16384}

に変更する。

Alpine Linux をインストール

インストーラーを起動

# setup-alpine

次の通りインストールする。

    ホスト名:nucbox5
    ドメイン:home.arpa
IPv4アドレス:192.168.1.4
ゲートウェイ:192.168.1.1
  アカウント:my_login_name

インストールスクリプトの応答は次の通り。

Select keyboard layout: [none] jp
Select variant (or 'abort'): jp

Enter system hostname (fully qualified form, e.g. 'foo.example.org') [localhost] nucbox5.home.arpa

Which one do you want to initialize? (or '?' or 'done') [eth0] eth0
Ip address for eth0? (or 'dhcp', 'none', '?') [dhcp] 192.168.1.4
Netmask? [255.255.255.0] 255.255.255.0
Gateway? (or 'none') [none] 192.168.1.1
Which one do you want to initialize? (or '?' or 'done'' [wlan0] done
Do you want to do any manual network configuration? (y/n) [n] n
DNS domain name? (e.g 'bar.com') home.arpa
DNS nameserver(s)? 192.168.1.1

New Password: 
Retype password: 

Which timezone are you in? ('?' for list) [UTC] Asia/Tokyo
HTTP/FTP proxy URL? (e.g. 'http://proxy:8080', or 'none') [none]
Which NTP client to run? ('budybox', 'openntpd', 'chrony', or 'none') [chrony] chrony

Enter mirror number (1-72 or URL to add (or r/f/e/done) [1]

Setup a user? (enter a lower-case koginname, or 'no') [no] my_login_name
Full name for user my_login_name [my_login_name] My Full Name
New Password: 
Retype password: 

Enter ssh key or URL for my_login_name (or 'none') [none]
Which SSH server? ('openssh', 'dropbear' or 'none') [openssh] openssh

Which disk(s) would you like to use? (or '? for help or 'none') [none] sda
How would you like to use it? ('sys', 'data', 'crypt', 'lvm' or '?' for help) [?] sys
WARNING: Erase the above disk(s) and continue? (y/n) [n] y

インストールを終えたら一旦電源OFF。

nucbox5:~# poweroff

shutdownじゃないんだね。

インストールの確認

USBメモリを抜いて内蔵SSDからブートするようにBIOSの設定を変更。再びrootでログイン。今度は先ほど設定したパスワードが必要。

Welcome to Alpine Linux 3.17
Kernel 5.15.111-0-lts on an x86_64 (/dev/tty1)

nucbox5.home.arpa login: root
Password:

念のため、ネットワークがつながっていることを確認。

# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:e0:4c:38:6e:b7 brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.4/24 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 2400:aaaa:bbbb:cccc:dddd:eeee:ffff:1111/64 scope global dynamic flags 100
       valid_lft 14316sec preferred_lft 12516sec
    inet6 fe80::wwww:xxxx:yyyy:zzzz/64 scope link
       valid_lft forever preferred_lft forever
3: wlan0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN qlen 1000
    link/ether aa:bb:cc:dd:ee:ff brd ff:ff:ff:ff:ff:ff

ディスクの確認。

# df -h
Filesystem                Size      Used Available Use% Mounted on
devtmpfs                 10.0M         0     10.0M   0% /dev
shm                       3.8G         0      3.8G   0% /dev/shm
/dev/sda3                15.6G    540.3M     14.2G   4% /
tmpfs                     1.5G    112.0K      1.5G   0% /run
df: /sys/kernel/debug/tracing: Permission denied
/dev/sda1               511.0M    280.0K    510.7M   0% /boot/efi
tmpfs                     3.8G         0      3.8G   0% /tmp

ルートパーティションは15.6GB割当られている。

インストールの続き

あとは粛々とインストールを進める。

パッケージのリポジトリを更新

/etc/apk/repositoriesを以下のように修正

http://dl-cdn.alpinelinux.org/alpine/v3.17/main
http://dl-cdn.alpinelinux.org/alpine/v3.17/community
#http://dl-cdn.alpinelinux.org/alpine/edge/main
#http://dl-cdn.alpinelinux.org/alpine/edge/community
#http://dl-cdn.alpinelinux.org/alpine/edge/testing

次のコマンドで更新。

# apk update
# apk upgrade

sudo の許可

# apk add sudo
# visudo
# %wheel ALL=(ALL) ALL

%wheel ALL=(ALL) ALL

に変更

# addgroup 自分のログインアカウント wheel

ここまできたら、コンソールではなく、sshで別のターミナルから自分のアカウントで接続可能になります。 以降、sshで接続した端末から、

$ sudo su

でルート権限を得て続行。

ディスクパーティション作成

GPTパーティション作成ツールを取得

# apk add -U gptfdisk sgdisk

GPTパーティション作成ツールを起動

# gdisk /dev/sda

GPT fdisk (gdisk) version 1.0.9.1

Partition table scan:
  MBR: protective
  BSD: not present
  APM: not present
  GPT: present

Found valid GPT with protective MBR; using GPT.

まず、「p」コマンドで現在のパーティションテーブルを見てみる。

Command (? for help): p
Disk /dev/sda: 1953525168 sectors, 931.5 GiB
Model: M.2 2242-1TB SSD
Sector size (logical/physical): 512/512 bytes
Disk identifier (GUID): 187F6277-94EA-E34A-A044-75EA74F20E45
Partition table holds up to 128 entries
Main partition table begins at sector 2 and ends at sector 33
First usable sector is 2048, last usable sector is 1953525134
Partitions will be aligned on 2048-sector boundaries
Total free space is 1910531471 sectors (911.0 GiB)

Number  Start (sector)    End (sector)  Size       Code  Name
   1            2048         1050623   512.0 MiB   EF00
   2         1050624         9439231   4.0 GiB     8200
   3         9439232        42993663   16.0 GiB    8300

3つのパーティションが出来ているのがわかる。1つ目がEFI、2つ目がswap、3つ目がルートパーティション。

「n」コマンドで、新たに /var にマウントする150GBの4つ目のパーティションを作成する。

Command (? for help): n
Partition number (4-128, default 4): 4
First sector (42993664-1953525134, default = 42993664) or {+-}size{KMGTP}:
Last sector (42993664-1953525134, default = 1953523711) or {+-}size{KMGTP}: +150G
Current type is 8300 (Linux filesystem)
Hex code or GUID (L to show codes, Enter = 8300):
Changed type of partition to 'Linux filesystem'

「n」コマンドで、新たに /home にマウントする5つ目のパーティションを作成する。容量は残り全部。

Command (? for help): n
Partition number (5-128, default 5):
First sector (357566464-1953525134, default = 357566464) or {+-}size{KMGTP}:
Last sector (357566464-1953525134, default = 1953523711) or {+-}size{KMGTP}:
Current type is 8300 (Linux filesystem)
Hex code or GUID (L to show codes, Enter = 8300):
Changed type of partition to 'Linux filesystem'

「p」コマンドで結果を確認。

Command (? for help): p
Disk /dev/sda: 1953525168 sectors, 931.5 GiB
Model: M.2 2242-1TB SSD
Sector size (logical/physical): 512/512 bytes
Disk identifier (GUID): 187F6277-94EA-E34A-A044-75EA74F20E45
Partition table holds up to 128 entries
Main partition table begins at sector 2 and ends at sector 33
First usable sector is 2048, last usable sector is 1953525134
Partitions will be aligned on 2048-sector boundaries
Total free space is 1423 sectors (711.5 KiB)

Number  Start (sector)    End (sector)  Size       Code  Name
   1            2048         1050623   512.0 MiB   EF00
   2         1050624         9439231   4.0 GiB     8200
   3         9439232        42993663   16.0 GiB    8300
   4        42993664       357566463   150.0 GiB   8300  Linux filesystem
   5       357566464      1953523711   761.0 GiB   8300  Linux filesystem

思い通りに出来たようだ。あとは「w」コマンドで書き出して終了。

Command (? for help): w

Final checks complete. About to write GPT data. THIS WILL OVERWRITE EXISTING
PARTITIONS!!

Do you want to proceed? (Y/N): Y
OK; writing new GUID partition table (GPT) to /dev/sda.
Warning: The kernel is still using the old partition table.
The new table will be used at the next reboot or after you
run partprobe(8) or kpartx(8)
The operation has completed successfully.

一旦再起動。

# reboot

ディスクをフォーマット

# mkfs.ext4 /dev/sda4
mke2fs 1.46.6 (1-Feb-2023)
/dev/sda4 contains a ext4 file system
        last mounted on /var on Thu May 11 15:39:40 2023
Proceed anyway? (y,N) y
Discarding device blocks: done
Creating filesystem with 39321600 4k blocks and 9830400 inodes
Filesystem UUID: a9202f44-b2ea-469e-8a25-d841cb7b19bb
Superblock backups stored on blocks:
        32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208,
        4096000, 7962624, 11239424, 20480000, 23887872

Allocating group tables: done
Writing inode tables: done
Creating journal (262144 blocks): done
Writing superblocks and filesystem accounting information: done

# mkfs.ext4 /dev/sda5
mke2fs 1.46.6 (1-Feb-2023)
/dev/sda5 contains a ext4 file system
        last mounted on /var/lib/mysql on Thu May 11 15:39:40 2023
Proceed anyway? (y,N) y
Discarding device blocks: done
Creating filesystem with 199494656 4k blocks and 49881088 inodes
Filesystem UUID: 314ba33a-65b4-422d-8fd7-9d0fce14871d
Superblock backups stored on blocks:
        32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208,
        4096000, 7962624, 11239424, 20480000, 23887872, 71663616, 78675968,
        102400000

Allocating group tables: done
Writing inode tables: done
Creating journal (262144 blocks): done
Writing superblocks and filesystem accounting information: done

ディスクの UUID を確認

# blkid
/dev/sda5: UUID="314ba33a-65b4-422d-8fd7-aaaaaaaaaaaa" TYPE="ext4"
/dev/sda4: UUID="a9202f44-b2ea-469e-8a25-bbbbbbbbbbbb" TYPE="ext4"
/dev/sda3: UUID="7103b6ae-310d-4dc2-8d54-cccccccccccc" TYPE="ext4"
/dev/sda2: UUID="c87181f4-75c4-4860-9d4d-dddddddddddd" TYPE="swap"
/dev/sda1: UUID="F13C-B659" TYPE="vfat"

/etc/fstabにマウントポイント追加

/etc/fstabにマウントポイント追加
UUID=a9202f44-b2ea-469e-8a25-bbbbbbbbbbbb /var            ext4    defaults 1 2
UUID=314ba33a-65b4-422d-8fd7-aaaaaaaaaaaa /home           ext4    defaults 1 2

一旦再起動。

# reboot

ディスクを確認

# df -h
Filesystem                Size      Used Available Use% Mounted on
devtmpfs                 10.0M         0     10.0M   0% /dev
shm                       3.8G         0      3.8G   0% /dev/shm
/dev/sda3                15.6G    609.4M     14.2G   4% /
tmpfs                     1.5G    108.0K      1.5G   0% /run
/dev/sda1               511.0M    280.0K    510.7M   0% /boot/efi
tmpfs                     3.8G         0      3.8G   0% /tmp
/dev/sda4               146.6G     96.0K    139.1G   0% /var
/dev/sda5               748.0G     28.0K    709.9G   0% /home

/varと/homeが出来ている。

ホームディレクトリを作り直す。

# cd /home
# mkdir my_login_name
# chown my_login_name:my_login_name my_login_name

自分の環境

Alpine Linuxのデフォルトのシェルはashなのでbashにする。

bashのインストール。

# apk add bash-completion

ホームディレクトリに.bashrcを置く。

~/.bashrc
# .bashrc

# Source global definitions
if [ -f /etc/bashrc ]; then
        . /etc/bashrc
fi
#export PS1="[\w]\\$ "
export PS1="\[\e[32m\][\w]\[\e[0m\]\\$ "
alias vi='vim'
alias cls='clear'
alias ll='ls -l --color=auto'
date

ホームディレクトリに.bash_profileを置く。

~/.bash_profile
# .bash_profile

# Get the aliases and functions
if [ -f ~/.bashrc ]; then
        . ~/.bashrc
fi

# User specific environment and startup programs

PATH=$PATH:$HOME/.local/bin:$HOME/bin

export PATH

ログインシェルをashから使い慣れたbashに変更する

/etc/passwd
root:x:0:0:root:/root:/bin/bash
...
my_login_name:x:1000:1000:My Full Name:/home/my_login_name:/bin/bash
$ source ~/.bashrc

vimのインストール

# apk add vim
~/.vimrc
set mouse-=a

ipv6の設定

自宅のネットがIPoE接続ならば、やっておいたほうがよい。

/etc/modulesにipv6の行があることを確認。

/etc/modules
ipv6

/etc/hostsを書き換え

/etc/hosts
127.0.0.1       localhost
192.168.1.4     nucbox5 nucbox5.home.arpa
::1             localhost ipv6-localhost ipv6-loopback localhost.localdomain
fe00::0         ipv6-localnet
ff00::0         ipv6-mcastprefix
ff02::1         ipv6-allnodes
ff02::2         ipv6-allrouters
ff02::3         ipv6-allhosts

/etc/network/interfacesをIPv4, IPv6デュアルスタックにする。

/etc/network/interfaces
auto lo
iface lo inet loopback

auto eth0
iface eth0 inet static
        address 192.168.1.4
        netmask 255.255.255.0
        gateway 192.168.1.1

iface eth0 inet6 static
        address 2400:aaaa:bbbb:cccc::4
        netmask 64
        gateway 2400:aaaa:bbbb:cccc:dddd:eeee:ffff:2222

2400:aaaa:bbbb:cccc:dddd:eeee:ffff:2222は自宅のIPv6ゲートウェイアドレス。

一旦再起動。

# reboot

IPv6アドレスが変わったことを確認。

# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:e0:4c:38:6e:b7 brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.4/24 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 2400:aaaa:bbbb:cccc::4/64 scope global
       valid_lft forever preferred_lft forever
    inet6 fe80::2e0:4cff:fe38:6eb7/64 scope link
       valid_lft forever preferred_lft forever
3: wlan0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN qlen 1000
    link/ether dc:21:5c:79:63:87 brd ff:ff:ff:ff:ff:ff

dockerのインストール

dockerをインストール

# apk add docker docker-cli-compose

次にdockerのネットワークをIPv6対応しておきます。fd6d:aaaa:bbbb:cccc::/64は適当に割り当てました。

/etc/docker/daemon.json
{
  "ipv6": true,
  "fixed-cidr-v6": "fd6d:aaaa:bbbb:cccc::/64"
}
# addgroup my_login_name docker

dockerを起動

# rc-service docker start

サーバ起動時にdockerを起動

# rc-update add docker boot

次のステップ

あとはサーバーアプリをガンガン入れていくだけ。


Written by questions6768 who lives in Uji, Kyoto.