Skip to content

Commit

Permalink
feat: add headless_nm module
Browse files Browse the repository at this point in the history
* Since RPI nor Armbian have a possibility to change (WiFi) networks
  after initial flash, adding a solution that it makes it possible to
  generate a new 'preconfigured.nmconnection' (this one is generated by
  rpi-imager)

* As discussed here #219

Signed-off-by: Stephan Wendel <[email protected]>
  • Loading branch information
KwadFan authored and guysoft committed Oct 27, 2024
1 parent cdc2c6f commit 6cdc70f
Show file tree
Hide file tree
Showing 10 changed files with 599 additions and 0 deletions.
28 changes: 28 additions & 0 deletions src/modules/headless_nm/config
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#!/usr/bin/env bash
#Shebang for better file detection
#### headless_nm install module
####
#### Written by Stephan Wendel aka KwadFan <[email protected]>
#### Copyright 2024 - till today
#### https://github.com/mainsail-crew/MainsailOS
####
#### This File is distributed under GPLv3
####

# shellcheck disable=all

# Use disable power save for wifi module
[ -n "$HEADLESS_NM_DISABLE_PWRSAVE" ] || HEADLESS_NM_DISABLE_PWRSAVE=yes

# Type of power save rclocal/service/udev
# rclocal - backwards compatibility, runs via rc.local
# service - will add an systemd.service to enable or disable behavior
# on reboots
# udev - creates a udev rules that should affect all wifi devices.

[ -n "$HEADLESS_NM_PWRSAVE_TYPE" ] || HEADLESS_NM_PWRSAVE_TYPE=udev


# DO NOT MODIFY BELOW THIS LINE UNLESS YOU KNOW CONSEQUENCES...

[ -n "$HEADLESS_NM_DEPS" ] || HEADLESS_NM_DEPS="network-manager dos2unix uuid"
59 changes: 59 additions & 0 deletions src/modules/headless_nm/filesystem/boot/WiFi-README.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
Wifi-README.txt

################################################################################
#### IMPORTANT WARNING ####
################################################################################
#### ####
#### First, make sure you have a decent text editor of your choice. ####
#### Notepad++, VSCode, SublimeText or similar are recommended. ####
#### ####
#### Do not use Wordpad to edit this file, it will corrupt it and your ####
#### configuration will not work. ####
#### ####
#### If you use Textedit to edit this file, ####
#### be sure to use "plain text format" and "disable smart quotes" ####
#### in "Textedit > Preferences", otherwise Textedit will use ####
#### incompatible characters and your network configuration won't work! ####
#### ####
################################################################################

How do I setup a new network on my OS_NAME ?
--------------------------------------------

1.) Copy and paste the 'headless_nm.txt.template'.
Rename this file to 'headless_nm.txt'

2.) Now open the file with your favourite text editor.
Windows and MacOS users please read the note above!

This file is pretty self explaining, just the 'REGDOMAIN'
needs some explaination:

Valid country codes are:

GB (United Kingdom)
FR (France)
DE (Germany)
US (United States)
SE (Sweden)

For a complete list, please visit https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2

3.) Remove the SD card afterwards.

4.) Almost done... Please put the SD card back into your SBC and wait for it to connect.

NOTE:

Plug in a monitor and watch the console output to get its IP address or
consult your router's setup page to get this information.

You could also try to reach it by its hostname.

http://<yourpisname>.local

If you did not change the hostname during the initial flash, you could use

http://OS_NAME.local

5.) Enjoy OS_NAME :)
14 changes: 14 additions & 0 deletions src/modules/headless_nm/filesystem/boot/headless_nm.txt.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#### Headless Wifi configuration

# Your Wifis SSID
SSID="<mySSID>"

# Your WiFis password
PASSWORD="<mySecretPasword>"

# Is your SSID in hidden state? [true/false]
HIDDEN="false"

# Wifi Country code
# See Wifi-README.txt for details!
REGDOMAIN="US"
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#### Disable wifi power_save
####
#### Written by Stephan Wendel aka KwadFan <[email protected]>
#### Copyright 2022
#### https://github.com/mainsail-crew/MainsailOS
####
#### This File is distributed under GPLv3
####
#### Note: This is based on:
#### https://www.intel.com/content/www/us/en/support/articles/000006168/boards-and-kits.html

[Unit]
Description=Disable power management for wlan0
After=network.target

[Service]
Type=oneshot
StandardOutput=tty
ExecStart=/usr/local/bin/pwrsave off

[Install]
WantedBy=multi-user.target
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#### headless_nm service
####
#### Written by Stephan Wendel aka KwadFan <[email protected]>
#### Copyright 2024
#### https://github.com/mainsail-crew/MainsailOS
####
#### This File is distributed under GPLv3
####

[Unit]
Description=Setup Wifi on headless machines using NetworkManager
Before=network.target NetworkManager.service

[Service]
Type=oneshot
StandardOutput=tty
ExecStart=/usr/local/bin/headless_nm

[Install]
WantedBy=multi-user.target
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
ACTION=="add", \
SUBSYSTEM=="net", \
KERNEL=="wlan*" \
RUN+="/usr/sbin/iw %k set power_save off"
183 changes: 183 additions & 0 deletions src/modules/headless_nm/filesystem/usr/local/bin/headless_nm
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
#!/usr/bin/env bash
#### headless_nm
####
#### Written by Stephan Wendel aka KwadFan <[email protected]>
#### Copyright 2024 - till today
#### https://github.com/mainsail-crew/MainsailOS
####
#### This File is distributed under GPLv3
####

#### Description:
#### This is a wrapper for network manager to be able to setup
#### Wifi connections on headless SBC.
#### Takes setup from a file in /boot (/boot/firmware) and recreates
#### Raspberrys 'preconfigured.nmconnection'

#### Copyright hint: This file contains code snippets from
#### Raspberrys raspi-config therefore it applies also there license
#### and copyrights!
#### See https://github.com/RPi-Distro/raspi-config/blob/bookworm/LICENSE

#### It also reuses parts of raspberry-sys-mods
#### See https://github.com/RPi-Distro/raspberrypi-sys-mods/blob/bookworm/usr/lib/raspberrypi-sys-mods/imager_custom

set -e

# Global Vars
DISTRO=""
CMDLINE="/boot/firmware/cmdline.txt"
ARMBIANENV="/boot/armbianEnv.txt"
UUID=""
PSK_HASH=""
KEYMGMT="wpa-psk"
CONNFILE=/etc/NetworkManager/system-connections/preconfigured.nmconnection
SETUPFILE="$(find /boot -name "headless_nm.txt")"
REGDOMAIN=""
CFG80211="/etc/modprobe.d/cfg80211.conf"


# functions
log() {
local msg
msg="${1}"
logger -t headless_nm "${msg}"
}

get_distro() {
local armbian rpi
armbian="$(find /boot -name "$(basename ${ARMBIANENV})")"
rpi="$(find /boot -name "$(basename ${CMDLINE})")"
log "Determine distribution ..."
if [[ -n "${armbian}" ]]; then
DISTRO="armbian"
elif [[ -n "${rpi}" ]]; then
DISTRO="rpi"
else
DISTRO=""
log "Could not determine distribution ... Exiting!"
exit 1
fi
if [[ -n "${DISTRO}" ]]; then
log "Using setup profile: ${DISTRO} ..."
fi
}

get_config() {
# shellcheck disable=SC1090
source "${SETUPFILE}"
}

gen_uuid() {
log "Generating UUID for connection..."
UUID="$(uuid -v4)"
declare -r UUID
}

gen_nmconnection() {
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
}

gen_keymgmt() {
PSK_HASH="$(gen_psk)"
if [[ -n "${PASSWORD}" ]]; then
cat <<- EOF >>${CONNFILE}
[wifi-security]
key-mgmt=${KEYMGMT}
psk=${PSK_HASH}
EOF
fi
}

gen_psk() {
wpa_passphrase "${SSID}" "${PASSWORD}" | sed -n "/^.*[ \t]psk.*/s/[ \t]psk=//p"
}

set_regdomain() {
log "Set registration domain to '${REGDOMAIN}' ..."
# Shameless borrowed from
# https://github.com/RPi-Distro/raspi-config/blob/d22643ade3851c42648f3676e577a622c34af49a/raspi-config#L830C3-L832C5
if ! ischroot; then
iw reg set "${REGDOMAIN}"
fi
# set permanent
case "${DISTRO}" in
"rpi")
# Shameless borrowed from
# https://github.com/RPi-Distro/raspi-config/blob/d22643ade3851c42648f3676e577a622c34af49a/raspi-config#L822C3-L825C15
sed -i \
-e "s/\s*cfg80211.ieee80211_regdom=\S*//" \
-e "s/\(.*\)/\1 cfg80211.ieee80211_regdom=$REGDOMAIN/" \
"${CMDLINE}"
;;
"armbian")
if [[ -f "${CFG80211}" ]]; then
rm -f "${CFG80211}"
fi
echo "options cfg80211 ieee80211_regdom=${REGDOMAIN}" > "${CFG80211}"
;;
esac
}

# MAIN
main() {
# Determine base distribution
get_distro

# Check setup file is present
if [[ -f "${SETUPFILE}" ]]; then
log "Configuration file found in ${SETUPFILE}, continuing...\n"
else
log "Configuration file not found! Nothing to do, exiting...\n"
exit 0
fi

# Generate UUID
gen_uuid

# Remove preconfiguration if present
if [[ -f "${CONNFILE}" ]]; then
rm -f "${CONNFILE}"
fi

# Read config file
get_config

# Generate preconfigured.nmconnection file
gen_nmconnection

# Add key management and psk to preconfigured.nmconnection file
gen_keymgmt

# Set REGDOMAIN
set_regdomain

# NetworkManager only accepts 0600 permissions for configs
chmod 0600 "${CONNFILE}"

# Cleanup
PSK_HASH=""
PASSWORD=""
SSID=""
log "Configuration successful written ..."
rm -f "${SETUPFILE}"
}

if [[ "${BASH_SOURCE[0]}" = "${0}" ]]; then
main
fi
Loading

0 comments on commit 6cdc70f

Please sign in to comment.