Arch Linux - WiFi接続、LVMで最強の自宅開発用サーバ構築

今回は総額30万かけて、CPU i9 (24スレッド)、メモリ128GB、ストレージ3TBの新しく自宅開発用としてサーバを準備しました。WiFIとLVMでサーバを作るのですが、ネット上では、ArchlinuxでLVM、WiFiで安定サーバ構築する手順が古かったり、要所の説明が抜けていたりと、分かりやすいのが見当たらなかったので、備忘録として、まとめておきます。随時、追加・更新していく予定です。ネット上の知見を実際に試して、ベストなやり方でまとめる方向ですが、よりベターなものや、修正点あればアドバイスお願いします！

# 開発用サーバスペック
```
CPU      : Intel Core i9-12900 [2.4GHz/16コア(Pコア8+Eコア8)24スレッド/UHD770/TDP65W] Alder Lake-S搭載モデル
MOTHER   : ASUS PRIME B660M-AJ D4 [Intel B660 chipset]
MEMORY   : 128GB[32GB*4枚] DDR4-3200 [メジャーチップ・8層基板] Dual Channel
HDD/SSD  : Western Digital WD Black SN850X WDS200T2X0E [M.2 PCI-E GEN4 SSD 2TB]★PCI-E4.0対応 超高速次世代SSD
HD/option: Crucial CT1000MX500SSD1 [SSD 1TB]
VGA      : GeForce GT1030 2GB [DVI/HDMI]
無線LAN      : 古いUSBタイプのもの
```

# 要件
- 24x365稼働
- ビッグデータ系MLに多用するのでCPUやストレージIO酷使
- SSDは３TBだが増設の余地を残す
- ネットワークはWiFi経由でつなぐ
- GUI不要
- バックアップは週１ぐらいでとる

# 目指すサーバ
- 安定性と拡張性を重視した、必要最小限で構成し、演算等に全リソースを振り向けるミニマリスト最強サーバ

# 構築するサーバ概要
先ずは、サーバ構築時に色々な構成を迷って、VirtualBox環境でかなりの時間を費やし試したり、ネットから情報収集したものを選別して、ポイントとなりそうな部分は下記のような構成でサーバの構築を進めます。
| 考慮点 | 選択 | 理由 |
| --- | --- | --- |
| Distribution | Arch | 安定性とカスタマイズ性などからArchを選択|
| File System | BTRFS | スナップショットや動的なパーティションでリソース最大限利用できるためBTRFSを選択 |
| WiFi | iwd | NWに最小限で安定的につなげられそうなのでiwdを選択 |
| Boot Loader | systemd-boot | systemdで統一したかったのでGrubではなくこちらを選択 |
| LVM | Yes | SSD増設時のLV構成拡張が簡単にできるようLVM2を選択 |
| Swap | zramd | swapも効率的にSWap使えるようzramdでLVM上に作ります |
| Kernel | linux-lts | 安定版を選択 |
| AUR Helper | paru | yayの後継を選択 |
| disk compress | zstd | 効率的な圧縮 |
| GPGPU | Nvidia Docker | 生で入れると環境がかなり汚れるためDockerで切り分けます |

## Kernelの種類
> 　カーネル（kernel）とは、オペレーティングシステム（OS）の基本機能の役割を担うソフトウェアを指します。カーネルは、OSの中でも特に中核的なプログラムであり、ハードディスクやメモリなど、コンピュータの資源管理を行なっています。カーネルは、アプリケーションの実行を許可し、プロセス管理を行います。また、安全なメモリへのアクセス管理や、コンピュータに接続された周辺機器のデバイス管理を行います。プロセス間の通信、割りこみ処理といった処理もカーネルによって行なわれています。
> 
> 　例えばLinux系OSは、OSの中核である「カーネル」と、OSを構成する「他のプログラム」から出来ています。Linux系OSは無償というイメージがありますが、開発者のリーナス・トーバルズ氏が無償で公開しているのは、カーネルの部分です。カーネルに加えて、Linuxカーネル上で動作するライブラリやサブシステム、アプリケーションソフトウェアなどをパッケージ化したものがLinuxディストリビューションと呼ばれており、様々な企業・団体から、商用あるいは無償で配布されています。[用語集｜カーネル](https://www.idcf.jp/words/kernel.html)

サーバ用途なので、今回はカーネルを安定したLTSにしますが、Arch Linuxには下記のKernelタイプがあります。
| Kernel Type | Desc       | Package     |
| ----------- | -----------| ----------- |
| Main |  バニラな Linux カーネルとモジュール、いくつかのパッチが適用 | linux |
| LTS  | 長期サポート (LTS) Linux カーネルおよびモジュール | linux-lts |
| Hardened | カーネルおよびユーザ空間の脆弱性を緩和するための一連の堅牢化パッチを適用した、セキュリティ特化 | linux-hardened |
| Zen | システムを最大限に活用した最新のカーネルからのフォーク。スループットと電力使用量を犠牲にして調整を提供 | linux-zen | 


# 　コンポーネントのレイヤー構成
![fs.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341150/2e49b819-948f-d1b0-8d75-0c9eb1ad8ff9.png)


# インストール手順
何回も仮想環境で色々と試し、最終的に下記の手順で1時間ぐらいで最強の自宅サーバを構築完了。ある程度慣れた人は、この手順を斜めに見てもらえると少しは参考になるかもです。細かい説明等は、先人の別サイト参照ください。

# 事前準備
## Fast Boot
Fast BootはブートローダをGrubではなく、systemd-bootを使う場合、有効にできます。今回はsystemd-bootのためONで変更しません。
> Fast Boot とは、PCの電源を入れた時や、Windows を再起動した際に、BIOSレベルのドライバ初期化などを最小限にとどめ (省略できる所は省略する)、PC起動時のPOSTにかかる時間を短縮する機能。
![Screen Shot 2022-09-25 at 8.28.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341150/67dbe9de-5d9f-da14-e45c-6a4ebc9eacd3.png)

## Secure Bootを無効
Secure Bootも下記の設定をPacman Hookとして入れることで有効にできるみたいですが、私は不要なので無効にしてます。
```
sudo vim /etc/pacman.d/hooks/99-secureboot.hook
==
[Trigger]
Operation = Install
Operation = Upgrade
Type = Package
Target = linux
Target = systemd

[Action]
Description = Signing Kernel for SecureBoot
When = PostTransaction
Exec = /usr/bin/sh -c "/usr/bin/find /boot/ -type f \( -name 'vmlinuz-*' -o -name 'systemd*' \) -exec /usr/bin/sh -c 'if ! /usr/bin/sbverify --list {} 2>/dev/null | /usr/bin/grep -q \"signature certificates\"; then /usr/bin/sbsign --key db.key --cert db.crt --output {} {}; fi' \;"
Depends = sbsigntools
Depends = findutils
Depends = grep
==
```
> 信頼していないOSを、PCで実行しないための仕組みがSecure Bootです。 Secure Bootは、ブートローダーを起動する前に、ブートローダーが特定の証明書を持っているか（電子署名されているか）を判断したのちに、ブートローダーを起動します。これにより、信頼できないブートローダー（改ざんされたブートローダー）を起動しない仕組みになっています。 信頼しているブートローダーであれば、信頼しているOSを実行する、ということが前提となっています。
![Screen Shot 2022-09-25 at 8.31.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/341150/d5859507-200f-5e5f-63c6-0d3c1e460467.png)


# パーティション
> ハードディスクやSSDなどの記憶装置は、利用開始時に内部を複数のパーティションに分割し、それぞれをあたかも一台の独立したストレージのように取り扱うことができる。区画に分割する処理のことをパーティショニング（partitioning）という。
> 
> Windowsパソコンとしてよく用いられるPC/AT互換機の場合、BIOSで制御する機種では一台のストレージ装置について4つまで基本パーティション（プライマリパーティション/基本区画）を作成できる。基本パーティションに代えて一台につき一つだけ拡張パーティション（拡張領域）を作成でき、その中に個数の制限なく論理パーティション（論理領域）を作成できる。
>  拡張パーティションには直接ファイルシステムを作成してデータを保存することはできず、一つ以上の論理パーティションを設定してそこにファイルシステムを置く形となる。OSを起動できるのは基本パーティションだけで、論理パーティションにシステムを置くことはできない。
> 
> BIOSに代えてEFI/UEFIを採用している機種ではGPT（GUIDパーティションテーブル）と呼ばれる新しいパーティション管理方式を採用しており、このような制限はないが、OS側が対応していなければ起動ディスクとすることはできない。[e-Words パーティション 【partition】](https://e-words.jp/w/%E3%83%91%E3%83%BC%E3%83%86%E3%82%A3%E3%82%B7%E3%83%A7%E3%83%B3.html)

USBメディアでArchを立ち上げてから、下記を進めていきます。
パーティションタイプのGUIDに関しては、参照 [ArchWiki GUID](https://wiki.archlinux.org/title/GPT_fdisk#Partition_number)

| gdisk code | Pattition Type |
|:------:|:------:|
| EF00  | EFI  |
| 8200  | SWAP |
| 8300  | Linux  |
```
// nvme0n1パーティション作成
gdisk /dev/nvme0n1

// ブートローダsystemd-boot用EFIパーティション
==
Command (? for help):n
Partition number: 1
First sector     : 何も押さずエンター
Last sector: +1G
Hex code or GUID : ef00
==

// LVM用パーティション
==
Command (? for help):n
Partition number: 2
First sector     : 何も押さずエンター
Last sector      : 何も押さずエンター
Hex code or GUID : 8300

//書き込み
# w
==

// 続いてsdaパーティション作成
gdisk /dev/sda
// LVM用
==
Command (? for help):n
Permission number: 1
First sector     : 何も押さずエンター
Last sector      : 何も押さずエンター
Hex code or GUID : 8300

//書き込み
# w
==
//以上でパーティション完了
```
# LVM
> LVMとは、UNIX系OSで利用できる機能の一つで、複数の外部記憶装置（ストレージ）やその内部のパーティションをまとめ、単一の記憶領域として利用する機能。LVMを利用するにはストレージ内に専用のパーティション（区画）を設ける。パーティション内部は数MB単位のPE（Physical Extent：物理エクステント）と呼ばれる管理単位に分割され、これを必要なだけ結合して単一の論理ボリューム（LV：Logical Volume）を構成する。
> 
> 利用者からは論理ボリュームを通常のパーティションと同じように扱うことができ、特定のファイルシステムでフォーマットして利用することができる。サイズは後から増減することができ、装置を追加して大きく拡大したり、特定の装置を切り離したりすることもできる。
> 
> 単一の広大なボリュームを作成し、利用規模に応じて柔軟に増減できる点が主なメリットだが、物理ディスクやパーティションに直接ファイルシステムを設ける一般的な運用に比べ導入や管理が煩雑で、ファイルシステムと装置の間にLVMが介在する分だけ性能も劣化する。ボリュームが複数の装置にまたがることで障害発生時の対応も複雑で困難になる。[e-Words LVM 【Logical Volume Manager】 論理ボリュームマネージャ](https://e-words.jp/w/LVM.html)
今後SSDの増設の可能性があるため、その際の作業を容易にするためにLVMで構成します。
```
// LVM関連の処理 PV=>VG=>LV作成します
// pv作成 && vg作成 
vgcreate arch_vg /dev/nvme0n1p2 /dev/sda1

// lv作成
lvcreate -n arch_root -l 100%FREE arch_vg
```
作成したストレージは、下記のコマンドで確認できます
```
//PV(フィジカルボリューム)
pvdisplay 

//VG(ボリュームグループ)
vgdisplay 

//LV(ロジカルボリューム)
lvdisplay
```

# ファイルシステム フォーマット
> ファイルシステムとは、OSの機能の一つで、永続的にデータを保存できる記憶装置（ストレージ/外部記憶装置）内部の記録状態を管理・制御し、人間に分かりやすいファイル単位でデータの書き込みや読み出しができるようにするシステム。ストレージ以外のシステム上の資源もファイル単位で取り扱えるようにするものもある。ファイルシステムはストレージ内に設けられた連続した領域（ディスクなどの記憶媒体そのものや、その内部を分割したパーティション、ボリュームなど）を等容量の微細な領域に区画分けし、そのどこに何が記録されているかを記録する管理領域を作成する。
> 
> データはファイル（file）と呼ばれる単位で管理され、任意の長さ（最大長に制限がある場合がある）のデータをストレージ上の空いている領域へ記録する。データは連続した領域に記録されるとは限らず、一つのファイルが複数の空き領域に分散して記録される場合もある。ファイルには任意のファイル名を付けることができ、作成日や最終更新日（タイムスタンプ）、ファイルシステム上での位置（どのディレクトリに含まれるか）などの情報が管理領域に記録される。
> 
> 人間や実行中のプログラムがストレージを操作する際は、いきなり内部の特定の位置を読み書きするのではなく、ファイルシステムに対してファイル名やパス（path：ストレージ内の位置情報）などを指定してファイルの作成や書き込み、読み込み、上書き、削除などの操作を依頼する。ファイルシステムは管理領域を参照して既存のファイルの記録位置を割り出し、読み込みや書き込みを行なったり、新しいファイル用の領域を確保して管理領域に追加したり、削除されたファイルの領域を解放して管理領域から抹消したりといった操作を行う。[e-Words ファイルシステム 【file system】 FS](https://e-words.jp/w/%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%82%B7%E3%82%B9%E3%83%86%E3%83%A0.html)

ストレージは、SSD (Solid State Drive) で、高速データ転送できます。Btrfs はSSDを扱うのによく最適化されているため、これでいきます。
```
// EFI領域をFat32でフォーマット
mkfs.vfat -F32 /dev/nvme0n1p1

// BTRFSにフォーマット
mkfs.btrfs /dev/arch_vg/arch_root

// カーネルによってすでにロードされている、あるいは組み込まれているファイルシステム
cat /proc/filesystems
```
# マウントとSubvolume作成
> subvolumeはBtrfs独特の概念で、ファイルシステムをさらに小分けにするというものです。何故これが必要かというと、例えば後述のスナップショットがあります。Btrfsでのスナップショットはsubvolume単位で行います。なので独立してバックアップを取りたい範囲にsubvolumeを切り出しておくことが重要です。

Btrfsで３つのSubvolume（/, /home, /opt）を切ります。サブボリュームは動的にサイズが調整されるので、無駄がないのがBTRFSです。
```

// マウント関連の処理
mount /dev/arch_vg/arch_root /mnt
cd /mnt
btrfs subvolume create @
btrfs subvolume create @home
btrfs subvolume create @opt
cd
umount /mnt

// BTRFSのマウント
mount -o noatime,space_cache=v2,compress=zstd,ssd,discard=async,subvol=@ /dev/arch_vg/arch_root /mnt
mount --mkdir  -o noatime,space_cache=v2,compress=zstd,ssd,discard=async,subvol=@home /dev/arch_vg/arch_root /mnt/home
mount --mkdir  -o noatime,space_cache=v2,compress=zstd,ssd,discard=async,subvol=@opt /dev/arch_vg/arch_root /mnt/opt

// EFIのマウント
mount --mkdir /dev/nvme0n1p1 /mnt/boot
```
# ネットワークの設定
Wifiネットワークを利用するための設定を行います。
> iwd (iNet wireless daemon) は Intel によって書かれた Linux 用の無線デーモンです。プロジェクトの中心的な目標は、外部ライブラリに依存せず、Linux カーネルが提供する機能を最大限に活用することにより、リソース使用率を最適化することです。
>
> iwd はスタンドアロンでも動作しますが ConnMan、systemd-networkd や NetworkManager のような包括的なネットワークマネージャーとの組み合わせて使うこともできます。
```
//NW接続
iwctl
==
//NWの設定
// WiFi Connection
iwctl
// ネットワークDeviceを確認
#device list
// ネットワークのScan
# station wlan0 scan
// APを取得
# station wlan0 get-networks
// AP接続
# station wlan0 connect aterm-xxxxxxxx
// iwから抜ける
# exit
==
```
iwctlその他の操作
```
// known network リスト表示
iwctl known-networks list

// known networkから削除
iwctl known-networks aterm-b90d0a-g forget
```
# Archインストール
ここからArchのベースシステムのインストールを始めます。
> Arch Linuxの特徴として、デフォルトでは必要最小限のソフトウェアしか入っていません。 そしてユーザは、ユーザが必要なものを選んでシステムを構築していくことを要求されます。 このことは、Arch Linuxはデスクトップ・サーバどちらの用途に向いているか？ はユーザ次第ということを意味します。

```
//マウントされているファイルシステムやスワップ領域をfstabに追記
genfstab -U /mnt >> /mnt/etc/fstab

//最低限のパッケージをインストール 
pacstrap /mnt base base-devel linux-lts linux-lts-headers linux-firmware intel-ucode lvm2 btrfs-progs iwd git vim zsh openssh

//ルートディレクト切り替え
arch-chroot /mnt
```

# initramfsインストール
> - かつてはinitrdという「ファイルシステムイメージ」と「RAM上に作られた擬似ブロックデバイス」を使っていました。
> - これだと、結局initrdを解釈するためのファイルシステムを組み込む必要があったりするなどデメリットが多いです。
> - そこで、今のinitramfsの仕組みができました。メモリ上にファイルシステムを作っておき、そこにinitramfsのイメージを展開します。
> - initramfsのイメージはcpio形式のアーカイブファイルをgzip圧縮したものです。(圧縮形式はgzip形式以外にも複数サポートしているようです)
> [Qiita initramfsについて](https://qiita.com/akachochin/items/d38b538fcabf9ff80531)
```
//先ずは、AUR ヘルパーでインストールするパッケージがあるため、実行権限の関係から一般ユーザを作ります。
//ROOTパスワード設定
passwd

//ユーザ追加
useradd -m -G wheel <USER> -s /bin/zsh

//パスワード設定
passwd <USER>

//sudoer追加
visudo
==
//コメントアウト
%wheel ALL=(ALL:ALL) ALL
==

# Cronでsudo使う処理がある場合、パスワード入力を回避する
sudo -su root
vim /etc/sudoers.d/10_cron
==
Defaults:user !requiretty
user ALL=(root)   NOPASSWD:    /opt/xxx/xxx.sh
==

chmod 440 /etc/sudoers.d/10_cron

visudo –c
==
/etc/sudoers: parsed OK
/etc/sudoers.d/10_cron: parsed OK
==


//AUR ヘルパーインストール
//一般ユーザからparuを実施
sudo su - <USER>
git clone https://aur.archlinux.org/paru.git
cd paru
makepkg -si

//Init RAMディスク生成するため必要なパッケージインストール
paru linux-firmware-qlogic
paru aic94xx-firmware 
paru wd719x-firmware 
paru upd72020x-fw

//以上でインストール完了
//Rootにもどる
exit

//Init RAM用の設定にlvm2を追加。順番重要なので、filesystemsの前に追記。またudevではなくsystemdを利用
vim /etc/mkinitcpio.conf
==
HOOKS=(base systemd autodetect modconf block lvm2 filesystems keyboard fsck)
==
//Init RAM生成
mkinitcpio -P

```
## paruオプション
> paru は AUR（Arch User Repository）ヘルパーであり、 yay のフォーク。
> yay は現在 yaourt の後継として多くの Arch 系 Linux ユーザに使われている。bash、fish、zshいずれのコマンドシェルでも利用可能でどなたにもオススメできる AURヘルパーだ。その yay のメインデベロッパーが抜けて作ったのが paru だ。
> paru は yay の Google Go 言語から最近多くの優秀なツールが書かれている Rust でコーディングされ直しており機能を少しずつ追加していきたいとのことだ。
> [Slack Note Arch Linux : AURヘルパー「paru」を導入する](https://slacknotebook.com/arch-linux-aur-helper-paru/#:~:text=paru%20%E3%81%AF%20AUR%EF%BC%88Arch%20User,%E3%82%AA%E3%82%B9%E3%82%B9%E3%83%A1%E3%81%A7%E3%81%8D%E3%82%8B%20AUR%E3%83%98%E3%83%AB%E3%83%91%E3%83%BC%E3%81%A0%E3%80%82)

| command | Desc |
| --- | --- |
| paru <ターゲット> |  対話的に<ターゲット>を検索し、インストール |
| paru | paru  -Syuのエイリアス |
| paru -S  | <target> 特定のパッケージをインストール |
| paru -Sua  | AUR パッケージをアップグレード |
| paru -Qua  | 利用可能な AUR のアップデートを表示 |
| paru -Gc <target>  | <target> の AUR コメントを表示 |
| paru -Ui PKGBUILD  | をビルドしてカレントディレクトリにインストール |

# ブートローダー
> ブートローダとは、コンピュータの起動直後に自動的に実行されるコンピュータプログラムで、ストレージ（外部記憶装置）からOSを読み出して起動するもの。実際には2段階の異なるプログラムに分かれていることが多く、そのいずれかあるいは両方を指す。
> 起動時に最初に実行されるのはBIOSやEFI/UEFIの一部として主基板（マザーボード）などにある不揮発性の読み出し専用メモリ（ROM）などに製造時に記録された小さなプログラムで、1次ブートローダとも呼ばれる。このプログラムは設定された起動デバイスの優先順位に従ってOSが格納されたストレージ装置へアクセスし、その先頭領域などに記録されたOS起動用のプログラム（2次ブートローダ）を主記憶装置（メインメモリ/RAM）に読み込んで実行する。
> 
> 2次ブートローダは起動すべきOSが記録されたストレージ（内の特定のパーティション）からOS本体の初期化プログラムなどを読み込んで実行し、以降はOSによる起動プロセスが始まる。コンピュータへのOSの導入（インストール）時に自動的に、あるいは利用者が明示的に導入して設定するソフトウェアであり、単にブートローダといった場合は通常はこれを指す。パソコンでよく用いられる2次ブートローダには、Linuxに付属していたLILO（Linux Loader）や様々なUNIX系OSで使われるGRUB（GRand Unified Bootloader）。systemd-boot は、systemd に含まれている、シンプルなブートローダです。UEFI のみ対応しています。
> [Arch Linux - ブートローダ](https://e-words.jp/w/%E3%83%96%E3%83%BC%E3%83%88%E3%83%AD%E3%83%BC%E3%83%80.html)

```
//ブートローダ設定 systemd-bootを使います（Grubではない）
//EFI システムパーティションに systemd-boot をインストール
bootctl --path=/boot install

//ローダーの設定
vim /boot/loader/loader.conf
==
timeout 5
default arch-lts
editor  no
==

//ブートメニューのアイテム追加
//初期はlinux-lts用とfallback用の２つを作成
//Nvidiaドライバを使う場合は、「ibt=off」をオプションに追加

vim /boot/loader/entries/arch-lts.conf
==
title   Arch Linux LTS
linux   /vmlinuz-linux-lts
initrd  /intel-ucode.img
initrd  /initramfs-linux-lts.img
options root=/dev/arch_vg/arch_root rootflags=subvol=@ rw transparent_hugepage=never ibt=off zswap.enabled=0 elevator=noop nvme_core.default_ps_max_latency_us=0 scsi_mod.use_blk_mq=1 quiet loglevel=3 nmi_watchdog=0 scsi_mod.use_blk_mq=1 snd_hda_intel.dmic_detect=0 nvme_core.default_ps_max_busy_us=0
==

/*
quiet：ブートメッセージを非表示にする
loglevel=3：ログレベルを3に設定する
i915.fastboot=1：i915ドライバを高速起動する
intel_idle.max_cstate=1：CPUの省電力状態を最小限にする
nmi_watchdog=0：NMIウォッチドッグを無効にする
mem_sleep_default=deep：スリープ時にメモリを深くスリープさせる
nvme_core.default_ps_max_latency_us=0 : このパラメータはNVMe SSDの省電力設定を制御します。値が大きいほど省電力機能が有効になり、値が小さいほど省電力機能が無効になります。これはSSDのパフォーマンスに影響します。値を小さくすることで、SSDの性能を最大限に引き出すことができます。
nvme_core.default_ps_max_busy_us=0
scsi_mod.use_blk_mq=1：SCSIブロックキューイングを有効にする
snd_hda_intel.dmic_detect=0：DMICを無効にする
*/

//Fallback用ブートメニューのアイテム追加
//Nvidiaドライバを使う場合は、「ibt=off」をオプションに追加

vim /boot/loader/entries/arch-lts-fallback.conf
==
title   Arch Linux LTS
linux   /vmlinuz-linux-lts
initrd  /intel-ucode.img
initrd  /initramfs-linux-lts-fallback.img
options root=/dev/arch_vg/arch_root rootflags=subvol=@ rw transparent_hugepage=never ibt=off
==

// systemd-boot が更新された場合は、自動的に*.efiを更新するHookを入れておきます
mkdir /etc/pacman.d/hooks
vim /etc/pacman.d/hooks/systemd-boot.hook
==
[Trigger]
Type = Package
Operation = Upgrade
Target = systemd

[Action]
Description = Updating systemd-boot
When = PostTransaction
Exec = /usr/bin/bootctl update
==

//chrootから抜ける
exit

//一旦サーバ再起動。USBメディアは抜いておきましょう
reboot
```
## カーネルパラメタの一覧
https://www.kernel.org/doc/html/v5.8/admin-guide/kernel-parameters.html


## TRANSPARENT HUGE PAGE (THP)を無効
上記のブートメニューアイテムのエントリにtransparent_hugepage=neverを追加してTHPを無効にしています。
>Linuxのカーネルはページという単位でメモリを管理して割り当てています。これまで1ページ4KBのサイズが割り当てられていました。しかしメモリが急激に大容量化するのに伴い管理するページ数や管理テーブルの段数が多くなりました。そしてメモリを管理するコストがパフォーマンス上の影響を及ぼすようになってきました。TRANSPARENT HUGE PAGE (THP)は大きなメモリサイズのページを透過的に割り当てることで問題を解決しようとする機能です。
> ## メリット
> THPは事前のHuge Pageの割り当て設定がなくても透過的に利用できるので、お手軽にHuge Pageが利用できます。メモリの使い方によってはアプリケーションのパフォーマンスが大きく改善する可能性があります。
> ## デメリット
> THPが有効になっていると逆にパフォーマンスが低下するアプリケーションも報告されています。主にメモリが従来の割り当て方式でチューニングされているDB関連でパフォーマンス低下の問題が起きやすいようです。



# ネットワークの設定
再起動後、今度はインストールした環境に移り設定を進めていきます。
```
//先ずは、NW関連の設定を行う
//Wifiネットワーク接続用サービスの起動
sudo systemctl --now enable iwd

// WiFi接続
iwctl
==
// ネットワークDeviceを確認
#device list
// ネットワークのScan
# station wlan0 scan
// APを取得
# station wlan0 get-networks
// AP接続
# station wlan0 connect aterm-xxxxxxxx
// iwから抜ける
# exit
==

//Static IP利用する設定いれます
vim /etc/systemd/network/25-wireless.network
==
[Match]
Name=wlan0
[Address]
Address=192.168.0.50/24
[Network]
DNS=192.168.0.1
[Route]
Gateway=192.168.0.1
==

//続いて、iwdサービスの起動順序を設定
mkdir /etc/systemd/system/iwd.service.d
vim /etc/systemd/system/iwd.service.d/override.conf
==
[Unit]
After=systemd-udevd.service systemd-networkd.service
==

// networkdのサービス起動
systemctl enable --now systemd-networkd

// DNS resolvedのサービス起動
systemctl enable --now systemd-resolved

//以上でネットワークにつながる
```
なお、今回は固定IPで設定してますが、DHCPを使う場合は下記でできます。
```
//固定IP使う場合は不要
//dhcpcdインストール
pacman -S dhcpcd

//wlan0用のDHCPクライアント設定
vim /etc/systemd/network/25-wireless.network
==
[Match]
Name=wlan0

[Network]
DHCP=yes
==

//DHCP Clientサービス設定
systemctl enable dhcpcd@wlan0 --now

//networkdの再起動
systemctl restart systemd-networkd
```

# サーバ環境の設定
```
// localtimeの設定
ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime
//これで日本時間JSTになります
date
==
Thu Sep 29 12:13:35 AM JST 2022
==

// ロケール設定
vim /etc/locale.gen
==
//コメントアウト
en_US.UTF-8 UTF-8
ja_JP.UTF-8 UTF-8
==

// ロケール生成
locale-gen

// LANG 環境変数を設定
vim /etc/locale.conf
==
LANG=en_US.UTF-8
==

// Hostname設定
vim /etc/hostname
==
arch-dev
==

// hosts設定
vim /etc/hosts
==
127.0.0.1	localhost
::1		localhost
127.0.1.1	arch-dev.localdomain	arch-dev
==
```
# Swap
> OSのメモリ管理機能の一つで、メインメモリ（RAM）とストレージ（外部記憶装置）の同容量の領域間でデータの交換を行う動作をメモリスワップと呼び、これを略して単にスワップという。これにより、物理的なメモリ容量より広いメモリ空間を扱えるようになる。[e-Words スワップ 【swap】](https://e-words.jp/w/%E3%82%B9%E3%83%AF%E3%83%83%E3%83%97.html)

> Zramdのメリット
> 特にswapが圧迫されているときに、システムの応答性を大幅に改善します。
> スワップが揮発性のメディアであるため、より安全です。
> swap-on-driveを使用しない場合、限られたリソースをより有効に活用することができます。
> さらに、ワークロードが限界を超えたときに、メモリ不足になるまでの時間を短縮することができます。
> [GitHub Zramd](https://github.com/maximumadmin/zramd)

zswapチェックしまずは、zswapを無効に
```
cat /sys/module/zswap/parameters/enabled
==
Y
==

### zswap を無効化する
//Kernel parameterに下記を追加
sudo vim /boot/loader/entries/arch-lts.conf

==
title Arch Linux LTS
linux /vmlinuz-linux-lts
initrd /intel-ucode.img
initrd /initramfs-linux-lts.img
options root=/dev/arch_vg/arch_root rootflags=subvol=@ rw transparent_hugepage=never ibt=off zswap.enabled=0 elevator=noop nvme_core.default_ps_max_latency_us=0 scsi_mod.use_blk_mq=1 quiet loglevel=3 nmi_watchdog=0 scsi_mod.use_blk_mq=1 snd_hda_intel.dmic_detect=0 nvme_core.default_ps_max_busy_us=0
==
```

ZramdでSwap作成
```
paru zramd
sudo systemctl enable --now zramd

//zramd systemd 
cat /usr/lib/systemd/system/zramd.service
==
[Unit]
Description=Automatically setup swap on zram

[Service]
Type=oneshot
EnvironmentFile=-/etc/default/zramd
ExecStart=/usr/bin/zramd start
ExecStop=/usr/bin/zramd stop
RemainAfterExit=yes
ProtectHostname=yes
PrivateNetwork=yes
IPAddressDeny=any
NoNewPrivileges=yes
RestrictNamespaces=yes
RestrictRealtime=yes
RestrictSUIDSGID=yes
MemoryDenyWriteExecute=yes
LockPersonality=yes
CapabilityBoundingSet=CAP_SYS_ADMIN CAP_SYS_MODULE
SystemCallFilter=@module @swap @system-service
SystemCallArchitectures=native
SystemCallErrorNumber=EPERM
DeviceAllow=block-* rw
DevicePolicy=closed
# https://github.com/systemd/systemd/issues/15753
RestrictAddressFamilies=AF_UNIX
RestrictAddressFamilies=~AF_UNIX

[Install]
WantedBy=multi-user.target
==

//zramd config
cat /etc/default/zramd
==
# See available algorithms by running "cat /sys/block/zramX/comp_algorithm"
# ALGORITHM=zstd

# Max fraction of physical memory to use
# FRACTION=1.0

# Max total swap size in MB
# MAX_SIZE=8192

# Number of zram devices to create
# NUM_DEVICES=1

# Swap priority
# PRIORITY=100

# Skip initialization if running inside a virtual machine
# SKIP_VM=false
==
```

# NTP
> NTPとは、TCP/IPネットワークを通じて現在時刻の情報を送受信するプロトコル（通信規約）の一つ。時刻情報を配信するサーバと時刻合わせを行うクライアント間、およびサーバ間の通信方法を定めている。
> 
> 　NTPはコンピュータ間で時刻情報をやり取りする方式を定めており、通信時の遅延を計測して補正する仕組みも提供する。標準のポート番号としてUDPの123番を使用する。インターネット上には時報のように現在時刻を配信するNTPサーバ（タイムサーバ）がいくつも公開・運用されている。パソコンなどで動作するNTPクライアントはサーバから時刻情報を取得し、コンピュータ内部の時計（RTC）を正しい時刻に調整することができる。
> NTPにはこのようなクライアント-サーバ間の通信の他に、時刻サーバ間で時刻情報を調整したり、上位サーバから下位サーバへの階層構造を構成・管理する機能なども定義している。
> 　クライアントからの時刻の問い合わせには、この用途に機能を限定したサブセットである「SNTP」（Simple NTP）が主に利用されてきたが、2010年のNTPv4でNTP本体に統合され、独立したプロトコルとしては廃止された。[e-Words NTP 【Network Time Protocol】 ネットワークタイムプロトコル](https://e-words.jp/w/NTP.html)

```
//NTP設定
vim /etc/systemd/timesyncd.conf
==
[Time]
NTP=ntp.jst.mfeed.ad.jp time.cloudflare.com
FallbackNTP=0.jp.pool.ntp.org 1.jp.pool.ntp.org 2.jp.pool.ntp.org 3.jp.pool.ntp.org
#RootDistanceMaxSec=5
#PollIntervalMinSec=32
#PollIntervalMaxSec=2048
#ConnectionRetrySec=30
#SaveIntervalSec=60
==

timedatectl set-ntp true
timedatectl status
==
               Local time: Sat 2022-09-24 14:53:09 JST
           Universal time: Sat 2022-09-24 05:53:09 UTC
                 RTC time: Sat 2022-09-24 05:53:09
                Time zone: Asia/Tokyo (JST, +0900)
System clock synchronized: yes
              NTP service: active
          RTC in local TZ: no
==
```


# Mirror List Auto Update
```
sudo pacman -S reflector
reflector --list-countries
sudo vim /etc/xdg/reflector/reflector.conf
==
--country 'Japan,Taiwan,United States'
==

//reflector.serviceは起動時にミラーリストを更新し、週に一度、reflector.timerによって自動的にトリガー
sudo systemctl enable reflector.service reflector.timer
sudo systemctl start reflector.service reflector.timer
cat  /etc/pacman.d/mirrorlist
==
Server = https://america.mirror.pkgbuild.com/$repo/os/$arch
Server = https://mirror.lty.me/archlinux/$repo/os/$arch
Server = https://arch.mirror.constant.com/$repo/os/$arch
Server = https://mirror.hackingand.coffee/arch/$repo/os/$arch
Server = https://arlm.tyzoid.com/$repo/os/$arch
Server = https://mirror.arizona.edu/archlinux/$repo/os/$arch
Server = https://arch.mirror.ivo.st/$repo/os/$arch
Server = https://mirrors.lug.mtu.edu/archlinux/$repo/os/$arch
Server = https://arch.hu.fo/archlinux/$repo/os/$arch
Server = https://mirror.zackmyers.io/archlinux/$repo/os/$arch
==
```
ただし、そう頻繁に変わるものではないので、たまに下記のサイトから取得するのでもよいかも。
https://archlinux.org/mirrorlist/

```
Server = http://mirrors.cat.net/archlinux/$repo/os/$arch
Server = https://mirrors.cat.net/archlinux/$repo/os/$arch
Server = http://ftp.tsukuba.wide.ad.jp/Linux/archlinux/$repo/os/$arch
Server = http://ftp.jaist.ac.jp/pub/Linux/ArchLinux/$repo/os/$arch
Server = https://ftp.jaist.ac.jp/pub/Linux/ArchLinux/$repo/os/$arch
Server = https://mirror.saebasol.org/archlinux/$repo/os/$arch
```

# SSHD
> SSHサーバとは、遠隔からコンピュータに接続して操作するSSH（secure shell）のサーバ側のソフトウェア。SSHクライアントと通信し、利用者の操作を受け付けて実行し、結果をクライアントに応答する。
> 
> SSHは暗号化された伝送経路を構築して安全にコンピュータを遠隔操作する通信手順（プロトコル）で、利用者が直に操作して入出力を行うソフトウェアをSSHクライアント、遠隔からの接続を受け付けて操作を実行するソフトウェアをSSHサーバという。標準ではTCPの22番ポートで接続を待ち受けるが、攻撃を避けるために他のポート番号を使用することも多い。クライアントが接続してきたら自身が本物であることを証明するため、電子署名によるホスト認証（サーバ認証）を提供する。本物と確認できたら共通鍵暗号の鍵交換を行い、暗号通信を開始する。暗号化された通信によりクライアントの認証を行う。事前に登録したパスワードによる認証か、公開鍵暗号による電子署名を応用した公開鍵認証を選択することができる。認証が成功すると操作の受付が開始され、一般的なUNIX系OSのシェルのようにコマンド入力と文字出力による対話的な操作（CLI/CUI）が可能となる。
> 　SSHプロトコルは標準化されており、クライアント、サーバともに様々なシステムに対応したソフトウェアが存在するため、クライアント側とサーバ側が異なるOSを利用していても問題なく操作できる。一般的なコマンド操作だけでなく、scpコマンドやsftpコマンド（SFTP）でローカル側とリモート側のファイル送受信などを行うこともできる。
> 　SSHサーバの著名な実装にオープンソースの「OpenSSH」があり、LinuxなどのUNIX系OSの多くに同梱され標準的に用いられている。UNIX系OSではSSHで接続を受け付ける常駐プログラム（デーモン）の名前として慣用的に「sshd」（ssh daemon）が用いられるため、SSHサーバのことを指してsshdと呼ぶことも多い。[e-Words SSHサーバ 【SSH server】 sshd / ssh daemon / sshデーモン](https://e-words.jp/w/SSH%E3%82%B5%E3%83%BC%E3%83%90.html)
```
//SSHDの設定
vim /etc/ssh/sshd_config
=====
//一旦パスワードでのログインも許可
PasswordAuthentication yes
=====

//SSHDサービス起動
systemctl enable --now sshd
```
# デバイスのファームウェアをアップデート

```
# パッケージインストール
sudo pacman -S fwupd

# 検出されたデバイスを確認
fwupdmgr get-devices

# 利用可能なアップデートのメタデータを更新
fwupdmgr refresh

# システムのアップデート一覧を確認
fwupdmgr get-updates

#アップデートをインストール
fwupdmgr update
```

# Python
Python 3.3以降、今3.10時点での最新の環境構築方法です。venvとpyenvを使って、しっかり開発仮想環境を分離します。環境を分離しないと、プロジェクトが増えてきた際に、環境が混ざって災難に見舞われるのでしっかりと管理します。
venv: モジュールを隔離環境にインストール。3.3以降はデフォルトで入ってます。
pyenv: 異なるバージョンを管理


```
//Python install
$ sudo pacman -S python-pip pyenv

//環境変数設定 
//zshを使っているので、.zshrcにPythonの設定を入れておきます。

$ vim ~/.zshrc
==
# Python settings
export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init --path)"
==

// zshrc読み込み
$ source ~/.zshrc

//初期化
$ pyenv init - 

// Python PJ1 (3.8.13)の作成例
//インストール可能なバージョン確認
$ pyenv install --list
==
  ...
  3.7.5
  3.7.6
  3.7.7
  3.7.8
  3.7.9
  ...
==

$ pyenv install 3.8.13
$ python -V
==
Python 3.10.7
==

$ mkdir PJ1
$ cd PJ1
//Python version インストール
$ pyenv local 3.8.13

//現在のバージョン
$ pyenv version                                                                                    
==
[/home/user/opt/PJ1]
3.8.13 (set by /home/user/opt/PJ1/.python-version)
==

$ python -m venv .venv
$ source .venv/bin/activate
(.venv) $ python -V
==
Python 3.8.13
==

(.venv) $ pip list 
Package    Version
---------- -------
pip        22.2.2
setuptools 56.0.0
==
// venvから抜ける
$ deactivate
```


## VPN接続
VPNサービスを提供しているSurfShark に契約していることを前提にopenvpnを利用してVPN接続できる環境を作ります。今回は、数ある接続から日本のアクセスポイントで設定します。他のアクセスポイントでもやり方は同じです。

```
#install
pacman -S openvpn 

# Surfshark OpenVPN configurationダウンロード
mkdir /tmp/surfshark
cd /tmp/surfshark
wget https://my.surfshark.com/vpn/api/v1/server/configurations
unzip configurations
rm configurations

# tcpのプロファイル削除
rm ./*_tcp.ovpn

# 認証ID/Passファイルを外部ファイルから読み込み 
find . -type f -name '*.ovpn' -exec sed -i -e 's/auth-user-pass/auth-user-pass auth.txt/g' {} \;

# ファイル名を国コード＋confに変更
for f in *; do [ -f "$f" ] && mv "$f" "${f:0:6}.conf"; done 

# OpenVPNフォルダへ設定を移動
sudo mv ./*.conf /etc/openvpn/client


cat /etc/openvpn/client/jp-tok.conf
==
proto udp #後ほどufwで利用
remote jp-tok.prod.surfshark.com 1194 #後ほどufwで利用
...
# ID/Passを自動で設定できるように下記の設定へ更新
auth-user-pass auth.txt
...
==


# SurfSharkのサイトへログインし、VPN>手動設定>OpenVPNよりユーザ名、パスワードを取得し、下記ファイル作成
sudo vim /etc/openvpn/client/auth.txt
==
[ユーザー名]
[パスワード]
==
```

以上で、各国にVPNでつながる設定ファイルの準備はOK

```

# OpenVPNをjpプロファイルで起動
sudo systemctl start openvpn-client@jp-tok.service


#check
systemctl list-units --type=service | grep openvpn-client
```
上記で、VPNでのアクセスができるようになります。一旦ここで接続確認。

### キルスイッチ機能を作成
キルスイッチとは、何らかの理由でVPNとの接続が切れた際に、ネットワーク接続を遮断する機能です。
```
sudo vim /etc/default/ufw
==
IPV6=no
==

sudo systemctl enable ufw --now 
sudo ufw status

sudo ufw default deny outgoing
sudo ufw default deny incoming

ip a
#この出力からNW IF、Local NWを確認

# VPN NWを許可
sudo ufw allow out on tun0 from any to any
sudo ufw allow in on tun0 from any to any

# Local NWを許可
sudo ufw allow in to 192.168.1.0/24
sudo ufw allow out to 192.168.1.0/24

# SurfSharkのVPNサーバ許可　jp.confのprotoとremoteの値から下記の設定
sudo ufw allow out to <jp-tok.prod.surfshark.comのIP> port 1194 proto udp

sudo ufw enable
sudo ufw status
```

上記で、OpenVPNとKillSwitchの設定が完了です。
ufwでルールを削除したいた場合は、
```
# ルール一覧表示
sudo ufw status numbered

# 指定したルールを削除
sudo ufw delete <NUMBER>

# ufw自体を無効化
sudo ufw disable
```
## VPNの接続シェル化
コマンドラインからVPN接続できるようにzshにファンクション追加しておきます。
```
#使用例：
#日本に接続
vpnopen jp-tok
#イタリアに接続
vpnopen it-rom

# VPN接続を停止
vpnstop
```
```
vim ~/.zshrc
==
vpnstop() {
	sudo ufw disable
	vpn_service=`systemctl list-units --type=service | grep openvpn | xargs | cut -f1 -d ' '  `
	if [ ${#vpn_service} -eq 29 ]; then
		echo "stopping... $vpn_service"
		sudo systemctl stop $vpn_service
	else
		echo "VPN is not activated. Skipping..."
	fi
}


vpnstart() {
	vpn_profile="jp-tok"
	if [[ $# -ne 1 ]] then
		echo "Invalid param. Using [jp] config..."
	else
		vpn_profile=$1	
	fi
	echo "VPN connection Using [${vpn_profile}] config..."
	sudo systemctl start openvpn-client@${vpn_profile}.service
	sudo ufw enable
}
==

```

# Docker & Nvidia GPGPU
GUIはないので、Nvidiaは、GPGPU（General-purpose computing on graphics processing units; GPUによる汎用計算）として利用できるように設定します。生環境にインストール進めると、TFやKerasのバージョン等、環境が汚染されるため、Dockerを使います。
```
//インストール
sudo pacman -S docker docker-compose docker-buildx

//check
docker --version
==
Docker version 20.10.18, build b40c2f6b5d
==

docker-compose --version
==
Docker Compose version 2.11.1
==

docker buildx version
==
github.com/docker/buildx 0.9.1 ed00243a0ce2a0aee75311b06e32d33b44729689
==

//ビルド buildxを使った場合
docker buildx bake -f docker-compose.yml

//ビルド BuildKitを使った場合
COMPOSE_DOCKER_CLI_BUILD=1 DOCKER_BUILDKIT=1 docker-compose build

//先ずは、インストール前に、事前の設定をしていきます。
//Nvidia Packageをアップグレードした後に 自動的にinitramfsをアップデートするHookを入れます。
# vim /etc/pacman.d/hooks/nvidia.hook
==
[Trigger]
Operation=Install
Operation=Upgrade
Operation=Remove
Type=Package
Target=nvidia-lts
Target=linux-lts

[Action]
Description=Update Nvidia module in initcpio
Depends=mkinitcpio
When=PostTransaction
NeedsTargets
Exec=/bin/sh -c 'while read -r trg; do case $trg in linux-lts) exit 0; esac; done; /usr/bin/mkinitcpio -P'
==

//Nvidia driver インストールします。nvidia-settingsはXが必要みたいなので入れず
pacman -S nvidia-lts nvidia-utils 
//インストールできているかチェック
pacman -Qs nvidia-lts
==
local/nvidia-lts 1:515.76-2
    NVIDIA drivers for linux-lts
==

//再起動
reboot

//きちんとNvidiaドライバが読み込まれているかチェック。nvidiaと出ればOKです
lspci -k | grep -A 2 -E "(VGA|3D)"
==
01:00.0 VGA compatible controller: NVIDIA Corporation GP108 [GeForce GT 1030] (rev a1)
	Subsystem: ASUSTeK Computer Inc. Device 85f4
	Kernel driver in use: nvidia
==


//Nvidia GPGPU （CUDA）として使う設定
// Dockerインストール
pacman -S docker

//ユーザをdockerグループに追加して、ユーザ権限でdockerコマンド打てるようにします
usermod -aG docker $USER

// Dockerサービス起動
systemctl enable docker --now

//Docker で NVIDIA GPU を利用する場合は、NVIDIA Container Toolkit (NVIDIA Docker)等が必要なのでいれます
//一般ユーザに変更
sudo su - <USER>
paru nvidia-container-toolkit
paru nvidia-container-runtime

//rootに戻ります
exit

//Docker利用時のNvidaランタイムの設定を入れておきます
//Dockerのイメージ、コンテナ類は/optは以下に配置する設定です
vim /etc/docker/daemon.json
==
{ 
  "data-root": "/opt/docker",
  "runtimes": {
    "nvidia": {
      "path": "/usr/bin/nvidia-container-runtime",
      "runtimeArgs": []
    }
  }
}
==

//GT1030対応した公式のイメージを実行します。コンテナ内でnvidia-smi実行して、何か表示できていれば大丈夫です。
docker run --rm --runtime=nvidia  --gpus all nvidia/cuda:11.0.3-base-ubuntu20.04 nvidia-smi -q
==
==============NVSMI LOG==============

Timestamp                                 : Wed Sep 28 10:50:58 2022
Driver Version                            : 515.76
CUDA Version                              : 11.7

Attached GPUs                             : 1
GPU 00000000:01:00.0
    Product Name                          : NVIDIA GeForce GT 1030
    Product Brand                         : GeForce
    Product Architecture                  : Pascal
    Display Mode                          : Enabled
    Display Active                        : Disabled
    Persistence Mode                      : Disabled
....
....
==

//Tensorflow用の公式Docker imageを落とし、python実行します。これで結果の出力があればOKです。
docker run --gpus all -it --rm tensorflow/tensorflow:latest-gpu  python -c "import tensorflow as tf; print(tf.reduce_sum(tf.random.normal([1000, 1000])))"

//次回以降コンテナ作って実行
docker run --gpus all -it tensorflow/tensorflow:latest-gpu bash

//指定したコンテナの中でプロセスを実行
 docker exec -it 86b590cadxxx bash

//実際コンテナ内からGPU使われているか確認するにはホスト側で下記のコマンド打って、コンテナでGPU使うプログラム実行した際に、PSが見えるか確認
nvidia-smi -l 3
+-----------------------------------------------------------------------------+
| Processes:                                                                  |
|  GPU   GI   CI        PID   Type   Process name                  GPU Memory |
|        ID   ID                                                   Usage      |
|=============================================================================|
|  No running processes found                                                 |
+-----------------------------------------------------------------------------+


//コンテナ内で何か実行したらPIDができました
+-----------------------------------------------------------------------------+
| Processes:                                                                  |
|  GPU   GI   CI        PID   Type   Process name                  GPU Memory |
|        ID   ID                                                   Usage      |
|=============================================================================|
|    0   N/A  N/A      9502      C   python                           1773MiB |
+-----------------------------------------------------------------------------+

//以上で、GPGPUを利用できるDocker環境ができました。今後、色々と使い込んで更新していきます。

```
## Nginx Docker
```
tree .
==
.
├── docker-compose.yml
├── nginx
    ├── cert
    │   ├── certificate.pem
    │   └── private.pem
    ├── conf.d
    │   ├── default.conf.20220930
    │   └── home.conf
    └── Dockerfile
==

//Nginx用のDockerfile作成
vim nginx/Dockerfile
==
# base image Live環境に合わせたバージョンを指定
FROM  nginx:1.14.2

# author
MAINTAINER  nkoyama

#ADD default.conf /etc/nginx/conf.d

RUN echo "now building nginx image..."
==

// docker-compose設定ファイル作成
vim docker-compose.yml
==
#Docker Composeのバージョン3を使用していることを表す。
version: "3.8"

#services セクションでは、これから作成するさまざまなコンテナを定義
services:
  nginx:
    #Dockerfileの場所を指定
    build:
      context: ./nginx
      dockerfile: Dockerfile
    # スタブサーバー起動後に動く
    depends_on:
      - splunk
    # コンテナに入るようにできる
    tty: true
    #Dockerfileがなく、ビルド済みのイメージを使ってサービスを実行したい場合、image節を使ってイメージの場所を指定します。Docker Composeは、そのイメージからコンテナをフォークします。
    # image: nginx:1.14.2
    container_name: nginx-fe

    #コンテナのポートをホストマシンにマッピングするために使用
    ports:
      - 80:80
      - 443:443

    #Dockerでディスクをマウントするための-vオプションと同じ
    volumes:
      - ./nginx/conf.d:/etc/nginx/conf.d
      - ./nginx/cert:/etc/nginx/cert/

    #あるサービスと別のサービスがリンク。ブリッジネットワークでは、リンクを用いてどのコンテナにアクセスできるようにするか指定する必要があります。
    # links:

    #このキーワードは、コンテナ内に環境変数を設定することができます。これは、Dockerでコンテナを実行する際の-e引数と同じです。
    # environment:
==


```
## サーバ証明書
Docker Nginxで使う自前サーバ証明書準備。
chromeで証明書エラー出た場合は[thisisunsafe]と打てばアクセスできる。
```
//作り方１つ目
// サーバ証明書 (および秘密鍵) の作成
openssl req -x509 -newkey rsa:2048 -nodes -days 3650 -keyout private.pem -out certificate.pem -config - <<EOF
[req]
distinguished_name = arch-dev
x509_extensions = usr_cert
prompt = no

[arch-dev]
C = JP
O = arch-dev
OU = Dev
CN = arch-dev

[usr_cert]
basicConstraints = critical, CA:FALSE
subjectAltName = DNS:localhost
EOF

// サーバ証明書の確認
openssl x509 -text -noout -in certificate.pem



//作り方２つ目
openssl genrsa 2048 > server.key
openssl req -new -key server.key > server.csr
openssl x509 -days 3650 -req -sha256 -signkey server.key < server.csr > server.crt
openssl x509 -text < server.crt

```



# SSD TRIM
SSD上のデータは削除しても削除マークが付くだけで削除されません。TRIMコマンドはOS上のファイルが不要になったことをSSDに伝えて明示的にデータの消去を行うコマンドです。ext4,xfs,btrfs等は対応
```
//ATA/IDE デバイスドライバでサポートされる色々なハードディスクの ioctl への、コマンドラインインタフェースを提供
sudo pacman -S hdparm 

//HDDがtrimサポートしているかチェック
sudo hdparm -I /dev/sda | grep -i trim
==
	   *	Data Set Management TRIM supported (limit 8 blocks)
==

//fstrimサービス起動
systemctl enable fstrim.timer
```

# pacman
pacmanの色、並列ダウンロード数、パックマンの設定をします。Low Priorityです。。
```
vim /etc/pacman.conf
==
// pacmanの出力をカラー化
Color

// 並列ダウンロードを有効化
ParallelDownloads = 5

// pacmanの出力にパックマンを登場
ILoveCandy
==

// リポジトリとローカルパッケージデータベースとの同期およびアップグレード
# pacman -Syyu


//インストール済みパッケージ一覧
pacman -Qqe

//依存しているパッケージ一覧
pacman -Qi <PKG> | grep 'Depends On'
//下のpacman-contrib を入れると使える別コマンド
pactree <PKG>

//依存されているパッケージ一覧
pacman -Sii <PKG> | grep 'Required By'

//下のpacman-contrib を入れると使える別コマンド
pactree -r <PKG>

// どのパッケージからも依存されていない孤児パッケージを表示
pacman -Qdt

// 孤児パッケージの削除
sudo pacman -Rs $(pacman -Qdtq)
```

## 便利なやつ
pacmanの便利なコマンドをまとめたパッケージ
```
// pacman便利系コマンドパッケージ　インストール
pacman -S pacman-contrib 

// インストール済みのパッケージのうちアップグレードがペンディングになっているもの
checkupdates
==
xkeyboard-config 2.36+89+g382c5feb-1 -> 2.37-1
==

// pacmanは/var/cache/pacman/pkgにダウンロードしたパッケージをキャッシュしておくが、自動的に削除されることはない。
// パッケージのダウングレードを簡単に行えたり、アンインストールしたパッケージの再インストールを簡単に行えるが、キャッシュが不要になった場合の操作

//サイズチェック
du -sh /var/cache/pacman/pkg
==
3.0G	/var/cache/pacman/pkg
==

//残っているキャッシュ全てについて3代残す。アンインストールしたパッケージについても残す
sudo paccache -r

//アンインストール済みパッケージのキャッシュを削除
paccache -ruk0

//定期実行
sudo systemctl enable paccache.timer

//依存しているパッケージ一覧
pactree <PKG>

//依存されているパッケージ一覧
pactree -r <PKG>

```
### Nautilusのロケーションバーを常にPath入力にする
Nautilusでフォルド移動する際にCTRL+LでURIのPath入力できますが、常にその状態にするために下記の設定をします。
```
gsettings set org.gnome.nautilus.preferences always-use-location-entry true
```

## Oh My Zsh & powerlevel10kをインストール
```
//Oh My Zshをインストール
sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"

// powerlevel10k用フォント
mkidr ~/.font
cd ~/.font
wget https://github.com/romkatv/powerlevel10k-media/raw/master/MesloLGS%20NF%20Regular.ttf

// powerlevel10kをテーマに適用
git clone git@github.com:romkatv/powerlevel10k.git ~/.oh-my-zsh/custom/themes/powerlevel10k

// 再設定
p10k configure
```

# efibootmgr
Linux上でUEFIブートを表示・管理をするためのコマンド。起動順序をOS側からいじれるので入れておきます。
「efibootmgr」は、UEFIブートマネージャーを操作するコマンドです。「efibootmgr」を利用すると、UEFIブートマネージャーに起動エントリーを作成したり、起動エントリーの順番を変更することができます。

```
pacman -S efibootmgr
efibootmgr
==
BootCurrent: 0000 //現在ブートしているシステムの番号(HEX値)
Timeout: 1 seconds //ブートマネージャーのタイムアウト秒数
BootOrder: 0001,0000 //ブート順番です。左から順にブート
//ブートのエントリ
//番号のあとに*が付いている場合は有効なブートエントリ
//付いていない場合は無効なブートエントリ
Boot0000* grub	HD(1,GPT,18b38c15-5591-4bb2-944b-8f63519e4529,0x800,0x100000)/File(\EFI\grub\grubx64.efi)
Boot0001* Linux Boot Manager	HD(1,GPT,18b38c15-5591-4bb2-944b-8f63519e4529,0x800,0x100000)/File(\EFI\systemd\systemd-bootx64.efi)
==

//次回ブートするエントリを設定する
// efibootmgr -n <番号(HEX値)>
# efibootmgr -n 0001 
```

# Vconsole
```
//Check current keymap and font settings
localectl status

// Terminal Font install
sudo pacman -Ss terminus-font

//インストールされているフォント一覧
ls -l /usr/share/kbd/consolefonts/

sudo vim /etc/vconsole.conf
==
KEYMAP="us" #英語キーボード
FONT="ter-v16n"
==

```

# NFS
NFSでArch-Mac間でファイルの共有をします
```
//NFSインストール
sudo pacman -S nfs-utils
sudo systemctl enable nfs-server.service --now

//共有フォルダ設定及びマウント
sudo mkdir -p /nfs/{home,opt,tmp}
sudo mount --bind /opt /nfs/opt 
sudo mount --bind /home/user /nfs/home 
sudo mount --bind /tmp /nfs/tmp 

// マウント設定永続化
sudo vim /etc/fstab
==
/opt /nfs/opt none defaults,bind 0 0
/home/user /nfs/home none defaults,bind 0 0
/tmp /nfs/tmp none defaults,bind 0 0
==

//NFS設定
sudo vim /etc/exports
==
/nfs/home 192.168.1.0/255.255.0.0(rw,sync,all_squash,subtree_check,insecure,anonuid=1000,anongid=1000)
/nfs/opt 192.168.1.0/255.255.0.0(rw,sync,all_squash,subtree_check,insecure,anonuid=1000,anongid=1000)
/nfs/tmp 192.168.1.0/255.255.0.0(rw,sync,all_squash,subtree_check,insecure,anonuid=1000,anongid=1000)
==
//設定反映
sudo exportfs -arv

//チェック
sudo exportfs -s

//マウントを永続化
sudo vim /etc/fstb
==
#Mount for NFS
/opt /nfs/opt none defaults,bind 0 0
/home/user /nfs/home none defaults,bind 0 0
/tmp /nfs/tmp none defaults,bind 0 0
==
```
クライアントのMac側での設定
```
//フォルダ作成
sudo mkdir /private/nfs
sudo chown -R user:staff /private/nfs
mkdir /private/nfs/{home,opt,tmp}

//Macからマウント
sudo mount -o resvport,rw -t nfs 192.168.1.50:/nfs/home  /private/nfs/arch_dev/home
sudo mount -o resvport,rw -t nfs 192.168.1.50:/nfs/opt  /private/nfs/arch_dev/opt
sudo mount -o resvport,rw -t nfs 192.168.1.50:/nfs/tmp  /private/nfs/arch_dev/tmp

//クライアント側でマウントのファンクションをZSHに追加しておくと、あとで楽
vim .zshrc
==
mnt() {
  sudo mount -o resvport,rw -t nfs 192.168.1.xx:/nfs/home  /private/nfs/arch_dev/home
  sudo mount -o resvport,rw -t nfs 192.168.1.xx:/nfs/opt  /private/nfs/arch_dev/opt
  sudo mount -o resvport,rw -t nfs 192.168.1.xx:/nfs/tmp  /private/nfs/arch_dev/tmp
}

umnt() {
  sudo umount /private/nfs/arch_dev/home
  sudo umount /private/nfs/arch_dev/opt
  sudo umount /private/nfs/arch_dev/tmp
  sudo umount /private/nfs/arch_home/home
}
==
```

# Samba
NFSでも用は足りますが、必要に応じて例えばWindowsマシンとかから、サーバのファイルシステムにFinder経由でアクセスできるよう、SMBを設定します。
> Sambaとは、Windows以外のOSでWindowsネットワークの諸機能を利用できるようにするソフトウェア。主にUNIX系OSで動作するコンピュータをWindowsネットワーク上のサーバやクライアントとして利用するために用いられるもので、GPL（GNU Public License）に基づいてオープンソースソフトウェアとして公開されている。
> 
> WindowsやWindows Serverに実装されているファイル共有機能などを移植した互換ソフトウェアで、SMB（Server Message Block）やCIFS（Common Internet File System）、NetBT（NetBIOS over TCP/IP）、MS-RPC（Microsoft Remote Procedure Call）などのプロトコル（通信規約）や仕様に対応し、ファイルサーバ、プリントサーバ、WINSサーバ、ドメインコントローラ（NTドメイン/Active Directoryドメイン）などとして機能する。
> クライアントとしてネットワーク上の他のWindows機やSamba機が提供する共有フォルダや共有プリンタを利用したり、NTドメインやActive Directoryドメインに参加したりすることもできる。[e-Words Samba](https://e-words.jp/w/Samba.html)
```
//インストール
pacman -Syu samba

//設定
vim /etc/samba/smb.conf
==
[global]

# 大文字と小文字を区別する。
case sensitive = yes

# 192.168.0.0/24 と 127.0.0.0/8 (Loopback) からのアクセスを許可する。
hosts allow = 192.168.0. 127.

# root ユーザからのアクセスを禁止する。
invalid users = root

# SMB1 は無効化し、SMB2 以降を使用する。
server min protocol = SMB2

# サーバーの説明文を設定する。%h はホスト名に置換される。
server string = Samba File Server on %h

# Mac が create mask を無視しておかしなパーミッションを設定する問題のワークアラウンド。
unix extensions = no

# サーバーが sendfile() をサポートする場合にこれを利用し、パフォーマンスを最適化する。
use sendfile = yes

# ワークグループの名前を適当に設定する。
workgroup = WORKGROUP

# 全ての Samba ユーザーからアクセス可能な共有ファイルサーバーを定義する。
[opt]

    # サーバー上のファイルパスを指定する。
    path = /opt

    # ユーザー名とパスワードを使用して認証を行う。
    security = user

    # 共有ファイルへの読み込みだけでなく書き込みも許可する。
    writable = yes


# 全ての Samba ユーザーからアクセス可能な共有ファイルサーバーを定義する。
[home]

    # サーバー上のファイルパスを指定する。
    path = /home/<user>

    # ユーザー名とパスワードを使用して認証を行う。
    security = user

    # 共有ファイルへの読み込みだけでなく書き込みも許可する。
    writable = yes
==

//既存のユーザをSambaサーバーアクセス用ユーザとする場合
sudo pdbedit -a <user>
//ユーザーアカウントを表示
sudo pdbedit -L

sudo systemctl enable smb nmb --now
```

# man (マニュアルページ)
manコマンドはマニュアルを表示するコマンドだ。Linuxには様々な機能やディレクトリの使い方に関するマニュアルがカタログページとして格納されている。カタログページは、標準では環境変数$MANPATHで指定されている場所に保存されている。マニュアルのカタログページを見やすい形で表示してくれるのがmanコマンドだ。
```
// インストール
sudo pacman -S man-db

// Search Cache 作成しキーワード検索できる様にする
sudo mandb

//　キーワード検索
// man -k <KEYWORD>
man -k pactree
==
pactree (8)          - package dependency tree viewer
==
```

# Cron
cron は Unix ライクなコンピュータオペレーティングシステムにおける時間基準のジョブスケジューラです。 cron を使うことでジョブ (コマンドやシェルスクリプト) をスケジュールして定期的に特定の時刻・時間に実行することが可能になります。 システムのメンテナンスや管理を自動化するためによく使われます。cron の実装はたくさん存在しますが、デフォルトではそのいずれもインストールされません。代わりにベースシステムは systemd/タイマー を使用しています。
```
// インストール
sudo pacman -S cronie msmtp-mta 

// メール送りたい場合の設定
crontab -e
==
MAILTO=your@email.com
==

//サービス起動
sudo systemctl enable cronie --now

//ログチェック
journalctl -u cronie.service
```

# GitHub
> GitHubは、ソフトウェア開発のプラットフォームであり、ソースコードをホスティングする。コードのバージョン管理システムにはGitを使用する。Ruby on RailsおよびErlangで記述されており、アメリカのカリフォルニア州サンフランシスコ市に拠点を置くGitHub社によって保守されている。

SSHで接続するための設定です。
```
//GitHub の電子メール アドレスに置き換えてpublic/private Keyの作成
ssh-keygen -t ed25519 -C "your_email@example.com"
==
> Enter passphrase (empty for no passphrase): [Type a passphrase]
> Enter same passphrase again: [Type passphrase again]
==

//バックグラウンドでssh-agentを開始します。
eval "$(ssh-agent -s)"

//SSH秘密鍵をssh-agentに追加します。
ssh-add ~/.ssh/id_ed25519

//GitHub のアカウントに SSH キーを追加します。
https://github.com/settings/keys

//check 
ssh -T git@github.com

//設定
vim ~/.ssh/config
==
Host github github.com
  HostName github.com
  IdentityFile ~/.ssh/id_ed25519
  User git
==

//Check
ssh -T github

//下記のコマンド形式で、DLできるかチェック
git clone git@github.com:xxx/smaplapp.git
```
# Redis
Redisとは、オープンソースのデータベースで、Redisの特徴には、さまざまなものがあります。Redisの特徴については、下記のようなものがあります。
1. メモリ上で動作する
1. データを永続的に保持できる
1. マスター・スレーブ型レプリケーション機能が利用できる
```
//Install 
pacman -S redis

//設定
vim /etc/redis.conf
==
#ログファイル設定
logfile /var/log/redis/redis.log
==

//logフォルダ作成
mkdir /var/log/redis/
sudo chown redis:redis /var/log/redis
sudo chmod 755 /var/log/redis

//サービス起動
sudo systemctl enable redis --now
```

# IPFS インストール
```
//Install
sudo pacman -S go-ipfs
ipfs init

//Prep user systemd
vim ~/.config/systemd/user/ipfs.service
==
[Unit]
Description=IPFS daemon
After=network.target

[Service]
ExecStart=/usr/bin/ipfs daemon
Restart=on-failure

[Install]
WantedBy=default.target
==

//enable and start systemd
systemctl --user enable --now ipfs

//modify IP to access from remote client
vim .ipfs/config
==
    "API": "/ip4/192.168.1.30/tcp/5001",
    "Gateway": "/ip4/192.168.1.30/tcp/8080"
==

//check
ipfs cat /ipfs/QmQPeNsJPyVWPFDVHb77w8G42Fvo15z4bG2X8D2GhfbSXc/readme
==
Hello and Welcome to IPFS!

██╗██████╗ ███████╗███████╗
██║██╔══██╗██╔════╝██╔════╝
██║██████╔╝█████╗  ███████╗
██║██╔═══╝ ██╔══╝  ╚════██║
██║██║     ██║     ███████║
╚═╝╚═╝     ╚═╝     ╚══════╝

If you're seeing this, you have successfully installed
IPFS and are now interfacing with the ipfs merkledag!

 -------------------------------------------------------
| Warning:                                              |
|   This is alpha software. Use at your own discretion! |
|   Much is missing or lacking polish. There are bugs.  |
|   Not yet secure. Read the security notes for more.   |
 -------------------------------------------------------

Check out some of the other files in this directory:

  ./about
  ./help
  ./quick-start     <-- usage examples
  ./readme          <-- this file
  ./security-notes
==

ipfs swarm peers
==
/ip4/104.129.21.yy/udp/4001/quic-v1/p2p/12D3KooW9q16uH4X55VjZVEPRGbnpFWGEdTHDzZhw88abd8iiREx
/ip4/104.168.70.zz/udp/4001/quic-v1/p2p/12D3KooWNHiAwPcevKzJDEeB7NqaeXrFLiY8M6aKm4F9Y9NzDpBy
/ip4/104.207.153.xx/udp/4001/quic-v1/p2p/12D3KooWJDJfi4XceBzxW6TYtHicDTHmfHzbhQVNQFQHGa7wasSo
...
==

//Cross Origin config 
ipfs config --json API.HTTPHeaders.Access-Control-Allow-Methods '["PUT", "POST"]'
ipfs config --json API.HTTPHeaders.Access-Control-Allow-Origin '["http://192.168.1.30:5001", "http://localhost:3000", "http://127.0.0.1:5001", "https://webui.ipfs.io"]'

//アクセス
http://192.168.1.30:5001/webui

//Test if my GW can fetch contents
http://192.168.1.30:8080/ipfs/QmQpxqZ6hPnx8ofapPVgbg9JAh7S9oh3fNYvWwU7okdCU8

```

# Troubleshooting
色々な環境でさまざまな問題が出てくると思うので、私の環境で潰していった問題を逐次追加していきます。

```
//Boot時にエラーが出ていないか確認
// p3 : プライオリティ　Error
// xb : 直近BootのExtra Info
journalctl -p3 -xb

//不要なサービスが動いてないか確認
systemctl list-units --type=service

//OSがディスクをssdとして認識しているか確認
cat /sys/block/sda/queue/rotational

//USB接続状況確認
pacman -S usbutils
lsusb -t

//ブートプロセスを解析
systemd-analyze
==
Startup finished in 13.797s (firmware) + 1.205s (loader) + 1.100s (kernel) + 778ms (initrd) + 19.572s (userspace) = 36.454s
graphical.target reached after 19.572s in userspace.
==
//起動するのにかかった時間でユニットファイルを並べて一覧
systemd-analyze blame
==
15.031s systemd-networkd-wait-online.service
10.309s dev-zram0.device
 2.680s reflector.service
 1.133s systemd-modules-load.service
 1.093s dev-disk-by\x2did-lvm\x2dpv\x2duuid\x2dl0Bjgs\x2dwfjZ\x2dKalm\x2dbVEL\x2dJM1y\x2djKo9\x2dcbWgOj.device
 1.093s sys-devices-pci0000:00-0000:00:17.0-ata5-host4-target4:0:0-4:0:0:0-block-sda-sda1.device
 1.093s dev-sda1.device
==
//systemd-networkd-wait-online.serviceの時間がかかってるのでdisableにしてみる。なくてもnwには繋がっているので不要？
sudo systemctl disable systemd-networkd-wait-online
systemd-analyze blame
==
11.383s dev-zram0.device
 1.311s dev-disk-by\x2did-lvm\x2dpv\x2duuid\x2dBZnsTx\x2dbpd5\x2dtelx\x2d2rw1\x2dXvoU\x2dAKTB\x2dZ9CKNn.device
 1.311s dev-disk-by\x2dpartuuid-8df8413f\x2db404\x2d40e2\x2d9072\x2d996c61f207e4.device
 1.311s dev-disk-by\x2dpath-pci\x2d0000:02:00.0\x2dnvme\x2d1\x2dpart2.device
 1.311s dev-disk-by\x2did-nvme\x2dWD_BLACK_SN850X_2000GB_22302G805257\x2dpart2.device
 1.311s dev-disk-by\x2did-nvme\x2deui.e8238fa6bf530001001b448b4bdabb35\x2dpart2.device
==

```


例えば下記のようなエラーが出ている場合
```
sudo journalctl -xb -p3

Mar 16 07:56:41 arch-dev (udev-worker)[500]: event7: Failed to call EVIOCSKEYCODE with scan code 0x7c, and key code 190: Invalid argument
```

```
//問題のModuleを確認
sudo libinput list-devices | grep -E '(Device:|Kernel:)'
==
Device:           Power Button
Kernel:           /dev/input/event2
Device:           Power Button
Kernel:           /dev/input/event1
Device:           Sleep Button
Kernel:           /dev/input/event0
Device:           Eee PC WMI hotkeys
Kernel:           /dev/input/event7
==

//問題のModuleの詳細を確認
sudo udevadm info /dev/input/event7
==
P: /devices/platform/eeepc-wmi/input/input7/event7
M: event7
R: 7
U: input
D: c 13:71
N: input/event7
L: 0
S: input/by-path/platform-eeepc-wmi-event
E: DEVPATH=/devices/platform/eeepc-wmi/input/input7/event7
E: DEVNAME=/dev/input/event7
E: MAJOR=13
E: MINOR=71
E: SUBSYSTEM=input
E: USEC_INITIALIZED=3854975
E: KEYBOARD_KEY_6b=f21
E: KEYBOARD_KEY_7c=f20
E: ID_INPUT=1
E: ID_INPUT_KEY=1
E: ID_PATH=platform-eeepc-wmi
E: ID_PATH_TAG=platform-eeepc-wmi
E: LIBINPUT_DEVICE_GROUP=19/0/0:eeepc-wmi
E: DEVLINKS=/dev/input/by-path/platform-eeepc-wmi-event
E: TAGS=:power-switch:
E: CURRENT_TAGS=:power-switch:
==

//modprobeで問題のModuleをBlacklistに追加
sudo vim /etc/modprobe.d/EVIOCSKEYCODE.conf
==
blacklist eeepc_wmi
==
```
以上でシステムログから当該エラーが出なくなります。

## OutOfMemory (OOM) check
OOM が出ているか確認、設定等
```
journalctl | grep oom-killer
==
Feb 21 01:28:59 arch-dev kernel: node invoked oom-killer: gfp_mask=0x1100cca(GFP_HIGHUSER_MOVABLE), order=0, oom_score_adj=0
Feb 22 01:27:17 arch-dev kernel: node invoked oom-killer: gfp_mask=0x1100cca(GFP_HIGHUSER_MOVABLE), order=0, oom_score_adj=0
==
// systemctlでOOMの確認
sudo systemctl enable systemd-oomd --now
sudo systemctl status systemd-oomd
==
● systemd-oomd.service - Userspace Out-Of-Memory (OOM) Killer
     Loaded: loaded (/usr/lib/systemd/system/systemd-oomd.service; enabled; preset: disabled)
     Active: active (running) since Thu 2023-03-16 11:42:40 JST; 2h 23min ago
TriggeredBy: ● systemd-oomd.socket
       Docs: man:systemd-oomd.service(8)
   Main PID: 103218 (systemd-oomd)
     Status: "Processing requests..."
      Tasks: 1 (limit: 154230)
     Memory: 1.6M (min: 64.0M low: 64.0M)
        CPU: 7.363s
     CGroup: /system.slice/systemd-oomd.service
             └─103218 /usr/lib/systemd/systemd-oomd
==

cat /etc/systemd/oomd.conf
==
[OOM]
#SwapUsedLimit=90%
#DefaultMemoryPressureLimit=60%
#DefaultMemoryPressureDurationSec=30s
==


oomctl
==
Dry Run: no
Swap Used Limit: 90.00%
Default Memory Pressure Limit: 60.00%
Default Memory Pressure Duration: 30s
System Context:
       Memory: Used: 4.0G Total: 125.5G
       Swap: Used: 0B Total: 7.9G
Swap Monitored CGroups:
Memory Pressure Monitored CGroups:
==
```
## iwlwifi Error
Intel wifi が少し不安定な場合のトラブルシュート
```
sudo dmesg | grep -i error
==
[  279.939197] iwlwifi 0000:02:00.0: Microcode SW error detected.  Restarting 0x2000000.
[  279.939345] iwlwifi 0000:02:00.0: Start IWL Error Log Dump:
[  279.939447] iwlwifi 0000:02:00.0: 0x00000000 | FSEQ_ERROR_CODE
==

//有効なパラメータ確認
modinfo iwlwifi
==
parm:           debug:debug output mask (uint)
parm:           swcrypto:using crypto in software (default 0 [hardware]) (int)
parm:           11n_disable:disable 11n functionality, bitmap: 1: full, 2: disable agg TX, 4: disable agg RX, 8 enable agg TX (uint)
parm:           amsdu_size:amsdu size 0: 12K for multi Rx queue devices, 2K for AX210 devices, 4K for other devices 1:4K 2:8K 3:12K (16K buffers) 4: 2K (default 0) (int)
parm:           fw_restart:restart firmware in case of error (default true) (bool)
parm:           nvm_file:NVM file name (charp)
parm:           uapsd_disable:disable U-APSD functionality bitmap 1: BSS 2: P2P Client (default: 3) (uint)
parm:           enable_ini:0:disable, 1-15:FW_DBG_PRESET Values, 16:enabled without preset value defined,Debug INI TLV FW debug infrastructure (default: 16)
parm:           bt_coex_active:enable wifi/bt co-exist (default: enable) (bool)
parm:           led_mode:0=system default, 1=On(RF On)/Off(RF Off), 2=blinking, 3=Off (default: 0) (int)
parm:           power_save:enable WiFi power management (default: disable) (bool)
parm:           power_level:default power save level (range from 1 - 5, default: 1) (int)
parm:           disable_11ac:Disable VHT capabilities (default: false) (bool)
parm:           remove_when_gone:Remove dev from PCIe bus if it is deemed inaccessible (default: false) (bool)
parm:           disable_11ax:Disable HE capabilities (default: false) (bool)
==

//モジュールのパラメタ設定
sudo vim  /etc/modprobe.d/iwlwifi.conf
==
options iwlwifi 11n_disable=1 swcrypto=0 bt_coex_active=0 power_save=0
options iwlmvm power_scheme=1
==
```
## regulatory.db Error
wifi 系エラーのトラブルシュート
```
sudo dmesg | grep -i error
==
platform regulatory.0: Direct firmware load for regulatory.db failed with error -2
==

//install
pacman -S crda wireless-regdb

//DBファイルができてるかチェック
ls -l /lib/firmware/regulatory.db*
==
-rw-r--r-- 1 root root 4676 Feb 15 00:27 /lib/firmware/regulatory.db
-rw-r--r-- 1 root root 1182 Feb 15 00:27 /lib/firmware/regulatory.db.p7s
==
```
## Memory Usage Check shell script 
メモリの使用量を確認するファンクションをZSHに追加
```
vim .zshrc
==
memcheck() {
  while read command percent rss; do 
    if [[ "${command}" != "COMMAND" ]]; then 
      rss="$(bc <<< "scale=2;${rss}/1024")" 
    fi
    printf " %-26s%-8s%s\n" "${command}" "${percent}" "${rss} MB" \
    | sed 's/COMMAND/PROGRAM/' | sed 's/RSS MB/#MEM/'
  done < <(ps -A --sort -rss -o comm,pmem,rss | head -n 20)
}
==


//実行
source .zshrc
memcheck
==
 PROGRAM                   %MEM    #MEM
 gunicorn                  0.3     388.21 MB
 gunicorn                  0.3     388.13 MB
 gunicorn                  0.2     335.77 MB
 gunicorn                  0.2     330.62 MB
 node                      0.1     255.30 MB
 node                      0.1     249.32 MB
 mongod                    0.0     127.21 MB
 python3.7                 0.0     91.73 MB
 node                      0.0     78.67 MB
==
 
```


## Unknown group "netdev" in message bus configuration file

```
//journalctl での出力
Mar 25 11:35:06 arch-dev dbus-daemon[706]: Unknown group "netdev" in message bus configuration file
```
上記のでは、netdevグループがないといわれている
```
//iwdにGroupの設定があり
cat /usr/share/dbus-1/system.d/iwd-dbus.conf
<!-- This configuration file specifies the required security policies
     for Wireless daemon to work. -->

<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
 "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
<busconfig>

  <!-- ../system.conf have denied everything, so we just punch some holes -->

  <policy user="root">
    <allow own="net.connman.iwd"/>
    <allow send_destination="net.connman.iwd"/>
    <allow send_interface="net.connman.iwd.Agent"/>
    <allow send_interface="net.connman.iwd.SignalLevelAgent"/>
  </policy>

  <policy group="wheel">
    <allow send_destination="net.connman.iwd"/>
  </policy>

  <policy group="netdev">
    <allow send_destination="net.connman.iwd"/>
  </policy>

  <policy context="default">
    <deny send_destination="net.connman.iwd"/>
  </policy>

</busconfig>

//Groupの追加
groupadd netdev 
```

# その他
なお、USBの規格は下記な感じ
| バージョン | 別名 | 対応コントローラー | 最大速度 |
| --- | --- | --- | --- |
| USB 3.1	| SuperSpeedPlus (Gen2)	| xHCI 1.1| 	10 Gbps |
| USB 3.0	| SuperSpeed (Gen1)	| xHCI (eXtensible HCI)| 	5 Gbps |
| USB 2.0	| High-Speed	| EHCI (Enhanced HCI)| 	480 Mbps |
| USB 1.0 (1.1)| 	Low-Speed, Full-Speed	| UHCI (Universal HCI)	| 1.5 Mbps, 12 Mbps |


TDB