###### tags: `Gentoo`
# Gentoo Installation (amd64)
[TOC]
幾乎所有的作業系統安裝流程都是分割硬碟、格式化硬碟、複製檔案或解壓縮檔案到硬碟上、設定 bootloader,最後在 chroot 環境裡根據硬體及使用環境做完一些基本設定後重新開機。大部分的作業系統安裝程式都被包裝成可以無腦安裝的形式,安裝 Gentoo 則需要手動進行這些流程。
## 開機及啟用 sshd
參閱官方 [Gentoo AMD64 Handbook](https://wiki.gentoo.org/wiki/Handbook:AMD64) 的 [choosing the right installation medium](https://wiki.gentoo.org/wiki/Handbook:AMD64/Installation/Media)。
1. 到 [Gentoo 官網](https://www.gentoo.org/downloads/)下載 amd64 的 Minimal Installation CD。
* 如果需要使用 USB 隨身碟開機,下載 [Rufus](https://rufus.ie/) 製作開機隨身碟。
2. 在 BIOS 設定成以 USB 隨身碟開機。
* 如為 legacy 開機模式,會先看到 boot: 提示符號,在這後面輸入 `gentoo-nofb nox`。
3. 用 `ifconfig` 確認主機 IP 位址供後續 ssh 連線用。
* 在有 DHCP server 的環境下進行安裝的話在這步驟只要看 IP 位址就好。
* 沒有 DHCP server 的環境必須依照 [configuring the network](https://wiki.gentoo.org/wiki/Handbook:AMD64/Installation/Networking) 的說明設定網路。
4. 設定 root 密碼。
5. 執行 `rc-service sshd start` 啟動 sshd。
* 如有必要的話先用 `nano -w /etc/ssh/sshd_config` 編輯相關設定再啟動,某些特定情況下會需要設定 `PasswordAuthentication yes`。
6. 回到自己電腦以慣用的 ssh client 連線到主機進行後續安裝。
## 磁碟分割及格式化
參閱 handbook 的 [preparing the disks](https://wiki.gentoo.org/wiki/Handbook:AMD64/Installation/Disks),這裡以安裝 UEFI 系統至 `/dev/sda` 為例。
1. 執行 `parted -a optimal /dev/sda` 開始分割硬碟。
2. 輸入 `mklabel gpt` 建立 GPT 分割表。
3. 依序輸入下列指令建立磁碟分割區:
```
mkpart primary fat32 0% 3mb
name 1 grub
set 1 bios_grub on
mkpart primary fat32 3mb 153mb
name 2 boot
set 2 boot on
mkpart primary ext4 153mb 60.2gb
name 3 rootfs
mkpart primary ext4 60.2gb 90.2gb
name 4 var
mkpart primary linux-swap 90.2gb 122.2gb
name 5 swap
mkpart primary ext4 122.2gb -1s
name 6 home
```
:::info
* 較為正式的系統,`/` 會分割 15 ~ 30GB,`/usr` 會分割 50 ~ 70GB (如果不想獨立分割 `/usr` 則與 `/` 合併計算),`/var` 分割 20 ~ 30GB,`swap` 會分割 32GB,其餘分割給 `/home`;部分軟體的資料如 mysql server 的預設 database 路徑會使用 `/var`,建議修改它的設定檔放到 `/home` 去;商用套裝軟體有時會被安裝在 `/opt` 下,但一般沒有特別獨立出 `/opt` 分割區,所以會佔用到 `/` 的空間,這種時候會建議建立符號連結將 `/opt` 指到 `/home` 分割區下的某個路徑。
* boot 分割區是 UEFI 系統需要用到的,一般掛在 `/boot/efi` 這個路徑下,而且必須是 `fat32` 格式,通常只要能容納約 128KB 的 `grubx64.efi`。習慣上 UEFI 系統不單獨分割 `/boot` 分割區,只會把 `/boot/efi` 獨立出來。
* 非 UEFI 系統也需要一個 boot 分割區,一般掛在 `/boot` 這個路徑下,不需要是 `fat32` 檔案系統,必須夠大且能容納 kernel 及 initramfs。
* 如果需要獨立的 `/usr` 分割區,做 kernel 時需要一併製作 initramfs 將該檔案系統對應的 fsck 工具放進去,ext4 檔案系統的 fsck 工具在 /sbin 目錄中,不需要這個步驟。
* 如果不想要使用 interactive mode 進行分割,上述指令也能當參數銜接在 `parted /dev/sda` 之後,譬如 `parted /dev/sda mklabel gpt`,需要以 script 大量部署機器時可以考慮使用。
* 如果虛擬機器內的虛擬磁碟機設定在實體機器的 SSD 上,建議在傳統硬碟上另外造一個 swap 空間專用的虛擬磁碟機,否則在記憶體分配不夠大的情況下使用 `make -j<N>` 會對 swap 空間進行大量的寫入操作,SSD 的壽命損耗速度會很驚人。
:::
:::warning
* 不使用 swap 空間的話必須確保系統上有安裝足夠的記憶體,否則在使用 emerge 以 `make -j<N>` 編譯套件原始碼時可能出現記憶體不足的錯誤。在虛擬機器內因為常分配較少的記憶體,沒有 swap 空間且 N 值夠大時容易造成 make 失敗。
:::
4. 輸入 `print` 指令確認分割結果:
```
Partition Table: gpt
Disk Flags:
Number Start End Size File system Name Flags
1 1049kB 3146kB 2097kB fat32 grub bios_grub
2 3146kB 153MB 150MB fat32 boot boot, esp
3 153MB 60.2GB 60.0GB ext4 rootfs
4 60.2GB 70.2GB 10.0GB ext4 var
5 70.2GB 122.2GB 32.0GB linux-swap swap
6 122.2GB 300GB 177.8GB ext4 home
```
:::warning
* `set 1 bios_grub on` 和 `set 2 boot on` 容易被遺忘,沒執行到的話這邊不會出現對應的 flags,務必做好檢查。
:::
5. 輸入 `quit` 退出 parted。
6. 依序執行以下指令格式化分割區:
```
mkfs.vfat -F 32 /dev/sda2
mkfs.ext4 /dev/sda3
mkfs.ext4 /dev/sda4
mkswap /dev/sda5
mkfs.ext4 /dev/sda6
```
7. 執行 `swapon /dev/sda5` 啟用 swap 空間。
8. 依序執行下列指令建立空目錄及掛載分割區:
```
mount /dev/sda3 /mnt/gentoo
mkdir /mnt/gentoo/var
mkdir /mnt/gentoo/home
mkdir -p /mnt/gentoo/boot/efi
mount /dev/sda2 /mnt/gentoo/boot/efi
mount /dev/sda4 /mnt/gentoo/var
```
:::info
* /home 分割區在安裝階段不需要掛載。
* 先前有建立 /usr 分割區的在這階段也需建立對應目錄及掛載。
:::
## 安裝 stage3 並進入 chroot 環境
參閱 [installing the Gentoo installation files](https://wiki.gentoo.org/wiki/Handbook:AMD64/Installation/Stage) 及 [installing the Gentoo base system](https://wiki.gentoo.org/wiki/Handbook:AMD64/Installation/Base) 前半部分。
1. 回到 [Gentoo 官網](https://www.gentoo.org/downloads/)下載 amd64 的 stage3 tarball,這裡選用 [openrc](https://wiki.gentoo.org/wiki/OpenRC) 的版本。如有需求,也可以在此選用 [systemd](https://wiki.gentoo.org/wiki/Systemd) 的版本。
2. 在 `/mnt/gentoo` 以 tar 指令解開 stage3 tarball,tar 解壓縮參數使用 `xpvf <filename> --xattrs-include='*.*' --numeric-owner`。
3. 執行 `nano -w /mnt/gentoo/etc/portage/make.conf` 編輯 make.conf,修改內容如下:
```!
# built this stage.
# Please consult /usr/share/portage/config/make.conf.example for a more
# detailed example.
COMMON_FLAGS="-O3 -pipe -fomit-frame-pointer -march=native -mtune=native"
CFLAGS="${COMMON_FLAGS}"
CXXFLAGS="${COMMON_FLAGS}"
FCFLAGS="${COMMON_FLAGS}"
FFLAGS="${COMMON_FLAGS}"
MAKEOPTS="-j8 -l8"
# WARNING: Changing your CHOST is not something that should be done lightly.
# Please consult http://www.gentoo.org/doc/en/change-chost.xml before changing.
CHOST="x86_64-pc-linux-gnu"
USE="aes avx avx2 fma3 mmx mmxext popcnt sse sse2 sse3 sse4_1 sse4_2 ssse3 -bindist threads vim-syntax"
# NOTE: This stage was built with the bindist Use flag enabled
PORTDIR="/usr/portage"
DISTDIR="/usr/portage/distfiles"
PKGDIR="/usr/portage/packages"
# This sets the language of build output to English.
# Please keep this setting intact when reporting bugs.
LC_MESSAGES=C
GENTOO_MIRRORS="http://ftp.twaren.net/Linux/Gentoo/ http://ftp.iij.ad.jp/pub/linux/gentoo/"
ACCEPT_LICENSE="*"
ACCEPT_KEYWORDS="~amd64"
FEATURES="splitdebug"
GRUB_PLATFORMS="emu efi-32 efi-64 pc"
```
:::info
* `PORTDIR`、`DISTDIR`、`PKGDIR` 在新版 stage3 提供的 make.conf 預設會放在 /var 下面,這些檔案有相當程度的大小,可根據磁碟分割方式自行決定位置。
* MAKEOPTS 必須根據 CPU threads 數做調整。
* USE 當中的 `aes avx avx2 fma3 mmx mmxext popcnt sse sse2 sse3 sse4_1 sse4_2 ssse3` 必須根據 CPU 特性調整,參考 `/proc/cpuinfo` 的內容。
* `ACCEPT_KEYWORDS` 選用 `~amd64` 是選用 amd64 平台的 testing 套件分支,詳情參閱[官網的說明](https://wiki.gentoo.org/wiki/KEYWORDS)。
* 使用 `valgrind` 除錯需要各套件是在啟用 `splitdebug` 這項 feature 的前提下編譯出來的。
* 如果是要在 `docker build` 的環境下建立 Gentoo 系統的 docker image,FEATURES 應加上 `-ipc-sandbox -pid-sandbox -mount-sandbox -network-sandbox`。
* `GENTOO_MIRRORS` 這行可以使用 `mirrorselect -i -o >> /mnt/gentoo/etc/portage/make.conf` 產生,需要在國外安裝主機時需要從這裡重新選取。
:::
4. 執行下列指令建立預設的 ebuild repository 設定檔
```!
mkdir -p /mnt/gentoo/etc/portage/repos.conf
cp -a /mnt/gentoo/usr/share/portage/config/repos.conf /mnt/gentoo/etc/portage/repos.conf/gentoo.conf
```
5. 執行 `nano -w /mnt/gentoo/etc/portage/repos.conf/gentoo.conf` 將內容修改如下:
```
[DEFAULT]
main-repo = gentoo
[gentoo]
location = /usr/portage
sync-type = rsync
sync-uri = rsync://rsync.tw.gentoo.org/gentoo-portage
auto-sync = yes
sync-rsync-verify-jobs = 1
sync-rsync-verify-metamanifest = yes
sync-rsync-verify-max-age = 24
sync-openpgp-key-path = /usr/share/openpgp-keys/gentoo-release.asc
sync-openpgp-keyserver = hkps://keys.gentoo.org
sync-openpgp-key-refresh-retry-count = 40
sync-openpgp-key-refresh-retry-overall-timeout = 1200
sync-openpgp-key-refresh-retry-delay-exp-base = 2
sync-openpgp-key-refresh-retry-delay-max = 60
sync-openpgp-key-refresh-retry-delay-mult = 4
sync-webrsync-verify-signature = yes
```
:::info
* 第一個修改點是將 `location` 修改為 `/usr/portage`,這個跟 `make.conf` 中的 `PORTDIR` 對應。
* 第二個修改點是將 `sync-uri` 修改為 `rsync://rsync.tw.gentoo.org/gentoo-portage`。如果要在台灣以外的地方安裝系統,可以透過 `mirrorselect -i -r -o` 選取適合的 rsync server。
:::
6. 使用 `date` 指令確認時間,如果不正確,執行 `ntpd -q -g` 或 `ntpdate clock.stdtime.gov.tw` 校正時間。
* 此時尚未設定 timezone,應留意使用 `date` 檢查時間時,其輸出時區是 `UTC`。
7. 執行 `cp -L /etc/resolv.conf /mnt/gentoo/etc/resolv.conf` 複製 DNS server 設定。
8. 執行下列指令掛載特殊檔案系統並進入 chroot 環境
```
mount --types proc /proc /mnt/gentoo/proc
mount --rbind /sys /mnt/gentoo/sys
mount --rbind /dev /mnt/gentoo/dev
chroot /mnt/gentoo /bin/bash
source /etc/profile
export PS1="(chroot) ${PS1}"
```
:::info
* `export PS1="(chroot) ${PS1}"` 用來變更命令列提示符號,提醒自己是在 chroot 環境下,可以隨意自訂。
:::
選用 systemd profile 的話在 chroot 前還需要額外執行這兩行:
```
mount --make-rslave /mnt/gentoo/sys
mount --make-rslave /mnt/gentoo/dev
```
## 初始化套件系統及更新 world
參閱 [installing the Gentoo base system](https://wiki.gentoo.org/wiki/Handbook:AMD64/Installation/Base) 後半部分。
1. 修改 `/etc/locale.gen` 並執行 `locale-gen`,建議的 `/etc/locale.gen` 內容如下:
```
C.UTF8 UTF-8
en_US.UTF-8 UTF-8
zh_CN.UTF-8 UTF-8
zh_TW.UTF-8 UTF-8
zh_TW BIG5
```
2. 使用 `eselect locale set <N>` 選取系統預設的 locale,列表可用 `eselect locale list` 查看,一般建議使用 `C.UTF-8`。
3. 執行 `emerge-webrsync` 下載 portage tree。
4. 執行 `emerge --sync` 同步最新的 portage tree。如果結束後提示要更新 portage 套件 (`* An update to portage is available. It is _highly_ recommended that you update portage now, before any other packages are updated.`),做完後面兩步選完 profile 和設完時區後,執行 `emerge --oneshot sys-apps/portage` 進行更新。提示執行 `eselect news read` 閱讀注意事項時 (`* IMPORTANT: 5 news items need reading for repository 'gentoo'. Use eselect news read to view new items.`),可以照著執行一次讀完全部,或者執行 `eselect news list` 後再用 `eselect news read <N>` 來閱讀指定的項目。
:::info
* 在系統預設 python 版本變遷的過渡時期,執行 `emerge --oneshot sys-apps/portage` 可能遭遇套件相依性問題,此時應閱讀 news 的內容來自力救濟。
* 看到下面的訊息時通常是 rsync server 中風,暫時更換 `/etc/portage/repos.conf/gentoo.conf` 裡的 `sync-uri` 或者新增一行 `sync-allow-hardlinks = no` 通常可以解決:
```!
* Verifying /usr/portage/.tmp-unverified-download-quarantine ...!!! Manifest verification failed:
Manifest mismatch for app-vim/project/Manifest
__exists__: expected: True, have: False
```
:::
5. 使用 `eselect profile set <N>` 選取 profile,列表可用 `eselect profile list` 察看,一般建議選取 `default/linux/amd64/<version>/no-multilib (stable)`。如果先前下載的 stage3 為 systemd 版而不是 openrc 版,這邊應選擇 `default/linux/amd64/<version>/systemd (stable)`。
6. 執行下列指令設定時區
```
echo "Asia/Taipei" > /etc/timezone
emerge --config sys-libs/timezone-data
```
7. 如果記憶體夠大,可以參閱官方文件 [Portage TMPDIR on tmpfs](https://wiki.gentoo.org/wiki/Portage_TMPDIR_on_tmpfs) 將 build 套件的暫存目錄放到記憶體上,官方推薦使用這個方式來延緩 SSD 壽命的損耗。大致上的做法是在 `/etc/fstab` 裡加上下面這行後執行 `mount -a`:
```
tmpfs /var/tmp/portage tmpfs size=4G,uid=portage,gid=portage,mode=775,nosuid,noatime,nodev 0 0
```
8. . 執行 `emerge -vp gcc` 確認套件系統中的 GCC 是否比目前安裝的版本還新,如果是的話,執行 `emerge gcc` 更新 GCC。更新完 GCC 後再執行 `gcc-config <N>` 切換系統 GCC 版本,可用 `gcc-config -l` 查詢可用選項。切換完系統 GCC 版本後,執行 `source /etc/profile` 更新當前 shell 環境變數。
9. 執行 `emerge -e @world` 重新編譯整個 world 的所有套件,如果上個步驟中已經編譯過 GCC 的話,可以改用 `emerge -e --exclude=sys-devel/gcc @world` 節省時間。
* 如果對於系統效能不感興趣,這一步按照官方 handbook 使用 `emerge --update --deep --newuse @world` 更新 world 即可。
10. 如果更新完 world 後看見下面的訊息,應該執行 `perl-cleaner --all` 重新安裝 perl 模組,否則可能會在安裝其它套件時遇到類似 `Can't locate Locale/gettext.pm in @INC` 的錯誤訊息:
```
* Messages for package dev-lang/perl-<version>:
* UPDATE THE PERL MODULES:
* After updating dev-lang/perl the installed Perl modules
* have to be re-installed. In most cases, this is done automatically
* by the package manager, but subsequent steps are still recommended
* to ensure system consistency.
*
* You should start with a depclean to remove any unused perl dependencies
* that may confuse portage in future. Regular depcleans are also encouraged
* as part of your regular update cycle, as that will keep perl upgrades working.
* Recommended: emerge --depclean -va
*
* You should then call perl-cleaner to clean up any old files and trigger any
* remaining rebuilds portage may have missed.
* Use: perl-cleaner --all
```
11. 如果更新完 world 看見 `Use emerge @preserved-rebuild to rebuild packages using these libraries` 的提示,執行 `emerge @preserved-rebuild`。
12. 如果前面更新過 GCC,可以使用 `emerge --unmarge =sys-devel/gcc-<version>` 移除舊版 GCC。
13. 使用 `dispatch-conf` 指令來協助合併 `/etc` 裡的各種設定檔,或者使用 `find /etc -name '._cfg*'` 找出因為舊版設定檔存在而被擱置的新版設定檔,自己決定要覆蓋或是手動合併。
## 編譯及安裝 kernel
參閱 [configuring the Linux kernel](https://wiki.gentoo.org/wiki/Handbook:AMD64/Installation/Kernel)。
### Option 1: 安裝 distribution kernel
適合懶人使用,比用 `genkernel` 還懶。
* 執行 `emerge sys-kernel/gentoo-kernel`,或者執行 `emerge sys-kernel/gentoo-kernel-bin` 安裝預先編譯好的 kernel。
* 這個安裝方式不適用於選用 systemd profile 的場合,但是想辦法偷 distribution kernel 的 `.config` 檔來小幅修改成適合在 systemd 環境用的版本是可行的。參閱[從 distribution kernel 換成自訂 kernel 的說明](https://hackmd.io/@tinlans/gentoo-maintenance#%E5%BE%9E-distribution-kernel-%E6%8F%9B%E6%88%90%E8%87%AA%E8%A8%82-kernel)先安裝 distribution kernel 再取出 `.config` 檔就行,不過因為沒有實際以這個 kernel 開機,所以是從 `/usr/src/linux/.config` 來獲取而不是去 `/proc/config.gz` 取得。實際上手動操作 `ebuild` 應該可以直接取出這個檔案而不用花時間編譯 distribution kernel,這個部分可以自行嘗試。
### Option 2: 手動設定及安裝 kernel
:::info
* 如果要加快編譯速度,這裡可以使用 `make` 的 `-j<N>` 參數。假設 CPU 有 8 threads,下面用到 `make` 指令的地方都可以使用 `make -j8`。
* 預設使用 ld.gold 當 linker 的場合,編譯 kernel 時的 `make` 參數需要加上 `LD=ld.bfd` 強制使用傳統的 BFD linker,譬如 `make LD=ld.bfd -j8`,因為 kernel 的編譯不支援 gold linker。
* 選用 systemd profile 的場合,必要的 kernel 選項參閱[官方的說明頁](https://wiki.gentoo.org/wiki/Systemd)。
:::
1. 執行 `emerge lshw` 及 `emerge pciutils` 安裝顯示硬體資訊的套件,透過這些工具來協助認識硬體配備和對應的驅動程式名稱。
2. 用 `emerge sys-kernel/gentoo-sources` 安裝 kernel source code,會裝在 `/usr/src` 下面,並建立一個符號連結 `/usr/src/linux`。
3. 執行下列指令進入 kernel 設定選單:
```
cd /usr/src/linux
make menuconfig
```
:::info
如果打算從 distribution kernel 的設定來修改,可以執行 `ebuild /usr/portage/sys-kernel/gentoo-kernel/gentoo-kernel-<version>.ebuild configure` 後把 `/var/tmp/portage/sys-kernel/gentoo-kernel-<version>/work/build/.config` 放到 `/usr/src/linux` 目錄下再做 `make menuconfig`;記得執行 `ebuild /usr/portage/sys-kernel/gentoo-kernel/gentoo-kernel-<version>.ebuild clean` 清除先前的工作目錄。
:::
4. 執行`make; make install` 編譯及安裝 kernel。
:::info
如果出現編譯失敗,可能是 `cpio` 沒有安裝,執行 `emerge cpio` 可以解決。
:::
5. 執行 `make modules_install` 安裝 kernel modules,kernel modules 會被安裝到 `/lib/modules/<kernel version>/kernel` 裡面。
:::info
* 如果先前有單獨建立 /usr 分割區且 roofs 的檔案系統不是 ext4 的話,需要先安裝對應的檔案系統工具,並額外安裝 `dracut` 並執行 `dracut -f --host-only --kver=<version>` 產生對應的 initramfs 檔案,其中 `<version>` 是 `/usr/src/linux` 的連結目錄名稱去除 `linux-` 的前綴,譬如 `5.11.4-gentoo`。
* 檔案系統工具可參考 [filesystem tools](https://wiki.gentoo.org/wiki/Handbook:AMD64/Installation/Tools#Filesystem_tools) 裡的表格。
* 如果有把各種驅動程式都編譯成 kernel modules 而不是內建在 kernel 裡的習慣,一般也需要 initramfs,譬如某些虛擬硬碟可能需要額外的驅動程式才能載入,這會導致 rootfs 所對應的裝置無法被 kernel 找到。
* 製作好 initramfs 之後,建議以 `lsinitrd /boot/initramfs-<version>.img | grep <driver name>` 的方式檢查需要的驅動程式是否已被放在裡面。
:::
### 開機自動載入 kernel modules
* 大部分的 kernel modules 在開機時會由 udevd 自動偵測並載入,只有無法自動偵測到的情況需要手動添加。
* 建立 `/etc/modules-load.d` 這個目錄,在裡面建立 `*.conf` 檔來自動載入需要的 kernel modules。
### firmware 安裝
* 有些硬體 (特別是網路卡) 的驅動程式還需要搭配韌體才能正常運作,這時需要用 `emerge linux-firmware` 安裝韌體包。
## 設定 bootloader
參閱 [configuring the bootloader](https://wiki.gentoo.org/wiki/Handbook:AMD64/Installation/Bootloader)。這邊以安裝 `grub2` 為例,近年有人推薦 `rEFInd` 可自行嘗試,可參閱 [rEFInd 的說明頁面](https://wiki.gentoo.org/wiki/Refind)。
1. `emerge grub`
2. `grub-install --target=x86_64-efi --efi-directory=/boot/efi`
* 非 UEFI 系統執行 `grub-install /dev/sda` 或 `grub-install --no-floppy /dev/sda`
* 如果開機光碟不是 Gentoo 官方的 minimal installation CD,可能會出現 `Could not prepare Boot variable: Read-only file system` 的錯誤,執行 `mount -o remount,rw /sys/firmware/efi/efivars` 即可正常執行 `grub-install`。
:::info
如果未來打算把硬碟拔去別台機器開機,這裡可以改執行 `grub-install --target=x86_64-efi --efi-directory=/boot/efi --removable` 將 BOOTX64.EFI 安裝到 /boot/efi/EFI/BOOT 裡,而不是將 grubx64.efi 安裝到 /boot/efi/EFI/gentoo 並透過 efibootmgr 等工具記錄在 EFI BIOS 上。
:::
3. 視需求修改 `/etc/default/grub`。
* 較舊的 CPU 可能會需要設定 `GRUB_CMDLINE_LINUX_DEFAULT="mitigations=off"` 犧牲安全性來提高效能,參閱 [HOWTO make Linux run blazing fast (again) on Intel CPUs](https://linuxreviews.org/HOWTO_make_Linux_run_blazing_fast_(again)_on_Intel_CPUs)。
:::info
如果選用 systemd profile 且不打算使用 initramfs 的話,應該在 `GRUB_CMDLINE_LINUX` 裡加入 `init=/lib/systemd/systemd`。如果有使用 dracut 產生 initramfs,通常 systemd 已經被放進去,就不需要加上。
:::
4. 執行 `grub-mkconfig -o /boot/grub/grub.cfg` 產生 `grub.cfg`,會掃描 `/boot/vmlinuz*` 和 `/boot/initramfs*` 來產生開機選單。
## 設定系統
參閱 [configuring the system](https://wiki.gentoo.org/wiki/Handbook:AMD64/Installation/System)、[installing system tools](https://wiki.gentoo.org/wiki/Handbook:AMD64/Installation/Tools) 及 [finalizing the installation](https://wiki.gentoo.org/wiki/Handbook:AMD64/Installation/Finalizing)。
### OpenRC 和 systemd 的共通部分
1. 建立 `/etc/fstab` 如下:
```
# <fs> <mountpoint> <type> <opts> <dump/pass>
UUID=47B6-7C16 /boot/efi vfat noauto,noatime 1 2
UUID=03be0c9d-2bc6-4d3b-8414-a49615d12e52 / ext4 noatime 0 1
UUID=51e02091-906f-4610-8854-e2c870decc8d /var ext4 noatime 0 2
UUID=19ea6cfa-6c44-4989-b262-cb238e312c36 /home ext4 noatime 0 2
UUID=33ba0cd8-ce60-4bd9-9ac5-9825ea0f2ab0 none swap sw 0 0
```
:::info
* 上述 UUID 不可照抄,應使用 `blkid` 或 `ls -l /dev/disk/by-uuid` 確認。
* 可以用 `blkid` 的 `PARTLABEL` 欄位資料來確認對應關係,這是先前在使用 `parted` 分割磁碟時所設定的名稱。其中 `rootfs` 的對應 mountpoint 為 `/`,`swap` 的 mountpoint 為 `none`。
* 使用 `blkid` 查詢 `UUID` 時要留意 `PARTUUID` 和 `UUID` 是不同的,應該使用 `UUID` 欄位,如果不放心的話建議用 `ls -l /dev/disk/by-uuid` 來對照最終的 `/etc/fstab` 做雙重確認。
:::
2. 在 `/etc/inputrc` 的適當處加入下列設定讓上下鍵可以進行 history search:
```
## arrow up
"\e[A": history-search-backward
## arrow down
"\e[B": history-search-forward
```
:::info
這個功能是如果先前已經執行過 `docker build --no-cache -f <name>.dockerfile -t <name>:0.0.1 .` 這道指令的話,只要再輸入 `docker b` 這樣前半段相同的部分指令內容,再按:arrow_up:就能把 match 到的歷史指令 `docker build --no-cache -f <name>.dockerfile -t <name>:0.0.1 .` 叫出來,前提是那道指令還在 history buffer 裡。
:::
3. 如果需要啟用 root 帳號,使用 `passwd` 修改 root 密碼。
4. 使用 `useradd` 指令新增使用者,使用 `passwd` 指令修改使用者密碼。
5. 安裝 `sudo` 套件,使用 `visudo` 進行設定。
6. 修改 `/etc/ssh/sshd_config`,如果要啟用 root 登入需要 `PermitRootLogin yes` 這項設定。習慣使用 public key authentication 方式登入的話,在這裡要記得把 public keys 放到指定帳號的 `~/.ssh/authorized_keys` 檔案中。
:::info
* OpenSSH 8.8 開始預設禁止 ssh-rsa 形式的 key,如果要重新啟用,在 `/etc/ssh/sshd_config` 加入下面這兩行:
```
PubkeyAcceptedAlgorithms=+ssh-rsa
HostKeyAlgorithms=+ssh-rsa
```
:::
7. 安裝 `gentoolkit` 增加套件系統管理的便利性,其中 `equery` 是最常被使用到的指令,可參閱其[說明頁面](https://wiki.gentoo.org/wiki/Equery)。
8. 如果想要使用 [NetworkManager](https://wiki.gentoo.org/wiki/NetworkManager) 代替 OpenRC 的 [netifrc](https://wiki.gentoo.org/wiki/Netifrc) 或 systemd 的 [networkd service](https://wiki.gentoo.org/wiki/Systemd#systemd-networkd),需要執行 `emerge networkmanager` 安裝它。然後在 OpenRC 系統,執行 `rc-update add NetworkManager default` 讓它在開機時啟動,在 systemd 系統則需要執行 `systemctl enable NetworkManager.service`。`NetworkManager` 在純文字模式使用 `nmtui` 指令進行設定,並將設定內容儲存在 `/etc/NetworkManager/system-connections/*`。
:::info
* 如果不希望 `NetworkManager` 接管某些網路卡並擅自啟用 DHCP,可以編輯 `/etc/NetworkManager/NetworkManager.conf` 並加入以下內容:
```
[main]
plugins=keyfile
[keyfile]
unmanaged-devices=interface-name:eno3,interface-name:eno4
```
這個例子是避免讓 `NetworkManager` 接管 `eno3` 和 `eno4` 兩張網路卡。
:::
9. 修改密碼複雜度限制
某個時間點開始 Gentoo 也要求密碼必須符合一定程度的複雜度限制,修改 `/etc/security/passwdqc.conf` 可以還原回舊版的設定:
```
min=8,8,8,8,8
max=40
passphrase=3
match=4
similar=deny
random=47
enforce=everyone
retry=3
```
### OpenRC 系統設定
1. 編輯 `/etc/conf.d/hostname` 加入主機名稱,譬如 `hostname="my-server1"`。
2. 選用 `NetworkManager` 的話,執行 `nmtui` 設定網路。選用 `netifrc` 的話則編輯 `/etc/conf.d/net` 內容如下:
```
modules="dhcpcd"
dns_domain_lo="tinlans.org"
config_eth0="dhcp"
```
:::info
* 網路卡名稱不一定是 `eth0`,應根據 `ifconfig` 的輸出結果來判斷。
* 如果區域網路上沒有 DHCP server 需要設定固定 IP,可以仿照下列格式設定:
```
dns_domain_lo="tinlans.org"
config_eth0="10.168.100.99 netmask 255.255.255.0 brd 10.168.100.255"
routes_eth0="default via 10.168.100.254"
```
* 完整設定範例參考 `/usr/share/doc/netifrc-<version>/net.example.bz2`,可以使用 `bzcat` 或 `bzless` 指令閱讀。
:::
3. 選用 `netifrc` 的話,執行下列指令讓系統在開機時自動啟用網路,必須代換 `eth0` 成實際的 interface name:
```
cd /etc/init.d
ln -fs net.lo net.eth0
rc-update add net.eth0 default
```
4. 將 `/etc/hosts` 裡 `127.0.0.1` 這行做適當修改,譬如 hostname 為 `my-server1` 的話,可以修改成 `127.0.0.1 my-server1.tinlans.org my-server1 localhost`。
5. 確認系統時鐘是否使用 UTC 時間,修改 `/etc/conf.d/hwclock` 的內容為 `clock="UTC"` 或 `clock="local"`,一般使用 `clock="local"`。
6. 執行 `rc-update add sshd default` 在開機完成後接受 SSH 登入。
7. 安裝 `sysklogd` 或 `syslog-ng` 並利用 `rc-update add` 設定開機自動啟動,讓系統 log 被寫入 `/var/log/*` 裡。
8. 安裝 `logrotate` 避免 log 檔爆掉。
9. 安裝 `cronie` 並執行 `rc-update add cronie default` 讓系統支援 cron jobs。
10. 其它還有什麼要裝的等重開進安裝好的系統裡之後再裝。
### systemd 系統設定
參閱 Gentoo 官方的 [systemd 說明頁面](https://wiki.gentoo.org/wiki/Systemd)。如果是從 OpenRC 轉到 systemd 但不熟悉指令差異的話,可以參閱 Gentoo 官方提供的 [OpenRC to systemd Cheatsheet](https://wiki.gentoo.org/wiki/OpenRC_to_systemd_Cheatsheet)。
在 systemd 文件中提及有一組 [preset services](https://wiki.gentoo.org/wiki/Systemd#Preset_services) 可以使用 `systemctl preset-all` 一口氣啟用。如果想知道裡面有什麼並且自行決定啟用哪些部分,可以閱讀 `/lib/systemd/system-preset/90-systemd.preset` 這個檔案的內容,而在這裡的範例並不打算使用該指令開啟 preset services。
systemd 系統的設定幾乎只能重開到安裝後的系統裡才能做,所以要先按照後面的[重開機流程](https://hackmd.io/@tinlans/gentoo-installation#%E9%87%8D%E9%96%8B%E6%A9%9F%E9%80%B2%E5%85%A5%E5%AE%89%E8%A3%9D%E5%BE%8C%E7%9A%84%E7%B3%BB%E7%B5%B1%E8%A3%A1)開進安裝後的系統再進行設定。重開之後,執行 `systemctl status` 確認 systemd 已經在運作中,再按照下面流程設定系統:
1. 執行 `systemd-machine-id-setup` 產生 machine ID 並自動建立 `/etc/machine-id`。如果是從 stage4 tarball 安裝,先執行 `rm -f /etc/machine-id` 刪除該檔後再執行。
2. 執行 `hostnamectl set-hostname <hostname>` 修改主機名稱,這個指令會將主機名稱寫入 `/etc/hostname` 檔中。
3. 執行 `timedatectl set-timezone Asia/Taipei` 設定時區。
4. 設定網路:
* 選用 `NetworkManager` 的話,先執行下列指令啟用 `NetworkManager` 再執行 `nmtui` 設定網路:
```
systemctl enable NetworkManager.service
systemctl start NetworkManager.service
```
如果所有網路卡都使用 DHCP 獲取 IP 則不需要設定,但還是建議執行 `nmtui` 檢查設定。
* 選用 `networkd` service 的話,如果使用 DHCP 獲取 IP 位址,新增一個檔案 `/etc/systemd/network/50-dhcp.network`,內容為:
```
[Match]
Name=eth0
[Network]
DHCP=yes
```
如果使用靜態 IP,新增一個檔案 `/etc/systemd/network/50-static.network`,內容為
```
[Match]
Name=eth0
[Network]
Address=10.168.100.99/24
Gateway=10.168.100.254
DNS=10.168.100.3
```
其中 `eth0` 為網路卡名稱,更詳細的設定格式可參閱 [systemd.network(5)](https://man7.org/linux/man-pages/man5/systemd.network.5.html)。依序執行以下指令以啟用網路:
```
systemctl enable systemd-networkd.service
systemctl start systemd-networkd.service
```
5. 如果透過 DHCP 獲取 DNS server 設定,編輯 `/etc/systemd/resolved.conf` 將預設搜尋網域加入 `Domains=`,譬如 `Domains=skymirror.com.tw`,然後依序執行以下指令以啟用 resolved service,並使用它所產生的 `resolv.conf` 檔:
```
rm -f /etc/resolv.conf
systemctl enable systemd-resolved.service
systemctl start systemd-resolved.service
ln -fs /run/systemd/resolve/resolv.conf /etc/resolv.conf
```
6. 將 `/etc/hosts` 裡 `127.0.0.1` 這行做適當修改,譬如 hostname 為 `my-server1` 的話,可以修改成 `127.0.0.1 my-server1.tinlans.org my-server1 localhost`。
7. 執行以下指令以啟用 sshd:
```
systemctl enable sshd.service
systemctl start sshd.service
```
8. 以 `emerge cronie` 安裝 `cronie`,再執行以下指令啟用它以支援 crontab:
```
systemctl enable cronie.service
systemctl start cronie.service
```
雖然官方文件建議安裝 `systemd-cron` 並啟用 `cron.target` 來模擬 cron 的行為,但這裡還是推薦使用 `cronie` 以獲得完整的使用體驗。另外,systemd 也推薦使用 [timer service](https://wiki.gentoo.org/wiki/Systemd#Timer_services) 來代替 cron,但不習慣的人還是很多,因此這邊還是建議安裝 `cronie`。
9. 預設啟動的 `journald` service 替代了以往的 `sysklogd` 或 `syslog-ng` 這類 log service 的角色,使用 [journalctl](https://wiki.gentoo.org/wiki/Systemd#Handling_of_log_files) 指令讀取 log,一般使用者如果要讀取 log 必須加入 `systemd-journal` 群組。預設最大使用 4GB 的空間,可以透過編輯 `/etc/systemd/journald.conf` 修改 `SystemMaxUse` 來調整,譬如 `SystemMaxUse=10G`。
10. 安裝 `logrotate` 防止會自行寫 log files 的程式把硬碟寫爆,安裝完後要執行 `systemd-tmpfiles --create /usr/lib/tmpfiles.d/logrotate.conf`。
11. `tmp.mount` 預設會將把 `tmpfs` 掛上 `/tmp`,最大可以佔用系統記憶體的 50%。變更它預設值的方式很多,systemd 推薦使用 `/etc/fstab` 的形式。首先執行 `systemctl cat tmp.mount` 查看設定,找到 `[Mount]` 段的 `Options` 的設定值,如果看到的內容是 `mode=1777,strictatime,nosuid,nodev,size=50%,nr_inodes=400k` 的話,對應的 `/etc/fstab` 設定如下:
```
tmpfs /tmp tmpfs mode=1777,strictatime,nosuid,nodev,size=50%,nr_inodes=400k 0 0
```
如果想將記憶體佔用量修改成 2GB,將 `size=50%` 修改成 `size=2G` 後重新開機即可。如果想讓設定立即生效,可以先執行 `systemctl stop tmp.mount` 後再執行 `mount -a`。因為 `tmp.mount` 只要發現系統上已經掛載 `/tmp` 就不會有任何動作,所以重新開機後會以 `/etc/fstab` 裡掛載 `/tmp` 的設定為主。
## 重開機進入安裝後的系統裡
參閱 [rebooting the system](https://wiki.gentoo.org/wiki/Handbook:AMD64/Installation/Bootloader#Rebooting_the_system)。
1. 執行 `exit` 退出 chroot 環境。
2. 執行 `cd` 回到 `/root` 下,總之不能停留在 `/mnt/gentoo` 底下的任何路徑。
3. 執行 `umount -l /mnt/gentoo/dev{/shm,/pts,}` 和 `umount -R /mnt/gentoo`,如果無法 umount,確認上一步是否確實做到。
4. 執行 `reboot`,拔除 USB 隨身碟或取出安裝光碟,並進入 BIOS 設定中確認開機順序是否符合預期。
## 其它常用套件
* `net-misc/ntp`: ntpdate, ntpd
* `net-misc/netkit-telnetd`: telnet, telnetd
* `net-ftp/ftp`: ftp
* `net-misc/netkit-fingerd`: finger, fingerd
* `net-misc/whois`
* `net-dns/bind-tools`: host, nslookup, dig
* `net-analyzer/traceroute`
* `net-analyzer/tcptraceroute`
* `net-analyzer/tcpdump`
* `sys-apps/ethtool`
* `sys-apps/ipmitool`
* `sys-apps/lshw`
* `dev-vcs/git`
* `app-misc/screen`
* `app-misc/tmux`
## stage4 tarball
stage3 通常已經提供了一個預先編譯好的 world 環境,只需要自行編譯 kernel 並設定 bootloader 即可完成安裝;而 stage4 則是連 kernel 都編譯好,並且在 world 中可能還會預先安裝一些額外的套件,只要設定好 bootloader 即可完成安裝。Gentoo 官方並不會提供 stage4 tarball,需要自行製作。
### 製作 stage4 tarball
參閱 [Mkstage4 - Stage 4 Tarballs Made Easy](https://www.tutorials.chymera.eu/blog/2014/05/18/mkstage4-stage4-tarballs-made-easy/)。
1. `emerge mkstage4`
2. `cd /home` 或選擇其它空間較大的分割區。
3. `mkstage4 -s <tarball name>`,會提示實際的指令內容是 `tar -cpP --ignore-failed-read --xattrs-include='*.*' --numeric-owner -j --exclude=/dev/* --exclude=/var/tmp/* --exclude=/media/* --exclude=/mnt/*/* --exclude=/proc/* --exclude=/run/* --exclude=/sys/* --exclude=/tmp/* --exclude=/var/lock/* --exclude=/var/log/* --exclude=/var/run/* --exclude=/var/lib/docker/* --exclude=/home/<tarball name>.tar.bz2 --exclude=/usr/portage/* --exclude=/usr/portage/distfiles/* -f /home/<tarball name>.tar.bz2 /`,按 yes 即會製作出 stage4 tarball,或者可以自行修改指令內容後手動執行。
### 使用 stage4 tarball 安裝系統
按照標準安裝流程以[光碟開機](https://hackmd.io/@tinlans/gentoo-installation#%E9%96%8B%E6%A9%9F%E5%8F%8A%E5%95%9F%E7%94%A8-sshd)、[分割硬碟、格式化、掛載分割區](https://hackmd.io/@tinlans/gentoo-installation#%E7%A3%81%E7%A2%9F%E5%88%86%E5%89%B2%E5%8F%8A%E6%A0%BC%E5%BC%8F%E5%8C%96)後,把原本[解開 stage3 tarball](https://hackmd.io/@tinlans/gentoo-installation#%E5%AE%89%E8%A3%9D-stage3-%E4%B8%A6%E9%80%B2%E5%85%A5-chroot-%E7%92%B0%E5%A2%83) 的步驟改成解開原先自己製作好的 stage4 tarball 再 chroot,跳過 world 及 kernel 的編譯流程,直接[安裝 bootloader](https://hackmd.io/@tinlans/gentoo-installation#%E8%A8%AD%E5%AE%9A-bootloader) 並[設定系統](https://hackmd.io/@tinlans/gentoo-installation#%E8%A8%AD%E5%AE%9A%E7%B3%BB%E7%B5%B1)後即可[重新啟動](https://hackmd.io/@tinlans/gentoo-installation#%E9%87%8D%E9%96%8B%E6%A9%9F%E9%80%B2%E5%85%A5%E5%AE%89%E8%A3%9D%E5%BE%8C%E7%9A%84%E7%B3%BB%E7%B5%B1%E8%A3%A1)完成安裝。
解壓 stage4 tarball 時並不需要加入任何複雜的參數,使用 `tar xvjpf <tarball name>.tar.bz2` 即可,官方 handbook 推薦的 stage3 tarball 解壓參數 `--xattrs-include='*.*' --numeric-owner` 已經在製作 stage4 tarball 時加入。
:::info
* 務必記得修改完 /etc/fstab 再重開機,否則無法正確掛載分割區。
* 使用 systemd 系統的話,重開機後要產生新的 machine id:
```
rm /etc/machine-id
systemd-machine-id-setup
```
:::