Raspberry Pi
Raspberry Pi OS Lite is an ARM64 port of Debian that excludes a desktop environment to remain lightweight. It utilizes specific, non-free proprietary firmware found in packages such as raspberrypi-bootloader and firmware-brcm80211 to manage the GPU, Wi-Fi, and Bluetooth. Consequently, the firmware-linux-free package is not required.
_,met$$$$$gg. ops@RaspberryPI
,g$$$$$$$$$$$$$$$P. -------
,g$$P"" """Y$$.". OS: Debian GNU/Linux 13 (trixie) aarch64
,$$P' `$$$. Host: Raspberry Pi 4 Model B Rev 1.5
',$$P ,ggs. `$$b: Kernel: Linux 6.12.62+rpt-rpi-v8
`d$$' ,$P"' . $$$ Uptime: 15 mins
$$P d$' , $$P Packages: 649 (dpkg)
$$: $$. - ,d$$' Shell: zsh 5.9
$$; Y$b._ _,d$P' Terminal: /dev/pts/0
Y$$. `.`"Y$$$$P"' CPU: BCM2711 (4) @ 1.80 GHz
`$$b "-.__ Memory: 187.08 MiB / 7.69 GiB (2%)
`Y$$b Swap: 0 B / 2.00 GiB (0%)
`Y$$. Disk (/): 4.22 GiB / 28.79 GiB (15%) - ext4
`$$b. Local IP (eth0): 172.30.30.125/24
`Y$$b. Locale: en_CA.UTF-8
`"Y$b._Setup
1. Flashing the operating system to microSD
-
Hardware Recommendations: A Class 10 microSD card larger than 16GB is recommended. Note that capacities above 2TB are not supported due to Master Boot Record (MBR) limitations. Use the Raspberry Pi Imager for a streamlined installation.
- Device: Select
Raspberry Pi 4 Model B 8GB1 - OS: Select
Raspberry Pi OS (other)>Raspberry Pi OS Lite (64-bit) - Customization Settings:
- Hostname: Set a single-word name using only letters, numbers, and hyphens. You can reach it at hostname.local, thanks to mDNS/Avahi, which is built into the OS
- Avoid using a Fully Qualified Domain Name (FQDN) unless you have specific SSL requirements:
- If you get an SSL certificate (via Let’s Encrypt), having the FQDN set can make some automated tools slightly easier to configure
- If you are mimicking a data center structure where every machine must belong to a specific sub-domain, especially with Public Certificates
- Avoid using a Fully Qualified Domain Name (FQDN) unless you have specific SSL requirements:
- Localization:
- Capital city:
Ottawa (Canada) - Time zone:
America/Toronto - Keyboard layout:
us
- Capital city:
- Credentials: Set a unique username and password
- Connectivity: Configure Wi-Fi: SSID/password if required and enable SSH with password authentication
- Raspberry Pi Connect2: Disable.
- Hostname: Set a single-word name using only letters, numbers, and hyphens. You can reach it at hostname.local, thanks to mDNS/Avahi, which is built into the OS
- Device: Select
-
Hardware Connection: Insert the card and connect the power supply. A steady red LED indicates power, and the device will boot immediately.
- Power Options:
- An USB-C Power Supply (5V 3A recommended)
- POE Injector (IEEE 802.3af/at)
- PoE splitter that converts Ethernet to 5V USB-C
- Power Options:
-
Initial Access:
- Connect via a 1GbE network cable, a micro-HDMI display and keyboard
- Alternatively, connect via SSH using:
ssh -o PreferredAuthentications=password -o PubkeyAuthentication=no user@hostname- This explicitly instructs the SSH client to use Password Authentication first. If you have existing SSH keys on your computer, your computer will try to use those keys to log into the Raspberry Pi automatically. You’ll get a “Permission denied (publickey)” error before ever giving you a chance to type a password.
- You may need to run ssh-keygen -R hostname.local on your main computer to clear the old SSH key if you change the device hostname or IP address
2. Initial Pi setup
- Login to the PI:
ssh -o PreferredAuthentications=password -o PubkeyAuthentication=no myuser@hostname - Install Chezmoi via the dotFiles repository3 to apply personal configurations:
sh -c "$(curl -fsLS get.chezmoi.io)" -- -b ~/.config/bin init --apply bhdicaire - Upload your public key if it’s not in the GitHub repository:
cat ~/.ssh/ops.pub | ssh myuser@hostname "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_key"- Alternatively, you can add a host entry in your local SSH config:
vi /.ssh/config
- Alternatively, you can add a host entry in your local SSH config:
Host pi
HostName hostname.local
User myuser
PreferredAuthentications password
PubkeyAuthentication no- Log out of your SSH session:
exit
3. Hardware Optimization
- Login to the PI:
ssh myuser@hostname - Hardware Optimization, edit
/boot/firmware/config.txtto reduce power consumption and heat for headless configurations. This includes disabling on-board Wi-Fi and Bluetooth. Replace the current content:sudo vi /boot/firmware/config.txt
# Core Settings
arm_64bit=1
arm_boost=1
disable_overscan=1
# Audio (Keep on if you need sound, otherwise comment out)
dtparam=audio=on
# Headless Optimizations
gpu_mem=16
# dtoverlay=vc4-kms-v3d
# camera_auto_detect=1
# display_auto_detect=1
# Hardware Disables (Assuming Ethernet usage)
dtoverlay=disable-wifi
dtoverlay=disable-bt
[cm4]
otg_mode=1
[all]
enable_uart=1- Restart the device:
sudo reboot
4. Firmware Update
- Login to the PI:
ssh myuser@hostname - Firmware Updates, check the EEPROM status using
sudo rpi-eeprom-updateand apply updates if necessarysudo rpi-eeprom-update -a. - Restart the device if you updated the firmware:
sudo reboot
5. System Fine-Tuning
- Login to the PI:
ssh myuser@hostname - System Fine-Tuning with
sudo raspi-config:- Ensure the tool itself is current:
8. update - Change the hostname if required
- Set your Timezone and WLAN Country[^5] if required :
5 Localisation Options>4 WLAN Country - Expand the Filesystem, although the Imager usually do it:
6. Advanced Options>A1 Expand - Set behaviour of GPIO case fan:
4 Performance>P3 Fan - Set storage location for logs:
6. Advanced Options>A12 logging>2 VolatileMode Storage Type Pros Cons Default SD Card Persistent across reboots; logs are never lost. High write wear on microSD cards which can lead to card failure over time Volatile RAM Extremely fast; zero wear on the SD card. All logs are deleted when the Pi is rebooted or loses power. Persistent SD Card (Optimized) Keeps logs through reboots. Still causes physical wear to the SD card though often handled more efficiently None Disabled Zero disk usage. Impossible to troubleshoot system crashes or errors after they happen
- Ensure the tool itself is current:
- Temperature Monitoring with
watch -n 2 vcgencmd measure_tempto measure in real-time- Idle temperatures between 35°C–45°C are excellent
- Under load, temperatures should remain below 70°C if the passive cooling case is performing correctly
- Check the current system information with
fastfetch
Standard microSD cards usually lack the S.M.A.R.T. (Self-Monitoring, Analysis, and Reporting Technology) controllers found in larger drives. Some high-end SD cards like those from SanDisk or Kingston have proprietary ways to report health. If your card supports it, you can check the sysfs interface: cat /sys/block/mmcblk0/device/life_time
- If this returns two values (e.g., 0x01 0x01), it represents a range of health in 10% increments
- On most consumer-grade Class 10 cards, this file often doesn’t exist or returns an empty value
MicroSD cards are designed to fail-safe by locking themselves into Read-Only mode once their write cycles are exhausted to prevent data corruption. You can check if the kernel has flagged any such issues: dmesg | grep -i "mmcblk. Look for errors like I/O error, Read-only file system, or Card stuck in recovery indicating a worn-out card.
A card that is nearly full (e.g., 90%+) will wear out much faster than a card with plenty of free space. This is because the controller has fewer “fresh” cells to rotate through for wear leveling. Keeping a 32GB card at only 15% usage, is actually the best way to preserve its life. Check with df -k.
Optional
TCP/IP
When running virtual machines on your network, consistent IP addresses make access and management much easier. Rather than configuring static IPs directly on each VM, you can use DHCP reservations in UniFi Network to ensure machines always receive the same address while still using automatic configuration.
Setting a Static IP via UniFi Network (DHCP Reservation)
- Open your UniFi Network controller
- Go to Client Devices and find your virtual machine (or wait for it to appear after connecting)
- Click on the client to open its details
- Click Settings (gear icon)
- Under Network, enable Fixed IP Address
- Enter your desired IP address
- Click Apply
Alternatively, if the client isn’t visible yet:
- Go to Settings → Networks
- Select your network
- Scroll to DHCP Service Management → Static IP Settings (or “DHCP Reservations” depending on controller version)
- Click Add Static IP
- Enter the MAC address of your virtual machine and the desired IP
- Save
Removing Static IP in UniFi Network
- Open your UniFi Network controller
- Go to Client Devices and find your machine
- Click on the client to open its details
- Click Settings (gear icon)
- Under Network, disable Fixed IP Address
- Click Apply
Or via the network settings:
- Go to Settings → Networks
- Select your network
- Scroll to DHCP Service Management → Static IP Settings
- Find the reservation and click the trash icon to delete it
- Save
Your machine will receive a new dynamic IP on its next DHCP lease renewal or immediately if you run sudo dhclient -r && sudo dhclient eth0 on Debian.
Disable IPv6 on Debian installations and LXC containers
On LXC containers, you may also need to disable IPv6 at the host/container configuration level depending on your hypervisor, in Proxmox, uncheck the IPv6 DHCP/SLAAC option on the container’s network interface.
- Create the sysctl configuration file:
sudo touch /etc/sysctl.d/99-disable-ipv6.conf - Add the following:
sudo vi /etc/sysctl.d/99-disable-ipv6.conf
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
net.ipv6.conf.lo.disable_ipv6 = 1- Apply the changes:
sudo sysctl --systemVerify IPv6 is disabled:ip -6 addr, if the output is empty, IPv6 has been successfully disabled
Re-enable IPv6
- Remove the configuration file
/rm /etc/sysctl.d/99-disable-ipv6.conf - Apply the changes:
sudo sysctl --system
Setting a Static IPv4 on Debian
The UniFi reservation method is often cleaner since it centralizes IP management and your Debian machine remains configured for DHCP.
Setting a Static IPv4 on Debian
Method 1: Using /etc/network/interfaces
- Edit the interfaces file:
sudo vi /etc/network/interfaces - Replace the DHCP configuration for your interface (commonly
eth0,enp0s3, or similar):
# The primary network interface
auto eth0
iface eth0 inet static
address 192.168.1.100
netmask 255.255.255.0
gateway 192.168.1.1
dns-nameservers 1.1.1.1 8.8.8.8- Then restart networking:
sudo systemctl restart networking
Method 2: Using NetworkManager (if installed)
nmcli con mod "Wired connection 1" \
ipv4.addresses 192.168.1.100/24 \
ipv4.gateway 192.168.1.1 \
ipv4.dns "1.1.1.1,8.8.8.8" \
ipv4.method manual
nmcli con up "Wired connection 1"Switching Back to DHCP on Debian
Method 1: Using /etc/network/interfaces
- Edit the interfaces file:
sudo vi /etc/network/interfaces - Replace the static configuration with:
# The primary network interface
auto eth0
iface eth0 inet dhcp- Then restart networking:
sudo systemctl restart networking
Method 2: Using NetworkManager (if installed)
nmcli con mod "Wired connection 1" ipv4.method auto
nmcli con mod "Wired connection 1" ipv4.addresses ""
nmcli con mod "Wired connection 1" ipv4.gateway ""
nmcli con mod "Wired connection 1" ipv4.dns ""
nmcli con up "Wired connection 1"Ghostty terminal emulator
Terminals applications, especially on macOS and Linux have a setting that automatically sends your local environment variables to the remote server. If you’re using Ghostty as your terminal emulator, it identifies itself to the Raspberry Pi as xterm-ghostty and you’ll get: “Error opening terminal: xterm-ghostty”.
My sessions stopped trying to be a Ghostty terminal and instead use the universal standard xterm-256color defined in the ~/.config/zsh/.zshrc/.
I prefer to generate the right locale setting. If you want to prevent this from happening with other future servers without fixing the server side, you can tell your local computer to stop sending those variables by editing ~/.ssh/config or /etc/ssh/ssh_config and comment out the line SendEnv LANG LC_*. and restart the SSH service sudo systemctl restart ssh
If you want to keep using Ghostty’s specific advanced features such as specific keybindings, you can “upload” Ghostty’s definition to the Pi from your local computer, not inside a SSH session with infocmp -x xterm-ghostty | ssh username@hostname -- tic -x -
Troubleshooting
The Raspberry Pi uses blinking LEDs to communicate system health status without the need for a display:
- Red LED (power indicator)
- Solid: The system is receiving a steady 5V (specifically above 4.63V).
- Flashing: Warning; the power supply is providing insufficient voltage (Under-voltage).
- Off: The Pi has no power or has experienced a brownout.
- Green LED (Activity Indicator)
- Solid: Typically occurs during the first second of boot. If it remains solid, the Pi cannot read the SD card.
- Irregular Rapid Blinking: Normal operation; indicates the Pi is reading from or writing to the microSD card or EEPROM.
- Regular Rhythmic Blinking: Indicates a boot failure:
- 4 blinks: start.elf not found (SD card may be empty or corrupted).
- 7 blinks: kernel.img not found (The OS is corrupted).
- 8 blinks: SDRAM failure (Hardware issue).
-
It’s highly recommended to use a case with heatsinks or a fan, as the Pi 4 runs hot such as the Miuzei Aluminiun Raspberry Pi Case Passive Cooling with Heatsink Cooler ↩︎
-
Refer to the README.md for details about the
run_once_before_install-packages.sh↩︎ -
This is vital for Wi-Fi stability, fortunately I prefer wired connection ↩︎