Raspberry Pi OS (bookworm) でOSインストール時に固定IPアドレスを設定するには
Raspberry Pi OS (bookworm) になってから dhcpcd による固定IPアドレスの設定ができなくなりました。
特にWiFi接続においては NetworkManager ベースに変更されたことにより固定IPアドレスをOSイントール時に設定できなくなりました。
OSインストール時に固定IPアドレスを設定できれば端末にモニターのみを接続し、リモートからSSHで接続できるのでメンテナンス操作が楽になります。
今回は Raspberry Pi OS with Desktop (bookworm) において有線ネットワーク接続を固定IPアドレスに設定する NetworkManager用の接続設定ファイルを生成するシェルスクリプトを紹介します。
リリースノート
Raspberry Pi OS (bookworm) Release notes
2023-10-10:
...途中省略...
* NetworkManager used instead of dhcpcd as networking interface; various changes made to networking plugin to support this
...以下省略...
参考サイト
Raspberry Pi 公式ドキュメント
Raspberry Pi Documentation: Configuration / raspi-config #networking
1 環境
1-1 検証用デバイス
- Raspberry Pi zero 2w
- インストールOS
- (A) Raspberry Pi OS (Legacy) with desktop 32bit bullseye
2024-10-22-raspios-bullseye-armhf.img.xz
※ネットワーク接続設定ファイルの比較としてインストールします - (B) Raspberry Pi OS with desktop 32bit bookworm
2024-11-19-raspios-bookworm-armhf.img.xz
- (A) Raspberry Pi OS (Legacy) with desktop 32bit bullseye
- インストールOS
1-2 開発用 PC
- Ubuntu 22-04 Desktop
- rpi-imager インストール済み
sudo apt-get install rpi-imager
2 ネットワーク接続設定
それぞれのOSイメージに共通なカスタマイズ設定を以下のとおりとします。
- ネットワーク接続
各自お使いの環境のアドレスに置き換えて下さい- デフォルトルート: 192.168.0.1
- 固定IPアドレス
- 有線接続: 192.168.0.19/24
- Wi-Fi接続: 192.168.0.49/24
- カスタム設定
- 一般
- ホスト名: raspi-2w-dev
- ユーサー名とパスワード設定する
- ロケールを設定する
(1) タイムゾーン: Asia/Tokyo
(2) キーボードレイアウト: jp
- サービス
- SSHを有効化する
公開鍵認証のみを許可する ※開発用PCの公開鍵を設定
- SSHを有効化する
- 一般
2-0 SDカードの再マウント
rpi-imager で書き込み完了後のSDカードを取り外し、再度 USBに挿したときのマウント先
※1 Ubuntu では bootfs は読み取り専用、rootfs は読み書きモードでマウントされます。
※2 私の環境ではデバイスは /dev/sdc1 (bootfs), /dev/sdc2 (rootfs1) でした。
$ LANG=C;lsblk -e7 | grep sdc
sdc 8:32 1 59.5G 0 disk
|-sdc1 8:33 1 512M 0 part /media/yukio/bootfs
`-sdc2 8:34 1 58.9G 0 part /media/yukio/rootfs1
# bootfs に移動
$ cd $ cd /media/yukio/bootfs/
/media/yukio/bootfs$ ls -l --time-style long-iso *.sh | grep -v total
-rw-r--r-- 1 yukio yukio 2520 2024-12-19 21:27 firstrun.sh
2-1 Raspberry Pi OS (Legacy)
Raspberry Pi Imager で OSイメージを SD カードに書き込みすると rootfs 上の /etc ディレクトリ内に固定IPアドレス設定の雛形となる dhcpcd.conf ファイルを出力していました。
イメージ書き込み後に SD カードを取り外し再度 SD カードを挿し直すと rootfs に読み書きモードでマウントするので容易に固定IPアドレスを設定するとこができます。
# A sample configuration for dhcpcd.
# See dhcpcd.conf(5) for details.
# ... 一部割愛 ...
# Generate SLAAC address using the Hardware Address of the interface
#slaac hwaddr
# OR generate Stable Private IPv6 Addresses based from the DUID
slaac private
# Example static IP configuration:
#interface eth0
#static ip_address=192.168.0.10/24
#static ip6_address=fd51:42f8:caae:d92e::ff/64
#static routers=192.168.0.1
#static domain_name_servers=192.168.0.1 8.8.8.8 fd51:42f8:caae:d92e::1
# It is possible to fall back to a static IP if DHCP fails:
# define static profile
#profile static_eth0
#static ip_address=192.168.1.23/24
#static routers=192.168.1.1
#static domain_name_servers=192.168.1.1
# fallback to static profile on eth0
#interface eth0
#fallback static_eth0
2-1-1 (A) WiFi接続のみを有効にする設定
[条件] OSカスタマイズで Wi-Fiを設定し各項目を設定済みであること
# Example static IP configuration:
以下のサンプル設定を全て削除し、下記のように WiFiインターフェース(wlan0)に対して固定アドレスを設定し変更を保存します。
# staticIp address for wlan0
interface wlan0
static ip_address=192.168.0.49/24
static routers=192.168.0.1
static domain_name_servers=192.168.0.1
[補足] OSのインストールが完了すると /etc/wpa_supplicant
ディレクトリに wpa_supplicant.conf ファイルが生成されます。
※ SSID と パスフレーズは適当に編集しています。
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
network={
ssid="xxxxxx2g-yyyyyy"
psk=1ebb370489744cc3ea554c2d61651b06361cb7b3b87bf9660d2b4dff4b7be7e1
}
OS イントール時のブートログ
※ジャーナルログからタイムスタンプを削除しています。
raspi-2w-dev dhcpcd[364]: dev: loaded udev
raspi-2w-dev dhcpcd[364]: forked to background, child pid 451
raspi-2w-dev dhcpcd[451]: wlan0: connected to Access Point `'
raspi-2w-dev dhcpcd[451]: eth0: waiting for carrier
raspi-2w-dev dhcpcd[451]: wlan0: waiting for carrier
raspi-2w-dev dhcpcd[451]: wlan0: waiting for carrier
raspi-2w-dev dhcpcd[451]: wlan0: carrier acquired
raspi-2w-dev dhcpcd[451]: wlan0: connected to Access Point `xxxxxx2g-yyyyyy'
raspi-2w-dev dhcpcd[451]: DUID 00:01:00:01:2e:aa:5e:a2:2c:cf:67:13:54:3c
raspi-2w-dev dhcpcd[451]: wlan0: IAID 67:13:54:3c
raspi-2w-dev dhcpcd[451]: wlan0: adding address fe80::ae45:94d9:3257:a6da
raspi-2w-dev dhcpcd[451]: wlan0: probing address 192.168.0.49/24
raspi-2w-dev dhcpcd[451]: wlan0: soliciting an IPv6 router
raspi-2w-dev dhcpcd[451]: wlan0: using static address 192.168.0.49/24
raspi-2w-dev dhcpcd[451]: wlan0: adding route to 192.168.0.0/24
raspi-2w-dev dhcpcd[451]: wlan0: adding default route via 192.168.0.1
raspi-2w-dev dhcpcd[451]: wlan0: no IPv6 Routers available
ディスクトップ画面にトーストで数秒間接続されたIPアドレスが表示されます。
2-1-2 (B) 有線ネットワークとWiFi接続を有効にする設定
dhcpcd.conf ファイルには複数のインターフェースを設定することができます。
※1 今回は複数のインターフェースが同時に有効になることを示すために2つ設定しました。
※2 通常は有線ネットワークインターフェース (eth0) のみを指定することになります。
# staticIp address for eth0
interface eth0
static ip_address=192.168.0.19/24
static routers=192.168.0.1
static domain_name_servers=192.168.0.1
# staticIp address for wlan0
interface wlan0
static ip_address=192.168.0.49/24
static routers=192.168.0.1
static domain_name_servers=192.168.0.1
OS イントール時のブートログ
※1 ジャーナルログからタイムスタンプを削除しています。
※2 2つのインターフェースが設定されいます。
raspi-2w-dev dhcpcd[364]: dev: loaded udev
raspi-2w-dev dhcpcd[364]: forked to background, child pid 440
raspi-2w-dev dhcpcd[440]: eth0: waiting for carrier
raspi-2w-dev dhcpcd[440]: eth0: waiting for carrier
raspi-2w-dev dhcpcd[440]: wlan0: connected to Access Point `'
raspi-2w-dev dhcpcd[440]: wlan0: waiting for carrier
raspi-2w-dev dhcpcd[440]: eth0: carrier acquired
raspi-2w-dev dhcpcd[440]: DUID 00:01:00:01:2e:aa:5e:9f:7c:c2:c6:28:b5:29
raspi-2w-dev dhcpcd[440]: eth0: IAID c6:28:b5:29
raspi-2w-dev dhcpcd[440]: eth0: adding address fe80::6b1e:5390:f669:c2a8
raspi-2w-dev dhcpcd[440]: eth0: probing address 192.168.0.19/24
raspi-2w-dev dhcpcd[440]: eth0: soliciting an IPv6 router
raspi-2w-dev dhcpcd[440]: wlan0: carrier acquired
raspi-2w-dev dhcpcd[440]: wlan0: connected to Access Point `xxxxxx2g-yyyyyy'
raspi-2w-dev dhcpcd[440]: wlan0: IAID 67:13:54:3c
raspi-2w-dev dhcpcd[440]: wlan0: adding address fe80::2ffa:11ae:ef44:510c
raspi-2w-dev dhcpcd[440]: wlan0: probing address 192.168.0.49/24
raspi-2w-dev dhcpcd[440]: eth0: using static address 192.168.0.19/24
raspi-2w-dev dhcpcd[440]: eth0: adding route to 192.168.0.0/24
raspi-2w-dev dhcpcd[440]: eth0: adding default route via 192.168.0.1
raspi-2w-dev dhcpcd[440]: wlan0: soliciting an IPv6 router
raspi-2w-dev dhcpcd[440]: wlan0: using static address 192.168.0.49/24
raspi-2w-dev dhcpcd[440]: wlan0: adding route to 192.168.0.0/24
raspi-2w-dev dhcpcd[440]: wlan0: adding default route via 192.168.0.1
raspi-2w-dev dhcpcd[440]: eth0: no IPv6 Routers available
raspi-2w-dev dhcpcd[440]: wlan0: no IPv6 Routers available
ディスクトップ画面にトーストで数秒間接続された2つのインターフェースのIPアドレスが表示されます。
2-2 Raspberry Pi OS (bookworm)
前回の下記投稿記事で rpi-imager が NetworkManager 対応の WiFi接続設定ファイルを出力するシェルスクリプトについて解説しました。
2-2-1 NetworkManager 対応の WiFi 接続
残念なことに NetworkManager 対応となった Raspberry Pi OS (bookworn) では固定IPアドレスによるWi-Fi ネットワーク接続ができなくなりました。
理由は OS カスタマイズ用のシェルスクリプトが、自動的にDHCP サーバーからIPアドレスを取得する Wi-Fi 接続設定ファイルを NetworkManager が管理するディレクトリに出力するように変更されたことによります。
OSカスタマイズ用のシェルスクリプト (/usr/lib/raspberrypi-sys-mods/imager_custom
) から Wi-Fi 接続設定ファイルを生成する処理部分のみを抜粋したものを以下に示します。
set_wlan () (
HIDDEN="false"
PLAIN=0
for arg in "$@"; do
# shellcheck disable=SC2031
if [ "$arg" = "-h" ] || [ "$arg" = "--hidden" ]; then
HIDDEN="true"
elif [ "$arg" = "-p" ] || [ "$arg" = "--plain" ]; then
PLAIN=1
elif [ -z "${SSID+set}" ]; then
SSID="$arg"
elif [ -z "${PASS+set}" ]; then
PASS="$arg"
elif [ -z "${COUNTRY+set}" ]; then
COUNTRY="$arg"
else
usage set_wlan
exit 1
fi
done
if [ -z "${SSID+set}" ]; then
usage set_wlan
exit 1
fi
if [ -n "$COUNTRY" ]; then
set_wlpreconfigured.nmconnectionan_country "$COUNTRY"
fi
CONNFILE=/etc/NetworkManager/system-connections/preconfigured.nmconnection
UUID=$(uuid -v4)
cat <<- EOF >${CONNFILE}
[connection]
id=preconfigured
uuid=${UUID}
type=wifi
[wifi]
mode=infrastructure
ssid=${SSID}
hidden=${HIDDEN}
[ipv4]
method=auto
[ipv6]
addr-gen-mode=default
method=auto
[proxy]
EOF
if [ ! -z "${PASS}" ]; then
cat <<- EOF >>${CONNFILE}
[wifi-security]
key-mgmt=wpa-psk
psk=${PASS}
EOF
fi
# NetworkManager will ignore nmconnection files with incorrect permissions,
# to prevent Wi-Fi credentials accidentally being world-readable.
chmod 600 ${CONNFILE}
)
[参考] 実際にインストール後に生成されたファイルを下記に示します。
※ ssid と psk は適当な値に修正しています。
[connection]
id=preconfigured
uuid=c9677410-652a-457f-abe2-0a3f7a1dd8af
type=wifi
[wifi]
mode=infrastructure
ssid=xxxxxx2g-yyyyyy
hidden=false
[ipv4]
method=auto
[ipv6]
addr-gen-mode=default
method=auto
[proxy]
[wifi-security]
key-mgmt=wpa-psk
psk=1ebb370489744cc3ea554c2d61651b06361cb7b3b87bf9660d2b4dff4b7be7e1
※ 同名のWi-Fi接続設定ファイルをSDカードにコピーしても OS イントール時に上書きされてしまいます。
OSイントール直後のデスクトップ画面にトーストとして表示された IPアドレス表示するスクリーンショットを下記に示します。
OS イントール時のブートログ
※1 ジャーナルログからタイムスタンプ、ホスト名、不要なログ情報列を削除しています。
※2 実際には "wpa_supplicant", "avahi-daemon" などのプロセスがWi-Fiネットワーク接続に関わっていますがログが大量なので一部省略したものを示します。
NetworkManager[457]: Wi-Fi P2P device controlled by interface wlan0 created
NetworkManager[457]: manager: (p2p-dev-wlan0): new 802.11 Wi-Fi P2P device (/org/freedesktop/NetworkManager/Devices/3)
# ...一部省略...
NetworkManager[457]: device (wlan0): Activation: (wifi) connection 'preconfigured' has security, and secrets exist. No new secrets needed.
NetworkManager[457]: device (wlan0): supplicant interface state: disconnected -> associating
NetworkManager[457]: device (p2p-dev-wlan0): supplicant management interface state: disconnected -> associating
NetworkManager[457]: device (wlan0): supplicant interface state: associating -> completed
NetworkManager[457]: device (wlan0): Activation: (wifi) Stage 2 of 5 (Device Configure) successful. Connected to wireless network "xxxxxx2g-yyyyyy"
NetworkManager[457]: device (p2p-dev-wlan0): supplicant management interface state: associating -> completed
NetworkManager[457]: device (wlan0): state change: config -> ip-config (reason 'none', sys-iface-state: 'managed')
NetworkManager[457]: dhcp4 (wlan0): activation: beginning transaction (timeout in 45 seconds)
NetworkManager[457]: dhcp4 (wlan0): state changed new lease, address=192.168.0.23
NetworkManager[457]: policy: set 'preconfigured' (wlan0) as default for IPv4 routing and DNS
NetworkManager[457]: device (wlan0): state change: ip-config -> ip-check (reason 'none', sys-iface-state: 'managed')
NetworkManager[457]: device (wlan0): state change: ip-check -> secondaries (reason 'none', sys-iface-state: 'managed')
NetworkManager[457]: device (wlan0): state change: secondaries -> activated (reason 'none', sys-iface-state: 'managed')
NetworkManager[457]: device (wlan0): Activation: successful, device activated.
2-2-2 NetworkManager 対応の 有線ネットワーク接続
有線ネットワークのみユーザが作成したネットワーク接続設定ファイルを NetworkManager が管理するディレクトリコピーすることでOSイントール時に端末を固定IPアドレスを割り当てることができます。
有線ネットワーク接続ファイルの設定については下記のサイトを参考にしました。
- NetworkManager
[2-2-1] で示した OSカスタマイズ用のシェルスクリプトを参考に作成した有線ネットワーク接続ファイル生成スクリプトを下記に示します。
- UUIDの生成
※ Raspberry Pi OS (Debian) で UUID を生成するのはuuid
コマンドですが、Ubuntu OS ではuuidgen
コマンドになります。 - タイムスタンプの生成
date コマンドで UNIXタイムスタンプを生成します。
インターフェース名に "eth0" を設定し、[wifi]セクション と [wifi-security]セクションを [ethernet] セクションに変更します。
出力ファイル名を [NetworkManger用ID名].connection としています。
- スクリプト引数
- NetworkManger用ID名
- 固定 IPv4 アドレス
#!/bin/bash
# ./gen_staticIP_ethernet_for_networkmanager.sh id_name ip_address
# [example]
# ./gen_staticIP_ethernet_for_networkmanager.sh wired_staticIp 192.168.0.26
if [ $# -ne 2 ]; then
SCRIPT_NAME=${0##*/}
echo "Usage: ./${SCRIPT_NAME} id_name ip_address"
exit 1
fi
ID_NAME=$1
IP_ADDR=$2
CONNFILE=~/bin/raspi/connections/${ID_NAME}.connection
UUID=$(uuidgen)
TIMESTAMP=$(date +'%s')
cat <<- EOF >${CONNFILE}
[connection]
id=Wired_staticIp
uuid=${UUID}
type=ethernet
autoconnect-priority=-999
interface-name=eth0
timestamp=${TIMESTAMP}
[ethernet]
[ipv4]
address1=${IP_ADDR}/24,192.168.0.1
dns=192.168.0.1;
method=manual
[ipv6]
addr-gen-mode=stable-privacy
method=auto
[proxy]
EOF
chmod 600 ${CONNFILE}
2-2-2-2 接続ファイル生成スクリプト実行
- 入力引数
- 接続ID名: Wired_staticIp
- 固定IPアドレス: 192.168.0.19
~$ cd ~/bin/raspi
~/bin/raspi$ ./gen_staticIP_ethernet_for_networkmanager.sh Wired_staticIp 192.168.0.19
生成した有線ネットワーク接続設定ファイルは以下のとおりです。
[connection]
id=Wired_staticIp
uuid=00b7c36a-6a93-4dbe-9007-9a41acca1ee4
type=ethernet
autoconnect-priority=-999
interface-name=eth0
timestamp=1735264145
[ethernet]
[ipv4]
address1=192.168.0.19/24,192.168.0.1
dns=192.168.0.1;
method=manual
[ipv6]
addr-gen-mode=stable-privacy
method=auto
[proxy]
2-2-3 接続設定ファイルをSDカードにコピーする
接続設定ファイルをルートファイルシステム上の下記ディレクトリにコピーする。
/media/yukio/rootfs1/etc/NetworkManager/system-connections
$ sudo cp Wired_staticIp.connection \
> /media/yukio/rootfs1/etc/NetworkManager/system-connections/
[sudo] yukio のパスワード:
$ ls -l /media/yukio/rootfs1/etc/NetworkManager/system-connections/
合計 4
-rw------- 1 root root 300 12月 27 10:54 Wired_staticIp.connection
2-2-4 イントール完了のIPアドレス確認
OSイントール完了後のディスクトップ画面のスクリーンショットを下記に示します。
※ 有線ネットワーク接続設定ファイルで指定した固定IPアドレス (192.168.0.19) がトーストで表示されています。
OS イントール時のブートログ
※ ジャーナルログからタイムスタンプ、ホスト名、不要なログ情報列を削除しています。
有線接続設定 (Wired_staticIp) が認識され、有線インターフェース (eth0) に設定した IPv4 アドレス (192.168.0.19) が割り当てられたことがログからわかります。
NetworkManager[488]: device (eth0): carrier: link connected
NetworkManager[488]: device (eth0): state change: unavailable -> disconnected (reason 'carrier-changed', sys-iface-state: 'managed')
NetworkManager[488]: policy: auto-activating connection 'Wired_staticIp' (00b7c36a-6a93-4dbe-9007-9a41acca1ee4)
NetworkManager[488]: device (eth0): Activation: starting connection 'Wired_staticIp' (00b7c36a-6a93-4dbe-9007-9a41acca1ee4)
NetworkManager[488]: device (eth0): state change: disconnected -> prepare (reason 'none', sys-iface-state: 'managed')
NetworkManager[488]: manager: NetworkManager state is now CONNECTING
NetworkManager[488]: device (eth0): state change: prepare -> config (reason 'none', sys-iface-state: 'managed')
NetworkManager[488]: device (eth0): state change: config -> ip-config (reason 'none', sys-iface-state: 'managed')
NetworkManager[488]: policy: set 'Wired_staticIp' (eth0) as default for IPv4 routing and DNS
avahi-daemon[384]: Joining mDNS multicast group on interface eth0.IPv4 with address 192.168.0.19.
avahi-daemon[384]: New relevant interface eth0.IPv4 for mDNS.
avahi-daemon[384]: Registering new address record for 192.168.0.19 on eth0.IPv4.
avahi-daemon[384]: Joining mDNS multicast group on interface eth0.IPv6 with address fe80::e734:10a4:a55f:3b93.
avahi-daemon[384]: New relevant interface eth0.IPv6 for mDNS.
avahi-daemon[384]: Registering new address record for fe80::e734:10a4:a55f:3b93 on eth0.*.
NetworkManager[488]: device (eth0): state change: ip-config -> ip-check (reason 'none', sys-iface-state: 'managed')
NetworkManager[488]: device (eth0): state change: ip-check -> secondaries (reason 'none', sys-iface-state: 'managed')
NetworkManager[488]: device (eth0): state change: secondaries -> activated (reason 'none', sys-iface-state: 'managed')
NetworkManager[488]: manager: NetworkManager state is now CONNECTED_SITE
NetworkManager[488]: device (eth0): Activation: successful, device activated.
NetworkManager[488]: manager: NetworkManager state is now CONNECTED_GLOBAL
NetworkManager[488]: manager: startup complete
最後に
今回はサーバー用途として使用する Raspberry Pi 端末の IPv4 アドレスを OS インストール時に固定IPアドレスに設定する方法を、レガシー OS (bullseye) と最新の OS イメージ (bookworm) で検証しました。
ネットワークアドレスの割当が NetworkManager ベースに変更されたことにより Wi-Fi接続の固定IP接続ができなくなったのは残念なことです。
参考までに OS イメージ (bookworm) で インストール後に Wi-Fi接続を変更する方法を以下に示します。
nmcli コマンドでの変更方法については下記サイトを参考にしました。
www.abelectronics.co.uk: Set a static IP Address on Raspberry Pi OS Bookworm
$ sudo nmcli c mod preconfigured \
ipv4.addresses 192.168.0.49/24 \
ipv4.gateway 192.168.0.1 \
ipv4.dns 192.168.0.1 \
ipv4.method manual \
ipv4.may-fail false
変更を反映させると変更されたIPアドレスが画面に出力されるます。
$ sudo nmcli c down "preconfigured" && sudo nmcli c up "preconfigured"
Connection 'preconfigured' successfully deactivated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/2)
Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/3)
[参考] 変更されたWi-Fi接続設定ファイル
[connection]
id=preconfigured
uuid=5dccc226-0e2e-493c-a9b8-9a154e5c2f5f
type=wifi
timestamp=1735261213
[wifi]
mode=infrastructure
ssid=elecom2g-27cbd9
[wifi-security]
key-mgmt=wpa-psk
psk=a729ec0f4cb652cc3873de1780a95ef8aec245c838e7ac61251c20b8ecb1ac8c
[ipv4]
address1=192.168.0.39/24,192.168.0.1
dns=192.168.0.1;
may-fail=false
method=manual
[ipv6]
addr-gen-mode=stable-privacy
method=auto
[proxy]