Target: pi@192.168.1.135 — Raspberry Pi (PocketTerm 3.5" / Waveshare display), headless console use
OS: Debian GNU/Linux 13 (trixie), systemd 257
Kernel: 6.18.40-v8-cjk+ (custom kernel8-cjk.img)
Date: 2026-08-14
| Metric | Before | After | Saved |
|---|---|---|---|
| Total boot | 55.78 s | 25.87 s | ~30 s |
| Kernel (systemd-analyze) | 9.04 s | 1.65 s | 7.4 s |
| Userspace | 46.75 s | 24.22 s | 22.5 s |
| Firmware+kernel wall time* | 11.8 s | 9.4 s | 2.4 s |
| Enabled services | 35 | 16 | 19 fewer |
* Wall-clock time before systemd's first log line (bootloader loading kernel from SD).
Boot messages remain visible on the console (we did not use
quiet).
systemd-analyze # totals: kernel + userspace
systemd-analyze blame # slowest units, descending
systemd-analyze critical-chain # the dependency path that gates the finishThe critical chain is what matters: blame shows slow units, but only units
on the critical chain actually delay the finish. A slow unit running in parallel
off the critical path costs nothing.
To see the true firmware+kernel cost (the bootloader loading the kernel off the SD
card, which systemd-analyze under-reports), read the monotonic timestamp of
systemd's first log line:
journalctl -b -o short-monotonic | grep -m1 'systemd 257'
# e.g. [ 9.373433] pi systemd[1]: systemd 257 running... => ~9.4s before userspaceThe original critical chain:
multi-user.target @45.3s
└─nginx.service +901ms
└─network-online.target
└─NetworkManager-wait-online.service +6.0s ← blocked waiting for DHCP
└─NetworkManager.service +6.9s
└─dbus.service
└─ ... sysinit ...
└─cloud-init-network.service
└─cloud-init-local.service +1.4s
└─cloud-init-main.service +8.4s ← cloud-init: ~10s, totally unused
└─boot-firmware.mount
└─fsck (FAT boot partition) +1.8s ← fsck every boot
Top offenders:
- cloud-init (~10 s on the critical path) — a cloud-provisioning tool for
AWS/Azure/etc. Pointless on a physical Pi. It was gating
sysinit.target. - NetworkManager-wait-online (6 s) — blocks boot until DHCP fully completes.
nginxpulled innetwork-online.target, forcing the whole boot to wait. - FAT boot-partition fsck (1.8 s every boot) — low value; the
/boot/firmwarepartition is rarely written. - initramfs (11.9 MB loaded off a slow SD card each boot) — unnecessary here
because the kernel has the SD (
bcm2835-mmc) andext4drivers built in. - 19 unused services — ModemManager, Bluetooth, CUPS (printing), avahi (mDNS), NFS/rpcbind, lightdm/X (headless!), RPi EEPROM update, X display-test probes, etc.
sudo touch /etc/cloud/cloud-init.disabled
sudo systemctl disable cloud-init-main cloud-init-local cloud-init-network \
cloud-config cloud-finalsudo systemctl disable NetworkManager-wait-online.serviceAnd a drop-in so nginx no longer pulls in network-online.target
(/etc/systemd/system/nginx.service.d/override.conf):
[Unit]
After=
After=network.target remote-fs.target nss-lookup.target
Wants=Plus an ssh drop-in so ssh doesn't order after network.target
(/etc/systemd/system/ssh.service.d/speedup.conf) — sshd binds to 0.0.0.0 and
serves as soon as an interface gets an address; it doesn't need to wait for DHCP.
sudo systemctl disable ModemManager bluetooth cups cups-browsed lightdm \
rpcbind nfs-blkmap e2scrub_reap rpi-eeprom-update \
accounts-daemon rp1-test glamor-test
sudo systemctl disable --now cups.socket cups.path rpcbind.socket \
avahi-daemon.service avahi-daemon.socketlightdm/accounts-daemon/rp1-test/glamor-test— GUI/X stuff, unused (console only)avahi— mDNS.localname resolution (you can still reach the Pi by IP)rpcbind/nfs-blkmap— NFS, unusedModemManager— cellular modems, none attached
In /etc/fstab, changed the /boot/firmware line's last field (fsck pass) from 2 to 0:
PARTUUID=0f319fba-01 /boot/firmware vfat defaults 0 0
boot_delay=0 # no artificial bootloader pause
camera_auto_detect=0 # don't probe CSI camera every boot (none attached)
auto_initramfs=0 # don't build/load initramfs — kernel has mmc+ext4 builtinauto_initramfs=0 above. Verified safe first — these are built into the kernel
(so root mounts without an initramfs):
grep -iE 'mmc_block|bcm2835|ext4' /lib/modules/$(uname -r)/modules.builtin/etc/systemd/journald.conf.d/speedup.conf:
[Journal]
SystemMaxUse=50M
RuntimeMaxUse=20MFinal critical chain:
multi-user.target @24.2s
└─ssh.service +1.3s
└─network.target
└─NetworkManager.service +6.5s ← top remaining software cost
└─ ... basic/sysinit @15.5s ...
└─local-fs.target @14.9s
└─boot-firmware.mount
└─dev-mmcblk0p1.device @13.8s ← SD card enumeration (hardware)
- ~9 s firmware + ~5 s SD-card device settling = mostly hardware-bound (slow SD card). A faster / higher-class SD card or USB/NVMe boot is the real fix.
- NetworkManager ~6.5 s — starts, loads the WiFi plugin, then does DHCP on both eth0 and wlan0. See the optional tweak below.
The Pi is on Ethernet (192.168.1.135) but also auto-connects to WiFi
(alibaba-guest, giving a 30.49.x address). If you don't need WiFi:
sudo nmcli connection modify alibaba-guest connection.autoconnect no
# repeat for JSBPI, JSBPI-5G, TunaInTheNorth-5GHz if desiredThis removes a parallel DHCP transaction during boot.
Backups were made on the Pi:
/etc/fstab.bak-speedup/boot/firmware/config.txt.bak-speedup/boot/firmware/cmdline.txt.bak-speedup/boot/firmware/RECOVERY-README.txt(initramfs rollback note)
If the Pi won't boot (most likely from the initramfs change): pull the SD card,
open config.txt on any computer, and set auto_initramfs=1.
To re-enable any service:
sudo systemctl enable --now <service>