lxc で Ubuntu 18.04 環境構築メモ

# 1. はじめに

この記事は Ubuntu 18.04 を lxc で構築する手順メモです。
ROS melodic を動作させる環境を確保するために lxc で構築したのですが、動作させたい環境が公式とは少し異なるため ROS melodic 環境を導入するまでは記述していません。
なお、ROS2 humble 向けに lxc で Ubuntu 22.04 環境構築を構築したメモは[こちら](https://qiita.com/Corgeek/items/71b9b1c2aa8fc06ab7e5)。

構成は下記の通り。

| 項目 |  |
|---|---|
| 機種名 | HP Pavilion Aero 13-bg |
| CPU | AMD Ryzen 7 8840U |
| GPU | Radeon 780M |
| RAM | 16 GB |
| SWAP | 16 GB |
| Host OS | Kubuntu 24.04 |
| Host OS 側ユーザー名 | user |
| Guest OS | Ubuntu 18.04 |
| Guest OS 側ユーザー名 | ubuntu (デフォルト＆変更可) |

# 2. 作業の流れ

3\. lxd / lxc の準備
　3.1\. lxd / lxc のインストール
　3.2\. lxc の設定
　3.3\. GUI / Sound の共有
　3.4\. ディレクトリの共有(任意)
　3.5\. 設定の確認
4\. コンテナ内環境構築
　4.1\. 基本パッケージ(日本語含む)のインストール
　4.2\. ssh の有効化
　4.3\. IP アドレスの固定

# 3. lxd / lxc の準備

コンテナ名を適宜決めて、一時的なシェル変数に設定。
ROS melodic を入れる前提のホスト名にしていますが、適宜変更してください。

```bash:Host 側
LXCNAME=ros1-melodic
```

## 3.1. lxd / lxc のインストール

今は lxd は snap 側で管理されているため、snap によるインストール＆初期設定。
lxd init での設定は、基本的にすべて default でも問題なし(好みで変更)

```bash: Host 側
sudo snap install lxd
sudo lxd init
```

コンテナの作成(初回はダウンロードで少し時間がかかります)

```bash: Host 側
sudo lxc launch ubuntu:18.04 $LXCNAME
```

## 3.2. lxc の設定

Host 側の UID/GID と共通化
(現在のアカウント以外と共通化する場合は適宜変更)

```bash: Host 側
sudo lxc config set $LXCNAME raw.idmap "both $(id -u) $(id -g)"
```

## 3.3. GUI / Audio の共有

GUI, Audio の作業ディレクトリを Host 側と bind して共有

```bash: Host 側
sudo lxc config device add $LXCNAME audio disk source=/run/user/1000/pulse/native path=/tmp/.pulse-native
sudo lxc config device add $LXCNAME xorg disk source=/tmp/.X11-unix/X0 path=/tmp/.X11-unix/X0
```

video グループの GID を gpu に割り当てて共有

```bash: Host 側
sudo lxc config device add $LXCNAME gpu gpu gid=`getent group video | cut -d: -f3`
```

## 3.4. ディレクトリの共有(任意)

その他、Host 側とディレクトリを共有したい場合は適宜下記コマンドで追加
(e.g. Host 側 /home/user/Downloads, Guest 側 /home/ubuntu/Downloads を共有する場合)

```bash: Host 側
sudo lxc config device add $LXCNAME share disk source=${HOME}/Downloads path=/home/ubuntu/Downloads
```

## 3.5. lxc 内で docker を動かす設定(任意)

lxc 内で docker を動かしたい場合は下記のコマンドでネストを有効化

```
sudo lxc config set $LXCNAME security.nesting true
```

## 3.6. インスタンスの自動起動を off にする(任意)

host 起動時に、毎回インスタンスを起動させたくない場合は以下のコマンドで抑制
(起動させたい場合は `sudo lxc start $LXCNAME` による手動)

```
sudo lxc config set $LXCNAME boot.autostart=false
```

## 3.7. 設定の確認

以下で設定を確認できます。
both 1000 1000, audio, xorg, gpu など追加されていることが確認できます。

```bash: Host 側
sudo lxc config show $LXCNAME
```

# 4. コンテナ内環境構築

コンテナ内で作業するため、bash を実行
(ログアウトするまでroot権限なので注意)

```bash: Host 側
sudo lxc exec $LXCNAME /bin/bash
```

## 4.1. 基本パッケージ(日本語含む)のインストール

まずは最新の環境にまで upgrade

```bash: Guest 側
apt update && apt full-upgrade -y && apt autoremove -y
```

基本的なパッケージのインストール

```bash: Guest 側
apt install -y x11-apps pulseaudio dbus-x11 language-pack-ja fonts-noto-cjk-extra language-pack-gnome-ja-base language-pack-gnome-ja gnome-user-docs-ja gnome-control-center fonts-noto-color-emoji manpages-ja ibus-mozc
```

サウンドの設定

```bash: Guest 側
sed -i "s/; enable-shm = yes/enable-shm = no/g" /etc/pulse/client.conf
```

日本語設定/ロケール設定

```bash: Guest 側
update-locale LANG=ja_JP.UTF-8
timedatectl set-timezone Asia/Tokyo
localectl set-locale LANG=ja_JP.UTF-8 LANGUAGE="ja_JP:ja"
localectl set-x11-keymap jp jp106
source /etc/default/locale
dbus-uuidgen > /var/lib/dbus/machine-id
```

ubuntu ユーザーに切り替えて、ユーザー個別の設定

```bash: Guest 側
su - ubuntu
source /etc/default/locale
```

下記コマンドで ~/.profile に追記

```bash: Guest 側
cat << 'EOF' >> ~/.profile
export PULSE_SERVER=unix:/tmp/.pulse-native
export LANG=ja_JP.UTF8
EOF
```

ここまでの作業を確実に反映させるためコンテナの再起動
(Host 側に戻ります)

```bash: Guest 側
sudo reboot
```

## 4.2. ssh の有効化

ホストからゲストに ssh でログインするための鍵を作成
(すべて未指定の改行のみでもOKですが、気になる方は適宜指定を)

```bash:Host 側
ssh-keygen -f ~/.ssh/${LXCNAME}
```

ここで作成された公開鍵(ros1-melodic.pub)の中身を後で使うので、画面上に表示やメモ帳などにコピーしておく(下記は cat で画面上に出力しているだけです)

```bash: 出力例
cat ~/.ssh/${LXCNAME}.pub
ssh-ed25519 ABCDEFG...(略) user@host
```

Guest 側に移行

```bash:Host 側
sudo lxc exec $LXCNAME /bin/bash
```

Guest 側に ssh をインストール

```bash:Guest 側
apt install ssh
```

鍵による認証を有効にするため `/etc/ssh/sshd_config` の `PubkeyAuthentication` のコメントアウトを外す

```bash: Guest 側
nano /etc/ssh/sshd_config
```
`#PubkeyAuthentication yes`
　　　　　　↓
`PubkeyAuthentication yes`


ユーザーを `ubuntu` に切り替えた後、先程作成した公開鍵を `~/.ssh/authorized_keys` に保存する。
(先述の `ssh-ed25519 ABCDEFG...(略) user@host` をそのまま `~/.ssh/authorized_keys` に書き込みでOK)

```bash:Guest 側
su - ubuntu
nano ~/.ssh/authorized_keys
```

```bash:Guest 側
cat ~/.ssh/authorized_keys
ssh-ed25519 ABCDEFG...(略) user@host
```

権限の設定

```bash:Geust 側
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
```


## 4.3. IP アドレスの固定

事前に lxdbr0 のネットワークアドレスを把握しておく。

```bash: Host 側
ip a |grep lxdbr0 | grep inet
```

手元では出力結果が 10.169.78.1/24 でした。

```bash:出力結果
    inet 10.169.78.1/24 scope global lxdbr0
```

下記コマンドで IP アドレスの固定化を行う。
IP は先程確認したネットワークアドレス内で決める(今回は `10.169.78.101` とした)。
その後再起動。

```bash: Host 側
sudo lxc network attach lxdbr0 ${LXCNAME} eth0 eth0
sudo lxc config device set ${LXCNAME} eth0 ipv4.address 10.169.78.101
sudo lxc restart ${LXCNAME}
```

コンテナにアクセスしやすいように、固定化したIPアドレスを登録させておく

```bash: Host 側
echo "10.169.78.101 ${LXCNAME}" | sudo tee -a /etc/hosts > /dev/null
```

Host 側のユーザーで、ssh で Guest 側にアクセスする際の設定を行う。
~/.ssh/config をエディタで開き、下記を追記
(-X オプションをデフォルトで有効にするため `ForwardX11 yes` を指定)

```: Host 側 ~/.ssh/config の設定
Host ros1-melodic
    HostName ros1-melodic
    ForwardX11 yes
    User ubuntu
    IdentityFile ~/.ssh/ros1-melodic
```

ssh 接続テスト

```bash: Host 側
ssh ros1-melodic
```

正常に接続を確認できれば、環境構築完了です。