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:
@@ -0,0 +1,3 @@
|
||||
[Seat:*]
|
||||
user-session=rpd-labwc
|
||||
autologin-session=rpd-labwc
|
||||
@@ -0,0 +1,3 @@
|
||||
[greeter]
|
||||
wallpaper=/usr/share/rpd-wallpaper/splash.png
|
||||
wallpaper_mode=crop
|
||||
13
emmc-provisioning/cloud-init/config-files/README.md
Normal file
13
emmc-provisioning/cloud-init/config-files/README.md
Normal 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.
|
||||
@@ -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
|
||||
2
emmc-provisioning/cloud-init/config-files/kdeglobals
Normal file
2
emmc-provisioning/cloud-init/config-files/kdeglobals
Normal file
@@ -0,0 +1,2 @@
|
||||
[General]
|
||||
ForceFontDPI=120
|
||||
4
emmc-provisioning/cloud-init/config-files/kwinrc
Normal file
4
emmc-provisioning/cloud-init/config-files/kwinrc
Normal file
@@ -0,0 +1,4 @@
|
||||
[Windows]
|
||||
BorderlessMaximizedWindows=true
|
||||
[Plugins]
|
||||
touchpointsEnabled=true
|
||||
@@ -0,0 +1,5 @@
|
||||
[Desktop Entry]
|
||||
Type=Application
|
||||
Name=Maliit Keyboard
|
||||
Exec=maliit-keyboard -r
|
||||
X-GNOME-Autostart-enabled=true
|
||||
@@ -0,0 +1,5 @@
|
||||
[Desktop Entry]
|
||||
Type=Application
|
||||
Name=Set rotation once
|
||||
Exec=/home/pi/set-rotation-once.sh
|
||||
X-GNOME-Autostart-enabled=true
|
||||
@@ -0,0 +1,5 @@
|
||||
[Desktop Entry]
|
||||
Type=Application
|
||||
Name=Set wallpaper once
|
||||
Exec=/home/pi/set-wallpaper-once.sh
|
||||
X-GNOME-Autostart-enabled=true
|
||||
30
emmc-provisioning/cloud-init/files-from-guard/README.md
Normal file
30
emmc-provisioning/cloud-init/files-from-guard/README.md
Normal 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.
|
||||
|
||||
---
|
||||
|
||||
## What’s 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 |
@@ -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
|
||||
@@ -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 |
155
emmc-provisioning/cloud-init/first-boot.md
Normal file
155
emmc-provisioning/cloud-init/first-boot.md
Normal 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 tee’d 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 pi’s 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 pi’s 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 pi’s 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 pcmanfm’s `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`.
|
||||
288
emmc-provisioning/cloud-init/first-boot.sh
Normal file
288
emmc-provisioning/cloud-init/first-boot.sh
Normal 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
|
||||
36
emmc-provisioning/cloud-init/fix-reterminal-display.sh
Normal file
36
emmc-provisioning/cloud-init/fix-reterminal-display.sh
Normal 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"
|
||||
5
emmc-provisioning/cloud-init/meta-data
Normal file
5
emmc-provisioning/cloud-init/meta-data
Normal 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
|
||||
21
emmc-provisioning/cloud-init/network-config
Normal file
21
emmc-provisioning/cloud-init/network-config
Normal 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"
|
||||
30
emmc-provisioning/cloud-init/set-rotation-once.sh
Normal file
30
emmc-provisioning/cloud-init/set-rotation-once.sh
Normal 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"
|
||||
36
emmc-provisioning/cloud-init/set-wallpaper-once.sh
Normal file
36
emmc-provisioning/cloud-init/set-wallpaper-once.sh
Normal 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"
|
||||
48
emmc-provisioning/cloud-init/start-chromium.sh
Executable file
48
emmc-provisioning/cloud-init/start-chromium.sh
Executable 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
|
||||
34
emmc-provisioning/cloud-init/user-data
Normal file
34
emmc-provisioning/cloud-init/user-data
Normal 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
|
||||
@@ -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
|
||||
@@ -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
|
||||
37
emmc-provisioning/cloud-init/user-data-remote-gnss.example
Normal file
37
emmc-provisioning/cloud-init/user-data-remote-gnss.example
Normal 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
|
||||
Reference in New Issue
Block a user