mmdebstrapを使ってJetson NanoへUbuntu 20.04環境を最小クリーンインストールする
概要
Jetson NanoのOSをubuntu 20.04以降へ更新するのはけっこう大変です。JetPack(ubuntu 18.04)をベースにアップデートすることはできますが、実際にやってみると時間がかかるうえ途中でダイアログを出して止まったりするので手間もかかります。依存関係をきちんと把握して対処しないと、netplanなどのOSの基本的なコンポーネントが削除されてネットにつながらないシステムが出来上がったりします。
今回、Jetson Nano用にミニマルな構成のubuntu 20.04環境をクリーンインストールすることができましたので、その作業手順をご紹介します。最小構成なら10〜20分程度でインストールが終わりますので、かなりの時短ができると思います。ミニマルなシステムをベースにして必要なコンポーネントをビルドアップする方が、かえって環境構築が簡単だと実感されるかも知れません。
作業の流れ
作業の流れは次のとおりです。
- Jetson NanoをJetPackで起動する
- USBカードリーダ経由で別のmicroSDカードへ最小構成のubuntuをインストールする
2.1.mmdebstrap
を使ってubuntuを展開する
2.1.chroot
で入ってJetson Linux Driver Package (L4T)を追加する - 必要に応じて開発環境やGUIデスクトップ環境などを追加する
これでシンプルなubuntu 20.04環境が出来上がります。
準備
用意するもの
SDカード2枚とUSBカードリーダを使用します。本記事では2枚のSDカードを区別するために、それぞれ親SD、子SDと呼ぶことにします。
- Jetson Nano
- microSDカード2枚
- 親SD:JetPackホスト用のmicroSD
- 子SD:ubuntu 20.04のインストールターゲットとなるmicroSD
- microSDカード用のUSBカードリーダ
JetPackのインストール(親SD、子SDとも)
親SD、子SDの両方にJetPackをインストールして、それぞれ一旦Jetson Nanoを起動して設定を終わらせておきます。子SDは後ほどパーティション1の中身を削除することになりますが、microSDカード上にはOSパーティション以外にも固有のパーティションが複数ありますので、それらを作成しておくためにこの作業が必要です。
クリーンインストール開始
Jetson Nanoの起動
準備を済ませた親SDでJetson Nanoを起動して、まずはJetPack自身のOSパッケージのアップデートを行います。
sudo apt update
sudo apt upgrade
sudo shutdown -r now
子SDのマウント
USBカードリーダをJetson NanoのUSBポートへ接続して、子SDのデバイスとパーティションを探します。パーティション1〜14が存在するsdデバイスが該当するmicroSDカードです。
ls /dev/sd*
/dev/sda /dev/sdc /dev/sdd1 /dev/sdd11 /dev/sdd13 /dev/sdd2 /dev/sdd4 /dev/sdd6 /dev/sdd8
/dev/sdb /dev/sdd /dev/sdd10 /dev/sdd12 /dev/sdd14 /dev/sdd3 /dev/sdd5 /dev/sdd7 /dev/sdd9
ここではsddが該当するmicroSDカードです。パーティション1を/mnt
へマウントします。
sudo mount /dev/sdd1 /mnt
マウントしたパーティション(子SDのパーティション1)の中身をすべて削除します。
sudo rm -rf /mnt/*
mmdebstrap
の実行
作業用コンテナのセットアップとmmdebstrap
はシステム環境構築ツールです。比較的新しいツールなので、ubuntuでは19.04以降で使用できます。JetPackのOSはubuntu 18.04であるためmmdebstrap
コマンドがありません。今回はLXD/LXCを使ってJetPack上にubuntu 20.04の作業用コンテナを立ち上げて、そこでmmdebstrap
を使用します。
sudo apt install -y lxd
sudo lxd init --auto
lxc launch ubuntu:20.04 mm
コンテナ名は短くmm
としました。続いて、ホストの/mnt
をコンテナの/mnt
にマウントします。その後、設定反映のためにコンテナを再起動してからコンテナに入ります。
lxc config device add mm mnt disk source=/mnt path=mnt
lxc config set mm security.privileged true
lxc config set mm security.nesting true
lxc restart mm
lxc exec mm -- /bin/bash
mmdebstrap
をインストールします。
apt update
apt upgrade -y
apt install -y mmdebstrap
mmdebstrap
を使ってubuntu 20.04 (名称focal) を/mnt
へインストールします。
mmdebstrap --components="main restricted universe multiverse" focal /mnt http://ports.ubuntu.com/ubuntu-ports
進捗を眺めながらインストールが終わるのを待ちます。数分程度です。
I: automatically chosen mode: root
I: chroot architecture arm64 is equal to the host's architecture
I: running apt-get update...
done
I: downloading packages with apt...
done
I: extracting archives...
done
I: installing packages...
done
I: downloading apt...
done
I: installing apt...
done
I: installing remaining packages inside the chroot...
done
I: cleaning package lists and apt cache...
done
done
USB2接続の場合、4分程度で終わりました。そのうち2/3以上はI/O waitに費やされているようです。
real 4m1.236s
user 0m54.472s
sys 0m16.680s
終わったらexit
してコンテナから抜けます。
exit
コンテナの役目はここまでです。
ubuntu 20.04環境の初期設定
親SDのJetPackからファイル3つをubuntu 20.04環境へコピーします。これらは後ほどL4Tをインストールする際に参照されます。
sudo cp -i /etc/nv_boot_control.conf /mnt/etc/
sudo cp -i /etc/apt/sources.list.d/nvidia-l4t-apt-source.list /mnt/etc/apt/sources.list.d/
sudo cp -r -i /boot/extlinux /mnt/boot/
このタイミングで子SDの/etc/apt/sources.list
ファイル(親SDからは/mnt/etc/apt/sources.list
として見える)を次のように編集しておきます。
deb http://ports.ubuntu.com/ubuntu-ports focal main restricted universe multiverse
deb http://ports.ubuntu.com/ubuntu-ports focal-updates main restricted universe multiverse
deb http://ports.ubuntu.com/ubuntu-ports focal-security main restricted universe multiverse
deb http://ports.ubuntu.com/ubuntu-ports focal-backports main restricted universe multiverse
必要なデバイスをmount
したうえで、chroot
でubuntu 20.04環境へ入ります。
sudo mount -t proc none /mnt/proc
sudo mount -t devtmpfs none /mnt/dev
sudo mount -t sysfs none /mnt/sys
sudo chroot /mnt /bin/su
以降はchroot
内での作業が続きます。
初期設定をおこないます。
cd
echo "/dev/root / ext4 defaults 0 1" >> /etc/fstab
echo "child" > /etc/hostname
echo "Asia/Tokyo" > /etc/timezone
cp /usr/share/zoneinfo/Japan /etc/localtime
locale-gen ja_JP.UTF-8
echo -e "network:\n version: 2\n ethernets:\n eth0:\n dhcp4: yes" > /etc/netplan/01-dhcp.yaml
ユーザを作成します。(ここではユーザ名をfooとしています)
adduser foo
usermod -aG sudo foo
L4Tのインストール準備
apt
にNVIDIAのキーを登録します。初回のapt update
ではエラーが出ますがキーを登録すれば消えますので問題ありません。
apt update
apt install -y gnupg
apt-key adv --fetch-key http://repo.download.nvidia.com/jetson/jetson-ota-public.asc
apt update
L4Tが依存するlibffi6
パッケージをubuntu 18.04用のリポジトリから取得してインストールします。(問題なくインストールできます)
apt install -y wget
wget http://ports.ubuntu.com/pool/main/libf/libffi/libffi6_3.2.1-8_arm64.deb
apt install -y ./libffi6_*_arm64.deb
後ほどI2Cを通してJetson Nano本体のブートローダを書き換えますので、あらかじめi2c-tools
をインストールしておきます。
apt install -y i2c-tools
L4Tのインストール
最初にnvidia-l4t-apt-source
をインストールします。既存ファイルを上書きさせます。
apt -o Dpkg::Options::="--force-confnew" install -y nvidia-l4t-apt-source
続いてnvidia-l4t-init
をインストールします。/etc/systemd/sleep.conf
ファイルがsystemd
パッケージとバッティングしますので上書きインストールします。
apt -o Dpkg::Options::="--force-overwrite" install -y nvidia-l4t-init
L4TのBSPコンポーネントグループをインストールします。
apt install -y \
jetson-gpio-common \
nvidia-l4t-3d-core \
nvidia-l4t-apt-source \
nvidia-l4t-bootloader \
nvidia-l4t-camera \
nvidia-l4t-configs \
nvidia-l4t-core \
nvidia-l4t-cuda \
nvidia-l4t-firmware \
nvidia-l4t-graphics-demos \
nvidia-l4t-gstreamer \
nvidia-l4t-init \
nvidia-l4t-initrd \
nvidia-l4t-jetson-io \
nvidia-l4t-jetson-multimedia-api \
nvidia-l4t-kernel \
nvidia-l4t-kernel-dtbs \
nvidia-l4t-kernel-headers \
nvidia-l4t-multimedia \
nvidia-l4t-multimedia-utils \
nvidia-l4t-oem-config \
nvidia-l4t-tools \
nvidia-l4t-wayland \
nvidia-l4t-weston \
nvidia-l4t-x11 \
nvidia-l4t-xusb-firmware \
python-jetson-gpio \
python3-jetson-gpio
Tegra用のDRM (Direct Rendering Manager)を入れておきます。
apt install -y libdrm-tegra0
インストール作業の終了
chroot
を抜けてJetson Nanoをシャットダウンします。
exit
sudo shutdown -h now
作成したUbuntu 20.04の起動とパッケージの追加
作成した子SDをJetson Nanoへ装着して起動します。最小インストールのシンプルなCLIのubuntuが起動します。
アクセス権の追加
最初に、ユーザに対してシステムリソースやデバイスへのアクセス権を付与します。
# ログファイル
sudo usermod -aG adm $USER
# GPU、オーディオ
sudo usermod -aG video $USER
sudo usermod -aG audio $USER
# 外部機器, I/O端子, ほか
sudo usermod -aG cdrom $USER
sudo usermod -aG plugdev $USER
sudo usermod -aG gpio $USER
sudo usermod -aG i2c $USER
sudo usermod -aG dip $USER
sudo usermod -aG lpadmin $USER
Timezoneの設定
システムのTimezoneも設定しておきましょう。
sudo timedatectl set-timezone Asia/Tokyo
swapの追加
デフォルトのswapはzramを使った2GBですので、すぐに足りなくなってしまいます。ファイルシステム上にスワップファイルを6GBほど確保して追加しておきます。
sudo fallocate -l 6g /swapfile
sudo mkswap /swapfile
sudo chmod 0600 /swapfile
sudo sh -c "echo /swapfile none swap defaults 0 0 >>/etc/fstab"
sudo swapon -p 1 /swapfile
追加パッケージのインストール
用途に応じて必要なパッケージを追加インストールします。参考までに次のパッケージのインストール方法を以下に記します。
- 言語パック
- 日本語キーボードの設定
- openssh-server
- nvidia-container
- CUDA および cuDNN
- VisionWorks
- VPI および nvidia-opencv
- gputools
- uff-converter-tf
- nsight-systems-cli
- deepstream
- graphsurgeon-tf
- cuda-minimal-build
- cuda-gdb-src
- TensorRT
- デスクトップ環境
- Unity
- GNOME3
- KDE
- LXQt
- XFce
- MATE
- Cinnamon
- Budgie
- UKUI
言語パック
sudo apt install -y language-pack-ja language-pack-en
日本語キーボードの設定
sudo dpkg-reconfigure keyboard-configuration
次の順に設定します。
- Generic 105-key (Intl) PC
- Japanese
openssh-server
sudo apt install -y openssh-server
nvidia-container
sudo apt install -y nvidia-container
CUDA および cuDNN
sudo apt install -y nvidia-cuda nvidia-cudnn8
Computer vision (VisionWorks)
sudo apt install -y nvidia-visionworks
Computer vision (VPI) および nvidia-opencv
依存関係がキツイので不足するコンポーネントをubuntu 18.04から取得します。libopencv-dev
がubuntu 20.04とバッティングしますのでnvidiaのパッケージバージョンを指定したうえholdマークを付けます。その際にubuntu 20.04由来のopencv
関連のパッケージが多数不要となりautoremove対象となります。
wget \
http://ports.ubuntu.com/pool/main/libv/libvpx/libvpx5_1.7.0-3ubuntu0.18.04.1_arm64.deb \
http://ports.ubuntu.com/pool/universe/f/ffmpeg/libavcodec57_3.4.8-0ubuntu0.2_arm64.deb \
http://ports.ubuntu.com/pool/universe/f/ffmpeg/libavformat57_3.4.8-0ubuntu0.2_arm64.deb \
http://ports.ubuntu.com/pool/universe/f/ffmpeg/libavutil55_3.4.8-0ubuntu0.2_arm64.deb \
http://ports.ubuntu.com/pool/universe/f/ffmpeg/libswresample2_3.4.8-0ubuntu0.2_arm64.deb \
http://ports.ubuntu.com/pool/universe/f/ffmpeg/libswscale4_3.4.8-0ubuntu0.2_arm64.deb \
http://ports.ubuntu.com/pool/universe/x/x264/libx264-152_0.152.2854+gite9a5903-2_arm64.deb \
http://ports.ubuntu.com/pool/universe/x/x265/libx265-146_2.6-3_arm64.deb
sudo apt install -y \
./libvpx5_*_arm64.deb \
./libavcodec57_*_arm64.deb \
./libavformat57_*_arm64.deb \
./libavutil55_*_arm64.deb \
./libswresample2_*_arm64.deb \
./libswscale4_*_arm64.deb \
./libx264-152_*_arm64.deb \
./libx265-146_*_arm64.deb
sudo apt install -y --allow-downgrades --allow-change-held-packages \
nvidia-opencv \
libopencv \
libopencv-dev=4.1.1-2-gd5a58aa75 \
libopencv-python \
libopencv-samples \
opencv-licenses
sudo apt-mark hold libopencv-dev
sudo apt install -y \
libnvvpi1 \
vpi1-demos \
vpi1-dev \
vpi1-samples \
python-vpi1
以下のパッケージが自動でインストールされましたが、もう必要とされていません:
gdal-data ibverbs-providers javascript-common libaec0 libarmadillo9
libarpack2 libavcodec-dev libavformat-dev libavresample-dev libavresample4
libavutil-dev libcaf-openmpi-3 libcfitsio8 libcharls2
libcoarrays-openmpi-dev libdap25 libdapclient6v5 libdc1394-22-dev
libepsilon1 libevent-2.1-7 libevent-core-2.1-7 libevent-dev
libevent-extra-2.1-7 libevent-openssl-2.1-7 libevent-pthreads-2.1-7
libexif-dev libexif-doc libexif12 libfreexl1 libfyba0 libgd3 libgdal26
libgdcm-dev libgdcm3.0 libgeos-3.8.0 libgeos-c1v5 libgeotiff5 libgif7
libgl2ps1.4 libgphoto2-6 libgphoto2-dev libgphoto2-l10n libgphoto2-port12
libhdf4-0-alt libhdf5-103 libhdf5-openmpi-103 libhwloc-dev libhwloc-plugins
libhwloc15 libibverbs-dev libibverbs1 libilmbase-dev libjbig-dev libjpeg-dev
libjpeg-turbo8-dev libjpeg8-dev libjs-jquery libkmlbase1 libkmldom1
libkmlengine1 liblept5 liblzma-dev libminizip1 libmysqlclient21
libnetcdf-c++4 libnetcdf15 libnl-3-200 libnl-3-dev libnl-route-3-200
libnl-route-3-dev libnspr4 libnss3 libnuma-dev libodbc1 libogdi4.1
libopencv-calib3d4.2 libopencv-contrib4.2 libopencv-core4.2 libopencv-dnn4.2
libopencv-features2d4.2 libopencv-flann4.2 libopencv-highgui4.2
libopencv-imgcodecs4.2 libopencv-imgproc4.2 libopencv-ml4.2
libopencv-objdetect4.2 libopencv-photo4.2 libopencv-shape4.2
libopencv-stitching4.2 libopencv-superres4.2 libopencv-video4.2
libopencv-videoio4.2 libopencv-videostab4.2 libopencv-viz4.2
libopencv4.2-java libopencv4.2-jni libopenexr-dev libopenmpi-dev libopenmpi3
libpciaccess0 libpmix2 libpng-dev libpng-tools libpoppler97 libpq5 libproj15
libprotobuf17 libqhull7 libraw1394-dev libraw1394-tools libsocket++1
libspatialite7 libsuperlu5 libswresample-dev libswscale-dev libsz2
libtbb-dev libtesseract4 libtiff-dev libtiffxx5 liburiparser1 libvtk6.3
libxerces-c3.2 libxnvctrl0 mysql-common odbcinst odbcinst1debian2
openmpi-bin openmpi-common poppler-data proj-bin proj-data
gputools
sudo apt install -y nvidia-l4t-gputools
uff-converter-tf
sudo apt install -y uff-converter-tf
nsight-systems-cli
sudo apt install -y nsight-systems-cli-2021.2.3
deepstream
sudo apt install -y deepstream-6.0
graphsurgeon-tf
sudo apt install -y graphsurgeon-tf
cuda-minimal-build
sudo apt install -y cuda-minimal-build-10-2
cuda-gdb-src
sudo apt install -y cuda-gdb-src-10-2
TensorRT (非推奨)
wget http://ports.ubuntu.com/pool/main/p/python3.6/python3.6_3.6.9-1~18.04ubuntu1.6_arm64.deb
wget http://ports.ubuntu.com/pool/main/p/python3.6/python3.6-minimal_3.6.9-1~18.04ubuntu1.6_arm64.deb
wget http://ports.ubuntu.com/pool/main/p/python3.6/libpython3.6-stdlib_3.6.9-1~18.04ubuntu1.6_arm64.deb
wget http://ports.ubuntu.com/pool/main/p/python3.6/libpython3.6-minimal_3.6.9-1~18.04ubuntu1.6_arm64.deb
wget http://ports.ubuntu.com/pool/main/r/readline/libreadline7_7.0-3_arm64.deb
wget http://ports.ubuntu.com/pool/main/p/python3-defaults/python3_3.6.7-1~18.04_arm64.deb
wget http://ports.ubuntu.com/pool/main/p/python3-defaults/python3-minimal_3.6.7-1~18.04_arm64.deb
wget http://ports.ubuntu.com/pool/main/p/python3-defaults/libpython3-stdlib_3.6.7-1~18.04_arm64.deb
sudo apt install -y --allow-downgrades \
./python3_*_arm64.deb \
./python3-minimal_*_arm64.deb \
./libpython3-stdlib_*_arm64.deb \
./python3.6_*_arm64.deb \
./python3.6-minimal_*_arm64.deb \
./libpython3.6-stdlib_*_arm64.deb \
./libpython3.6-minimal_*_arm64.deb \
./libreadline7_*_arm64.deb
sudo apt install -y nvidia-tensorrt python3-libnvinfer python3-libnvinfer-dev
sudo apt-mark hold nvidia-tensorrt python3-libnvinfer python3-libnvinfer-dev
デスクトップ環境
デスクトップ環境を利用するためにはGPUとオーディオデバイスへのアクセス権が必要です。
sudo usermod -aG video $USER
sudo usermod -aG audio $USER
また、使用するディスプレイマネージャに応じてアクセス権を設定してください。
# gdm
sudo usermod -aG video gdm
sudo usermod -aG gdm $USER
# lightdm
sudo usermod -aG video lightdm
sudo usermod -aG lightdm $USER
# sddm
sudo usermod -aG video sddm
sudo usermod -aG sddm $USER
Unity
sudo apt install -y ubuntu-unity-desktop
sudo usermod -aG video $USER
sudo usermod -aG audio $USER
sudo usermod -aG video lightdm
sudo usermod -aG lightdm $USER
GNOME3
sudo apt install -y ubuntu-desktop
sudo usermod -aG video $USER
sudo usermod -aG audio $USER
sudo usermod -aG video gdm
sudo usermod -aG gdm $USER
KDE
sudo apt install -y kubuntu-desktop
sudo usermod -aG video $USER
sudo usermod -aG audio $USER
sudo usermod -aG video sddm
sudo usermod -aG sddm $USER
SDDM
が使えない場合はlightdm
で代替できます。
LXQt
sudo apt install -y lubuntu-desktop
sudo usermod -aG video $USER
sudo usermod -aG audio $USER
sudo usermod -aG video sddm
sudo usermod -aG sddm $USER
SDDM
が使えない場合はlightdm
で代替できます。GPUリソースをあまり使わないようなので動作が軽いです。
Xfce
sudo apt install -y xubuntu-desktop
sudo usermod -aG video $USER
sudo usermod -aG audio $USER
sudo usermod -aG video lightdm
sudo usermod -aG lightdm $USER
ログイン画面lightdm
のテーマlightdm-gtk-greeter
がインストールされますがミニキーボードのNumLk制御との相性がよくありませんでした。同様の環境の方へはlightdm-gtk-greeter
のアンインストールをおすすめします。
MATE
sudo apt install -y ubuntu-mate-desktop
sudo usermod -aG video $USER
sudo usermod -aG audio $USER
sudo usermod -aG video lightdm
sudo usermod -aG lightdm $USER
GPUリソースをあまり使わないようです。
Cinnamon
sudo apt install -y cinnamon-desktop-environment
sudo usermod -aG video $USER
sudo usermod -aG audio $USER
sudo usermod -aG video lightdm
sudo usermod -aG lightdm $USER
Budgie
sudo apt install -y ubuntu-budgie-desktop
sudo usermod -aG video $USER
sudo usermod -aG audio $USER
sudo usermod -aG video lightdm
sudo usermod -aG lightdm $USER
nvpmodel_indicator.py
がパネル上で大きな顔をしますので対応が必要です。
UKUI
sudo apt install -y ubuntukylin-desktop
sudo usermod -aG video $USER
sudo usermod -aG audio $USER
sudo usermod -aG video lightdm
sudo usermod -aG lightdm $USER
Jetson NanoのGPUに対して画面エフェクトが多めです。
まとめ
mmdebstrap
で作成したブートストラップ環境にL4Tを追加することで、Jetson Nano用のUbuntu 20.04の最小クリーンインストールを行うことができます。必要に応じてコンポーネントを追加することにより、フットプリントが小さくて実用的なファイルシステムが作成できます。
本稿の手順でubuntu 21.10環境のインストールも可能でした。
Discussion