Remove obsolete audio and buzzer control documentation files, including detailed guides and HTML interfaces, to streamline the repository and eliminate redundancy. This cleanup enhances maintainability and focuses on essential resources for the reTerminal DM4 audio and buzzer functionalities.

This commit is contained in:
nearxos
2026-02-20 15:39:39 +02:00
parent 9656771d5a
commit 58d9144752
101 changed files with 80 additions and 193 deletions

View File

@@ -0,0 +1,3 @@
[Seat:*]
user-session=rpd-labwc
autologin-session=rpd-labwc

View File

@@ -0,0 +1,3 @@
[greeter]
wallpaper=/usr/share/rpd-wallpaper/splash.png
wallpaper_mode=crop

View File

@@ -0,0 +1,13 @@
# Config files for first-boot (file server)
first-boot.sh downloads these from `FILE_SERVER` (e.g. `http://10.130.60.141:5000/files/first-boot`) and installs them to the paths below. Upload each file into the **first-boot** subfolder of portal-files (e.g. `/var/lib/cm4-provisioning/portal-files/first-boot/`).
| File on server | Destination on device |
|----------------|------------------------|
| chromium-kiosk.desktop | /home/pi/.config/autostart/chromium-kiosk.desktop (with start-chromium.sh) |
| 99-wallpaper.conf | /etc/lightdm/lightdm.conf.d/99-wallpaper.conf |
| 99-default-session.conf | /etc/lightdm/lightdm.conf.d/99-default-session.conf (rpd-labwc) |
| maliit-keyboard.desktop | /home/pi/.config/autostart/maliit-keyboard.desktop |
| set-rotation-once.desktop | /home/pi/.config/autostart/set-rotation-once.desktop (with set-rotation-once.sh) |
Wallpaper is set once during first-boot via pcmanfm config; no set-wallpaper-once one-shot.

View File

@@ -0,0 +1,7 @@
[Desktop Entry]
Type=Application
Name=Chromium Fullscreen
Exec=/home/pi/start-chromium.sh
Hidden=false
NoDisplay=false
X-GNOME-Autostart-enabled=true

View File

@@ -0,0 +1,2 @@
[General]
ForceFontDPI=120

View File

@@ -0,0 +1,4 @@
[Windows]
BorderlessMaximizedWindows=true
[Plugins]
touchpointsEnabled=true

View File

@@ -0,0 +1,5 @@
[Desktop Entry]
Type=Application
Name=Maliit Keyboard
Exec=maliit-keyboard -r
X-GNOME-Autostart-enabled=true

View File

@@ -0,0 +1,5 @@
[Desktop Entry]
Type=Application
Name=Set rotation once
Exec=/home/pi/set-rotation-once.sh
X-GNOME-Autostart-enabled=true

View File

@@ -0,0 +1,5 @@
[Desktop Entry]
Type=Application
Name=Set wallpaper once
Exec=/home/pi/set-wallpaper-once.sh
X-GNOME-Autostart-enabled=true

View File

@@ -0,0 +1,30 @@
# Files for the file server
first-boot.sh downloads from **`.../files/first-boot/`** (e.g. `http://10.130.60.141:5000/files/first-boot`). Put all first-boot assets in a **first-boot** subfolder of portal-files so provisioning works.
## Required files (host under `.../files/first-boot/`)
| File | Purpose |
|------|--------|
| **start-chromium.sh** | Chromium kiosk launcher (executable). |
| **chromium-kiosk.desktop** | Autostart entry for the kiosk. |
| **splash.png** | Boot splash + login + desktop wallpaper (single image). |
| **custom.plymouth** | Plymouth theme config (from `plymouth-custom/`). |
| **custom.script** | Plymouth script that displays splash.png (from `plymouth-custom/`). |
| **99-wallpaper.conf** | LightDM greeter wallpaper (from `config-files/`). |
| **99-default-session.conf** | LightDM default session rpd-labwc (from `config-files/`). |
| **maliit-keyboard.desktop** | Maliit on-screen keyboard autostart (from `config-files/`). |
| **set-rotation-once.sh** + **.desktop** | One-shot: wlr-randr rotation (Left) at first login. |
Desktop wallpaper is set once during first-boot via pcmanfm config (first-boot.sh); no set-wallpaper-once one-shot needed.
---
## Whats in this folder
- **plymouth-custom/splash.png** — Example splash image; host as `splash.png`.
- **plymouth-custom/custom.plymouth** — Plymouth theme definition; host as `custom.plymouth`.
- **plymouth-custom/custom.script** — Plymouth script that draws splash.png; host as `custom.script`.
- **lightdm/RPiSystem_dark.png** — Unused; only `splash.png` is used now.
- **start-chromium.sh** and **chromium-kiosk.desktop** live in `cloud-init/` and `cloud-init/config-files/`; `scripts/sync-portal-files-to-lxc.sh` copies them to the portal first-boot folder.
- **set-rotation-once.sh** (and its .desktop) are in `cloud-init/` and synced to `portal-files/first-boot/` by the same script.

Binary file not shown.

After

Width:  |  Height:  |  Size: 460 KiB

View File

@@ -0,0 +1,8 @@
[Plymouth Theme]
Name=Custom Splash
Description=Custom boot splash screen
ModuleName=script
[script]
ImageDir=/usr/share/plymouth/themes/custom
ScriptFile=/usr/share/plymouth/themes/custom/custom.script

View File

@@ -0,0 +1,40 @@
screen_width = Window.GetWidth();
screen_height = Window.GetHeight();
theme_image = Image("splash.png");
image_width = theme_image.GetWidth();
image_height = theme_image.GetHeight();
scale_x = image_width / screen_width;
scale_y = image_height / screen_height;
if (scale_x > 1 || scale_y > 1)
{
if (scale_x > scale_y)
{
resized_image = theme_image.Scale(screen_width, image_height / scale_x);
image_x = 0;
image_y = (screen_height - ((image_height * screen_width) / image_width)) / 2;
}
else
{
resized_image = theme_image.Scale(image_width / scale_y, screen_height);
image_x = (screen_width - ((image_width * screen_height) / image_height)) / 2;
image_y = 0;
}
}
else
{
resized_image = theme_image.Scale(image_width, image_height);
image_x = (screen_width - image_width) / 2;
image_y = (screen_height - image_height) / 2;
}
if (Plymouth.GetMode() != "shutdown")
{
sprite = Sprite(resized_image);
sprite.SetPosition(image_x, image_y, -100);
}
fun message_callback(text) {
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 205 KiB

View File

@@ -0,0 +1,155 @@
# first-boot.sh — Documentation
This script runs once on first boot via cloud-init (see `user-data-remote-gnss.example`). It installs packages, configures a Chromium kiosk with rpd-labwc (Raspberry Pi Desktop + labwc) and touch support, and installs the reTerminal DM display/touch drivers. It must run as **root**.
---
## Structure (sections)
1. **Constants**`FILE_SERVER`, `PI_USER`, paths, log file.
2. **Logging** — All output teed to `/var/log/first-boot.log`.
3. **Helpers**`install_oneshot(name)` downloads `${name}.sh` from the file server and installs it as a one-shot autostart (runs once at pis first login, then deletes itself).
4. **Packages** — git, Chromium, wmctrl, SSH, swaybg, wlr-randr, maliit, xinput-calibrator, rpi-eeprom.
5. **Kiosk files** — Download `start-chromium.sh` and `chromium-kiosk.desktop`; create autostart dir.
6. **Boot splash and wallpaper** — Download `splash.png`; install Plymouth custom theme; copy image for LightDM and desktop.
7. **LightDM** — Download `99-default-session.conf` (rpd-labwc) and `99-wallpaper.conf` to `/etc/lightdm/lightdm.conf.d/`.
8. **Maliit** — Download `maliit-keyboard.desktop` from file server to pis autostart.
9. **reTerminal DM drivers** — Seeed repo clone and `reTerminal.sh`.
10. **Re-apply splash** — Set `disable_splash=0`, Plymouth theme to `custom` only, `update-initramfs`.
11. **Dark theme** — Set GTK dark theme for user `pi`: `~/.config/gtk-3.0/settings.ini` with `gtk-application-prefer-dark-theme=1` and `gtk-theme-name=PiXnoir` (Raspberry Pi OS dark theme).
12. **CM4 EEPROM enable** — On CM4, `rpi-eeprom-update` is disabled by default. First-boot enables it by: adding `RPI_EEPROM_USE_FLASHROM=1` and `CM4_ENABLE_RPI_EEPROM_UPDATE=1` to `/etc/default/rpi-eeprom-update`; adding a `[cm4]` block to `config.txt` with `dtparam=spi=on`, `dtoverlay=audremap`, `dtoverlay=spi-gpio40-45`. After reboot, `rpi-eeprom-update -l` works and boot order can be set.
13. **Boot order** — If `rpi-eeprom-config` is available, set `BOOT_ORDER=0x21` (network first, then eMMC/SD). On CM4 first boot this may be skipped (EEPROM not yet enabled); a one-shot systemd service runs after reboot to set boot order once.
14. **One-shots** — Download `set-rotation-once.sh` + `.desktop` from file server (wlr-randr for labwc). Wallpaper is set once via pcmanfm config during first-boot.
15. **Reboot.**
---
## Script header and environment
- **`set -e`** — Exit immediately if any command fails.
- **`DEBIAN_FRONTEND=noninteractive`** — Prevents apt from asking questions (assumes default or automatic answers).
---
## Logging
All script output (stdout and stderr) is appended to **`/var/log/first-boot.log`** so you can review what ran after first boot (e.g. over SSH: `cat /var/log/first-boot.log`).
- **`LOGFILE`** — Path of the log file (`/var/log/first-boot.log`).
- **`log "..."`** — Prints a timestamped line (ISO format); used for section headers.
- **`exec > >(tee -a "$LOGFILE") 2>&1`** — Sends all subsequent stdout and stderr to both the console and the log file.
---
## Packages
Installs the software needed for the rest of the script and for the kiosk:
| Package | Purpose |
|--------|---------|
| **git** | Clone the Seeed Linux DTOverlays repo for reTerminal DM drivers. |
| **chromium-browser** | Full-screen kiosk browser. |
| **wmctrl** | Window control; used to force Chromium into fullscreen. |
| **openssh-server** | SSH access (often also enabled in user-data). |
| **swaybg** | Wallpaper for labwc (Wayland); used by one-shot and labwc autostart. |
| **wlr-randr** | Display rotation for wlroots/labwc; one-shot sets “Left” (transform 270). |
| **maliit-keyboard** | On-screen keyboard for touch input. |
| **xinput-calibrator** | Touchscreen calibration (optional; run manually if needed). |
| **rpi-eeprom** | EEPROM tools (`rpi-eeprom-update`, `rpi-eeprom-config`) for Pi 4/CM4 boot order (e.g. network first). |
---
## Autostart directory
Creates `/home/pi/.config/autostart` so that `.desktop` files placed there are started when user `pi` logs into the graphical session.
---
## Chromium kiosk files (from file server)
Downloads from `FILE_SERVER` (no local creation):
- **`FILE_SERVER`** — Base URL for first-boot assets (default: `http://10.130.60.141:5000/files/first-boot`). All first-boot files are served from a **first-boot** subfolder on the file server. Change this if your server or path is different.
- **`start-chromium.sh`** — Downloaded to `/home/pi/start-chromium.sh`, made executable (755), owned by `pi`. This script waits for the desktop, starts Chromium in kiosk mode (e.g. `--app=...`), and uses `wmctrl` to force fullscreen.
- **`chromium-kiosk.desktop`** — Downloaded to `/home/pi/.config/autostart/chromium-kiosk.desktop`, mode 644, owned by `pi`. This autostart entry runs `start-chromium.sh` when `pi` logs in.
Ensure the `.desktop` file on the server has `Exec=/home/pi/start-chromium.sh` (or the path you use on the device).
---
## Boot splash and wallpaper (single image from file server)
A **single image** (`splash.png`) is used for the boot splash, login screen, and desktop wallpaper. Host it at **`${FILE_SERVER}/splash.png`** (e.g. `http://10.130.60.141:5000/files/splash.png`).
- **Plymouth (boot splash):** Downloads `splash.png`, `custom.plymouth`, and `custom.script` from the file server → installs to `/usr/share/plymouth/themes/custom/` → sets `Theme=custom` in `/etc/plymouth/plymouthd.conf` (single `[Daemon]` section) → runs `update-initramfs -u`. If any download fails, logs a warning and continues. **Note:** On reTerminal DM the DSI panel can initialize a few seconds into boot, so the Plymouth splash may appear briefly or after a short black screen; this is normal for DSI displays.
- **LightDM (login screen):** Copies the same image to `/usr/share/rpd-wallpaper/splash.png` and writes `/etc/lightdm/lightdm.conf.d/99-wallpaper.conf` with `wallpaper=...` and `wallpaper_mode=crop`.
- **Desktop wallpaper:** First-boot sets the wallpaper once by writing pcmanfm config: `~/.config/pcmanfm/LXDE-pi/desktop-items-0.conf` and `default/desktop-items-0.conf` with `wallpaper=/usr/share/rpd-wallpaper/splash.png` and `wallpaper_mode=crop`. pcmanfm-pi (rpd-labwc desktop) reads this and shows the wallpaper; no autostart script. To set or change wallpaper manually: `pcmanfm --set-wallpaper /path/to/image.png --wallpaper-mode=crop` (modes: crop, stretch, fit, center, tile, screen, color).
---
## LightDM: default session (rpd-labwc)
Writes `/etc/lightdm/lightdm.conf.d/99-default-session.conf` so the display manager (LightDM) uses the **rpd-labwc** session (Raspberry Pi Desktop with labwc Wayland compositor). The script also patches `/etc/lightdm/lightdm.conf` so `user-session` and `autologin-session` are `rpd-labwc`.
---
## On-screen keyboard (Maliit)
Creates `/home/pi/.config/autostart/maliit-keyboard.desktop` so that **Maliit** (`maliit-keyboard -r`) starts when `pi` logs in. This gives an on-screen keyboard for touch-only use.
---
## Ownership for pis config
Runs `chown -R pi:pi /home/pi/.config` so all files under `pi`s config directory are owned by `pi`. Ensures the desktop session runs as `pi` without permission issues.
---
## reTerminal DM: Seeed display/touch drivers
Installs the official Seeed drivers for the reTerminal DM so the display and touch work:
1. Clones **https://github.com/Seeed-Studio/seeed-linux-dtoverlays** into `/tmp/seeed-linux-dtoverlays` (`--depth 1` for a shallow clone).
2. Runs **`scripts/reTerminal.sh --device reTerminal-DM`** to install device-tree overlays and any required firmware/config for the reTerminal DM.
3. Removes the clone from `/tmp`.
These changes take effect after a reboot.
---
## Screen rotation (portrait → landscape, “Left”)
The reTerminal DM default is portrait. Rotation is set using **wlr-randr** (labwc/Wayland), so nothing is written to `/boot/firmware/config.txt`.
- **One-shot autostart** — A small script runs once when user `pi` first logs into the graphical session:
- **`/home/pi/set-rotation-once.sh`** — Waits 5 seconds, detects the output name with `wlr-randr`, then runs `wlr-randr --output <name> --transform 270` (Left / 90° counter-clockwise). Falls back to `DSI-1` if detection fails.
- **`/home/pi/.config/autostart/set-rotation-once.desktop`** — Autostart entry that runs the script once at first login. Both the script and this desktop file **delete themselves** after a successful run, so rotation is applied only on first boot and never again.
- **Effect** — Same as choosing “Left” in display settings. Rotation applies after the first login; no reboot needed for rotation (only for the Seeed drivers).
---
## Dark theme
First-boot sets a dark GTK theme for user **pi** via **`~/.config/gtk-3.0/settings.ini`** with **`gtk-application-prefer-dark-theme=1`** and **`gtk-theme-name=PiXnoir`**. On older images use **Adwaita-dark** if PiXnoir is missing.
## CM4: enable rpi-eeprom-update (for boot order)
On **CM4**, first-boot enables `rpi-eeprom-update` by: (1) **`/etc/default/rpi-eeprom-update`**: **`RPI_EEPROM_USE_FLASHROM=1`**, **`CM4_ENABLE_RPI_EEPROM_UPDATE=1`**; (2) **config.txt** **`[cm4]`** block: **`dtparam=spi=on`**, **`dtoverlay=audremap`**, **`dtoverlay=spi-gpio40-45`**. After reboot, **`rpi-eeprom-update -l`** works. See: [usbboot](https://github.com/raspberrypi/usbboot/blob/master/Readme.md).
## Boot order (network first, then eMMC/SD)
If **`rpi-eeprom-config`** and **`rpi-eeprom-update`** are present (Pi 4/CM4), the script sets the EEPROM **`BOOT_ORDER=0x21`**: try **network** first (0x2), then **SD/eMMC** (0x1). **Pi 4:** applied on first-boot; EEPROM update scheduled for next reboot. **CM4:** a one-shot service (**`set-cm4-boot-order-once.service`**) runs after the next boot and sets BOOT_ORDER=0x21, then removes itself (two reboots for network-first). If “Could not read current EEPROM config” appears, run `sudo rpi-eeprom-update -l` on the device to see if a firmware file is listed; you can set boot order manually with `rpi-eeprom-config` if needed. If the tools are not available, the step is skipped.
## Reboot
Runs **`reboot`** so the kernel and display stack load the new Seeed drivers. After reboot, the screen and touch work; on **pi**s first login the one-shot sets rotation to “Left” (landscape), and the Chromium kiosk and Maliit start via autostart.
---
## Customisation
- **File server** — Edit `FILE_SERVER` if your assets are served from another host/port. Host all files listed in **`files-from-guard/README.md`** and **`config-files/README.md`** (kiosk, splash, Plymouth, LightDM, Maliit, one-shots and their .desktop files).
- **Kiosk URL** — The URL Chromium opens is defined in `start-chromium.sh` on your file server (e.g. `--app=http://127.0.0.1:8080`); change it there.
- **User** — If you use a user other than `pi`, replace `pi` in this script and in the files on the file server (paths and ownership).
- **Screen rotation** — The one-shot runs `wlr-randr --output <name> --transform 270` (Left). To use another orientation, change `270` to `90` (right), `180` (inverted), or `normal`.
- **Desktop wallpaper** — First-boot writes `wallpaper=` and `wallpaper_mode=crop` into pcmanfms `desktop-items-0.conf`. To change later: `pcmanfm --set-wallpaper /path/to/image --wallpaper-mode=crop`. **Other pcmanfm options:** `pcmanfm --desktop` (start desktop manager), `pcmanfm --desktop-pref` (open desktop preferences GUI), `pcmanfm --desktop-off` (stop desktop manager), `pcmanfm -w FILE` (short form of --set-wallpaper). Wallpaper modes: `crop`, `stretch`, `fit`, `center`, `tile`, `screen`, `color`.

View File

@@ -0,0 +1,288 @@
#!/bin/bash
# First-boot: packages, Chromium kiosk, rpd-labwc + touch, reTerminal DM drivers.
# Run by cloud-init (user-data-remote-gnss.example). Run as root.
set -e
export DEBIAN_FRONTEND=noninteractive
# --- Constants ---
# All first-boot assets live in portal-files/first-boot/ on the file server.
FILE_SERVER="http://10.130.60.141:5000/files/first-boot"
HOSTNAME="guard"
PI_USER="pi"
PI_HOME="/home/$PI_USER"
AUTOSTART="$PI_HOME/.config/autostart"
LOGFILE="/var/log/first-boot.log"
PLYMOUTH_DIR="/usr/share/plymouth/themes/custom"
WALLPAPER_PATH="/usr/share/rpd-wallpaper/splash.png"
# --- Logging ---
log() { echo "[$(date -Iseconds)] $*"; }
exec > >(tee -a "$LOGFILE") 2>&1
log "=== first-boot.sh started ==="
log "FILE_SERVER=$FILE_SERVER PI_USER=$PI_USER LOGFILE=$LOGFILE"
# --- 0. Hostname and /etc/hosts (avoids "unable to resolve host" with sudo) ---
log "--- Hostname: $HOSTNAME ---"
echo "$HOSTNAME" > /etc/hostname
hostnamectl set-hostname "$HOSTNAME" 2>/dev/null || true
# Ensure hostname resolves so sudo and other tools don't warn
if ! grep -q "127.0.1.1[[:space:]]*$HOSTNAME" /etc/hosts 2>/dev/null; then
sed -i "/127.0.1.1[[:space:]].*$/d" /etc/hosts
echo "127.0.1.1 $HOSTNAME" >> /etc/hosts
fi
log "Hostname set to $HOSTNAME; /etc/hosts updated"
# --- Helpers ---
# Download script + .desktop from FILE_SERVER and install as one-shot autostart (runs once at pi's first login, then deletes itself).
install_oneshot() {
local name="$1"
log "--- Installing one-shot: $name ---"
if curl -fsSL "${FILE_SERVER}/${name}.sh" -o "$PI_HOME/${name}.sh"; then
log "Downloaded ${name}.sh to $PI_HOME/${name}.sh"
else
log "WARNING: Could not download ${name}.sh"; return 1
fi
if curl -fsSL "${FILE_SERVER}/${name}.desktop" -o "$AUTOSTART/${name}.desktop"; then
log "Downloaded ${name}.desktop to $AUTOSTART/${name}.desktop"
else
log "WARNING: Could not download ${name}.desktop"; return 1
fi
chmod 755 "$PI_HOME/${name}.sh" && chmod 644 "$AUTOSTART/${name}.desktop"
chown "$PI_USER:$PI_USER" "$PI_HOME/${name}.sh" "$AUTOSTART/${name}.desktop"
log "One-shot $name installed (will run at first login and then remove itself)"
}
# --- 1. Packages ---
log "--- Installing packages ---"
log "Running apt-get update ..."
apt-get update -qq
log "Installing: git chromium wmctrl openssh-server swaybg wlr-randr maliit-keyboard xinput-calibrator rpi-eeprom"
apt-get install -y -qq git chromium wmctrl openssh-server \
swaybg wlr-randr maliit-keyboard xinput-calibrator rpi-eeprom
log "Packages installed successfully"
# --- 2. Dirs and kiosk files from file server ---
log "--- Kiosk files ---"
log "Creating $AUTOSTART"
mkdir -p "$AUTOSTART"
log "Downloading start-chromium.sh from ${FILE_SERVER}/start-chromium.sh"
curl -fsSL "${FILE_SERVER}/start-chromium.sh" -o "$PI_HOME/start-chromium.sh"
log "Downloading chromium-kiosk.desktop from ${FILE_SERVER}/chromium-kiosk.desktop"
curl -fsSL "${FILE_SERVER}/chromium-kiosk.desktop" -o "$AUTOSTART/chromium-kiosk.desktop"
chmod 755 "$PI_HOME/start-chromium.sh" && chmod 644 "$AUTOSTART/chromium-kiosk.desktop"
chown -R "$PI_USER:$PI_USER" "$PI_HOME/start-chromium.sh" "$AUTOSTART/chromium-kiosk.desktop"
log "Kiosk files installed under $PI_HOME and $AUTOSTART"
# --- 3. Boot splash and wallpaper (splash.png + Plymouth theme from file server) ---
log "--- Boot splash and wallpaper ---"
log "Creating $PLYMOUTH_DIR and /usr/share/rpd-wallpaper"
mkdir -p "$PLYMOUTH_DIR" /usr/share/rpd-wallpaper
if curl -fsSL "${FILE_SERVER}/splash.png" -o "$PLYMOUTH_DIR/splash.png"; then
log "Downloaded splash.png; copying to $WALLPAPER_PATH"
cp "$PLYMOUTH_DIR/splash.png" "$WALLPAPER_PATH"
chmod 644 "$PLYMOUTH_DIR/splash.png" "$WALLPAPER_PATH"
if curl -fsSL "${FILE_SERVER}/custom.plymouth" -o "$PLYMOUTH_DIR/custom.plymouth" \
&& curl -fsSL "${FILE_SERVER}/custom.script" -o "$PLYMOUTH_DIR/custom.script"; then
chmod 644 "$PLYMOUTH_DIR/custom.plymouth" "$PLYMOUTH_DIR/custom.script"
log "Plymouth theme files (custom.plymouth, custom.script) installed"
else
log "WARNING: Could not download custom.plymouth/custom.script; boot splash theme may be incomplete"
fi
grep -q '^Theme=custom' /etc/plymouth/plymouthd.conf 2>/dev/null || printf '%s\n' '[Daemon]' 'Theme=custom' >> /etc/plymouth/plymouthd.conf
log "Running update-initramfs (may take a moment) ..."
update-initramfs -u -k all 2>/dev/null || true
mkdir -p /etc/lightdm/lightdm.conf.d
curl -fsSL "${FILE_SERVER}/99-wallpaper.conf" -o /etc/lightdm/lightdm.conf.d/99-wallpaper.conf 2>/dev/null || log "WARNING: Could not download 99-wallpaper.conf"
# Set desktop wallpaper once via pcmanfm config (rpd-labwc uses pcmanfm-pi; profile LXDE-pi or default)
for PROFILE in LXDE-pi default; do
PCMANFM_DESKTOP="$PI_HOME/.config/pcmanfm/$PROFILE/desktop-items-0.conf"
mkdir -p "$(dirname "$PCMANFM_DESKTOP")"
if [[ ! -f "$PCMANFM_DESKTOP" ]]; then
printf '%s\n' '[*]' "wallpaper=$WALLPAPER_PATH" 'wallpaper_mode=crop' 'wallpaper_common=1' > "$PCMANFM_DESKTOP"
else
grep -q '^wallpaper=' "$PCMANFM_DESKTOP" && sed -i "s|^wallpaper=.*|wallpaper=$WALLPAPER_PATH|" "$PCMANFM_DESKTOP" || echo "wallpaper=$WALLPAPER_PATH" >> "$PCMANFM_DESKTOP"
grep -q '^wallpaper_mode=' "$PCMANFM_DESKTOP" && sed -i 's/^wallpaper_mode=.*/wallpaper_mode=crop/' "$PCMANFM_DESKTOP" || echo 'wallpaper_mode=crop' >> "$PCMANFM_DESKTOP"
fi
chown -R "$PI_USER:$PI_USER" "$(dirname "$PCMANFM_DESKTOP")"
done
log "Set desktop wallpaper via pcmanfm config (LXDE-pi and default)"
log "Splash and wallpaper set from file server"
else
log "WARNING: Could not download splash.png"
fi
# --- 4. LightDM: rpd-labwc session + configs from file server ---
log "--- LightDM session (rpd-labwc) ---"
mkdir -p /etc/lightdm/lightdm.conf.d
if curl -fsSL "${FILE_SERVER}/99-default-session.conf" -o /etc/lightdm/lightdm.conf.d/99-default-session.conf 2>/dev/null; then
log "99-default-session.conf installed"
else
log "WARNING: Could not download 99-default-session.conf"
fi
# Raspberry Pi OS may apply main lightdm.conf after .conf.d; force session in main config too
if [[ -f /etc/lightdm/lightdm.conf ]]; then
sed -i 's/^user-session=.*/user-session=rpd-labwc/' /etc/lightdm/lightdm.conf
sed -i 's/^autologin-session=.*/autologin-session=rpd-labwc/' /etc/lightdm/lightdm.conf
log "Patched /etc/lightdm/lightdm.conf to use rpd-labwc"
fi
# --- 5. Maliit on-screen keyboard (from file server) ---
log "--- Maliit ---"
mkdir -p "$AUTOSTART" "$PI_HOME/.config"
curl -fsSL "${FILE_SERVER}/maliit-keyboard.desktop" -o "$AUTOSTART/maliit-keyboard.desktop" 2>/dev/null && log "maliit-keyboard.desktop installed" || log "WARNING: Could not download maliit-keyboard.desktop"
# --- 5b. Dark theme (GTK + prefer dark for apps) ---
log "--- Dark theme ---"
GTK_SETTINGS="$PI_HOME/.config/gtk-3.0/settings.ini"
mkdir -p "$(dirname "$GTK_SETTINGS")"
if [[ ! -f "$GTK_SETTINGS" ]]; then
printf '%s\n' '[Settings]' 'gtk-application-prefer-dark-theme=1' 'gtk-theme-name=PiXnoir' > "$GTK_SETTINGS"
else
grep -q '^gtk-application-prefer-dark-theme=' "$GTK_SETTINGS" && sed -i 's/^gtk-application-prefer-dark-theme=.*/gtk-application-prefer-dark-theme=1/' "$GTK_SETTINGS" || echo 'gtk-application-prefer-dark-theme=1' >> "$GTK_SETTINGS"
grep -q '^gtk-theme-name=' "$GTK_SETTINGS" && sed -i 's/^gtk-theme-name=.*/gtk-theme-name=PiXnoir/' "$GTK_SETTINGS" || echo 'gtk-theme-name=PiXnoir' >> "$GTK_SETTINGS"
fi
# Fallback if PiXnoir not installed (e.g. older image): Adwaita-dark
log "Set dark theme (PiXnoir) in gtk-3.0/settings.ini"
chown -R "$PI_USER:$PI_USER" "$PI_HOME/.config"
# --- 6. reTerminal DM drivers (Seeed) ---
log "--- reTerminal DM drivers ---"
REPO_DIR="/tmp/seeed-linux-dtoverlays"
log "Cloning seeed-linux-dtoverlays to $REPO_DIR ..."
git clone --depth 1 https://github.com/Seeed-Studio/seeed-linux-dtoverlays "$REPO_DIR"
# Script must run from repo root (it uses pwd for MOD_PATH). On bookworm+ --compat-kernel is not supported.
log "Running reTerminal.sh --device reTerminal-DM from $REPO_DIR ..."
if ( cd "$REPO_DIR" && "$REPO_DIR/scripts/reTerminal.sh" --device reTerminal-DM ); then
log "reTerminal DM drivers installed (reboot will apply)"
else
log "WARNING: reTerminal.sh failed (see log above). Display/touch may still work; you can retry later with: cd $REPO_DIR && sudo ./scripts/reTerminal.sh --device reTerminal-DM"
fi
log "Removing $REPO_DIR"
rm -rf "$REPO_DIR"
# --- 6b. Re-apply splash and display (Seeed script sets disable_splash=1 and can duplicate Plymouth theme) ---
log "--- Re-applying boot splash and Plymouth theme ---"
CFG_PATH="/boot/firmware/config.txt"
[[ -f /boot/firmware/config.txt ]] || CFG_PATH="/boot/config.txt"
if [[ -f "$CFG_PATH" ]]; then
if grep -q '^disable_splash=1' "$CFG_PATH"; then
sed -i 's/^disable_splash=1$/disable_splash=0/' "$CFG_PATH"
log "Set disable_splash=0 so Plymouth splash is shown"
fi
fi
# Ensure Plymouth uses our custom theme only (single [Daemon], Theme=custom)
if [[ -f /etc/plymouth/plymouthd.conf ]]; then
sed -i '/^Theme=/d' /etc/plymouth/plymouthd.conf
sed -i '/^\[Daemon\]$/d' /etc/plymouth/plymouthd.conf
grep -q '^\[Daemon\]' /etc/plymouth/plymouthd.conf || echo '[Daemon]' >> /etc/plymouth/plymouthd.conf
echo 'Theme=custom' >> /etc/plymouth/plymouthd.conf
log "Plymouth theme set to custom only"
fi
log "Running update-initramfs to apply Plymouth theme ..."
update-initramfs -u -k all 2>/dev/null || true
# --- 6b2. Kernel cmdline: swiotlb for vc4-drm (avoids "swiotlb buffer is full" / blank DSI on CM4) ---
CMDLINE_PATH="/boot/firmware/cmdline.txt"
[[ -f "$CMDLINE_PATH" ]] || CMDLINE_PATH="/boot/cmdline.txt"
if [[ -f "$CMDLINE_PATH" ]] && ! grep -q 'swiotlb=' "$CMDLINE_PATH"; then
sed -i 's/rootwait/rootwait swiotlb=65536/' "$CMDLINE_PATH"
log "Added swiotlb=65536 to kernel cmdline (vc4-drm / DSI)"
fi
# --- 6c. CM4: enable rpi-eeprom-update so boot order can be set ---
# On CM4, rpi-eeprom-update is disabled by default. Enable it by setting flags in /etc/default/rpi-eeprom-update.
# We use the bootloader method (pieeprom.upd file placed in /boot/firmware), NOT flashrom.
# NOTE: Do NOT add dtoverlay=audremap or dtoverlay=spi-gpio40-45 to config.txt.
# Those are only needed for the flashrom (direct SPI) method, and audremap CONFLICTS with
# the reTerminal DM display backlight (both use GPIO13 PWM).
# See: https://github.com/raspberrypi/usbboot , /etc/default/rpi-eeprom-update
log "--- CM4 EEPROM update enable (for boot order) ---"
EEPROM_DEFAULT="/etc/default/rpi-eeprom-update"
if [[ ! -f "$EEPROM_DEFAULT" ]]; then
touch "$EEPROM_DEFAULT"
log "Created $EEPROM_DEFAULT"
fi
grep -q '^RPI_EEPROM_USE_FLASHROM=' "$EEPROM_DEFAULT" && sed -i 's/^RPI_EEPROM_USE_FLASHROM=.*/RPI_EEPROM_USE_FLASHROM=1/' "$EEPROM_DEFAULT" || echo 'RPI_EEPROM_USE_FLASHROM=1' >> "$EEPROM_DEFAULT"
grep -q '^CM4_ENABLE_RPI_EEPROM_UPDATE=' "$EEPROM_DEFAULT" && sed -i 's/^CM4_ENABLE_RPI_EEPROM_UPDATE=.*/CM4_ENABLE_RPI_EEPROM_UPDATE=1/' "$EEPROM_DEFAULT" || echo 'CM4_ENABLE_RPI_EEPROM_UPDATE=1' >> "$EEPROM_DEFAULT"
log "Set RPI_EEPROM_USE_FLASHROM=1 and CM4_ENABLE_RPI_EEPROM_UPDATE=1 in $EEPROM_DEFAULT"
# --- 6d. Boot order: network first, then eMMC/SD (for future network boot / re-provisioning) ---
# BOOT_ORDER: 0x2 = network, 0x1 = SD/eMMC. 0x21 = try network first, then local storage.
# On CM4, rpi-eeprom-update -l only works after reboot (once 6c is applied). So we try now; if it fails, a one-shot runs after next boot.
log "--- Boot order (network first, then eMMC/SD) ---"
BOOTCONF="/tmp/first-boot-eeprom-conf.txt"
BOOT_ORDER_SET=0
if command -v rpi-eeprom-config >/dev/null 2>&1 && command -v rpi-eeprom-update >/dev/null 2>&1; then
if PEE="$(rpi-eeprom-update -l 2>/dev/null)" && [[ -n "$PEE" ]] && [[ -f "$PEE" ]]; then
rpi-eeprom-config "$PEE" > "$BOOTCONF" 2>/dev/null || true
fi
if [[ -s "$BOOTCONF" ]]; then
sed -i 's/^BOOT_ORDER=.*/BOOT_ORDER=0x21/' "$BOOTCONF"
grep -q '^BOOT_ORDER=' "$BOOTCONF" || echo 'BOOT_ORDER=0x21' >> "$BOOTCONF"
if rpi-eeprom-config --apply "$BOOTCONF" 2>/dev/null; then
log "Boot order set to 0x21 (network first, then eMMC/SD); EEPROM update scheduled for next reboot"
BOOT_ORDER_SET=1
else
log "WARNING: rpi-eeprom-config --apply failed; boot order unchanged"
fi
else
log "rpi-eeprom-update -l did not return a config (on CM4 this is normal until after reboot with 6c applied); scheduling one-shot to set boot order after next boot"
fi
rm -f "$BOOTCONF"
else
log "rpi-eeprom-config/rpi-eeprom-update not found; skipping boot order (not a Pi4/CM4 or package missing)"
fi
# If boot order was not set (e.g. CM4 first boot), install a one-shot systemd service to set it after reboot
if [[ "$BOOT_ORDER_SET" -eq 0 ]] && command -v rpi-eeprom-config >/dev/null 2>&1 && command -v rpi-eeprom-update >/dev/null 2>&1; then
ONCE_SCRIPT="/usr/local/bin/set-cm4-boot-order-once.sh"
ONCE_SVC="/etc/systemd/system/set-cm4-boot-order-once.service"
cat > "$ONCE_SCRIPT" << 'SETBOOTEOF'
#!/bin/bash
# One-shot: set BOOT_ORDER=0x21 (network first) when rpi-eeprom-update becomes available (e.g. after CM4 enable and reboot).
BOOTCONF="/tmp/eeprom-boot-order-once.txt"
if PEE="$(rpi-eeprom-update -l 2>/dev/null)" && [[ -n "$PEE" ]] && [[ -f "$PEE" ]]; then
rpi-eeprom-config "$PEE" > "$BOOTCONF" 2>/dev/null
if [[ -s "$BOOTCONF" ]]; then
sed -i 's/^BOOT_ORDER=.*/BOOT_ORDER=0x21/' "$BOOTCONF"
grep -q '^BOOT_ORDER=' "$BOOTCONF" || echo 'BOOT_ORDER=0x21' >> "$BOOTCONF"
if rpi-eeprom-config --apply "$BOOTCONF" 2>/dev/null; then
echo "Boot order set to 0x21 (network first, then eMMC/SD)"
fi
fi
rm -f "$BOOTCONF"
fi
systemctl disable set-cm4-boot-order-once.service 2>/dev/null || true
rm -f /etc/systemd/system/set-cm4-boot-order-once.service
rm -f "$0"
SETBOOTEOF
chmod 755 "$ONCE_SCRIPT"
cat > "$ONCE_SVC" << 'SVCEOF'
[Unit]
Description=Set CM4 boot order once (network first)
After=multi-user.target
[Service]
Type=oneshot
ExecStart=/usr/local/bin/set-cm4-boot-order-once.sh
RemainAfterExit=no
[Install]
WantedBy=multi-user.target
SVCEOF
systemctl enable set-cm4-boot-order-once.service 2>/dev/null && log "Enabled set-cm4-boot-order-once.service to set boot order after next boot"
fi
# --- 7. One-shots (rotation at first login; wallpaper already set in pcmanfm config above) ---
log "--- One-shot scripts (run at pi first login) ---"
install_oneshot set-rotation-once || true
log "One-shots will append to $LOGFILE when they run at first login"
# --- 8. Allow pi to append to first-boot.log (for one-shot scripts) ---
chmod 666 "$LOGFILE"
log "Log file $LOGFILE is now appendable by user $PI_USER for one-shot scripts"
# --- 9. Reboot ---
log "=== first-boot.sh finished, rebooting ==="
reboot

View File

@@ -0,0 +1,36 @@
#!/bin/bash
# One-time fix for reTerminal DM after first-boot: splash, Plymouth theme, rotation, wallpaper.
# Run on the device as root (e.g. sudo bash fix-reterminal-display.sh).
# Or run over SSH: ssh pi@DEVICE_IP 'sudo bash -s' < fix-reterminal-display.sh
set -e
PI_USER="${PI_USER:-pi}"
PI_HOME="/home/$PI_USER"
CFG_PATH="/boot/firmware/config.txt"
[[ -f "$CFG_PATH" ]] || CFG_PATH="/boot/config.txt"
echo "=== Fixing boot splash (disable_splash=0) ==="
if [[ -f "$CFG_PATH" ]]; then
sed -i 's/^disable_splash=1$/disable_splash=0/' "$CFG_PATH" || true
grep -q '^disable_splash=' "$CFG_PATH" || echo 'disable_splash=0' >> "$CFG_PATH"
echo "Done. config: $(grep disable_splash "$CFG_PATH")"
fi
echo "=== Fixing Plymouth theme (custom only, no duplicate [Daemon]) ==="
if [[ -f /etc/plymouth/plymouthd.conf ]]; then
sed -i '/^Theme=/d' /etc/plymouth/plymouthd.conf
sed -i '/^\[Daemon\]$/d' /etc/plymouth/plymouthd.conf
grep -q '^\[Daemon\]' /etc/plymouth/plymouthd.conf || echo '[Daemon]' >> /etc/plymouth/plymouthd.conf
echo 'Theme=custom' >> /etc/plymouth/plymouthd.conf
echo "Done. plymouthd.conf Theme: $(grep Theme= /etc/plymouth/plymouthd.conf)"
fi
update-initramfs -u -k all 2>/dev/null || true
echo "=== Rotation and wallpaper (rpd-labwc / labwc Wayland) ==="
echo "To set rotation and wallpaper now (in a labwc session), run as $PI_USER:"
echo " wlr-randr --output \$(wlr-randr | awk '/^[A-Za-z0-9_-]+ /{print \$1; exit}') --transform 270"
echo " pcmanfm --set-wallpaper /usr/share/rpd-wallpaper/splash.png --wallpaper-mode=crop"
echo ""
echo "Or ensure one-shots run at next login (they are in autostart if still present)."
echo "=== Reboot to apply splash and initramfs ==="
echo " sudo reboot"

View File

@@ -0,0 +1,5 @@
# NoCloud meta-data: enables cloud-init. Optional instance-id for multi-device.
# Copy to the boot (FAT32) partition of your image as 'meta-data'.
instance-id: gnss-guard-01
# local-hostname: gnss.guard # optional override; first-boot.sh also sets this

View File

@@ -0,0 +1,21 @@
# Cloud-init network-config (NoCloud). Copy to boot partition as 'network-config'.
# Adjust for your LAN: DHCP or static.
version: 2
ethernets:
eth0:
dhcp4: true
# eth0:
# addresses:
# - 192.168.1.100/24
# gateway4: 192.168.1.1
# nameservers:
# addresses:
# - 8.8.8.8
# Optional WiFi (uncomment and set your SSID/password)
# wlan0:
# dhcp4: true
# access-points:
# "YourSSID":
# password: "YourPassword"

View File

@@ -0,0 +1,30 @@
#!/bin/bash
# One-shot: set reTerminal DM (labwc/Wayland) rotation to Left via wlr-randr, then remove self.
# Runs once as user pi at first login; deletes its autostart and this script so it never runs again.
# Logs to /var/log/first-boot.log.
FIRST_BOOT_LOG="/var/log/first-boot.log"
log() { echo "[$(date -Iseconds)] [set-rotation-once] $*" >> "$FIRST_BOOT_LOG" 2>/dev/null || true; }
log "started (labwc/wlr-randr)"
log "waiting 5s for compositor ..."
sleep 5
OUTPUT=""
if command -v wlr-randr &>/dev/null; then
OUTPUT=$(wlr-randr 2>/dev/null | awk '/^[A-Za-z0-9_-]+ /{print $1; exit}')
fi
if [[ -z "$OUTPUT" ]]; then
OUTPUT="DSI-1"
log "using default output: $OUTPUT"
fi
if [[ -n "$OUTPUT" ]] && command -v wlr-randr &>/dev/null; then
log "applying rotation left (transform 270) on $OUTPUT"
wlr-randr --output "$OUTPUT" --transform 270 2>&1 | while read -r line; do log "$line"; done
else
log "WARNING: wlr-randr not found or no output"
fi
log "removing one-shot desktop and script"
rm -f /home/pi/.config/autostart/set-rotation-once.desktop /home/pi/set-rotation-once.sh
log "finished"

View File

@@ -0,0 +1,36 @@
#!/bin/bash
# One-shot: set desktop wallpaper for labwc (swaybg) and persist via labwc autostart, then remove self.
# Runs as user pi at first login. Logs to /var/log/first-boot.log.
FIRST_BOOT_LOG="/var/log/first-boot.log"
log() { echo "[$(date -Iseconds)] [set-wallpaper-once] $*" >> "$FIRST_BOOT_LOG" 2>/dev/null || true; }
WALLPAPER="/usr/share/rpd-wallpaper/splash.png"
LABWC_AUTOSTART="$HOME/.config/labwc/autostart"
log "started (labwc/swaybg)"
log "waiting 8s for compositor ..."
sleep 8
if [[ ! -f "$WALLPAPER" ]]; then
log "WARNING: wallpaper not found $WALLPAPER"
else
mkdir -p "$(dirname "$LABWC_AUTOSTART")"
if [[ ! -f "$LABWC_AUTOSTART" ]]; then
echo '#!/bin/sh' > "$LABWC_AUTOSTART"
chmod +x "$LABWC_AUTOSTART"
fi
if ! grep -q 'swaybg.*splash.png' "$LABWC_AUTOSTART" 2>/dev/null; then
echo "swaybg -i $WALLPAPER -m fill &" >> "$LABWC_AUTOSTART"
log "added swaybg to labwc autostart"
fi
if command -v swaybg &>/dev/null; then
log "applying wallpaper now: $WALLPAPER"
swaybg -i "$WALLPAPER" -m fill &
else
log "WARNING: swaybg not installed"
fi
fi
log "removing one-shot desktop and script"
rm -f /home/pi/.config/autostart/set-wallpaper-once.desktop /home/pi/set-wallpaper-once.sh
log "finished"

View File

@@ -0,0 +1,48 @@
#!/bin/bash
# Disable keyring prompts
export GNOME_KEYRING_CONTROL=""
export DISPLAY=:0
# Force X11 instead of Wayland for better fullscreen support
export GDK_BACKEND=x11
unset WAYLAND_DISPLAY
# Wait for display and desktop environment to be ready
# Check if DISPLAY is accessible (wait up to 30 seconds)
for i in {1..60}; do
if xset q >/dev/null 2>&1 || [ -n "$DISPLAY" ]; then
# Wait for desktop environment to be fully loaded
if pgrep -x pcmanfm >/dev/null 2>&1 || pgrep -x lxsession >/dev/null 2>&1 || pgrep -x xfdesktop >/dev/null 2>&1; then
break
fi
fi
sleep 0.5
done
# Additional delay to ensure window manager is fully ready
sleep 5
# Start Chromium with flags to avoid keyring and ensure proper fullscreen
# Force X11 platform and add fullscreen-related flags
# Fullscreen mode (current active)
/usr/bin/chromium --start-fullscreen --noerrdialogs --disable-infobars --disable-session-crashed-bubble --disable-restore-session-state --no-first-run --password-store=basic --use-mock-keychain --ozone-platform=x11 --disable-features=UseChromeOSDirectVideoDecoder --app=http://127.0.0.1:8080 &
# Wait for Chromium window to appear and then force fullscreen
sleep 3
# Try to find Chromium window and force it to fullscreen
for i in {1..10}; do
WINDOW_ID=$(wmctrl -l 2>/dev/null | grep -i chromium | head -1 | awk '{print $1}')
if [ -n "$WINDOW_ID" ]; then
wmctrl -i -r "$WINDOW_ID" -b add,fullscreen 2>/dev/null
break
fi
sleep 0.5
done
# Keep script running
wait
# Kiosk mode (commented out - uncomment to use instead of fullscreen)
# /usr/bin/chromium --kiosk --noerrdialogs --disable-infobars --disable-session-crashed-bubble --disable-restore-session-state --no-first-run --password-store=basic --use-mock-keychain --ozone-platform=x11 --app=http://127.0.0.1:8080

View File

@@ -0,0 +1,34 @@
#cloud-config
# Cloud-init user-data for reTerminal DM4 golden image (eMMC).
# Copy to the boot (FAT32) partition of your image as 'user-data'.
# Raspberry Pi OS uses NoCloud: meta-data, user-data, network-config on boot partition.
package_update: true
package_upgrade: false
packages:
- chromium-browser
- wmctrl
# - python3-pip # uncomment if you need Flask/other apps
# Optional: set hostname from serial or leave default
# hostname: reterminal-%s # %s = first column of meta-data instance-id if set
# Optional: enable I2C/SPI for reTerminal peripherals (LED, buzzer, etc.)
# Uncomment if your image does not already enable these:
# write_files:
# - path: /boot/firmware/config.txt.d/99-reterminal.txt
# content: |
# dtparam=i2c_arm=on
# dtparam=spi=on
# Run once on first boot (e.g. copy kiosk scripts, start Chromium on boot)
runcmd:
# Example: ensure Chromium kiosk autostart
# - systemctl enable chromium-kiosk
- cloud-init single --name cc_final_message
# Power state after first boot (optional)
# power_state:
# mode: reboot
# delay: 1

View File

@@ -0,0 +1,118 @@
#cloud-config
# Example: create user (pi) with password, enable SSH, install KDE Plasma with touch options,
# set KDE as default GUI, and deploy Chromium kiosk autostart.
# Uses start-chromium.sh and chromium-kiosk.desktop from this project (emmc-provisioning/cloud-init/).
#
# 1. Generate a password hash on a Linux host:
# mkpasswd -m sha-512 'YourPassword'
# or: openssl passwd -6 'YourPassword'
# Paste the full output (e.g. $6$...) into the passwd: line below.
# 2. To use a different username than "pi", replace every "pi" in this file.
# 3. To change the kiosk URL, edit the --app=... line in the start-chromium.sh content below.
package_update: true
package_upgrade: false
packages:
- chromium-browser
- wmctrl
- openssh-server
# KDE Plasma + touchscreen
- kde-plasma-desktop
- maliit-keyboard
- xinput-calibrator
# Create user and set password (use hash from mkpasswd -m sha-512 or openssl passwd -6)
users:
- name: pi
groups: [adm, sudo, video]
lock_passwd: false
passwd: "$6$7xWGhGc6d1lJx1dU$4E8r1mkzVj51bjEbfzdP8wPxso..C36LbXkqU/X4oBGq94aGFMSrZb0PVI8zs/Om1Jm97/D..Apy2HTdCn3FV1"
shell: /bin/bash
# Enable SSH (allow password auth so you can log in with the user above)
write_files:
- path: /etc/ssh/sshd_config.d/99-cloud-init.conf
content: |
PasswordAuthentication yes
PermitRootLogin no
- path: /home/pi/start-chromium.sh
content: |
#!/bin/bash
export GNOME_KEYRING_CONTROL=""
export DISPLAY=:0
export GDK_BACKEND=x11
unset WAYLAND_DISPLAY
for i in {1..60}; do
if xset q >/dev/null 2>&1 || [ -n "$DISPLAY" ]; then
if pgrep -x plasma_session >/dev/null 2>&1 || pgrep -x kwin_x11 >/dev/null 2>&1 || pgrep -x pcmanfm >/dev/null 2>&1 || pgrep -x lxsession >/dev/null 2>&1; then
break
fi
fi
sleep 0.5
done
sleep 5
/usr/bin/chromium --start-fullscreen --noerrdialogs --disable-infobars --disable-session-crashed-bubble --disable-restore-session-state --no-first-run --password-store=basic --use-mock-keychain --ozone-platform=x11 --disable-features=UseChromeOSDirectVideoDecoder --app=http://127.0.0.1:8080 &
sleep 3
for i in {1..10}; do
WINDOW_ID=$(wmctrl -l 2>/dev/null | grep -i chromium | head -1 | awk '{print $1}')
if [ -n "$WINDOW_ID" ]; then
wmctrl -i -r "$WINDOW_ID" -b add,fullscreen 2>/dev/null
break
fi
sleep 0.5
done
wait
owner: pi:pi
permissions: "0755"
- path: /home/pi/.config/autostart/chromium-kiosk.desktop
content: |
[Desktop Entry]
Type=Application
Name=Chromium Fullscreen
Exec=/home/pi/start-chromium.sh
Hidden=false
NoDisplay=false
X-GNOME-Autostart-enabled=true
owner: pi:pi
permissions: "0644"
# KDE Plasma: switch to KDE as default session (X11 for Chromium compatibility)
- path: /etc/lightdm/lightdm.conf.d/99-default-session.conf
content: |
[Seat:*]
user-session=plasmax11
permissions: "0644"
# KDE touch-friendly: UI scale and input (for pi after first login)
- path: /home/pi/.config/kdeglobals
content: |
[General]
ForceFontDPI=120
owner: pi:pi
permissions: "0644"
- path: /home/pi/.config/kwinrc
content: |
[Windows]
BorderlessMaximizedWindows=true
[Plugins]
touchpointsEnabled=true
owner: pi:pi
permissions: "0644"
# Start on-screen keyboard (maliit) with KDE for touch input
- path: /home/pi/.config/autostart/maliit-keyboard.desktop
content: |
[Desktop Entry]
Type=Application
Name=Maliit Keyboard
Exec=maliit-keyboard -r
X-GNOME-Autostart-enabled=true
owner: pi:pi
permissions: "0644"
runcmd:
- mkdir -p /home/pi/.config/autostart
- chown -R pi:pi /home/pi/.config
# Set KDE Plasma (X11) as default session so next boot uses KDE
- update-alternatives --set x-session-manager /usr/bin/startplasma-x11 2>/dev/null || true
- systemctl enable ssh
- systemctl start ssh
- cloud-init single --name cc_final_message

View File

@@ -0,0 +1,21 @@
#cloud-config
# Example user-data that downloads and runs a script from a file server.
# Use this so you can change first-boot behaviour without rebuilding the golden image.
# Copy to boot partition as 'user-data' and set BOOTSTRAP_URL to your script URL.
package_update: true
package_upgrade: false
packages:
- curl # or wget if you prefer
# Download script from file server and run it (runcmd runs after network is up)
runcmd:
- curl -fsSL "http://YOUR_FILE_SERVER/provisioning/bootstrap.sh" -o /tmp/bootstrap.sh
- chmod +x /tmp/bootstrap.sh
- /tmp/bootstrap.sh
# Optional: remove after run
# - rm -f /tmp/bootstrap.sh
# Optional: finish cloud-init
# - cloud-init single --name cc_final_message

View File

@@ -0,0 +1,37 @@
#cloud-config
# Example: create user (pi), enable SSH, then download and run first-boot.sh to install
# Chromium kiosk, rpd-labwc, and touch options. Edit FIRST_BOOT_URL to point to your
# hosted first-boot.sh (e.g. file server or raw GitHub).
#
# 1. Generate a password hash: mkpasswd -m sha-512 'YourPassword' or openssl passwd -6 'YourPassword'
# Paste the full output into the passwd: line below.
# 2. Host first-boot.sh (same dir as this repo: cloud-init/first-boot.sh) at FIRST_BOOT_URL.
# 3. To use a different username than "pi", replace every "pi" in this file and in first-boot.sh.
package_update: true
package_upgrade: false
packages:
- curl
users:
- name: pi
groups: [adm, sudo, video]
lock_passwd: false
passwd: "$6$7xWGhGc6d1lJx1dU$4E8r1mkzVj51bjEbfzdP8wPxso..C36LbXkqU/X4oBGq94aGFMSrZb0PVI8zs/Om1Jm97/D..Apy2HTdCn3FV1"
shell: /bin/bash
write_files:
- path: /etc/ssh/sshd_config.d/99-cloud-init.conf
content: |
PasswordAuthentication yes
PermitRootLogin no
runcmd:
- systemctl enable ssh
- systemctl start ssh
- curl -fsSL "http://10.130.60.141:5000/files/first-boot.sh" -o /tmp/first-boot.sh
- chmod +x /tmp/first-boot.sh
- /tmp/first-boot.sh
# - rm -f /tmp/first-boot.sh
- cloud-init single --name cc_final_message