Plugins
July 9, 2026 · View on GitHub
Plugin Overview
Plugins are a modular way to extend sdm capabilities. Plugins are similar to Custom Phase Scripts, but can work both during customization and/or when burning an SSD/SD Card.
It makes sense to include some plugins into the IMG you're creating (e.g., postfix, samba) so they are installed onto every system burned from that IMG, but some are typically installed once per network (e.g., apt-cacher-ng), or not needed on every system. In that case you can use the plugin when burning the SSD/SD for that specific system.
The set of plugins provided with sdm are documented here.
Other plugins are planned. If there are any specific plugins you're interested in, let me know!
You can add your own plugins as well. Put your plugin script in /usr/local/sdm/local-plugins, and it will be automatically found. sdm looks at local-plugins first, so you can override an sdm-provided plugin with your modifications if desired.
You can also specify the plugin name with a full path. sdm will copy the plugin to /usr/local/sdm/local-plugins if it does not exist or the one specified is newer than the one in local_plugins.
Invoking a plugin on the sdm command line
Specify each plugin with a separate --plugin switch:
sdm --plugin samba:"args" --plugin postfix:"args" . . .
Multiple --plugin switches can be used on the command line. This includes specifying the same plugin multiple times (the apps plugin, for example).
Another way to specify plugins is via the --plugin @/path/to/pluglist, where pluglist consists of plugin invocations, one per line, without the --plugin switch. For example:
user:userlist=/rpi/etc/sdm/bls-users
system:name=0|systemd-config=timesyncd=/rpi/systemd/timesyncd.conf|eeprom=stable|sysctl=/rpi/etc/sysctl.d/01-disable-ipv6.conf|fstab=/rpi/etc/fstab.lan|motd=/dev/null
system:name=1||service-disable=apt-daily.timer,apt-daily-upgrade.timer,wpa_supplicant,avahi-daemon,avahi-daemon.socket,ModemManager,rsync,mdadm-shutdown
network:nmconn=/rpi/etc/NetworkManager/system-connections/eth0.nmconnection,/rpi/etc/NetworkManager/system-connections/homewifi.nmconnection|wifissid=myhomewifif|wifipassword=homewifipassword|wificountry=US
disables:triggerhappy|wifi|bluetooth|piwiz
quietness:consoleblank=300|noquiet=keep|nosplash=keep|noplymouth
L10n:host
One key benefit of using a pluglist file is the argument list does not need to be quoted ("). This is only needed on the command line to keep bash from doing silly things.
Plugins are run in the order they are encountered on the command line or the plugin @file,
The complete plugin switch format is:
--plugin plugname:"key1=val1|key2=val2|key3=val3"
Enclose the keys/values in double quotes as above if there is more than one key/value or bash will be confused by the "|".
See below for plugin-specific examples and important information.
It is recommended that all files that you provide to sdm, whether on the command line or in arguments to a plugin, use full paths. For instance, to use a file in your home directory, don't use file or ~/file, use /home/<mylogin>/file. Relative file paths generally work, but if you run into problems, switch to using a ful path.
It is not possible to use a tilde ("~") as an argument value for a plugin. A good example of this is for WiFi passwords for the network plugin. In this case (and if you encounter any others) you must provide a fully-formed .nmconnection file. The tilde is used internally by sdm to separate a plugins concatenated together (in a string).
NOTE: An argument can only be used once per plugin invocation. This is not a problem with most plugins, but you might find a use for multiple uses in some plugins, such as bootconfig. This is discussed in the bootconfig plugin.
Burn Plugins
Burn plugins are special plugins that are run after a burn has completed on a disk (--burn) or disk image (--burnfile). Only plugins designated as burn plugins in this document can be used with --burn-plugin. sdm doesn't check whether a plugin is burn-plugin capable, so trying to use a non-burn-plugin as a burn-plugin will likely be interesting.
Burn plugins can also be used with --runonly plugins to operate on an IMG or disk. The parted plugin can be used in this manner.
sdm --runonly plugins --burn-plugin parted:"addpartition=2048,ext4" 2023-12-05-raspios-bookworm-arm64.img
sdm --runonly plugins --burn-plugin extractfs:"rootfs=/path/to/rootfs|bootfs=/path/to/bootfs" 2023-12-05-raspios-bookworm-arm64.img
Plugin ordering notes
There are a couple of plugin ordering issues to be aware of.
- The
userplugin(s) should be the first plugin. Several other plugins expect this. - The
cryptrootplugin must be after the graphics plugin in order to properly manage boot behavior during the encryption process - The
boot_behaviorfinal setting is order-sensitive. The last modification wins.- During the post-install phase, if
--plugin graphicsis used, thegraphicsplugin will set the boot behavior. If thegraphicsplugin is not used, this will run automatically at the end of the post-install phase.- If the display manager is lightdm,
boot_behavioris set: B3 or B4 per the--autologinswitch - If the display manager is xdm or wdm,
boot_behavioris set: B1 or B3 per the setting ofnodmconsole
- If the display manager is lightdm,
- Calling the
raspiconfigplugin during burn and specifying theboot_behaviorargument will unconditionally set the new boot behavior
- During the post-install phase, if
WiFi device must have the WiFi country
If you want to use the WiFi device either configured for a network or simply enabled, you must specify the WiFi country.
Plugins btwifi, L10n, and network will all correctly configure the network country (and rfkill) if the wificountry argument is provided. If you simply want to have the WiFi enabled without configuring the WiFi network via any of these plugins, use --plugin L10n:wificountry=xx.
Plugin-specific documentation
sdm-plugin-template
sdm-plugin-template can be used to build your own plugin. It contains some code in Phase 0 demonstrating some of the things you can do with the plugin_getargs function and how to access the results.
apps
Use the apps plugin to install applications. The apps plugin can be called multiple times on a command line or in a pluglist. The name can be any alphanumeric (including "-", "_", etc.) you want.
Arguments
- apps — Specifies the list of apps to install or @filename to provide a list of apps (one per line) to install. Comments are indicated by a pound sign (#) and are ignored, so you can document your app list if desired. If the specified @filename is not found, sdm will look in the sdm directory (/usr/local/sdm).
- defer — Specifies the list of apps for which to defer install until after sdm FirstBoot has completed (and rebooted), speeding up the customization process. Equivalent to using
--plugin defer-plugin:"apps=list,of,apps". - name — Specifies the name of the apps list. The default name is default. The
nameargument is a convenience and is not required. - remove — Specifies the list of apps to remove ofr @filename to provide a list of apps (one per line) to remove. The
removeargument is processed before theappsargument. If you try to remove an apt packge that doesn't exist it will log in /etc/sdm/apt.log and sdm will notify you at the end of the customize: '? apt reported errors; review /etc/sdm/apt.log'
Examples
--plugin apps:"remove=wolfram-engine|apps=emacs"— Remove wolfram-engine, and install emacs--plugin apps:"apps=@my-apps" --plugin apps:"apps=@my-xapps"— Install the list of apps in the file @my-apps, and the list of apps in @my-xapps--plugin apps:"apps=@my-apps|name=myapps" --plugin apps:"apps=@my-xapps|name=myxapps"— Install the list of apps in the file @my-apps, and the list of apps in @my-xapps--plugin apps:"apps=zile|defer=emacs"— Install zile immediately, but defer the install of emacs until the system is fully operational.--plugin apps:"apps=@mycoreapps|name=core-apps"--plugin apps:"apps=@myaddtlapps|name=extra-apps"— Install the list of apps from @mycoreapps and @myaddtlapps
apt-addrepo
apt-addrepo adds Repos and gpgkeys to apt
Arguments
- gpgkey — /path/to/keyname.gpg
- gpgkeyname — Provide a different filename for the key in /etc/apt/trusted.gpg.d
- name — Name of the repo file in /etc/apt/sources.list.d for a
repostring - repo — A repo string that will be written to the named file in /etc/apt/sources.list.d
- repofile — File containing an apt repo that is copied to /etc/apt/sources.list.d
Examples
--plugin apt-addrepo:"repo=deb http://repo.feed.flightradar24.com flightradar24 raspberrypi-stable|gpgkey=/path/to/gpgkey.gpg"--plugin apt-addrepo:"repofile=/path/to/some-repo.list"
apt-cacher-ng
apt-cacher-ng installs the RasPiOS apt-cacher-ng service into the IMG or onto the SSD/SD card (If used with --burn).
Arguments
NOTE: All arguments are optional
- gentargetmode — Possible values: 'Set up once', 'Set up now and update later', and 'No automated setup'. [Default: 'No automated setup']. TBH not sure what this does. If you figure it out, let me know ;)
- bindaddress — the IP address to which the server should bind. [Default: 0.0.0.0], which is all IP addresses on the server.
- cachedir — apt-cacher-ng directory. [Default: /var/cache/apt-cacher-ng]
- port — TCP port [Default: 3142]
- tunnelenable —Do not enable this. [Default: false]
- proxy —TBH not sure what this does. If you figure it out, let me know ;)
The default apt-cacher-ng server install uses port 3142. apt-cacher-ng will be enabled by sdm FirstBoot and ready to process requests after the FirstBoot process completes.
NOTE: The apt-cacher-ng plugin installs the apt-cacher-ng server. The --aptcache command line switch configures the IMG to be an apt-cacher-ng client and use the specified apt-cacher-ng server.
The plugin configures apt as a client to use itself as the apt caching server. This is typically not what you want on every system, so consider using --plugin apt-cacher-ng on the --burn command line for those systems that will be actually be deployed as apt caching servers.
NOTES
Unfortunately the apt-cacher-ng package has some issues. These show up at totally random times in cacher clients as "invalid hash" or "check DiMaxRetries" and probably some other strange and wondrous messages.
Quite annoying, but even so, I think apt-cacher-ng is still much better than waiting for apt downloads unless you're on a super-fast connection and have high-speed connectivity between you and the apt servers.
When apt-cacher-ng craps out, login on the caching server and issue the following command: sudo reset-apt-cacher, and then try the client operation again. The apt-cacher-ng plugin installs reset-apt-cacher during customization.
apt-config
apt-config provides some control over apt in the customized IMG
Arguments
no-install-recommends— Disable installing recommended softwareconfnew— — always replace a config file without promptingconfold— — always keep old unmodified copy of a config file without promptingconfdef— prefer the default method in the package for handling config file conflicts. If no default action specified by a package, falls back toconfoldif specifiednopager— Disable use of pager inaptlisting commandsnocolor— Disable use of color inaptlisting commands
Examples
--plugin apt-config:"no-install-recommends|nopager|nocolor"— Disable installing recommended software and paged and colored apt listing output
apt-file
apt-file installs the apt-file command and builds the database. This is very handy for looking up apt-related information.
Arguments
There are no --plugin arguments for apt-file
bootconfig
The bootconfig plugin configures the contents of /boot/firmware/config.txt.
Arguments
-
comment — Append the comment to the end of config.txt. Comments can also be specified by an argument starting with
#or\n. In the latter case, the comment is transformed to\n# comment stringresulting in a blank line before the comment. -
commentize — Comment out the specified line if it exists in config.txt. The line must be fully-specified and exactly match.
-
inline — If
inlineis provided as an argument (does not take a value), the plugin will replace existing settings in config.txt (if they exist) with any new value provided to the plugin. If it doesn't exist, or ifinlineis not provided, new arguments are appended to the end of the file. -
reset — If
resetis provided /boot/firmware/config.txt will be saved as /boot/firmware/config.txt.sdm. If no value is provided forresetthen /boot/firmware/config.txt will be set to a null file. Ifreset=/path/to/fileis provided, the specified file will replace /boot/firmware/config.txt. To work correctly,resetmust be specified before any other arguments (this is not enforced or specifically logged by sdm). -
section — The
sectionargument takes a value likepi4or[pi4], and appends the appropriately-bracketed section value to the end of config.txt preceded by a blank line. -
somename=somevalue — All other key/value settings are presumed to be settings in config.txt and added to it. There is no validity checking, so typos are propagated. But, on the other hand, the
bootconfigplugin doesn't need to be updated every time a brand new setting is added to config.txt. NOTE: Eachsomenamecan only be used once perbootconfigplugin invocation. See the examples in the following section for further details.
Examples
--plugin bootconfig:"section=[pi4]|somesetting=somevalue"--plugin bootconfig:"commentize=camera_auto_detect=1"--plugin bootconfig:"inline|hdmi_group=72|hdmi_force_hotplug=1|hdmi_mode=40|hdmi_ignore_edid"— The plugin adds the correct value forhdmi_ignore_edid(0xa5000080)--plugin bootconfig:"reset|dtparam=audio=on|camera_auto_detect=1|display_auto_detect=1|dtoverlay=vc4-kms-v3d|max_framebuffers=2|arm_64bit=1|disable_overscan=1|section=cm4|otg_mode=1|section=pi4|arm_boost=1|section=all"— An identical replacement for the Bullseye /boot/config.txt but with no comments or blank lines
You may want to add multiple dtparam items to config.txt, and be tempted to put all of them in a single invocation, such as:
--plugin bootconfig:"dtparam=fan_temp1=62500,fan_temp1_hyst=5000,fan_temp1_speed=128|dtparam=fan_temp0=55000,fan_temp0_hyst=5000,fan_temp0_speed=75"
This does not work. These must be broken up into separate plugin invocations:
--plugin bootconfig:"dtparam=fan_temp1=62500,fan_temp1_hyst=5000,fan_temp1_speed=128"
--plugin bootconfig:"dtparam=fan_temp0=55000,fan_temp0_hyst=5000,fan_temp0_speed=75"
Alternatively, you can use:
--plugin bootconfig:"dtparam=fan_temp1=62500,fan_temp1_hyst=5000,fan_temp1_speed=128,fan_temp0=55000,fan_temp0_hyst=5000,fan_temp0_speed=75"
RasPiOS has a line length limit of 98 for config.txt, and silently ignores characters beyond that length. The bootconfig plugin limits lines to 96 characters.
btrfs-config
The btrfs-config plugin is a --burn-plugin to apply btrfs-specific optimizations. It should be used with --convert-root btrfs.
The plugin works with both device burns (--burn) and file burns (--burnfile).
Note: You may also want to use --convert-root-mount-options "compress=zstd" to save space and IO.
Arguments
- imgtype — (Required) The image type being burned
- preset — Subvolume layout preset. Default:
default - verbose — Print the voluminous output from moving top-level contents into @ subvolume. Default: Don't print.
Presets
Currently the only preset is default, to:
- move root filesystem to a new
@subvolume - set
@subvolume the default of filesystem (filesystem root can still be mounted withsubvol=/) - add
rootflags=subvol=@to cmdline.txt - set mount option
defaults,subvol=@,compress=zstd,noatime,nodiratimeto fstab
Other settings can be defined as new preset. One can also mount again after sdm --burn completes and tune as needed.
Examples
sdm --burn /dev/sdc --convert-root btrfs --expand-root --burn-plugin btrfs-config /path/to/raspios.img— Burn to a device withdefaultpreset
btwifiset
btwifiset is a service that enables WiFi SSID and password configuration over Bluetooth using a mobile app. Once the service is running, you can use the BTBerryWifi iOS app to connect to the service running on your Pi and configure the WiFi. See https://github.com/nksan/Rpi-SetWiFi-viaBluetooth for details on btwifiset itself.
Arguments
- country — The WiFi country code. This argument OR wificountry is mandatory
- wificountry — Another way to specify the WiFi country code, compatible with other plugins
- localsrc — Locally accessible directory where the btwifiset.py can be found, instead of downloading from GitHub
- btwifidir — Directory where btwifiset will be installed. [Default: /usr/local/btwifiset]
- password — Password to use for encrypted bluetooth communication [Default: Host name on which btwifiset runs after boot]
- timeout — After timeout seconds the btwifiset service will exit [Default: 15 minutes]
- logfile — Full path to btwifiset log file [Default: Writes to syslog]
chrony
Chrony installs the chronyd time service.
Arguments
- conf — /full/path/to/confname.conf that will be placed into /etc/chrony/conf.d
- conf2 — /full/path/to/confname2.conf that will be placed into /etc/chrony/conf.d
- conf3 — /full/path/to/confname3.conf that will be placed into /etc/chrony/conf.d
- sources — /full/path/to/sourcename.conf that will be placed into /etc/chrony/sources.d
- sources2 — /full/path/to/sourcename2.conf that will be placed into /etc/chrony/sources.d
- sources3 — /full/path/to/sourcename3.conf that will be placed into /etc/chrony/sources.d
- nodistsources — Removes the Debian vendor zone pool from chrony.conf
Chrony processes the files in the conf.d and sources.d directories on startup. Having 3 provides flexibility in how these are structured. See man chrony.conf for details.
A RasPiOS system should only have one time service enabled. It's up to you to disable others. For instance, on a standard RasPiOS IMG you should add --svc-disable systemd-timesyncd to disable the in-built time service, which is enabled by default.
NOTES:
- At least on Bookworm (didn't check earlier versions) installing chrony causes systemd-timesyncd to be removed.
- Adding
iburstto aserverorpoolstatement in a sources file seems to result in chrony syncing the time much more quickly
clockfake
The fake-hwclock provided with RasPiOS runs hourly as a cron job. clockfake does the same thing as fake-hwclock, but you control the interval, and it's always running. Lower overhead, less processes activated, and more control. Life is good.
Arguments
- interval — Interval in minutes between fake hardware clock updates
cloudinit
The cloudinit plugin facilitates adding additional yaml information to /boot/firmware/user-data, which will get processed at the next reboot.
Arguments
- cfg — Specifies a comma-separated list of yaml files with file type
.cfgto place in /etc/cloud/cloud.cfg.d for system-level configuration - netconfig — Specifies a comma-separated list of yaml files with file type
.yamlto append to /boot/firmware/network-config for network configuration - userdata — Specifies a comma-separated list of yaml files with file type
.yamlto append to /boot/firmware/user-data for user-level configuration
The cfg files are processed by cloud-init in lexical order. Values in lexically later files overwrite values in earlier files.
See https://www.raspberrypi.com/news/cloud-init-on-raspberry-pi-os/ for overview information on RasPiOS and cloud-init.
Refer to Complete cloud-init documentation for details on the available cloud-init modules, examples, etc.
After cloud-init has processed the user-data file, subsequent runs will NOT redo the operations unless something changes in the OS (app or configuration removed, etc).
If desired, cloud-init processing can be disabled by: sudo touch /etc/cloud/cloud-init.disabled. Similarly, cloud-init can be re-enabled by sudo rm -f /etc/cloud/cloud-init.disabled.
Examples
--plugin cloudinit:"cfg=/path/to/99cfg1.cfg,/path/to/99cfg2.cfg|netconfig=/path/netcfg.yaml|userdata=/path/usercfg.yaml"
cmdline
Replace cmdline.txt with a new command line and/or modify the existing cmdline.txt. If /boot/firmware/cmdline.txt is present it will be used. If not, /boot/cmdline.txt is assumed.
Arguments
- add — Add the specified elements to the existing cmdline.txt. If element exists in cmdline.txt already it is replaced.
- delete — Delete the specified elements from the existing cmdline.txt
- replace — Replace the entire contents of cmdline.txt with the provided new cmdline
add, delete, and replace can each only be specified once per plugin invocation. If there are multiple, the last one wins. If this is needed for some reason, use multiple invocations of the cmdline plugin.
Examples
--plugin cmdline:"add=video=HDMI-A-1:1920x1080@60D"— Add the stringvideo=HDMI-A-1:1920x1080@60Dto cmdline.txt--plugin cmdline:"delete=console splash"— Remove the stringsconsoleandsplashfrom cmdline.txt--plugin cmdline:"replace="consoleblank=3600 root=PARTUUID=6ea5963a-02 rootfstype=ext4 fsck.repair=yes rootwait"— Replace cmdline.txt with the provided new cmdline
copydir
Copy a directory tree from the host system into the IMG
Arguments
- from — /full/path/to/sourcedir
- to — /full/path/to/destdir
- rsyncopts — Additional switches for the
rsynccommand. Ifrsyncoptsis specified, ALL desired rsync switches must be included. Ifrsyncoptsis NOT provided, the default switch-ais used - stderr — /path/to/file where stderr from the rsync command is written [D:/dev/null]
- stdout — /path/to/file where stdout from the rsync command is written [D:/dev/null]
The copydir plugin behavior is dependent on whether the from file contains a trailing slash, just like the rsync command. The rsync man page states: A trailing slash on the source changes this behavior to avoid creating an additional directory level at the destination. You can think of a trailing / on a source as meaning "copy the contents of this directory" as opposed to "copy the directory by name", but in both cases the attributes of the containing directory are transferred to the containing directory on the destination.
copyfile
Copy one or more files from the host system into the IMG
Arguments
- from — /full/path/to/sourcefile on the host system
- to — /path/in/IMG to place the file in the IMG. This must be a directory, not a file. The directory must already exist
- chown — The
user:groupto set the file ownership - chmod — The mode to set the file protection (e.g., 755, 644, etc)
- mkdirif — Create the directory if it doesn't exist
- runphase — Normally files are copied to their final destinations in Phase 1. Use
runphase=postinstallto have a single file copied in the post-install phase - filelist — The /full/path/to/file of a file on the host OS of a list of files to copy. See below.
The filelist=/full/path/to/file option points to a file that consists of one line per file in the format:
from=/path/to/file|to=/some/dir|chown=user:group|chmod=filemode|runphase=postinstall
chown and chmod are optional. If not specified, the file attributes will not be set, and will be whatever they were on the host system. runphase is optional, and if not specified, the file is copied in Phase 1.
copyfile copies the files into the IMG in /etc/sdm/assets/copyfile during Phase 0, and copies them into their target locations in the phase 1 or post-install phase (conditioned on runphase) once all packages have been installed, all users have been added, etc.
Examples
--plugin copyfile:"from=/usr/local/bin/myconf.conf|to=/usr/local/etc"The config file will be copied from /usr/local/bin/myconf.conf on the host system to /usr/local/etc/myconf.conf in the IMG during Phase1. The file will be owned by the same user:group as on the host, the file protection will be the same as well.--plugin copyfile:"filelist=/usr/local/bin/myfileslist". The list of files in the providedfilelistwill be processed per above.
cryptpart
Encrypts an already-created partition. The partition must not be the rootfs, and must already be created on the disk. See the parted plugin for details on creating disk partitions.
Arguments
- cryptname — The encrypted mapped device name (must be unique for each encrypted partition)
- fslabel — File system label for the created file system
- fstype — File system type.
ext4[Default] andbtrfsare valid - keydisk-id — The identifier for the USB keydisk. Can be LABEL=thelabel or PARTUUID=thepartuuid for the USB keydisk. Required if
keyfile-locationisusb.sdm-make-luks-keycan be used to create a key disk with a specified label. - keyfile — /path/to/keyfile
- keyfile-location — Valid locations are
usb(on a USB disk) orroot(in /root). Default isroot - mountpoint — /path/to/directory for the partition mount point. If not specified, it will not be configured
- nbde-server — URL of NBDE server. See here for details.
- nocreate — Do not encrypt the partition nor make a file system on it. See Notes below.
- nonint — Perform the encryption non-interactive. Requires
keyfileorpassphrase - nopwd — Do not add an unlock passphrase. Requires
keyfile - partname — Partition to encrypt [/dev/sdXn, e.g., /dev/sda3]. Required. See Encrypting Other Partitions for details.
- passphrase — Unlock passphrase. Must be specified if
nonintand no keyfile provided.
cryptname, fstype, and partname arguments are required. if nonint is specified, one of keyfile or passphrase is required.
Examples
--plugin cryptpart:"nopwd|cryptname=datapart|fstype=ext4|keyfile=/root/521f4471-8fa2-4ac3-ab96-6e5f00f67291.lek|mountpoint=/foo|partname=/dev/sda3|keyfile-location=usb|keydisk-id=LABEL=MYLABEL|nonint"— Encrypt partition /dev/sda3 using the specified keyfile. The partition will be mounted on/foo. During boot the system will look for the keyfile on a USB disk with the label MYLABEL.--plugin defer-plugin:"cryptpart:nopwd|cryptname=datapart|fstype=ext4|keyfile=/root/521f4471-8fa2-4ac3-ab96-6e5f00f67291.lek|mountpoint=/foo|partname=/dev/sda3|keyfile-location=usb|keydisk-id=LABEL=MYLABEL|nonint"— This is an example of using the abovecryptpartexample with thedefer-pluginin a burn command so that the partition is encrypted after the FirstBoot process has completed.
Notes
-
The
cryptpartplugin can only be run on a live system usingsdm --runonly plugins. To include it in the burn process use thedefer-pluginplugin -
The
cryptpartplugin can be used such that the entire encryption process is nearly automatic. See Disk Encryption for details. When using thecryptpartplugin withdefer-pluginto encrypt a data partition, it will be done in a totally non-interactive manner. This means: -
You MUST always specify
nonintand provide eithernopwdANDkeyfile(nonint|nopwd|keyfile=file.lek), or alternatively, do not includenopwdbut do includepassphrase(nonint|passphase=yourpassphrase). sdm does NOT check this! -
If you're using a keyfile without
keyfile-location=usb, you must ensure that the keyfile is in the IMG. One way to do this:--plugin copyfile:"from=/root/3449424f-1348-489d-9cdc-d4a2e1b6beef.lek|to=/root", which will copy the file from /root on the host system to /root in the IMG. -
The
nocreateargument can be used to wire up an already-encrypted partition into the system. The partition must be encrypted with a keyfile and/or a passphrase. If using a keyfile, the keydisk must be available during the system boot. The system will prompt for the unlock passphrase if only a passphrase is configured (that is, no keyfile).- You must specify the unlock options (passphrase and/or keyfile) correctly. These are NOT verified by the plugin.
-
If both
passphraseandkeyfileare provided, thekeyfilewill be used by systemd-cryptsetup during system boot. Thepassphrasecan be used for manually unlocking the partition outside of the normal boot flow, if needed. -
The
nbde-serverargument is incompatible withkeydisk-location=usb(systemd service orchestration problems) -
When
nbde-serveris used with a passphrase and the NBDE server is not reachable, the boot will continue, but the encrypted partition will not be mounted. In this case, unlock and mount the encrypted partition via the commandsystemd-tty-ask-password-agent --queryfrom a logged-in session.
cryptroot
Configures the rootfs for encryption. See Disk Encryption for complete details
Arguments
- auto-encrypt — Specifies that automatic rootfs encryption should be done. The required value specifies the name of the scratch disk (e.g., /dev/sdb). Requires
nopwdandkeyfile - authkeys — Provides an SSH authorized keys file for use in the initramfs
- crypto — Specifies the encryption to use.
aesused by default. Usexchachaon Pi4 and earlier for best performance. - dns — DNS server address for the intramfs network client to use
- gateway — gateway address for the intramfs network client to use
- ihostname — hostname for the intramfs network client to use
- ipaddr — IP address for the intramfs network client to use
- keyfile — A keyfile used for passphrase-less booting. See Unlocking rootfs with a USB Keyfile Disk for details
- mapper — Mapper name for the rootfs encryption (shows up, for instance, in the
dflisting) - nbde-server — URL of NBDE server. See here for details.
- netmask — Network mask for the intramfs network client to use
- no-expand-root — Do not expand the encrypted rootfs. See btrfs and rootfs expansion for details.
- nopwd — Configure only a keyfile to unlock the rootfs. No passphrase will be configured. The
keyfileargument is required - ssh — Enable SSH in the initramfs
- sshbash — Leave bash enabled in the SSH session rather than switching to the captive cryptroot-unlock (DEBUG only!)
- sshport — Use the specified port rather than the Default 22
- sshtimeout — Use the specified timeout rather than the Default 300 seconds
- uniquesshkey — Use a unique SSH key in the initramfs. Default is to use the host SSH key (of the system being encrypted)
authkeys is required with ssh
These are discussed further in the above-mentioned Disk Encryption page.
Examples
--plugin cryptroot:"authkeys=/home/bls/.ssh/authorized_keys|sshConfigures the rootfs for encryption and enables SSH into the initramfs with keys authorized in the named authorized_keys file.
Notes
- Unlike the
cryptpartplugin,keyfile-location=usbCAN be used in conjunction withnbde-server(different code paths) with thecryptrootplugin.
defer-plugin
The defer-plugin is a bit different from other plugins. It takes a single argument, which is a plugin string. The specified plugin is run VERY late: After the system has fully booted. This means that sdm-cryptconfig has completed and rebooted the system, and there is no rootfs encryption in progress.
This plugin is useful to accomplish tasks you want to complete on the newly-booted system that aren't needed immediately.
For instance, the apt-file plugin installs apt-file and does an update. This is typically not needed initially when you first boot the system, and the update takes a bit of time. Use the defer-plugin to run the apt-file plugin later (see example), speeding up the customization process.
The list of plugins that have been tested with defer-plugin: apps, apt-file, cryptpart, runatboot, and vnc.
apps:apps=list and defer-plugin:apps=list are equivalent.
Arguments
Generally, this plugin has no defined argument names. However, there are two special arguments:
defer-reboot— Takes an optional argument which is the number of seconds until the system reboots [Default:5]defer-command— takes a string which is the command to run
The above arguments are run after all deferred plugins are run.
Examples
--plugin defer-plugin:"apt-file"— Run theapt-fileplugin to install and update apt-file--plugin defer-plugin:"vnc:tigervnc=2540x1350,1880x960,1700x1200,1880x1100"— Install and configure tigervnc virtual desktops
When used in a pluglist, the above two would be:
defer-plugin:apt-file
defer-plugin:vnc:tigervnc=2540x1350,1880x960,1700x1200,1880x1100
Here are a couple of examples of the defer-command and defer-reboot
--plugin defer-plugin:"defer-command:ls -l /"— Perform anls -l /command. The output of anydefer-commandwill be found in the system journal (journalctl)--plugin defer-plugin:"defer-command:sleep 30"— Pause the defer processing for 30 seconds. This may be useful ahead of adefer-rebootto give you time to check the system journal output--plugin defer-plugin:defer-reboot— Reboot the system in 5 seconds--plugin defer-plugin:defer-reboot:20— Reboot the system in 20 seconds
disables
The disables plugin makes it easy to disable a few complex functions.
Arguments
- bluetooth — Disables bluetooth via a blacklist file in /etc/modprobe.d
- cloudinit — Disables cloud-init services.
- piwiz — Disables piwiz during the first system boot. You must set up everything with sdm that piwiz does or you may not like the results: User, Password, Keymap, Locale, and Timezone.
- triggerhappy — Disable the triggerhappy service. If you're not using it, this will eliminate the log spew it creates
- wifi — Disables WiFi via a blacklist file in /etc/modprobe.d
Examples
--plugin disables:"bluetooth|piwiz|triggerhappy"— Disable Bluetooth, Triggerhappy, and piwiz, but leave WiFi enabled
docker-install
Installs Docker per the Docker install guide.
Arguments
This plugin has no arguments
Examples
--plugin docker-install
dovecot-imap
The dovecot-imap installs and configures dovecot as an imap server.
Arguments
These arguments are for configuring the openssl cert that is generated. They are all optional at the moment.
- email-address — Specify the email address to include in the generated SSL Cert
- common-name — Specify the common name to include in the generated SSL Cert
- org-name — Specify the org name to include in the generated SSL Cert
Examples
--plugin dovecot-imap:"email-address=root@mydomain.com|common-name=MyCommonName.com|org-name=MyOrgname"--plugin dovecot-imap
explore
The explore plugin is a --burn-plugin that can be used to explore or mount the newly-burned device after the burn has completed.
Arguments
- mount — Mount the device into the host system rather than exploring the device container
Examples
--burn-plugin explore— After the burn completes mount the device and enter the container.--burn-plugin explore:mount— Like the previous example, but does not enter the container and operates in the context of the host system.
extractfs
The extractfs plugin is a non-general purpose --burn-plugin that is used to copy the boot and root trees from an IMG into directories in the file system
Arguments
- bootfs — Directory where the
boottree will be written - rootfs — Directory where the
roottree will be written - img — /path/to/IMG.IMG from which the trees will be copied
Examples
--burn-plugin extractfs:"bootfs=/path/to/bootfs|rootfs=/path/to/rootfs"
gadgetmode
Configures a Pi to be in gadget mode so it can connect via USB to a gadget mode host providing it with a network connection.
Arguments
autoconnect-retries— Sets the number of retries for the gadget to obtain a DHCP address via the USB gadget connection [D:5]dhcp-timeout— Configures the DHCP timeout for each attempt to get a DHCP address via the USB connection [D:60]gadget-mode— Configures the gadget mode. Default is unsharedsimplemode.gadget-mode=sharedenables the gadget device to be shared using libcompositemac-vendor— Specifies the first 3 segments of the MAC address. [D:dc:a6:32]static-ip— Specifies a static IP address to be used for the gadget. This also forces a static MAC addressstatic-mac— Configures the provided static MAC address for the USB gadget device. Useful so the Pi gets the same IP address every time, but only withgadget-mode=simpleIfstatic-modeis specified without a value, the plugin will generate a MAC address and make it static.noipv6— Do not configure ipv6 on the gadget USB connection
Examples
--plugin gadgetmode:"static-mac=aa:bb:cc:dd:ee:ff"— Configure simple gadget mode with a static MAC address- `--plugin gadgetmode:"gadget-mode=libcomposite|static-mac=fa:ce:fe:ed:00" — Configure shared gadget mode with a static MAC address
Notes
- The
autoconnect-retriesanddhcp-timeoutvalues are set high to improve success when connected to slower devices
git-clone
Clones the specified repository to the specified directory.
Arguments
repo— Full path to the git repository. Must be network-accessible either via https or some other mechanism (NFS, etc)gitdir— Directory into which to place the clone. sdm will do amkdir -pto ensure the directory exists. The clone is done directly into the specified directorygitsw— Additional switches to use on thegitcommanduser— User that will be used to run git. The user must already existpreclone— Command to run immediately before the clone. If the command starts with@it is the name of a script to runpostclone— Command to run immediately after the clone. Otherwise same aspreclonegitphase— By default thegitcommand is run in sdm Phase 1. Specifygitphase=post-installto run git in the post-install phase.cert— Not Yet Implementedlogspace— Specify this flag to have the disk space logged immediately before and after thegit clone
Examples
--plugin git-clone:"repo=https://github.com/gitbls/sdm|gitdir=/home/bls/work/sdm|user=bls|logspace"— Clone the sdm repo into /home/bls/work/sdm as user bls. Disk space will be logged before and after the clone.
graphics
The graphics plugin configures various graphics-related settings. It doesn't do much for wayland at the current time, although you might use it to set the video mode in /boot/firmware/cmdline.txt.
Arguments
-
graphics — Supported values for the graphics keyword are
labwc,wayfireandX11.If
graphicsis set tolabwcorwayfire, the corresponding software (labwc or wayfire) must already be installed. sdm will use raspi-config to appropriately configure lightdm as requested.If
graphicsis set toX11, the Core X11 packages (xserver-xorg, xserver-xorg-core, and xserver-common) are installed if not already installed. In the post-install phase, the plugin will look for a known Display Manager (lightdm, xdm, or wdm), and make appropriate adjustments (see below) -
nodmconsole — If
graphics=X11,nodmconsoledirects sdm to NOT start the Display Manager on the console, if the Display Manager is lightdm, wdm, or xdm. -
videomode — Specifies the string to add to the video= argument in cmdline.txt. See below for an example.
Currently, labwc is the Default graphics subsystem on Bookworm with Desktop images, so graphics=labwc is effectively redundant on those images. The plugin currently will not install labwc or wayfire on a Bookworm Lite IMG. labwc and wayfire are not supported by sdm on releases prior to Bookworm.
If graphics=X11 and the Display Manager is known, the graphics plugin makes a few adjustments. Specifically:
- If LXDE is installed, the mouse will be set to left-handed if specified on the command line. This works for wayland as well.
- For Display Managers lightdm, wdm, and xdm, sdm will cause the boot behavior you might specify to be delayed until after the First Boot.
For graphics=labwc or graphics=wayfire, use the labwc or lxde plugin to perform specific configuration such as lhmouse and/or apply personalized configuration settings.
The videomode argument takes a string of the form: 'HDMI-A-1:1024x768M@60D'. sdm will add video=HDMI-A-1:1024x768M@60D to /boot/firmware/cmdline.txt
Examples
--plugin graphics:"graphics=X11|nodmconsole"— Installs the X11 core components and disables the Display Manager on the console--plugin graphics:"videomode=HDMI-A-1:1920x1280@60D"— Sets the specified video mode in /boot/firmware/cmdline.txt
hotspot
The hotspot plugin configures the specified wireless device or USB0 to be a hotspot. The hotspot plugin supports Bookworm and later releases and is implemented using NetworkManager. In most situations a routed hotspot is preferable, but both are provided.
Arguments
- config — Config file with all the arguments (see Example)
- device — Device name [D:wlan0]. Use
device=usb0for a tether host. - dhcpmode — Mode for DHCP server. Controls whether NetworkManager uses its internal dnsmasq DHCP server or not. Valid settings are
noneandnm. If set tonone, you must configure a DHCP server for the hotspot. [D:nm] Ifdhcpmode==nonethenwlanipmust be provided. - hsenable — If hsenable=y set the hotspot to enable as part of system boot [D:y]. Can be specified as simply
hsenable. To disable, usehsenable=n - hsname — Set the hotspot name [D:Hotspot]
- ipforward — For routed hotspots, controls whether IP forwarding is enabled. If specified, must be the name of the network device to which network traffic is forwarded. [D:""] For bridged hotspots
ipforwardcontrols the network device to which the WiFi traffic is bridged [D:eth0] - portal — Install the portal described here as a service that runs at system startup.
portalifmust be specified. - portalif — Use the specified WiFi device for the portal. A second adapter is required, so typically it will be wlan1 (but not defaulted).
- pskencrypt — Save the encrypted PSK in the .nmconnection file rather than the plaintext PSK
- type — Type of hotspot (routed or bridged) [D:routed]
- wifipassword — WiFi hotspot password [D:password]
- wifissid — WiFi hotspot SSID [D:MyPiNet]
- wlanip — IP address of the hotspot in routed mode when
dhcpmode==none[D:""].wlanipis ignored in bridged mode and routed mode ifdhcpmode==nm(the default)
These 3 arguments are used to augment the NetworkManager config settings for the hotspot or bridge. The argument string is taken as is and fed to an appropriate nmcli command. See the example below.
- hotspot-add-config — Add the specified config settings to the NetworkManager hotspot (routed or bridged hotspot)
- bridge-add-config — Add the specified config settings to the NetworkManager bridge (bridged hotspot)
- bridge-slave-add-config — Add the specified config settings to the NetworkManager bridge slave (bridged hotspot)
Examples
-
--plugin hotspot— Create a routed hotspot named Hotspot on wlan0 with WiFi SSID 'MyPiNet', password 'password'. NetworkManager will use its internal DHCP server. wlan0's IP address will be set to the NetworkManager default (10.42.0.1). No IP forwarding is configured. The hotspot will be enabled. -
--plugin hotspot:"hotspot-add-config=802-11-wireless.hidden true"— As above, but add802-11-wireless.hidden trueto the hotspot configuration.bridge-add-configandbridge-slave-add-configoperate similarly. -
--plugin hotspot:"hsname=myhotspot|wifissid=myssid|wifipassword=mypassword|ipforward=eth0|hsenable|type=routed"— Configure a routed hotspot namedmyhotspoton wlan0 (the default), with SSIDmyssidand passwordmypassword, forwarding IP traffic toeth0. -
--plugin hotspot:"device=wlan1|hsname=myhotspot|ipforward=eth0|hsenable|type=routed|dhcpmode=none|wlanip=10.6.0.1"— Configure a routed hotspot on wlan1. wlan1's IP address will be set to 10.6.0.1, and you must configure your own DHCP server using, for instance, dnsmasq or the sdm pluginndmExample using the ndm plugin to configure dnsmasq (in pluglist format):
ndm:dhcpserver=dnsmasq|dnsserver=dnsmasq|dobuild|doinstall|dhcprange=10.6.0.2,10.6.0.100|domain=me|externaldns=1.1.1.1|gateway=10.6.0.1|myip=10.6.0.1|hostname=myap|dnsfqdn=myap.me|mxfqdn=myap.me|timeserver=10.6.0.1|netdev=wlan0|enablesvcs -
--plugin hotspot:"device=usb0|hsname=myusbhotspot|ipforward=eth0|hsenable|type=routed"— Configure a routed hotspot on usb0 so it can be a tethering host -
--plugin hotspot:"hsname=myhotspot|hsenable|type=bridged"— Configure a bridged hotspot
The Config file consists of the above arguments (except for config), one per line. Arguments that are not provided are defaulted as specified above.
device=wlan0
hsenable=true
hsname=myhotspot
ipforward=eth0
type=routed
wifipassword=SecretPassword
wifissid=myhotspot
Notes
The hotspot plugin does not configure a firewall. Adding an appropriate firewall is important in risky environments.
The wireless device (specified with device and defaults to wlan0) cannot be both an Access Point and a WiFi client. If you need both the Access Point and WiFi client (to another WiFi network), you will need to use a second WiFi adapter.
imon
imon installs an Internet Monitor that can monitor:
- Dynamic DNS (DDNS) Monitor — Monitors your external IP address. If it changes changes, your action script is called to take whatever you'd like, such as update your ddns IP address.
- Network Failover Monitor — If your system has two connections to the internet, imon can provide a higher availability internet connection using a primary/secondary standby model.
- Ping monitor — Retrieve ping statistics resulting from pinging an IP address at regular intervals.
- Up/down IP Address Monitor — Monitors a specified IP address, and logs outages.
Arguments
There are no --plugin arguments for imon
knockd
knockd installs the knockd service and pktables to facilitate easier knockd iptables management.
Arguments
- config — Full path to your knockd.conf. If config isn't provided, /etc/knockd.conf will be the standard knockd.conf
- localsrc — Locally accessible directory where pktables, knockd-helper, and knockd.service can be found, instead of downloading them from GitHub. If there is a knockd.conf in this directory, it will be used, unless overridden with the config argument
kvm
Enable virtualization on the host system. The kvm plugin:
- Installs the necessary software packages (libvirt, qemu, etc)
- Configures a network bridge for Network Manager enabling you to create VMs on a network that is:
- Routed to the LAN
- Bridged to the LAN so the VM appears directly on the LAN
- Assigns the optional specified user to the
libvirtgroup. This can also be done later with
sudo usermod -a -G libvirt a_user
sudo usermod -a -G libvirt-qemu a_user
- Creates a few scripts in /usr/local/sdm/kvm that you may find useful/handy. See getting started with kvm virtualization for details.
Arguments
gui— Also install the virt-manager GUIifname— Network interface to use for the bridge [D:eth0]user— Username to be added to thelibvirtandlibvirt-qemugroups
Examples
--plugin kvm:"gui|user=myuser"— Install virtualization; addmyuserto thelibvirtandlibvirt-qemugroups, Also install virt-manager GUI
L10n
Use the L10n plugin to set the localization parameters: keymap, locale, and timezone. You can find the valid values for these arguments with
sudo sdm --info keymap # Displays list of valid keymaps
sudo sdm --info locale # Displays list of valid locales
sudo sdm --info timezone # Displays list of valid timezones
Arguments
- keymap — Specify the keymap to set
- locale — Specify the locale for the system
- timezone — Specify the timezone
- wificountry — Specify the WiFi country setting
- host — Get the above settings from the host system on which sdm is running
NOTE: To disable the RasPiOS initial boot query for these configuration items, add --plugin disables:piwiz to your customize or burn command line. This works for both Desktop and Lite IMGs.
Examples
--plugin L10n:"keymap=us|locale=en_US.UTF-8|timezone=America/Los_Angeles"--plugin L10n:"host"
labwc
Provide labwc your fully-configured desktop settings.
Arguments
- all-config — Specify an existing directory created by
sdm-collect-labwc-config. This includes all the files that can be provided withapp-configandlabwc-config, so those arguments are not needed ifall-configis provided. sdm does not check for any argument conflicts, butall-configis processed before any other arguments. - app-config — Specify existing config files for
libfm,pcmanfm, andlxterminal. See the example, and see Using LXDE configuration for details - labwc-config — Specify existing config files for 'autostart', 'desktop-items', 'environment', 'menu', 'rc' 'shutdown' and 'themerc'
- lhmouse — Configure labwc for a left-handed mouse
- numlock — Configure the numlock state. Values (sdm does not validate): 'on', 'off'
- user — The settings apply to the specified user. If no
userargument is specified, they apply to the first user created with theuserplugin. Theuserplugin must be specified on the command line before thelabwcplugin - wf-panel-pi — Specify existing wf-panel-pi.ini config file for
wayfirewhich is copied to the ~/.config directory of the specified user. HINT: Useposition=bottomin this file to move the task bar to the bottom of the screen.
Use the L10n plugin to configure the labwc keymap.
If the IMG being customized does not have labwc installed, the assets will be copied to /etc/sdm/assets in Phase 0, but not applied to the user's home directory
The best way to use this plugin is:
- Boot a RasPiOS Desktop system with labwc (the default as of 2024-10-22)
- Configure the system as you'd like it, including pcmanfm, lxterminal, and labwm itself
- Run
/usr/local/sdm/sdm-collect-labwc-config/path/to/savedir as the logged in user (e.g., no sudo)- If no argument provided /tmp/labwc will be used
- Copy the created directory to the system where you run sdm to customize IMGs
- Provide that directory to sdm when customizing an IMG:
--plugin labwc:all-config=/path/to/dir
Examples
- `--plugin labwc:"all-config=/path/to/labwc-config-dir"
--plugin labwc:"app-config=libfm:/path/to/libfm.conf,pcmanfm=/path/to/pcmanfm.conf,lxterminal=/path/to/lxterminal.conf"--plugin labwc:"lhmouse|user=someuser"--plugin labwc:"labwc-config=autostart:/path/to/autostart,environment=/path/to/environment"
ln
The ln plugin creates a link, either hard or symbolic.
Arguments
linkname — The linkname that will be created symbolic — Make a symbolic link. If not specified, a hard link will be created target — The target of the link. If creating a hard link, the target file must exist
Examples
--plugin ln:"target=/usr/bin/less|linkname=/usr/bin/lessismore"— Create a hard link to target /usr/bin/less with name /usr/bin/lessismore--plugin ln:"symbolic|target=/nfs/server1/data/org1|linkname=/org1"— Create a symbolic link /org1 that links to an nfs-mounted disk
Notes
- Although the link will always be created by root, a non-privileged user can remove a link from a directory with write access to the directory.
logwatch
Use the logwatch plugin to install the logwatch package.
Arguments
- sendto — Email address where logwatch report should be mailed. You must have a properly configured mail server to send the mail. See the
postfixplugin - sendfrom — Email address for where the mail should be sent from
Examples
- `--plugin logwatch:"sendto=myname<myuser@myemail.com>|sendfrom=myhost-logwatch<myuser@myemail.com>"
lxde
Use the lxde plugin with wayfire to establish your preferred settings, such as left-handed mouse, and config files for libfm, pcmanfm, and lxterminal. These are not well-documented. The best way to create your personalized versions is to use RasPiOS to configure the desktop as you'd like it, and then save the files. NOTE: Use the labwc plugin for configuring labwc.
Arguments
- lhmouse — Set LXDE for a left-handed mouse
- lxde-config — Specify existing config files for
libfm,pcmanfm, andlxterminal. See the example, and see Using LXDE configuration for details - user — The settings apply to the specified user. If no
userargument is specified, they apply to the first user created with theuserplugin. Theuserplugin must be specified on the command line before thelxdeplugin - wayfire-ini — Specify existing wayfire.ini config file for
wayfirewhich is copied to the ~/.config directory of the specified user - wf-panel-pi — Specify existing wf-panel-pi.ini config file for
wayfirewhich is copied to the ~/.config directory of the specified user. HINT: Useposition=bottomin this file to move the task bar to the bottom of the screen.
Examples
--plugin lxde:"lxde-config=libfm:/path/to/libfm.conf,pcmanfm=/path/to/pcmanfm.conf,lxterminal=/path/to/lxterminal.conf"--plugin lxde:"lhmouse|user=someuser"
mkdir
Create the specified directory and optionally set directory owner and protection
Arguments
- dir — Full path of the directory to create
- chmod — Directory protection
- chown — Directory owner:group
Examples
--plugin mkdir:"dir=/usr/local/foobar|chown=bls:users|chmod=740"
NOTE: The directory is created in Phase 0, so it is available as early as during customization. The owner and protection are not set until the post-install phase, since it's possible that the owner account may not be created until Phase 1.
modattr
Use the modattr plugin to change file attributes such as the file owner and file protection.
Arguments
- path — File specification (see below)
- chmod — Directory protection
- chown — Directory owner:group
- R — Perform the chmod and/or chown recursively
- recursive — Same as
R - runphase — Specify the phase in which the attribute modifications will be done (
phase1orpost-install). Default isphase1 - verbose — Specify the verbosity level (
changes,silent, orverbose), corresponding to the chown/chmod switches--changes,--silent, and--verbose
Path argument processing notes
The path argument is processed as follows:
- Single file: Attributes of that file will be modified
- Directory: Attributes of the directory will be modified, using
--recursiveifRorrecursiveprovided - Wildcard specification: each expanded element is examined and processed as either a directory or file
Examples
--plugin modattr:"path=/path/to/file|chown=user:group|chmod=644"— Change the file owner and protection of the specified file--plugin modattr:"path=/path/to/dir|chown=user:group|chmod=755|R"— Change the file owner and protection recursively of the specified directory. If recursive is not specified, only the given directory will be modified.--plugin modattr:"path=/path/to/dir/*|chmod=755|R"— Change the file protection on all files matching the providedpath. Matches that are directories will be processed per above.
ndm
The ndm plugin installs ndm (https://github.com/gitbls/ndm), named (bind9) and isc-dhcp-server which enables the resulting system to operate as a full DHCP/DNS server with an easy-to-use command-line interface. ndm makes it super-simple to run your own DHCP/DNS server on RasPiOS with useful logging capabilities.
Arguments
- config — Existing ndm config file (dbndm.json) to build a new server with an existing ndm config file
- dhcplease — Sets the DHCP lease time in seconds (Default: ndm defaults to 86400)
- dhcpserver — Specifies which DHCP server to use (dnsmasq or isc-dhcp-server) (Default: isc-dhcp-server)
- dnsserver — Specifies which DNS server to use (bind9 or dnsmasq). (Default: bind9). If dnsmasq is chosen for either dhcpserver or dnsserver they both must be set to dnsmasq.
- dobuild — Do an
ndm buildafter the system has been configured. See building, installing and enabling services - doinstall — Do an
ndm installafter the system has been configured. See building, installing and enabling services - enablesvcs — Enable the DHCP and DNS server services after configuration. See building, installing and enabling services
- importnet — Provides /path/to/import-host-list.txt, which is a list of host definitions to import. See importing a network database for details on the host definition format.
- localsrc — Specifies the directory containing the already-downloaded ndm files
In addition, these arguments, which control the ndm DHCP and DNS configuration, are also accepted. See the ndm documentation for details.
- dhcprange — Sets the range of addresses that the DHCP server will serve dynamically
- dnsfqdn — FQDN of the host on which ndm will be running [D:
hostname.domain] - domain — Domain name [D:my.sdm]
- externaldns — IP address of the external (internet) DNS server
- gateway — Gateway IP from LAN to the internet
- hostname — Hostname of the host on which ndm will be running
- mxfqdn — Mail server FQDN. Use the DNS server FQDN if you don't have a mail server
- myip — IP address of host on which ndm will be running. NOTE: This does NOT configure the network. Use the
networkplugin for that. - netdev — Network device that the DNS and DHCP servers listen on [D:eth0]
- timeserver — IP address of timeserver to provide to DHCP clients
The ndm plugin will install the requested DHCP and DNS server services, and configure them appropriately per the provided arguments.
Building, installing, and enabling services
The dobuild argument requires one of:
- An ndm config file via argument
config - OR all of these arguments:
dhcprange,dnsfqdn,domain,externaldns,gateway,hostname,mxfqdn,myip,netdev, andtimeserver
The doinstall argument requires a satisfied dobuild
The enablesvcs argument requires satisfied dobuild and doinstall arguments
Examples
--plugin ndm— Installs ndm, named, and isc-dhcp-server. Both named and isc-dhcp-server services are disabled, and must be re-enabled once ndm has been used to generate the config files for these two services.--plugin ndm:"config=/path/to/dbndm.json|dhcpserver=dnsmasq|dnsserver=dnsmasq|dobuild|doinstall|netdev=eth0"— Installs dnsmasq, performs anndm buildandndm install, but does not enable the services.- Also see the example used in conjunction with the
hotspotplugin
network
Use the network plugin to configure various network settings. Each invocation of the network plugin performs one of two functions:
- Configure network settings using the
nmconfandnmconnarguments to provide ready-to-go files for NetworkManager - Configure a single connection for a single device. A device can have more than one connnection configured for it, but pay attention to
autoconnectandautoconnect-priorityso that the proper connection is started by default.
sdm does not pay attention to, nor do anything to improve or restrict multiple connections on a single device. They will work correctly when properly configured.
Arguments
All arguments except dhcpcdappend, dhcpcdwait, nowifi, and wpa are valid for NetworkManager. The only arguments valid for dhcpcd are these four plus noipv6
-
netman — Specify which network manager to use. Supported values are
dhcpcd,network-manager, andnm(short for network-manager). Ifnetmanis not specified, by default sdm will use dhcpcd on Bullseye (Debian 11) and earlier, while on Bookworm and later sdm will use NetworkManager. -
autoconnect — Takes the value
trueorfalse. Sets the connection's autoconnect value -
autoconnect-priority — Sets the connection's
autoconnect-priorityto the provided value -
cname — Name the NetworkManager connection. Default is
ifname, the interface name -
ctype — If cname is a WiFi device with a name other than
wlan*, specifyctype=wifi -
dhcpcdappend — Specifies a file that should be appended to /etc/dhcpcd.conf. Only processed if
netman=dhcpcd -
dhcpcdwait — Specifies that dhcpcd wait for network online should be enabled. Only processed if
netman=dhcpcd -
ifname — Specifies network device name to configure. Default is
eth0. To configure WiFi usingwifissidandwifipasswordifnamemust be specified and configured to a WiFi device (e.g.,wlan0). -
ipv4-route-metric — Specify the route metric for the network
-
nmconf — Specifies a comma-separated list of NetworkManager config files that are to be copied to /etc/NetworkManager/conf.d (*.conf)
-
nmconn — Specifies a comma-separated list of NetworkManager connection definitions (each a separate file) that are to be copied to /etc/NetworkManager/system-connections (*.nmconnection)
-
nmdebug — Enables NetworkManager debug mode logging for those hard-to-diagnose NM issues
-
noipv6 — Specifies that IPv6 should be disabled for this connection. Works with both
netman=dhcpcdandnetman=nm -
nowifi — If
netman=dhcpcdand WiFi settings not configured, this prevents a warning message about no WiFi configured -
powersave — Specify the WiFi powersave setting. Values: 0:Use default value; 1:Leave as is; 2:Disable powersave; 3:Enable powersave
-
ipv4-static-ip — Configure the connection with this static IP address and subnet mask. The default subnet mask
/24. -
ipv4-static-gateway — Configure the connection with this static gateway
-
ipv4-static-dns — Configure the connection with this DNS server IP
-
ipv4-static-dns-search — Set DNS suffix search list for the configuration (Ex:
ipv4-static-dns-search=my.com,dyn.my.com) -
pskencrypt — Save the encrypted PSK in the .nmconnection file rather than the plaintext PSK
-
wifissid or wifi-ssid — Specifies the WiFi SSID for the connection. If
ifnameis configured and is a WiFi device, andwifissid,wifipassword, andwificountryare all set, the network plugin will configure the WiFi connection (NetworkManager) or will create /etc/wpa_supplicant/wpa_supplicant.conf (ifnetman=dhcpcd). -
wifipassword or wifi-password — Password for the
wifissidnetwork. Seewifissid -
wificountry or wifi-country — WiFi country for the
wifissidnetwork. Seewifissid -
wpa — Specifies the file to be copied to /etc/wpa_supplicant/wpa_supplicant.conf. Only processed if
netman=dhcpcd. NetworkManager does not use wpa_supplicant.conf -
zeroconf — (NetworkManager only) If eth0 does not properly connect (e.g., doesn't get a DHCP address) then bring up zeroconf (169.254.x.y) on the adapter.
This can take some time due to NetworkManager default settings and timeouts. You can use the NetworkManager settings
ipv4.dhcp-timeoutandconnection.autoconnect-retrieson the eth0 nmconnection to reduce the delay if desired.See Network Manager nmcli settings for complete details on connection settings.
Examples
--plugin network:"ifname=eth0"— Configure network connection for deviceeth0. It will be configured for both IPV4 and IPV6 DHCP configuration. The connection will be namedeth0--plugin network:"ifname=eth0|cname=myeth0"— As above, but the connection will be namedmyeth0--plugin network:"nmconf=file1.conf,file2.conf|nmconn=/path/to/myconn1.nmconnection,/path/to/myconn2.nmconnection"— Copy the provided NetworkManager config files and nmconnection files to their destination directories. No other network configuration is done.--plugin network:"ifname=wlp3s0|cname=wlan2|ctype=wifi|wifi-ssid=myssid|wifi-password=myssidpassword|wificountry=US"— Configure a WiFi connection namedwlan2configured with the provided SSID/Password/country for network devicewlp3s0--plugin network:"ipv4-static-ip=192.168.14.32|ipv4-static-gateway=192.168.41.1|ipv4-static-dns=192.168.14.1|ipv4-static-dns-search=mydom.com"— Configureeth0(default if noifnamespecified) with the specified static IP configuration. The DNS search mechanism will search unqualified names in the domainmydom.com--plugin network:"netman=dhcpcd|noipv6"— Set the network manager to dhcpcd (and disable NetworkManager), and do not request an IPv6 address.
parted
parted is a --burn-plugin that operates on a device, disk, or disk image and enables you to
- Expand the root partition by a specified number of MiB
- Add one or more partitions of a specified size with a specified file system type on it
Using the parted burn plugin implicitly sets --no-expand-root when used on a burn command.
Arguments
- rootexpand — Expand the root partition by the number of MiB specified as the value for this argument. A value of 0 expands the partition to fill the disk. A value of 0 is not allowed when used with
--burnfile. If specified,rootexpandmust be used before anyaddpartitionarguments. - addpartition — Adds another partition at the end of the IMG. Arguments: size[fstype][,mountpoint,] where:
sizeis the number of MiB for the partitionfstypeis the type of file system. Supported file systems are:btrfs,ext2,ext3,ext4[default],fat16,fat32,hfs,linux-swap,none,ntfs,udf,vfs, andxfs. Some file systems may require you to install additional apt packages on the host before running this pluginmountpointis the location in the filesystem where you expect to mount your new partition. This will be added to fstab, and is optional.- NOTE: Multiple partitions can be named on the command line by separating them with
+. See example below.
Examples
--burn-plugin parted:"rootexpand=2048|addpartition=1024,ext4"— Expand the RasPiOS root partition by 2048MiB and add a 1024MiB ext4 partition--burn-plugin parted:"rootexpand=2048|addpartition=1024,ext4+2048,btrfs,/data/backups,MyBTRFS"— Expand the RasPiOS root partition by 2048MiB and add: a 1024MiB ext4 partition and a 2048MiB btrfs partition--burn-plugin parted:"rootexpand=1024|addpartition=@/path/to/partition-list"where the file partition-list has one line for each partition to be added in the form:nnnn,fstype,partitiontype,label
Example partition-list file
This is a sample file for the addpartition=@/path/to/partition-list directive. It will expand the root partition by 2048MiB (2GiB) add a 1024MiB partition and ext4 file system, a 4096MiB partition and btrfs file system, and a 16GiB Swap partition. This method enables easily adding multiple partitions with a single plugin invocation, so the ability to use + for multiple partitions mentioned above does not work in a partition-list file.
1024,ext4,,ext4label
4096,btrfs,/data/backups,btrfslabel
16384,linux-swap,,swaplabel
If you enable --gpt, and use addpartition to create one of every partition type, without adding optional mount points your /etc/fstab will look something like (note, however that a mount point was specified for the first btrfs partition, hence is preceded by a commented notice to alert that the mount point directory /mybtrfs was not created.
proc /proc proc defaults 0 0
PARTUUID=c352087d-56a1-4dca-ad2e-e8a8fd0979fc /boot/firmware vfat defaults 0 2
PARTUUID=35cadb8e-949c-4bad-89e2-d942a13c5dd8 / ext4 defaults,noatime,commit=300 0 1
PARTUUID=b98b8d45-2d03-4d6e-b02f-aa5ff6cc5bdf none swap defaults,nofail 0 0
#** Create mount point '/mybtrfs' before uncommenting this VV fstab entry
#PARTUUID=a834c0dd-a717-4c1e-8094-366f3b22b282 /mybtrfs btrfs defaults,noatime 0 0
#PARTUUID=de934be9-ad00-451a-8d8b-7df2ccb8ee7b /mnt/p5/btrfs btrfs defaults,noatime 0 0
#PARTUUID=172a749a-7e6a-405e-806d-3de45dcf6787 /mnt/p6/ext2 ext2 defaults,errors=remount-ro,noatime 0 2
#PARTUUID=5c41fe01-7299-4e95-92ed-501f8b332116 /mnt/p7/ext3 ext3 defaults,errors=remount-ro,noatime 0 2
#PARTUUID=3397c0e0-954c-45c1-9647-11d3104016e6 /mnt/p8/ext4 ext4 defaults,errors=remount-ro,noatime 0 2
#PARTUUID=a0eaa88b-2d1e-4a18-9266-e4c94ee9e583 /mnt/p9/fat16 vfat defaults,noatime 0 0
#PARTUUID=94ad3300-2a73-43e6-a1b0-c72c3b9c5aba /mnt/p10/fat32 vfat defaults,noatime 0 0
#PARTUUID=71ebc6f1-04e0-4f2d-8337-e12f2059529c /mnt/p11/vfat vfat defaults,noatime 0 0
#PARTUUID=5d71f86d-1baa-4ab7-8433-40f4d48506b7 /mnt/p12/hfs hfs defaults,noatime 0 0
#PARTUUID=2c3bee4f-47cf-4aaf-b882-f8d041d72fe8 /mnt/p13/ntfs ntfs defaults,noatime 0 0
#PARTUUID=16e7158f-aba4-45b0-abe0-3e80fa128ff8 /mnt/p14/udf udf defaults,noatime 0 0
#PARTUUID=4020da32-ac0e-43f0-8775-231e5da6dfd7 /mnt/p15/xfs xfs defaults,noatime 0 0
Notes
- The
partedplugin can only create up to 4 partitions when burning to an IMG, and conversion to GPT partition table is not supported - Partition type
hfscreates a HFS+ partition - The
partedburn plugin adds an entry to /etc/fstab for each additional partition. These won't interfere with use of thesystemplugin'sfstabfeature if you also use that.linux-swap: Provides an uncommented fstab entry so that your swap partition will activate on boot- All others: If the specified mount point does not exist, the entry is commented out, but provides useful information such as the PARTUUID, partition number, and filesystem type. The other settings are sane for most partitions, although you should check they meet your needs.
- If you create your mount point during
customizeorburnwith themkdirplugin before thepartedplugin runs, the partition will be uncommented and effective when the system boots. If the directory does not exist, you should only need to create the directory later, edit /etc/fstab, uncomment the line, and check the mount options to complete the process - Be sure to check that fstab is set how you want. Refer to man swapon(8), mount(8), and fstab(5) for additional information
piapps
Installs pi-apps (https://github.com/Botspot/pi-apps). That's it!
Arguments
- user — Specify the user that piapps should be installed for. The user must already exist. If not specified, the first created user ($myuser) will be used
Examples
--plugin piapps:"user=bls"— Install piapps for user bls. The user was already created with theuserplugin
pihole
Install Pi-hole. This plugin requires that you first install Pi-hole manually and save off the /etc/pihole/pihole.toml file. You then feed that toml file to this plugin. You can hand-edit the file to update it as appropriate for your configuration.
Arguments
- toml — /path/on/host/to/your-pihole.toml. This file is loaded into the IMG and Pi-hole uses it for configuration.
Examples
--plugin pihole:toml=/path/to/my-pihole.toml
pistrong
pistrong installs the strongSwan IPSEC VPN server and pistrong. pistrong provides
- A fully-documented, easy-to-use Certificate Manager for secure VPN authentication with Android, iOS, Linux, MacOS, and Windows clients
- Tools to fully configure a Client/Server Certificate Authority and/or site-to-site/host-to-host VPN Tunnels. Both can be run on the same VPN server instance
In addition to simply installing pistrong and strongSwan, this plugin enables:
- After FirstBoot system can be fully configured and operational with host/host tunnels and/or client/server VPNs with no intervention
- Two hosts can be built up from scratch with an operational site/site host/host VPN tunnel with one sdm customize and 2 sdm burn commands
Arguments
- calife — Set the CA Certificate lifetime in days [Default: 3650 days]
- uclife — Set the User Certificate lifetime in days [Default: 730 days]
- certpack — Import an already-generated CertPack and install it in the customized IMG or burned disk
- enablesvc — Enable the
strongswanservice to start on first system boot - ipforward — Enable IP forwarding from the VPN server onto the LAN. Value can be
yesorno[Default: no] - iptables — Collect the iptables configuration from available CA and Tunnel definitions into /etc/swanctl/pistrong/iptables and enable the service pistrong-iptables-load
- makemyca — Provide a configuration answer file for MakeMyCA to enable the CA to be automatically configured with no intervention
- maketunnel — Provide a configuration answer file for makeTunnel to enable the tunnel to be automatically configured with no intervention
- hostname — Provide the hostname that will ultimately be used for the host so makeTunnel recognizes that the Tunnel configuration is for this host
- vpnmon — Enable the VPN monitor on this host, which tries to always keep the VPN tunnel connection up. Requires
vpnmonping - vpnmonping — Specifies the IP address that the VPN monitor should test for the VPN tunnel being up. Typically this would be the LAN IP address of the VPN server at the other end of the tunnel
Examples
--plugin pistrong:"calife=7300|uclife=7300|makemyca=/path/to/makemyca.conf"— Install strongSwan, create a CA with the specified Cert lifetimes, and configure the CA with the parameters provided in makemyca.conf--plugin pistrong:"maketunnel=/path/to/maketunnel.conf"— Install pistrong and build a VPN tunnel with the parameters defined in maketunnel.conf--plugin pistrong:"certpack=/path/to/Tunnel-node1-node2.zip|enablesvc|vpnmon|vpnmonping=192.168.47.3"— Install pistrong, import the VPN CertPack and install it. Enable the VPN monitor checking the LAN IP address on the other end of the tunnel specified byvpnmonping
NOTE: Documentation on the makemyca and maketunnel config files is not yet available. If you're interested in using this capability, please post an issue on the sdm GitHub.
postburn
postburn is a --burn-plugin that enables you to:
- Copy files from the burned disk to the host OS file system
- Run a script that has access to the burned disk in either Phase 0 or Phase 1 mode
Arguments
savefrom— /path/to/file for the file(s) to be copied from the burned disk.*is supported for use in the filenamesaveto— /path/to/dir to define where the files will be copied torunscript— /path/to/script of a script that will be run after the burn completes. The script must exist and be executablerunphase— Specify context for runningrunscript. [Default:phase1]. Supported values:phase0— Runsrunscriptin the context of the burned disk being mounted in the host OSphase1— Runsrunscriptin the context of the burned disk in a container
where— Where the script is located.hostspecifies thatrunscriptpath is in the host OS. Any other value:runscriptpath is in the burned disk
Examples
--burn-plugin postburn:"savefrom=/etc/swanctl/pistrong/server-assets/*.zip|saveto=/my/dir"— Copies all the *.zip files from the specified directory in the burned disk to/my/diron the host file system--burn-plugin postburn:"runscript=/usr/local/bin/do-something|runphase=phase0|where=host"— Runs the host-located script/usr/local/bin/do-somethingin the context of the host OS--burn-plugin postburn:"runscript=/usr/local/bin/do-something|runphase=phase1|where=host"— Runs the host-located script/usr/local/bin/do-somethingin the context of the burned disk container. Therunscriptis copied onto the burned disk in /usr/local/bin, and removed after it has been run--burn-plugin postburn:"runscript=/usr/local/bin/do-something|runphase=phase1"— Runs the burned disk-located script/usr/local/bin/do-somethingin the context of the burned disk container
postfix
postfix installs the postfix mail server. This plugin installs the postfix server but at the moment doesn't do too much to simplify configuring postfix. BUT, once you have a working /etc/postfix/main.cf, it can be fed into this plugin to effectively complete the configuration.
Arguments
- enablesvc — Enable the postfix service
- maincf — The full /path/to/main.cf for an already-configured /etc/postfix/main.cf. If provided, it is placed into /etc/postfix after postfix has been installed.
- mailname — Domain name [Default: NoDomain.com]
- main_mailer_type — Type of mailer [Default: Satellite system]
- relayhost — Email relay host DNS name [Default: NoRelayHost]
Examples
--plugin postfix:"maincf=/path/to/my-postfix-main.cf"— Uses a fully-configured main.cf, and postfix will be ready to go.--plugin postfix:"relayhost=smtp.someserver.com|mailname=mydomain.com|rootmail=myemail@somedomain.com"— Set some of the postfix parameters, but more configuration will be required to make it operational. A good reference will be cited here at some point.
quietness
The quietness plugin controls the quiet and splash settings in /boot/firmware/cmdline.txt
Arguments
- consoleblank — Set a console blanking timeout (Default: 300 seconds)
- quiet — Enables 'quiet' in /boot/firmware/cmdline.txt
- noquiet — Disable 'quiet' in /boot/firmware/cmdline.txt. If
noquiet=keepis NOT specified, sdm will re-enable 'quiet' in cmdline.txt after the First Boot. - splash — Enables 'splash' in /boot/firmware/cmdline.txt
- nosplash — Disable 'splash' in /boot/firmware/cmdline.txt. If
nosplash=keepis NOT specified, sdm will re-enable 'splash' in cmdline.txt after the First Boot. - plymouth — Enables Plymouth in /boot/firmware/cmdline.txt. Not Yet Implemented
- noplymouth — Disables the Plymouth graphical splash screen for the First Boot (only). It is re-enabled at the end of First Boot.
Examples
--plugin quietness:"consoleblank|noquiet=keep|nosplash=keep"— Remove 'quiet' and 'splash' from cmdline.txt and do not re-enable them. Console blanking timeout set to 300 seconds (5 minutes)--plugin quietness:"consoleblank=600|noquiet|nosplash|noplymouth"— Remove 'quiet' and 'splash' from cmdline.txt, and disable plymouth. All will be re-enabled after the First Boot. Console blanking timeout set to 600 seconds (10 minutes).
raspiconfig
the raspiconfig plugin is used to modify settings supported by raspi-config. This is not necessarily the complete list (done quickly), and one or two of these may not be supportable. There's more work to do on this one!
See RaspberryPi Documentation for raspi-config for details.
Arguments
- audio
- audioconf
- blanking
- boot_behaviour, boot_behavior
- boot_order
- boot_splash
- boot_wait
- camera
- composite
- glamor
- gldriver
- i2c
- leds
- legacy
- memory_split
- net_names
- onewire
- overclock
- overlayfs — Enables the readonly file system. Optional value specifies whether bootfs should be 'ro' (default) or 'rw'
- overscan
- pi4video
- pixdub
- powerled
- proxy
- rgpio
- serial — Deprecated. See the serial plugin
- spi
- xcompmgr
Examples
--plugin raspiconfig:"net_names=1|boot_splash=1"--plugin raspiconfig:overlayfs=ro— Enable the rootfs readonly file system with a read-only bootfs also--plugin raspiconfig:overlayfs— Enable the rootfs readonly file system with a read-only bootfs also--plugin raspiconfig:overlayfs=rw— Enable the rootfs readonly file system with a read/write bootfs
Notes
The 'overlayfs' setting enables the read-only file system. The file system is not made read-only until sdm FirstBoot has completed and the system restarts. If you need a swapfile, you'll need to configure it on another disk or partition, since the boot disk isn't writeable. At the moment sdm doesn't provide any support for swapfile management with overlayfs.
runatboot
The runatboot plugin provides a way to run an arbitrary script during the First Boot of the system. The script is run as root or user if specified, with no other provisions or control made by sdm. Behavior, output, logging content, etc is all the responsibility of the script.
Arguments
- script — /full/path/to/the/script that should be run
- args* — The arguments to provide to the script
- user — If provided use sudo to run script as the specified user. User must exist at time of First Boot
- sudoswitches — If
userprovided, include these sudo switches - output — Where to set stdout. Default is /dev/null. The directory must already exist, and the user (root or
userif specified) must be able to write the output file in that directory - error — Where to set stderr. Default is the same as stdout (
2>&1)
Examples
--plugin runatboot:"script=/path/to/script|args=arg1 arg2 arg3"— Run the specified script with the 3 provided arguments--plugin runatboot:"user=me|sudoswitches=-H|script=/path/to/script|args=arg1 arg2 arg3"— Run the specified script with the 3 provided arguments as the specified user and include-Hon the sudo command--plugin runatboot:"script=/path/to/script2|args=arg1 arg2 arg3|output=/var/log/myscript.log"— Run the specified script with the 3 provided arguments with output and error going to /var/log/myscript.log
runcommand
The runcommand plugin runs a bash command during customization or burning.
Arguments
- dir — Optional directory in which to run the command (as the default directory). The directory will be created if it doesn't exist. Use a /full/path/to/dir
- runphase — Specifies the phase (
1orpost-install) in which to run the script. Default is1 - command — The command to run
- user — The user under which to run the script. The user must exist by the time the script is run in Phase 1 or post-install. If not specified the script is run as
root. Ifuseris notroot, then you must specify thedirargument or the plugin will be unable to write the output and error files. - stdout — Specifies stdout for the script output. /full/path/to/stdout must be specified (but not checked by sdm)
- stderr — Specifies stderr for the script output. /full/path/to/stderr must be specified (but not checked by sdm)
Examples
--plugin runcommand:"command=ls -lR /bin|stdout=/root/ls.out|stderr=/root/ls.error"— Run the provided commandls -lR /binas root. The stdout and stderr files will be written to the specified files.--plugin runcommand:"command=/usr/local/bin/myscript|dir=/home/myuser|user=myuser"— Run the specified command as the usermyuser. stdout and stderr files will be written to /home/myuser.
runscript
The runscript plugin runs a script during customization or burning
Arguments
- dir — Optional directory in which to run the script (as the default directory). The directory will be created if it doesn't exist. Use a /full/path/to/dir
- runphase — Specifies the phase (
1orpost-install) in which to run the script. Default is1 - script — /full/path/to/script on the host to run. The script will be copied into the IMG
- user — The user under which to run the script. The user must exist by the time the script is run in Phase 1 or post-install. If not specified the script is run as
root - stdout — Specifies stdout for the script output. /full/path/to/stdout must be specified (but not checked by sdm)
- stderr — Specifies stderr for the script output. /full/path/to/stderr must be specified (but not checked by sdm)
The script is called with one argument: the current Phase (either 1 or post-install).
The default for stdout and stderr if not specified are $(basename $script).out and $(basename $script).error. If dir is specified the files will be written to dir. If not, the files will be written to /etc/sdm/assets/runscript.
Each script (unique filename) can be run on behalf of multiple users, by using multiple invocations of the runscript plugin with different users, but each script can ONLY be run ONCE PER USER. A second runscript call with the same script name and user will elicit an error. This plugin treats the same script name in different directories as the same script, so qualify them further for uniqueness if needed.
Examples
--plugin runscript:"dir=/home/work|script=/path/to/my/script|user=bls"— The directory /home/work is created and owned by user bls. The script specified is run during Phase 1, and the ouptut and error files are saved in /home/work--plugin runscript:"/path/to/my/script"— The script is run as root during Phase 1. Output and error are saved in /etc/sdm/assets/runscript/sdm-runscript-$script.out and .error--plugin runscript:"stdout=/dev/stdout|stderr=/dev/stderr|script=/path/to/my/script"— redirect the output of the script to the console instead of a file in the image
Example runscript
This simple demo script prints out some environmental information including the username, group ids, and current working directory. Save the file somewhere with execute permission and use --plugin runscript:"script=myrunscript.sh|stdout=/dev/stdout|stderr=/dev/stderr"
#!/bin/bash
echo "In the runscript"
echo "* whoami: $(whoami)"
echo "* ids: $(id)"
echo "* pwd: $(pwd)"
rxapp
rxapp is a handy tool to securely and remotely start X11 apps via SSH without a password. You can read about it here.
rxapp is included because it is generally useful, but also as a demonstration of how to copy a file from the network (GitHub in this case) into the IMG in a plugin.
Arguments
There are no --plugin arguments for rxapp
samba
Arguments
- smbconf — Full /path/to/smb.conf for an already-configured /etc/samba/smb.conf. If provided it is placed into /etc/samba after samba has been installed.
- shares — Full /path/to/shares.conf for a file containing only the samba share definitions. If provided it is appended to /etc/samba/smb.conf after samba has been installed.
- dhcp — TBH not sure what this does. If you figure it out, let me know ;)
- do_debconf — TBH not sure what this does. If you figure it out, let me know ;)
- workgroup — Workgroup name to replace WORKGROUP in the default /etc/samba/smb.conf. If smbconf is specified, the workgroup is NOT modified.
Examples
--plugin samba:smbconf=/home/bls/mylan-smb.conf— Use the provided fully-configured file for /etc/samba/smb.conf--plugin samba:"shares=/home/bls/mysmbshares.conf"— Append the provided share definitions to the end of the default /etc/samba/smb.conf--plugin samba:"workgroup=myworkgroup|shares=/home/bls/mysmbshares.conf"— Use the default /etc/samba/smb.conf, set the workgroup name to myworkgroup and append the provided share definitions to /etc/samba/smb.conf
serial
The serial plugin is used to configure the serial port. Although the serial setting on the raspiconfig plugin still works, as of 2023-12-28 it prompts, which is obviously annoying when you're in the middle of an sdm customize.
There's a second issue in that the serial setting for the Pi5 is different than for other Pis, and raspi-config checks the system on which it is running, which can likely be incorrect when doing an sdm customize.
The serial plugin addresses these issues. You can use it during a customize if you know the target hardware. Otherwise, when you burn the disk for a target system, you can run the plugin then to set it correctly for the target hardware.
Arguments
- disableshell — Explicitly disables the shell on the console serial port
- enableshell — If set, enable a shell on the console serial port. Also enables the uart
- enableuart — Enable the console serial port uart without enabling the shell
- pi5 — If set, configure the serial port for a Pi5
- pi5debug — If set, configure the debug serial port for a Pi5
Examples
--plugin serial— Configure the serial port for a Pi other than a Pi5 and disable the login shell on it--plugin serial:pi5— Configure the serial port for a Pi5 and disable the login shell on it--plugin serial:disableshell— Another way to disable the login shell on the console serial port--plugin serial:enableshell— Configure the serial port for a Pi other than a Pi5 and enable a login shell on it--plugin serial:pi5|enableshell— Configure the serial port for a Pi5 and enable a login shell on it--plugin serial:pi5debug— Configure the debug serial port for a Pi5
speedtest
The speedtest plugin creates a service that remains running and regularly runs speedtest, with a mechanism for reporting out-of-bounds results for ping, download speed and upload speed.
Arguments
- alertping — Call
alertscriptif a speedtest ping result is greater thanalertping - alertdown — Call
alertscriptif a speedtest download speed result is less thanalertdown - alertup — Call
alertscriptif a speedtest upload speed result is less thanalertup - alertscript — /path/to/alertscript. See below for an example alertscript
- interval — Run the speedtest every
intervalseconds. Note that running too frequently will likely elicit errors from speedtest. Default is 3600 seconds (1 hour) - log — /path/to/logfile for speedtest logging. Default is /var/log/sdm-speedtest-monitor.log
- rawlog — /path/to/rawlog for raw speedtest result logging, which captures the output from the speedtest commands. This is optional and not logged if not provided.
Examples
--plugin speedtest:"alertping=8|alertdown=600000000|alertup=600000000|alertscript=/usr/local/bin/alertscript"— Calls specified alert script if ping is greater than 8ms, or download or upload speed is less than 600mb. Logs to /var/log/sdm-speedtest-monitor.log
Example alertscript:
#!/bin/bash
if [ -f /etc/default/sdm-speedtest ]
then
source /etc/default/sdm-speedtest
else
logger "sdm-speedtest alertscript: ? /etc/default/sdm-speedtest not found"
exit 1
fi
ping=\$2
download=\$3
upload=\$4
case "\$1" in
alert)
[ $ping -gt $alertping ] && logger "sdm-speedtest alert: Ping $ping gt $alertping"
[ $download -lt $alertdown ] && logger "sdm-speedtest alert: Download $download lt $alertdown"
[ $upload -lt $alertup ] && logger "sdm-speedtest alert: Upload $upload lt $alertup"
;;
error)
logger "sdm-speedtest alertscript error: |\$2|"
;;
esac
sshd
The sshd plugin configures:
- The SSH service to be enabled or disabled. This service is enabled by default, even if the
sshdplugin is not used. Use thesshdservice to disable the SSH service if needed - Various SSH service configuration items
Arguments
These configuration items affect the SSH service.
-
enablesvc — Enable or disable the service. [Default: enabled]. Values supported:
yes,no, orsocket -
Arguments that modify /etc/sshd_config
- listen-address — IP address on which to listen [Default: 0.0.0.0] (all IP addresses on the server)
- password-authentication — Enable/disable password authentication. [Default:
yes]. Disable this (no) to restrict logins to public key only - port — Port number SSH service should listen on [Default: 22]
Examples
- `--plugin sshd:"enablesvc=no" — Disable the SSH service
- `--plugin sshd:"port=22222|listen-address=192.168.16.16" — Enable the SSH service, which will listen on port 2222 and only on the IP address 192.168.16.16 (which must be an IP address on the target system)
- `--plugin sshd:"password-authentication=no" — Disable password authentication
sshhostkey
The sshhostkey plugin allows the generation new or import of existing SSH host keys.
Importing SSH host keys is useful to generate images with deterministic keys.
Generating SSH host keys during an sdm customize or burn can be beneficial because the entropy during Pi's first boot is very limited, whereas sdm can access the entropy pool of the host OS.
Note, however, that unless you fully understand the ramifications of multiple hosts sharing SSH host keys, if the customized IMG is to be used by multiple host systems, you should only use the sshhostkey plugin during burn so that each host has unique SSH host keys.
One nice use of this plugin in Trixie is to use it at burn time, along with the --expand-at-boot command line switch.
Arguments
- generate-keys — Create a new set of keys in phase 1.
- import-keys — Copy files from the given host directory to /etc/ssh.
Examples
--plugin sshhostkey:"generate-keys"— Generate a new set of host keys.--plugin sshhostkey:"import-keys=/path/to/hostkeys"— Copyssh_host_*_keyandssh_host_*_key.pubfiles from the specified host directory to the Pi's /etc/ssh/ directory--plugin sshhostkey:"generate-keys|import-keys=/path/to/hostkeys"— Useful to import a subset (e.g. RSA only) keys, and re-create the rest.
sshkey
The sshkey plugin creates an SSH key or imports an SSH key for a user. In either case, you can optionally create a Putty private key for it.
Arguments
- sshuser — The user for whom the SSH key is targeted. The user must already exist
- authkey — Add the created SSH public key to
sshuser's ~/.ssh/authorized_keys - import-key — Instead of creating an SSH key, import the specified SSH key from the provided file in the host OS
- import-pubkey — Import the provided SSH public key and add it to
sshuser's ~/.ssh/authorized_keys. The key is not checked in any way - keyname — Name the key that is to be created
- keytype — Type of key to create. Accepted values:
ecdsa,ecdsa-sk,ed25519,ed25519-sk,rsa. [Default:ecdsa] - passphrase — Passphrase to secure the SSH key. The same passphrase is used when creating a putty key
- putty-keyname — If specified, create a putty key in ~/.ssh with the provided key name
Examples
--plugin sshkey:"sshuser=bls|keyname=mykey|keytype=ed25519|passphrase=itsasecret|putty-keyname=myputtykey"— Create a new SSH key for userbls, with the parameters as specified. Additionally, the Putty keymyputtykey.ppkis created using the same passphrase--plugin sshkey:"sshuser=bls|import-key=/home/bls/.ssh/myotherkey|putty-keyname=otherputty|passphrase=anothersecret"— Import the specified private key from the host system. Use the provided passphrase to access the imported key and create a Putty key using the same passphrase.
swap
The swap plugin configures rpi-swap.
Arguments
config— Provides a configured swap.conf. Start with /rpi/etc/swap.conf and edit as desired. The provided file is placed in /etc/rpi/swap.conf.dfilesize— Specifies the size for the swap file. Modifications are stored in /etc/rpi/swap.conf.dzramsize— Specifies the size for the zram device. Modifications are stored in /etc/rpi/swap.conf.d
Examples
--plugin swap:"config=/path/to/myswap.conf"— Copies the configured swap config file to /etc/rpi/swap.conf.d--plugin swap:"filesize=2048|zramsize=1024"— Configure a 2GB swapfile and a 1GB zram device
syncthing
The syncthing plugin installs syncthing and configures it for the user specified by runasuser.
Arguments
- connect-address — Address or host name to use when attempting to connect to this device. Must be fully specified. For example: tcp://0.0.0.0:22001. See listen-addresses for specfication details.
- enablesvc — Enable the syncthing service during sdm FirstBoot
- gui-address — GUI listen address. Default is 127.0.0.1:8384 For example: 0.0.0.0:8384 or http://0.0.0.0:8384
- gui-password — GUI authentication password used in conjunction with the
gui-user - gui-user — GUI authentication username
- homedir — Home directory to use. Default:
runasuserhome directory - nolinger — Do not start syncthing for user until user logs in. Default: syncthing started for user at system boot once enabled by
enablesvcor manually viasystemctl enable --user syncthingfrom the user account- Can be controlled manually after system up and running. If modifying other than current user specify
usernameand usesudo- Enable linger:
loginctl enable-linger [username] - Disable linger:
loginctl disable-linger [username]
- Enable linger:
- Can be controlled manually after system up and running. If modifying other than current user specify
- release — syncthing release to install. Default:
stable - runasuser — Username to be used to run the syncthing service. Default: First user created with the
userplugin - sendstats — Send statistics setting (-1: Never, 0: Ask, 1: Always). Default: Always
- synchost — Hostname that will eventually be used for this host. (Sorry that you need to specify this here)
Examples
--plugin syncthing— Install syncthing. GUI username/password will not be set. GUI will only be accessible from browsers running on the same host as syncthing. syncthing will run as the first user created with theuserplugin. Hostname will be set tosdm, which can be edited in config.xml--plugin syncthing:"enablesvc|gui-address=0.0.0.0:8384|gui-password=asecret|gui-user=syncuser"— Install syncthing. GUI username/password will be set. GUI will be accessible from browsers running on any LAN host. syncthing will run as the first user created with theuserplugin. The syncthing listenAddress will be set to the default (tcp://0.0.0.0:22000)--plugin syncthing:"enablesvc|gui-address=0.0.0.0:8384|gui-password=asecret|gui-user=syncuser" --plugin syncthing:"runasuser=syncuser2|enablesvc|gui-address=0.0.0.0:8385|gui-password=asecret|gui-user=syncuser2|connect-address=tcp://0.0.0.0:22001"- Install and configure syncthing for the first user created with the
userplugin as in the previous example - A second user,
syncuser2will also be configured. The usersyncuser2must be created using theuserplugin before referencing it in thesyncthingplugin. syncthing will listen ontcp://0.0.0.0:22001for the second user - Each user must have a unique listenAddress
- Install and configure syncthing for the first user created with the
Notes
Final syncthing configuration is done during sdm FirstBoot. The script that will be run is in /etc/sdm/0piboot/098-enable-syncthing-runasuser.sh
For a user's syncthing service to be started at boot enablesvc must be set and nolinger must NOT be set.
system
The system plugin is a collection of system-related configuration settings. You are responsible for using correct file types expected by each function (e.g., .conf, .rules, etc). The plugin does no checking/modification of file types.
If the system plugin is invoked more than once in an IMG, either on customize or burn, you must include the name=somename argument for correct operation.
Arguments
- Cron control arguments
- cron-d — Comma-separated list of files to copy to /etc/cron.d
- cron-daily — Comma-separated list of files to copy to /etc/cron.daily
- cron-hourly — Comma-separated list of files to copy to /etc/cron.hourly
- cron-weekly — Comma-separated list of files to copy to /etc/cron.weekly
- cron-monthly — Comma-separated list of files to copy to /etc/cron.monthly
- cron-systemd — Takes no value. Switches from using cron to systemd-based cron timers
- eeprom — Supported values are critical, stable, and beta
- exports — Comma-separated list of files to append to /etc/exports
- fstab — Comma-separated list of files to append to /etc/fstab
- journal — Configure systemd journal. Supported values are persistent, volatile, and none. By default Bullseye uses rsyslog and
journal=volatilewhile Bookworm usesjournal=persistent. NB RasPiOS changed again. It's best to use this configuration setting if you care.persistent: Makes a permanent journal in /var/logvolatile: The journal is in memory and not retained across system restartsnone: There is no system journal
- ledheartbeat — Enable LED heartbeat flash on Pi systems that have /sys/class/leds/PWR/trigger, such as the Pi4 and Pi5.
- modprobe — Comma-separated list of files to copy to /etc/modprobe.d
- motd — Single /path/to/file to use for /etc/motd. /dev/null results in an empty motd
- name — Name of this invocation. This must be included if the
systemplugin is invoked more than once in an IMG, including between customize and burn. Best practice to avoid problems is to give each and every invocation a name. - rclocal — Comma-separated list of ordered commands to add to /etc/rc.local. An item starting with '@' is interpeted as a file whose contents will be included.
- Service control arguments
- service-disable — Comma-separated list of services to disable
- service-disable-at-boot — Comma-separated list of services to disable at first boot
- service-enable — Comma-separated list of services to enable
- service-enable-at-boot — Comma-separated list of services to enable at first boot
- service-mask — Comma-separated list of services to mask
- swap — disable or integer swapsize in MB to set
- sysctl — Comma-separated list of files to copy to /etc/sysctl.d
- systemd-config — Comma-separated list of
type:/path/to/file.conf, where type is one of login, network, resolve, system, timesync, or user. Copies the provided file to /etc/systemd/type.conf.d NOTE: file must be specified as a full /path/to/file.conf and the file type MUST be.conf - udev — Comma-separated list of files to copy to /etc/udev/rules.d
Examples
--plugin system:"cron-d=/path/to/crondscript|exports=/path/to/e1,/path/to/e2"--plugin system:"systemd-config=timesync=/path/to/timesync.conf,user=/path/to/user.conf|service-disable=svc1,svc2"--plugin system:"name=s1|cron-d=/path/to/crondscript|exports=/path/to/e1,/path/to/e2" --plugin system:"name=s2|fstab=myfstab"
Notes
If you're having issues with settings in your systemd-config files, here are some handy infobits:
-
The command
sudo systemd-analyze cat-config systemd/service.conf(where service is one of journald, logind, networkd, pstore, sleep, system, timesyncd, or user) will display the settings in precedence order. This is very handy in sorting out what config file is providing which setting. -
The files in /lib/systemd/service.conf.d and /etc/systemd/service.conf.d appear to have their files unified and processed in ascending alphabetical order. For instance,with /lib/systemd/journal.conf.d/70-xx.conf and /etc/systemd/journal.conf.d/030-xx.conf, 030-xx.conf is processed first, so any settings in 70-xx.conf will override settings in 030-xx.conf.
-
The
swapargument controls whichever ofrpi-swapordphys-swapfileis installed.swap=0disables swap. Also see theswapplugin for fine-grained configuration ofrpi-swap. -
The
service-disableandservice-enablearguments operate immediately on the specified services, whereas theservice-disable-at-bootandservice-enable-at-bootarguments operation is delayed and performed during sdm FirstBoot.For instance, if a service is dependent on other operations that must be completed at boot time, you can use
service-disableduring customization to disable the service, and useservice-enable-at-boot. In this scenario the service will run for the first time on the reboot AFTER sdm FirstBoot has completed.Similarly, if you only want a service to run on the very first system boot BEFORE sdm FirstBoot completes, use
service-enableto enable it during customization, andservice-disable-at-bootto disable it for all subsequent system boots.
trim-enable
trim-enable will enable SSD Trim on all or only selected devices. Trim is not actually enabled on the devices until the system first boots.
This plugin can be run manually on a running sdm-customized system by
sdm --runonly plugins --plugin trim-enable:"disks=/dev/sda,/dev/sdb"
The optional switch --oklive can be used to avoid the Prompt "Do you really want to run plugins live on the running host?"
Arguments
- disks — Specifies the disks on which to enable trim.
disks=allwill enable trim on all drives. Multiple disk names can be specified by, for example,disks=/dev/sda,/dev/sdb. If no disks are specified,disks=allis the default.
Additional information on SSD Trim for RasPiOS and Linux can be found here, here, and here.
ufw
Install and configure the ufw firewall
Arguments
ufwscript— a list of one or more /path/to/script containing a she-bang (#!/bin/bash) and series of one or more ufw commands to configure the firewall. The traditionalsudois not required, since the script is run as root. Multiple scripts, if provided, are run in lexical order.savescriptdir— Specifies a directory where the ufw plugin will save the providedufwscriptscripts. If not provided, the scripts will be saved in/usr/local/bin.
Examples
--plugin ufw:"/ufwscript=/path/to/script1,/path/to/script2"— Install ufw and configure it with the two provided script files. Save the script files in the IMG in /usr/local/bin--plugin ufw— Install ufw, do not configure any rules. ufw documentation says that all inbound network accesses are denied by default
update-alternatives
Use the update-alternatives plugin to manipulate the Debian alternatives system.
Arguments
- get-selections — Output the current alternatives list to the console and /etc/sdm/history
- query-alternative — Provide a listing of the specified alternatives in a human-readable format
- set-one — Set one alternative.
set-oneprovides the name to set (e.g.,editor) andpathprovides the value - setpath — The path to a registered alternative for selection
set-one - set-many — Set a series of alternatives. See below
- install-alternative — Install an alternative in the system with the name provided as the
install-alternativevalue. Requireslink,installpath, andpriorityarguments. See Examples - link — The generic name for the master link (e.g., /usr/bin/something)
- installpath — The path to an alternative for
install-alternative - priority — Sets the priority for the alternative. When a link group is in automatic mode, the alternatives pointed to will be those which have the highest priority.
Examples
--plugin update-alternatives:get-selections— Print the list of alternatives--plugin update-alternatives:"query-alternative=editor,pager"— Print the configuration of the specified alternatives--plugin update-alternatives:"set-one=x-terminal-emulator|setpath=/usr/bin/xterm"— Set the selectionx-terminal-emulatorto alternative/usr/bin/xterm--plugin update-alternatives:"set-many=/path/to/list"— Set many alternatives at once.--plugin update-alternatives:"install-alternative=x-www-browser|link=/usr/bin/x-www-browser|installpath=/usr/bin/netsurf|priority=40"Install a new alternative group
Example series of alternatives for set-many
Each line in the file for set-many consists of three fields: selection-name manual /path/to/alternative
The specified alternative must already be registered in the Debian alternatives system, typically when the package is installed
editor manual /bin/ed
pager manual /bin/more
These two paragraphs from the update-alternatives man page are helpful in understanding whether to use auto or manual. Hint: Use manual if you want the alternative setting to actually change.
Each link group is, at any given time, in one of two modes: automatic or manual. When a group is in automatic mode, the alternatives system will automatically decide, as packages are installed and removed, whether and how to update the links. In manual mode, the alternatives system will retain the choice of the administrator and avoid changing the links (except when something is broken).
Link groups are in automatic mode when they are first introduced to the system. If the system administrator makes changes to the system's automatic settings, this will be noticed the next time update-alternatives is run on the changed link's group, and the group will automatically be switched to manual mode.
user
Use the user plugin to delete, create, or set passwords for users
Arguments
- userlist — Value is a /path/to/file with a list of "commands". See the discussion below
- Syntax: userlist=/path/to/file
- log — Value is a /path/to/file on the host system where the log is to be created. NOTE: The log is written in Phase 0, while the actual user management is done in Phase 1, except for setting Samba passwords, which is done in the post-install phase.
- Syntax: log=/path/on/host/to/logfile
- adduser — Add the specified user
- Syntax:
adduser=username
- Syntax:
- deluser — Delete the specified user
- Syntax:
deluser=username
- Syntax:
- setpassword — Set the password for the specified user. The user must already exist
- Syntax:
setpassword=username|password=newpassword
- Syntax:
- addgroup — Add a new group
- Syntax:
addgroup=groupname,gid
- Syntax:
- homedir — Specify the home directory for a new user. Default is /home/username. A home directory will not be created if
nohomediris specified- Syntax:
homedir=/home/not-the-usual-place
- Syntax:
- uid — Force the new user's ID to be the given number Default is the next uid to be assigned
- Syntax:
uid=name-or-number
- Syntax:
- password — Specify the password for
adduserandsetpassword- Syntax:
password=topsecretpassword
- Syntax:
- password-hash — Specify a hashed password for
adduser. Create the hashed password withmkpasswd --method=SHA=512 --rounds=4096 password - password-plain — Synonym for the
passwordargument - nohomedir — Do not create a home directory for this user
- Syntax:
nohomedir
- Syntax:
- noskel — Do not copy /etc/skel files to the newly-created login directory
- Syntax:
noskel
- Syntax:
- nochown — Do not set the home directory file ownership. Useful for home directories that need to be secured from their users
- Syntax:
nochown
- Syntax:
- Group — Set the initial login group
- Syntax:
Group=primary-group-name
- Syntax:
- groupadd — Augment the user's groups (see
groupsargument) with these. See discussion below- Syntax:
groupadd=groups,to,add
- Syntax:
- groups — Set the list of groups for a user. If not specified,
--groupsis used, with the default:
users,adm,dialout,audio,netdev,video,plugdev,cdrom,games,input,gpio,spi,i2c,render,sudo
- prompt — Prompt for the user's password
- Syntax:
prompt
- Syntax:
- rootpwd — Set the root account password to this user's password
- Syntax:
rootpwd
- Syntax:
- redact — At the end of
userplugin processing, redact all passwords- Syntax:
redact
- Syntax:
- nosudo — Do not enable this account for password-less
sudo. If you want to remove sudo capability completely for a user, use the commandgpasswd --delete user sudoin an easily-created personal plugin.- Syntax:
nosudo
- Syntax:
- linger — Enable service lingering for this user
- Syntax:
linger
- Syntax:
- samba — Set a Samba username and password for this user
- Syntax:
samba
- Syntax:
- smbpasswd — Use the provided password for the Samba password instead of the user's password
- Syntax:
smbpasswd=smbpasswdforuser
- Syntax:
- shell — Set the user's shell
- Syntax:
shell=/sbin/nologin
- Syntax:
Overview and handling multiple accounts
Conceptually, each invocation of the user plugin, or each line in a userlist file, consists of a verb or directive and some arguments. Verbs are:
adduser— Adds the user as described by the rest of the argumentsdeluser— Deletes the specified usersetpassword— Set the user's passwordaddgroup— Add a new group
So, some example lines in a userlist (or each set of arguments for several --plugin user command line switches) are:
deluser=pi
addgroup=myhomegroup,7654
addgroup=demousers
adduser=bls|uid=4321|password=mypassword|groupadd=myhomegroup|Group=users
adduser=demo1|prompt|nohomedir|groups=demousers|nosudo
adduser=demo2|nohomedir|groups=demousers|nosudo|prompt
adduser=demo3|nosudo
setpassword=demo3|password=thenewpassword
In the above
-
The pi account will be deleted, if it exists
-
The two groups will be added.
myhomegroupwill have gid 7654. -
The user
blsaccount will be created with the specifiedGroup, and a default login group ofusers. The groupmyhomegroupwill be added to the default set of groups (--groupsor the plugingroupargument). -
The user
demo1will be created with no home directory. The groupdemouserswill be added to the default set of groups for this user. sdm will prompt for the password. -
The user
demo2will be created, sdm will prompt for the password -
The user
demo3will be created and a home directory /home/demo3 will be created -
sdm will set the password for demo3 as a separate step (this is not necessary, btw; one could use the
password=argument on the demo3 line)The plugin will prompt for the user's password
The above userlist can be equivalently placed on the command line:
--plugin user:"deluser=pi" \
--plugin user:"addgroup=myhomegroup,7654" \
--plugin user:"addgroup=demousers" \
--plugin user:"adduser=bls|uid=4321|password=mypassword|groupadd=myhomegroup|Group=users" \
--plugin user:"adduser=demo1|prompt|nohomedir|groups=demousers" \
--plugin user:"adduser=demo2|nohomedir|groups=demousers|nosudo|prompt" \
--plugin user:"adduser=demo3|nosudo" \
--plugin user:"setpassword=demo3|password=thenewpassword"
Plugins are run in the order they are specified on the command line. I recommend that the user plugin be as close to the first plugin run as possible, so that the first created user ($myuser) is available to other plugins.
Notes
- If you add any users and/or add a password for the user
piyou probably don't want the RasPiOS services to run at first system boot that help you configure a user. That is exactly what this plugin does, so you can and should disable the RasPiOS services with--plugin disables:piwiz. - If you want to set a username or password that contains the dollar sign (
$) special treatment is required:
venv
Use the venv plugin to do perform one or two python virtual environment (venv) functions:
- Optionally create and populate the venv. If you want to create the venv use one of
createorcreateif. The venv will be crated and populated. - Optionally pip install one or more packages via
install,requirements, or both
Arguments
path is required. All other arguments are optional.
- chown — Set the
owner:groupof all files in the created venv as specified by thechownvalue - create — Create the venv at the provided path. Fail if it already exists.
- createif — Create the venv at the provided path if it doesn't exist. Fail if it already exists and is not a venv ($path/pyenv.cfg doesn't exist)
- createoptions — Switches to add to the
python -m venvcommand (e.g.,--system-site-packages; see Creating virtual environments) - install — Comma-separated list of pip modules to install
- installoptions — Switches to add to the
pip installcommand (seesudo pip install --help | less) - list — After the venv has created, list the installed modules with
pip listto the console and /etc/sdm/history - path — Path to venv directory specifies the path to the venv
- requirements — /path/to/requirements-file. See Requirements file format
- runphase — Specify the phase when the venv should be created. Values are
phase1orpost-install[D:phase1] - pyver — Specify the python version. Not currently used, and set to "3"
- name — Name to use for the venv asset storage. Default is the filename of the
path. Must be used if, for instance two venv invocations create venvs with the same directory name in the same IMG customization
NOTES:
- The venv is always created by root. Use the
chownargument to set different file ownership --requirementand--constraintare not supported in requirements.txt files. Use-rand/or-c- If provided, a requirements file may use
-rand/or-c. Those files, however, may NOT have any further nesting.
Examples
--plugin venv:"path=/usr/local/bin/myvenv|create|install=urllib3,requests"— Installs modulesurllib3andrequests--plugin venv:"path=/home/bls/myvenv|create|list|chown=bls:users|install=urllib3,requests|requirements=/ssdy/work/myrqs.txt"— Installs modulesurllib3,requestsand any modules listed in the requirements.txt file.
vnc
Install and configure either or both of Virtual VNC and RealVNC.
Arguments
- vncbase=port — Starting port for VNC Servers (default: 5900)
- realvnc=resolution — Install RealVNC server with the specified resolution on the console. The resolution is optional.
- tigervnc=res1,res2,...resn — Install tigervnc server with virtual VNC servers for the specified resolutions
- tightvnc=res1,res2,...resn — Install tightvnc server with virtual VNC servers for the specified resolutions
- wayvnc[=res] — Enable wayvnc server. If resolution is specified, set it has the Wayland headless resolution
Only one of tigervnc or tightvnc can be installed and configured on a system by sdm.
Examples
--plugin vnc:"realvnc|tigervnc=1280x1024,1600x1200"— Install RealVNC server for the console and tigervnc virtual desktop servers for the specified resolutions.--plugin vnc:"realvnc=1600x1200"— Install RealVNC server and configure the console for 1600x1200, just as raspi-config VNC configuration does.--plugin vnc:"tigervnc=1024x768,1600x1200,1280x1024"— Install tigervnc virtual desktop servers for the specified resolutions. Only configure RealVNC if it is already installed (e.g., RasPiOS with Desktop IMG).
Additional details
By default Virtual VNC desktops are configured with ports 5901, 5902, ... This can be modified with the --vncbase base switch. For instance, --vncbase 6400 would place the VNC virtual desktops at ports 6401, 6402, ... Setting --vncbase does not change the RealVNC server port.
For RasPiOS Desktop, RealVNC Server will be enabled automatically. Well, actually, it will be disabled for the first boot of the system as will the graphical desktop, and the sdm FirstBoot service will-reenable both for subsequent use.
For RasPiOS Lite, if the nodmconsole keyword is specified to the graphics plugin AND the Display Manager is xdm or wdm, the Display Manager will not be started on the console, and neither will RealVNC Server. It can be started later, if desired, with sudo systemctl enable --now vncserver-x11-serviced. Note, however, that you must enable the Display Manager as well for it to really be enabled. To enable the Display Manager:
- xdm:
sed -i "s/\#\:0 local \/usr\/bin\/X :0 vt7 -nolisten tcp/\:0 local \/usr\/bin\/X :0 vt7 -nolisten tcp/" /etc/X11/xdm/Xservers - wdm:
sed -i "s/\#\:0 local \/usr\/bin\/X :0 vt7 -nolisten tcp/\:0 local \/usr\/bin\/X :0 vt7 -nolisten tcp/" /etc/X11/wdm/Xservers
wificonfig
wificonfig is used to enable the sdm Captive Portal to delay WiFi SSID/Password configuration until the first system boot.
Arguments
- apssid=APSSID —SSID for the Access Point. Default: sdm
- apip=ap.ip.ad.dr —IP Address for the Access Point. Default: 10.1.1.1
- country=cc —Two-letter WiFi country code. The codes are found in /usr/share/zoneinfo/iso3166.tab
- defaults=/path/to/defaults —Path to defaults file. See Defaults file for details
- facility=facname —Facility name. Default: sdm
- retries=n —Maximum number of retries for the user to set the SSID/Password. Default: 5
- timeout=n —Captive Portal timeout (interval between network packets from the connecting device). Default: 900 seconds (15 minutes)
- wifilog=/path/to/wifilog —Log file for the Captive Portal. Default: /etc/sdm/wifi-config.log
wireguard
The wireguard plugin simplifies and scripts the configuration of Wireguard endpoints. The plugin design is oriented around easily configuring a two-node Wireguard VPN but it can be used for general wireguard host configuration as well.
Arguments
- address — Specifies the IP address for this end of the tunnel. In the form x.x.x.x/24, e.g., 10.1.10.1/24
- allowed-ips — Specifies the remote IP addresses that can access the tunnel. Typically this will include the remote host's tunnel IP address (e.g., 10.1.10.2/24) and the remote host's LAN IP address (192.168.44.10/24)
- addpeer — Add a Peer section to an existing interface configuration. Settings supported:
allowed-ips,endpoint,remote-public-key,generate-remote-keys,preshared-key,persistent-keepalive - dns — Specify the DNS server for the tunnel peer(s). Typically a DNS server on the host's LAN or a public DNS server (1.1.1.1, 8.8.8.8, etc)
- endpoint — Specify the remote endpoint DNS name or IP address, and port in the form dns-or-name:port (e.g., myhost.domain.com:51820 or 44.44.44.44:51820)
- generate-host-keys — Generate host public and private keys for this interface. Conflicts with
import-public-keyandimport-private-key - generate-remote-keys — Generate remote keys for this
addpeer. Conflicts withimport-public-keyon anaddpeerpeer configuration - import-private-key — Import a host's private key specified by /path/to/private-key. Conflicts with
generate-host-keyson an interface definition - import-public-key — Import a host's public key specified by /path/to/public-key. Conflicts with
generate-host-keyson an interface definition - ipforward — Enable IP forwarding on this host onto the LAN (See below for details)
- listen-port — Port on which wireguard should listen [D:51820]
- persistent-keepalive — See the section NAT and Firewall Traversal Persistence for details on
persistent-keepalive - preshared-key — Specify a pre-shared key for a peer. Both peers must share the same key
- preup — Command to run immediately prior to a connection starting
- predown — Command to run immediately prior to a connection terminating
- postup — Command to run immediately after a connection is started
- postdown — Command to run immediately after a connection is terminated
- remote-public-key — Provide the public key for a remote host in the form /path/to/remote.public-key
- svcenable — Enable the connection
- wghostname — Provide a hostname to use for the host keys instead of the connection name [D:copied from
wgname] - wgname — Specify the connection name [D:wg0]
Notes
Use ipforward on a host if you want the remote host to have access to other hosts on this host's LAN.
ipforward=nftables,ipforward=yor simplyipforward— Enable IP forwarding withnftablesand enablenet.ipv4.ip_forward=1ipforward=iptables— Use iptables rules instead of nftables
In each of the above cases, postup and postdown settings are configured for nftables or iptables as appropriate.
The default preup/postup/predown/postdown settings can be overridden by specifying any one of them. In that case, all that should be set must be specified.
In all the above cases, net.ipv4.ip_forward is set, and the system will route wireguard packets for this wireguard interface to the LAN
Examples
Creating a fully-configured Wireguard interface requires two unique invocations of the wireguard plugin. The first time defines the interface (e.g., wg0), and the second (and others, if desired) defines the Wireguard peer using the addpeer argument.
See this detailed guide for information on the 3 different strategies for configuring wireguard keys, and fully-functional examples.
wsdd
wsdd is the Web Service Discovery host daemon. It's very useful in Windows/Samba environments. You can read about it at https://github.com/christgau/wsdd
Note that wsdd is available in Bookworm via apt, so this plugin is not needed on Bookworm (Debian 12) or later, although it can still be used if you prefer.
Arguments
- wsddswitches=switchlist — List of switches to write into /etc/default/wsdd
- localsrc=/path/to/files — Local directory with cached copy of wsdd (files: wsdd.py wsdd.8 wsdd.defaults wsdd.service)
x11
The x11 plugin installs the core X11 packages, and optionally installs a Display Manager, and Window Manager.
Arguments
- apps=list,of,packages — List of additional packages to install
- dm=displaymanager — Name of display manager package. Known display managers include
lightdm,wdm, andxdm, but this is not checked - fonts=list,of,font,packages — List of X11 font packages to install in addition to the default font packages (
xfonts-base,xfonts-100dpi,xfonts-75dpi,xfonts-scalable) - nodmconsole — Do not enable the display manager on the system console
- wm=windowmanager — name of window manager package. There are many to choose from!
Notes
- If either
dmorwmis not specified,nodmconsolewill be set. - The x11 plugin ensures a non-graphical console mode for FirstBoot if a known display manager (
lightdm,wdm, andxdm) is installed, and then enables graphical console (if requested), providing more visbility into the first boot process. - The x11 plugin does not do any special configuration for any display manager beyond delaying the graphical console to after Firstboot for
lightdm,wdm, andxdm. Both wdm and xdm just work. It appears that furherlightdmconfiguration is required beyond the basic install, and is not provided by this plugin.
Examples
- `--plugin x11:"dm=xdm|wm=icewm" — Install X11 with the default set of fonts with the xdm display manager and icewm window manager.