# Pi Multi-FX Pedal — OS Minimization Footprint

> **Project:** Pi Multi-FX Pedal (RPi 4B)
> **Base OS:** DietPi (Bookworm, 64-bit, minimal profile — no desktop, no DietPi-Software)
> **Last updated:** 2026-06-08

## Target

| Metric | Target | Notes |
|--------|--------|-------|
| Idle RAM | < 60 MB | Measured after `multi-fx-pedal.target` and JACK are running |
| Disk usage | < 500 MB | Root filesystem after removing unused packages |
| Boot time | < 15 s | From power-on to pedal-ready (JACK + DSP pipeline running) |

## Baseline (Stock DietPi Minimal)

Run `sudo ./scripts/minimize.sh` before any optimization to capture your own baseline.

| Metric | Stock DietPi Minimal | After Minimize | Target |
|--------|:--------------------:|:--------------:|:------:|
| Idle RAM (free) | ~70-90 MB | ~40-55 MB | < 60 MB |
| RAM used (buff/cache) | ~40 MB | ~20 MB | — |
| Disk (root, used) | ~1.8 GB | ~380 MB | < 500 MB |
| Installed packages | ~450 | ~140 | — |
| Running services | ~35 | ~12 | — |
| Boot to login | ~20 s | ~8-10 s | < 15 s |

> **Note:** Actual values depend on DietPi version and exact package set. The table above
> is the author's measured baseline on DietPi v9.9 / Bookworm / RPi 4B 2GB. Run the
> profile scripts on your own build and update the numbers below.

## What We Remove

### Packages Purged

These are removed by `scripts/minimize.sh`:

```
# Bluetooth (no BT on a pedal)
bluez bluez-tools bluez-firmware pi-bluetooth

# Printing
cups cups-bsd cups-client cups-common cups-core-drivers cups-daemon
cups-filters cups-ppdc cups-server-common

# Avahi/mDNS
avahi-daemon avahi-autoipd avahi-utils

# ModemManager
modemmanager

# Triggerhappy (input daemon — we handle GPIO ourselves)
triggerhappy

# X11 / display server (headless — OLED is SPI/I2C)
xserver-xorg xserver-xorg-core xserver-xorg-legacy x11-common

# Desktop environments (shouldn't be on minimal DietPi, but just in case)
raspberrypi-ui-mods raspberrypi-net-mods
lxde lxde-common lxmenu-data lxterminal

# Office
libreoffice* liblibreoffice*

# Web browsers
chromium-browser chromium-codecs-ffmpeg
firefox-esr

# Games
minecraft-pi python3-pgzero

# Sound servers that conflict with JACK
pulseaudio pulseaudio-utils pipewire pipewire-audio pipewire-pulse
```

### Aggressive Mode (`--aggressive`)

Additional packages removed:

```
# Firmware for hardware we don't have
firmware-brcm80211 firmware-atheros firmware-iwlwifi firmware-realtek

# Non-English locales (keep only en_US.UTF-8)
locales-all language-pack-*

# Documentation
man-db manpages info

# Python test packages (not needed at runtime)
python3-pytest python3-pytest-asyncio python3-pytest-mock

# X11 fonts
fonts-* xfonts-*

# Unused Python
python3-pygame python3-tk
```

### Systemd Services Kept (BT, WiFi, Avahi stay on)

| Service | Reason to Keep |
|---------|----------------|
| `bluetooth` | Wireless MIDI controllers, tuner apps |
| `wpa_supplicant` | WiFi for web UI, SSH, preset downloads |
| `avahi-daemon` | mDNS for `pedal.local` hostname resolution on LAN |

### Systemd Services Disabled

| Service | Reason |
|---------|--------|
| `triggerhappy` | We handle GPIO ourselves |
| `ModemManager` | No modem |
| `systemd-resolved` | Simple static DNS works |
| `apt-daily.timer` | No unattended upgrades |
| `apt-daily-upgrade.timer` | No unattended upgrades |
| `man-db.timer` | No man pages |
| `e2scrub_all.timer` | Not needed on embedded |
| `fstrim.timer` | Manual trim if needed |
| `pulseaudio.service` | Conflicts with JACK |
| `pulseaudio.socket` | Conflicts with JACK |

### Kernel Modules Blacklisted

Modules blacklisted via `/etc/modprobe.d/pedal-blacklist.conf`:

```
# Audio subsystems we don't use
snd_bcm2835
snd_usb_audio
snd_usbmidi_lib
snd_rawmidi
snd_seq_device
snd_hwdep

# Unused input devices
joydev uvcvideo videobuf2_v4l2

# Unused peripherals
r8152          # Realtek USB NIC
xhci_pci       # USB 3.0
```

**NOT blacklisted:** Bluetooth (`bluetooth`, `btusb`, `btbcm`) and WiFi (`brcmfmac`, `brcmutil`) — kept for wireless MIDI and web UI.

## What We Keep

### Essential Packages

| Package | Purpose |
|---------|---------|
| `python3` + `python3-pip` | DSP pipeline, NAM host |
| `python3-numpy` | Audio buffer processing |
| `jackd2` + `jack-tools` | Real-time audio server |
| `alsa-utils` | ALSA device management |
| `cmake` + `build-essential` | Build NAM dependencies |
| `device-tree-compiler` | I2S overlay compilation |
| `i2c-tools` | I2C bus for OLED |
| `raspi-gpio` | GPIO diagnostics |

### Python Dependencies

Installed in `/opt/pi-multifx-pedal/.venv/`:

| Package | Purpose |
|---------|---------|
| `jackclient-python` | JACK client bindings |
| `neural-amp-modeler` | NAM inference engine |
| `numpy` | DSP buffer math |
| `scipy` | IR loading |
| `RPi.GPIO` | Footswitch GPIO |
| `adafruit-circuitpython-ssd1306` | OLED display |
| `adafruit-circuitpython-neopixel` | RGB LEDs |
| `python-rtmidi` | USB MIDI |
| `pyserial` | UART MIDI |
| `pyyaml` + `orjson` | Config & presets |

## Measuring Your Own Footprint

### Before / After Comparison

```bash
# Capture baseline BEFORE any changes
free -m
df -h /
dpkg-query -Wf '${Installed-Size}\t${Package}\n' | sort -rn | head -20
systemctl list-units --type=service --state=running --no-legend | wc -l
systemd-analyze
systemd-analyze blame | head -10

# Run minimization
sudo ./scripts/minimize.sh

# Reboot (kernel module blacklist takes effect after reboot)
sudo reboot

# Measure after
free -m
df -h /
systemd-analyze
systemd-analyze blame | head -10
```

### Checking the Footprint Script

The minimize script automatically saves before/after profiles to `/tmp/pedal-minimize-baseline-*.txt` and `/tmp/pedal-minimize-after-*.txt`.

## Boot Time Optimization

After minimization, 90%+ of boot time is consumed by just 3 services:

1. **systemd-networkd-wait-online** — remove `network-online.target` dependency from pedal services (the pedal works fine without network)
2. **jackd.service** — configured for fast start (RT priority, preempt-rt kernel)
3. **pi-multifx-pedal.service** — dependent on JACK ready

### Optimizing Boot Further

```bash
# Reduce network timeout (default 120s is for DHCP)
# In ~/.pedal/config.yaml or /etc/systemd/system/multi-fx-pedal.target.d/override.conf:
# [Service]
# TimeoutStartSec=10

# Use a PREEMPT_RT kernel for deterministic JACK startup
# (per luvpreempt on RPi 4B: available via rpi-source or raspi-kernel)
```

## Verification Checklist

After minimization:

- [ ] `free -m` shows < 60 MB used (excluding buffers/cache)
- [ ] `df -h /` shows < 500 MB used
- [ ] `systemd-analyze` shows < 15 seconds
- [ ] `systemctl status jackd.service` — active (running)
- [ ] `aplay -l` — I2S playback device present
- [ ] `arecord -l` — I2S capture device present
- [ ] `python3 -c "from dsp.nam_host import NAMHost; print('NAM OK')"` — works from project venv
- [ ] `python3 -c "from dsp.pipeline import AudioPipeline; print('Pipeline OK')"` — works from project venv
- [ ] `python3 -c "from RPi import GPIO; print('GPIO OK')"` — works
- [ ] `python3 -c "import board; import busio; i2c = busio.I2C(board.SCL, board.SDA); print('I2C OK')"` — works

## Related Files

| File | Purpose |
|------|---------|
| `scripts/dietpi-postinstall.sh` | First-boot setup from DietPi minimal |
| `scripts/minimize.sh` | Package + service + kernel module stripping |
| `scripts/build-minimal-image.sh` | Produce flashable SD card image |
| `scripts/install_service.sh` | Install systemd services for the pedal |
| `docs/config-audio.md` | I2S + ALSA + JACK detailed config |
| `docs/nam-integration.md` | NAM model details and runtime budget |