You are correct that sdm's raison d'etre is to cusotmize IMGs. However, sdm's plugins can be run on a booted, running system.sdm's hotspot capability uses nmcli exclusively and works great. Documentation here and here.This seems to be for creating disc images; I don't understand how it's relevant to wifi hotspots.
I had a Pi4 up and running Trixie. I plugged a WiFi adapter into it and ran:
Code:
sdm --runonly plugins --plugin hotspot:"device=wlan1|ipforward=wlan0" --okliveCode:
bls@p83~> sudo -i # Convenience. All the following commands require "sudo"p83~# nmcli c showNAME UUID TYPE DEVICE eth0 aafb8b76-81da-3a3e-b525-f5b9194ab3cb ethernet eth0 lo 79592bb2-58a5-4a01-84e4-afb94e4208df loopback lo MyHomeWiFi 28eee37b-32ed-4de3-bf37-07adcd6fa493 wifi wlan0 p83~# ip a1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host proto kernel_lo valid_lft forever preferred_lft forever2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000 link/ether e4:5f:01:10:ea:bd brd ff:ff:ff:ff:ff:ff inet 192.168.92.224/24 brd 192.168.92.255 scope global dynamic noprefixroute eth0 valid_lft 86365sec preferred_lft 86365sec3: wlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000 link/ether e4:5f:01:10:ea:be brd ff:ff:ff:ff:ff:ff inet 192.168.92.225/24 brd 192.168.92.255 scope global dynamic noprefixroute wlan0 valid_lft 86365sec preferred_lft 86365sec4: wlan1: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default qlen 1000 link/ether 1c:bf:ce:ee:dd:9e brd ff:ff:ff:ff:ff:ffp83~# nmcli c showNAME UUID TYPE DEVICE eth0 aafb8b76-81da-3a3e-b525-f5b9194ab3cb ethernet eth0 lo 79592bb2-58a5-4a01-84e4-afb94e4208df loopback lo MyHomeWiFi 28eee37b-32ed-4de3-bf37-07adcd6fa493 wifi wlan0 p83~# sdm --runonly plugins --plugin hotspot:"device=wlan1|ipforward=wlan0" --oklive* Run selected plugins on the host system> Run Plugins Phase '0'> Run Plugin 'hotspot' (/usr/local/sdm/plugins/hotspot) Phase 0 with arguments: 'device=wlan1|ipforward=wlan0'* Plugin hotspot: Start Phase 0> Plugin hotspot: Keys/values found: device: wlan1 ipforward: wlan0% Plugin hotspot: No 'config' provided; Generate config from arguments and defaults: device: wlan1 [Argument] dhcpmode: nm [Default] pskencrypt: [Default] hsenable: y [Default] hsname: Hotspot [Default] ipforward: wlan0 [Argument] portal: [Default] portalif: [Default] type: routed [Default] wifipassword: password [Default] wifissid: MyPiNet [Default] wlanip: [Default]* Plugin hotspot: Complete Phase 0> Run Plugins Phase '1'> Run Plugin 'hotspot' (/usr/local/sdm/plugins/hotspot) Phase 1 with arguments: 'device=wlan1|ipforward=wlan0'* Plugin hotspot: Start Phase 1* Plugin hotspot: Complete Phase 1> Run Plugins Phase 'post-install'> Run Plugin 'hotspot' (/usr/local/sdm/plugins/hotspot) Phase post-install with arguments: 'device=wlan1|ipforward=wlan0'* Plugin hotspot: Start Phase post-install> Prefix hotspot: Configure hotspot 'Hotspot' with Network Manager> Plugin hotspot: Write sdm First Boot script to configure routed hotspot 'Hotspot' with method=shared* Plugin hotspot: Complete Phase post-install* Run plugin FirstBoot script '/etc/sdm/0piboot/092-nm-hotspot-routed.sh'Device 'wlan1' successfully activated with 'efdae58e-ceba-455c-a960-b4389c6984a9'.Hint: "nmcli dev wifi show-password" shows the Wi-Fi name and password.Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/5)p83~# nmcli c showNAME UUID TYPE DEVICE Hotspot efdae58e-ceba-455c-a960-b4389c6984a9 wifi wlan1 eth0 aafb8b76-81da-3a3e-b525-f5b9194ab3cb ethernet eth0 lo 79592bb2-58a5-4a01-84e4-afb94e4208df loopback lo MyHomeWiFi 28eee37b-32ed-4de3-bf37-07adcd6fa493 wifi wlan0 p83~# ip a1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host proto kernel_lo valid_lft forever preferred_lft forever2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000 link/ether e4:5f:01:10:ea:bd brd ff:ff:ff:ff:ff:ff inet 192.168.92.224/24 brd 192.168.92.255 scope global dynamic noprefixroute eth0 valid_lft 86265sec preferred_lft 86265sec3: wlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000 link/ether e4:5f:01:10:ea:be brd ff:ff:ff:ff:ff:ff inet 192.168.92.225/24 brd 192.168.92.255 scope global dynamic noprefixroute wlan0 valid_lft 86265sec preferred_lft 86265sec4: wlan1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000 link/ether 1c:bf:ce:ee:dd:9e brd ff:ff:ff:ff:ff:ff inet 10.42.0.1/24 brd 10.42.0.255 scope global noprefixroute wlan1 valid_lft forever preferred_lft foreverp83~# cat /etc/NetworkManager/system-connections/Hotspot.nmconnection [connection]id=Hotspotuuid=efdae58e-ceba-455c-a960-b4389c6984a9type=wifiautoconnect-priority=150interface-name=wlan1timestamp=1765807565 [wifi]mode=apssid=MyPiNet [wifi-security]group=ccmp;key-mgmt=wpa-pskpairwise=ccmp;proto=rsn;psk=password [ipv4]method=shared [ipv6]addr-gen-mode=defaultmethod=disabled [proxy]p83~## The hotspot plugin also configures nftables for the required routingp83~# nft list rulesettable ip nm-shared-wlan1 { chain nat_postrouting { type nat hook postrouting priority srcnat; policy accept; ip saddr 10.42.0.0/24 ip daddr != 10.42.0.0/24 masquerade } chain filter_forward { type filter hook forward priority filter; policy accept; ip daddr 10.42.0.0/24 oifname "wlan1" ct state { established, related } accept ip saddr 10.42.0.0/24 iifname "wlan1" accept iifname "wlan1" oifname "wlan1" accept iifname "wlan1" reject oifname "wlan1" reject }}p83~#- If your system is not fully up to date, you'll need to do: sudo apt update
- Install sdm. sdm installs into /usr/local/sdm and /etc/sdm and is totally innocuous in an already-running system. That is, it does not change anything else on your system.The installer will download and install sdm, and then install several apt packages on your system if they are not installed: binfmt-support coreutils gdisk keyboard-configuration parted qemu-user-static rsync systemd-container uuid
Code:
curl -L https://raw.githubusercontent.com/gitbls/sdm/master/install-sdm | bash - Enjoy your hotspot!
Statistics: Posted by bls — Mon Dec 15, 2025 2:25 pm