Raspberry Pi 5 setup for a buddying coder
As a certain season approaches, I embarked in a little side quest: to setup a Raspberry Pi 5 for a good bro who is learning to code and wants to learn more about Linux as well. Since his goal is learning to code rather than (I hope) getting lost down the infinite rabbit holes of tinkering with the OS and tools, I set this up so he doesn't have to, but otherwise left it basic and uncomplicated.
Hardware
As this setup has been working quite well for Alfred, the hardware chosen is a the same except for the case, due to short-term availability:
- Raspberry Pi 5 8GB
- Samsung 990 EVO Plus (2000 GB, M.2 2280)
- Argon NEO 5 M.2 NVME PCIE Case for Raspberry Pi 5
- Raspberry Pi Official 5 power supply, 27W USB-C
Argon cases with NVMe extensions are tricky to assemble, one has to follow instructions carefully and make sure the PCIe cable is connected the right way and fully connected. This case actually came with two PCIe cables and a couple of spare screws, which is nice.
See also this In-Depth Review Raspberry Pi 5 Argon NEO 5 Case.
Install to NVMe SSD
To install Raspberry Pi Os directly on the NVMe drive, it goes first into an ICY BOX IB-1817M-C31 USB 3.1 NVMe enclosure, so the installation can be done on the SSD directl instead of using an Micro SD card.
Only the best for my bro, so I installed Raspberry Pi OS Full which is a port of Debian Trixie with desktop environment and recommended applications and came out only last month (Release date: 1 Oct 2025).
Tip
Always download Raspberry Pi OS images from the official Raspberry Pi OS downloads and check its SHA256 against the profided integrity hash.
Using rpi-imager there is no need to even download images manually, the tool does it
automatically once the Raspberry Pi model (device) and OS version is chosen. The tool
also allows setting a few basic parameter such as the password, WiFi network, etc.
Once the installation is done, the original partitions are replaced with just two
(bootfs, rootfs):
GPT would be necessary only if the disk is larger than 2TB.
Booting Pi from NVME greater than 2TB (GPT as opposed to MBR) includes manual instructions to install Raspberry Pi OS on a 4TB NVME using a GPT table. If you image a disk which is larger than 2TB with the Raspberry Pi tools or images, your disk will be limited to 2TB because they use MBR (Master Boot Record) instead of GPT (GUID partition table).
Custom partitions
It always felt odd, if not wrong, to run a Raspberry Pi with a large SSD disk without
having most of the space allocated to a separate partition (e.g. /home), so I took
the liberty of resizing the rootfs partition to mount most of the 2TB disk as /home.
Note
This may not be entirely useful when it comes to reinstalling the OS, since tools
like rpi-imager will anyway wipe the entire device regardless of partitions, and
in all honesty I am yet to reinstall the OS in any of my devices.
This involved deleting the root partitiona and then recreating it with a different size, to then create a new primary partition taking the rest of the disk.
For reference, see also:
Since the disk has old-fashined MBR partitions, fdisk can be used. Note that this
is done while the SSD is not yet installed in the Raspberry Pi, but on the USB adapter.
The starting point is that rpi-imager has created only a 512MB boot partition and a
8.5GB root partition:
# fdisk /dev/sdf
Welcome to fdisk (util-linux 2.39.3).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.
Command (m for help): p
Disk /dev/sdf: 1.82 TiB, 2000398934016 bytes, 3907029168 sectors
Disk model: SSD 990 EVO
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disklabel type: dos
Disk identifier: 0x796ebf23
Device Boot Start End Sectors Size Id Type
/dev/sdf1 16384 1064959 1048576 512M c W95 FAT32 (LBA)
/dev/sdf2 1064960 18792447 17727488 8.5G 83 Linux
Command (m for help): q
There is a small empty space before the first partition, which requires a bit of maneuviring around. Attempting to create new partitions with default values will first create a tiny 7MB partition at the start of the disk:
Command (m for help): n
Partition type
p primary (2 primary, 0 extended, 2 free)
e extended (container for logical partitions)
Select (default p): p
Partition number (3,4, default 3):
First sector (2048-3907029167, default 2048):
Last sector, +/-sectors or +/-size{K,M,G,T,P} (2048-16383, default 16383):
Created a new partition 3 of type 'Linux' and of size 7 MiB.
Command (m for help): n
Partition type
p primary (3 primary, 0 extended, 1 free)
e extended (container for logical partitions)
Select (default e): p
Selected partition 4
First sector (18792448-3907029167, default 18792448):
Last sector, +/-sectors or +/-size{K,M,G,T,P} (18792448-3907029167, default 3907029167):
Created a new partition 4 of type 'Linux' and of size 1.8 TiB.
Command (m for help): p
Disk /dev/sdf: 1.82 TiB, 2000398934016 bytes, 3907029168 sectors
Disk model: SSD 990 EVO
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disklabel type: dos
Disk identifier: 0x796ebf23
Device Boot Start End Sectors Size Id Type
/dev/sdf1 16384 1064959 1048576 512M c W95 FAT32 (LBA)
/dev/sdf2 1064960 18792447 17727488 8.5G 83 Linux
/dev/sdf3 2048 16383 14336 7M 83 Linux
/dev/sdf4 18792448 3907029167 3888236720 1.8T 83 Linux
Partition table entries are not in disk order.
Command (m for help): q
To make things more interesting, consider that a root partition of 8.5 GB may not be
enough. Despite having all user data in another patition, there are scenarios where a
lot more than 10 GB of space is needed for system files, e.g. the
Kubernetes cluster in octavo
has 45GB under /var/lib/containerd. In case this Raspberry Pi may developt such needs,
the root partition is resized to a generous 200MB; this involves the nerve-racking
operation of deleting that partition, to the re-created starting on the same sector:
- Start from the original 2 partitions; delete partitons 3 and 4 is previously created.
- Create partitioan 3 (7MB) to fill the odd gap at the stat of the disk.
- Delete partition 2 (root).
- Create new partition 2 starting on the same sector (1064960, which should be the
default, thanks to partition 3 filling the gap) with the desired size (e.g.
+200G). Do not delete theext4signature. - Create new partition 4 taking the rest of the space (default start and end).
- Delete partition 3; probably not necessary, just to reduce visual clutter.
- Write changes to the partition table, once
# fdisk /dev/sdf
Welcome to fdisk (util-linux 2.39.3).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.
Command (m for help): p
Disk /dev/sdf: 1.82 TiB, 2000398934016 bytes, 3907029168 sectors
Disk model: SSD 990 EVO
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disklabel type: dos
Disk identifier: 0x796ebf23
Device Boot Start End Sectors Size Id Type
/dev/sdf1 16384 1064959 1048576 512M c W95 FAT32 (LBA)
/dev/sdf2 1064960 18792447 17727488 8.5G 83 Linux
Command (m for help): n
Partition type
p primary (2 primary, 0 extended, 2 free)
e extended (container for logical partitions)
Select (default p): p
Partition number (3,4, default 3):
First sector (2048-3907029167, default 2048):
Last sector, +/-sectors or +/-size{K,M,G,T,P} (2048-16383, default 16383):
Created a new partition 3 of type 'Linux' and of size 7 MiB.
Command (m for help): d
Partition number (1-3, default 3): 2
Partition 2 has been deleted.
Command (m for help): n
Partition type
p primary (2 primary, 0 extended, 2 free)
e extended (container for logical partitions)
Select (default p): p
Partition number (2,4, default 2):
First sector (1064960-3907029167, default 1064960):
Last sector, +/-sectors or +/-size{K,M,G,T,P} (1064960-3907029167, default 3907029167): +200G
Created a new partition 2 of type 'Linux' and of size 200 GiB.
Partition #2 contains a ext4 signature.
Do you want to remove the signature? [Y]es/[N]o: n
Command (m for help): n
Partition type
p primary (3 primary, 0 extended, 1 free)
e extended (container for logical partitions)
Select (default e): p
Selected partition 4
First sector (420495360-3907029167, default 420495360):
Last sector, +/-sectors or +/-size{K,M,G,T,P} (420495360-3907029167, default 3907029167):
Created a new partition 4 of type 'Linux' and of size 1.6 TiB.
Command (m for help): p
Disk /dev/sdf: 1.82 TiB, 2000398934016 bytes, 3907029168 sectors
Disk model: SSD 990 EVO
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disklabel type: dos
Disk identifier: 0x796ebf23
Device Boot Start End Sectors Size Id Type
/dev/sdf1 16384 1064959 1048576 512M c W95 FAT32 (LBA)
/dev/sdf2 1064960 420495359 419430400 200G 83 Linux
/dev/sdf3 2048 16383 14336 7M 83 Linux
/dev/sdf4 420495360 3907029167 3486533808 1.6T 83 Linux
Partition table entries are not in disk order.
Command (m for help): d
Partition number (1-4, default 4): 3
Partition 3 has been deleted.
Command (m for help): p
Disk /dev/sdf: 1.82 TiB, 2000398934016 bytes, 3907029168 sectors
Disk model: SSD 990 EVO
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disklabel type: dos
Disk identifier: 0x796ebf23
Device Boot Start End Sectors Size Id Type
/dev/sdf1 16384 1064959 1048576 512M c W95 FAT32 (LBA)
/dev/sdf2 1064960 420495359 419430400 200G 83 Linux
/dev/sdf4 420495360 3907029167 3486533808 1.6T 83 Linux
Command (m for help): w
The partition table has been altered.
Calling ioctl() to re-read partition table.
Syncing disks.
One the root partition has the desired size, it is possible to resize the Ext4 file system in it; but first one has to run a file system check:
# resize2fs /dev/sdf2 200G
resize2fs 1.47.0 (5-Feb-2023)
Please run 'e2fsck -f /dev/sdf2' first.
# e2fsck -f /dev/sdf2
e2fsck 1.47.0 (5-Feb-2023)
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
rootfs: 183284/554880 files (0.1% non-contiguous), 1954143/2215936 blocks
# resize2fs /dev/sdf2 200G
resize2fs 1.47.0 (5-Feb-2023)
Resizing the filesystem on /dev/sdf2 to 52428800 (4k) blocks.
The filesystem on /dev/sdf2 is now 52428800 (4k) blocks long.
# e2fsck /dev/sdf2
e2fsck 1.47.0 (5-Feb-2023)
rootfs: clean, 183284/13056000 files, 2741779/52428800 blocks
# mkfs.ex /dev/sdf4
mkfs.exfat mkfs.ext2 mkfs.ext3 mkfs.ext4
# mkfs.ext4 /dev/sdf4
mke2fs 1.47.0 (5-Feb-2023)
Creating filesystem with 435816726 4k blocks and 108961792 inodes
Filesystem UUID: 95b56139-4931-4dac-ab92-859e0d576453
Superblock backups stored on blocks:
32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208,
4096000, 7962624, 11239424, 20480000, 23887872, 71663616, 78675968,
102400000, 214990848
Allocating group tables: done
Writing inode tables: done
Creating journal (262144 blocks): done
Writing superblocks and filesystem accounting information: done
At this point the resized file system can be mounted, which will come in handy later.
# mount /dev/sdf2 /mnt
# ls /mnt/
bin boot dev etc home lib lost+found media mnt opt proc root run sbin srv sys tmp usr var
# ls /mnt/home/
pi rpi-first-boot-wizard
Pre-boot tweaks
The following adjustments can be make by editing files in the boot partition (sdf1)
before booting the Raspberry Pi OS for the first time; mount it under /mnt/boot
once the root file system is mounted on /mnt.
Note
This partition will be mounted as /boot/firmware after booting the Raspberry
Pi OS for the first time.
PCIe Gen 3
NVMe SSD boot with the Raspberry Pi 5, at least with this Argon ONE case, turned out to
be easy. When using a HAT+-compliant NVMe adapter, there is no need to enable
the external PCIe port, it will be enabled automatically, but it is useful to
force PCIe Gen 3 speeds using these options in /mnt/boot/config.txt
Enable CGroups
Troubleshooting Bootstrap
for Kubernetes on the previous Raspberry Pi OS revealed that the required CGroups
are not enabled by default. Since these may be needed by popular development tools,
e.g. to run in Docker, enable these in /mnt/boot/cmdline.txt
cgroup_enable=cpuset cgroup_memory=1 cgroup_enable=memory console=serial0,115200 console=tty1 root=PARTUUID=796ebf23-02 rootfstype=ext4 fsck.repair=yes rootwait resize quiet splash plymouth.ignore-serial-consoles cfg80211.ieee80211_regdom=CH systemd.run=/boot/firstrun.sh systemd.run_success_action=reboot systemd.unit=kernel-command-line.target
System Configuration
WiFi (re)configuration
Just as it happened with Alfred,
the WiFi connection was not established even though the system booted just fine the
first time. Instead of going through the menus with raspi-config, access via SSH was
gained by connecting the device to the LAN, which naturally worked like a charm:
pi@roach:~ $ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host noprefixroute
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether 88:a2:9e:10:1b:5d brd ff:ff:ff:ff:ff:ff
inet 192.168.0.70/24 brd 192.168.0.255 scope global dynamic noprefixroute eth0
valid_lft 86268sec preferred_lft 86268sec
inet6 fe80::6e5d:6e2d:f3cf:d040/64 scope link noprefixroute
valid_lft forever preferred_lft forever
3: wlan0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc fq_codel state DOWN group default qlen 1000
link/ether 88:a2:9e:10:1b:5e brd ff:ff:ff:ff:ff:ff
Additional WiFi networks
How to add a second WiFi network to your Raspberry Pi (updated for OS Bookworm) explains how the wpa_supplicant.conf file is no longer used to configure Wi-Fi connections and, instead, the current Raspberry Pi OS (based on Bookworm) uses NetworkManager to manage network connections, including Wi-Fi.
There is a separate configuration file for each WiFi connection under
/etc/NetworkManager/system-connections, all it takes to configure additional
WiFi connections is to
- Copy a working file with a new name (e.g. the SSID name).
- Replace the SSID and password.
- Replace the
idwith a new unique value of choice. - Replace the
uuidwith a new unique value from runninguuid. - Set the permissions to
600
This can be done in advance of replacing WiFi access points, etc.
WiFi connections are not effective immediately after rebooting, but after a couple of
minutes there is a new IP address assigned to the wireless device (wlan0):
pi@roach:~ $ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host noprefixroute
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether 88:a2:9e:10:1b:5d brd ff:ff:ff:ff:ff:ff
inet 192.168.0.70/24 brd 192.168.0.255 scope global dynamic noprefixroute eth0
valid_lft 79805sec preferred_lft 79805sec
inet6 fe80::6e5d:6e2d:f3cf:d040/64 scope link noprefixroute
valid_lft forever preferred_lft forever
3: wlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether 88:a2:9e:10:1b:5e brd ff:ff:ff:ff:ff:ff
inet 192.168.0.71/24 brd 192.168.0.255 scope global dynamic noprefixroute wlan0
valid_lft 84609sec preferred_lft 84609sec
inet6 fe80::8194:2d69:f7fb:c23e/64 scope link noprefixroute
valid_lft forever preferred_lft forever
At this point the wired connecion to the LAN network can be removed.
Disable power save for WiFi
Raspberry Pi enables power save on WiFi by default:
[ 5.598286] brcmfmac: F1 signature read @0x18000000=0x15264345
[ 5.600446] brcmfmac: brcmf_fw_alloc_request: using brcm/brcmfmac43455-sdio for chip BCM4345/6
[ 5.600754] usbcore: registered new interface driver brcmfmac
[ 5.790052] brcmfmac: brcmf_c_process_txcap_blob: no txcap_blob available (err=-2)
[ 5.790325] brcmfmac: brcmf_c_preinit_dcmds: Firmware: BCM4345/6 wl0: Aug 29 2023 01:47:08 version 7.45.265 (28bca26 CY) FWID 01-b677b91b
[ 6.423812] brcmfmac: brcmf_cfg80211_set_power_mgmt: power save enabled
This can lead to losing connectivity in certain conditions, so disable power save of WiFi to avoid having to deal with such problems like Reconnect on WiFi drop.
Fix locales
The above looks like rpi-imager took my PC’s locale settings:
The solution is to generate en_US.UTF-8 and set it as the system default. To do this,
run raspi-config and go into 5. Localisation Options then L1 Locale, enable
en_US.UTF-8 and set it as the Default locale for the system environment.
$ sudo raspi-config
...
Generating locales (this might take a while)...
en_GB.UTF-8... done
en_US.UTF-8... done
Generation complete.
To Swap Or Not To Swap
With 8 GB of RAM there should be no reason to need disk swap, never mind that it would be rather fast in this system. Besides, Kubernetes doesn't like swap and similar issues may be encountered by other tools. On the other hand, running a desktop environment and compilers could lead to actually neededing swap.
Therefore, instead of directly disabling swap entirely, lets leave its default setup.
Debian 13 (Trixie), on which Raspberry Pi OS is based, introduced a different mechanism for enabling and disabling the swap file. View which swap units are running:
pi@roach:~ $ systemctl list-units --quiet --type=swap
dev-zram0.swap loaded active active rpi-swap managed swap device (zram+file)
The default configuration is to automatically create swap when needed. To entirely
disable it, create /etc/rpi/swap.conf.d/99-disable-swap.conf with the contents:
Then stop the running swap unit:
pi@roach:~ $ sudo systemctl daemon-reload
pi@roach:~ $ systemctl list-units --quiet --type=swap
dev-zram0.swap loaded active active Compressed Swap on /dev/zram0
pi@roach:~ $ sudo systemctl stop dev-zram0.swap
pi@roach:~ $ systemctl list-units --quiet --type=swap
But for now, let leave it at its default configuration.
Install latest updates
Before moving forward, make sure the system is up-to-date:
pi@roach:~ $ sudo apt update
Hit:1 http://deb.debian.org/debian trixie InRelease
Hit:2 http://deb.debian.org/debian trixie-updates InRelease
Hit:3 http://archive.raspberrypi.com/debian trixie InRelease
Hit:4 http://deb.debian.org/debian-security trixie-security InRelease
129 packages can be upgraded. Run 'apt list --upgradable' to see them.
$ sudo apt full-upgrade -y
Upgrading:
agnostics libssl3t64 raspi-utils rpicam-apps-opencv-postprocess
bluez-firmware libswresample5 raspi-utils-core rpicam-apps-preview
chromium libswscale8 raspi-utils-dt rpinters
chromium-common libtiff6 raspi-utils-eeprom userconf-pi
chromium-l10n libvlc-bin raspi-utils-otp vlc
chromium-sandbox libvlc5 raspinfo vlc-bin
ffmpeg libvlccore9 rasputin vlc-data
firefox lpplug-bluetooth rc-gui vlc-l10n
ghostscript lpplug-clock rp-bookshelf vlc-plugin-access-extra
gui-pkinst lpplug-ejecter rp-prefapps vlc-plugin-base
gui-updater lpplug-menu rpcc vlc-plugin-notify
libavcodec61 lpplug-netman rpd-applications vlc-plugin-qt
libavdevice61 lpplug-power rpd-common vlc-plugin-samba
libavfilter10 lpplug-updater rpd-developer vlc-plugin-skins2
libavformat61 lpplug-volumepulse rpd-graphics vlc-plugin-video-output
libavutil59 lxpanel-pi rpd-preferences vlc-plugin-video-splitter
libcamera-ipa mesa-libgallium rpd-theme vlc-plugin-visualization
libcamera-tools mesa-vulkan-drivers rpd-utilities wayvnc
libcamera-v4l2 openjdk-21-jre rpd-wayland-core wf-panel-pi
libcamera0.5 openjdk-21-jre-headless rpd-wayland-extras wfplug-bluetooth
libdtovl0 openssl rpd-x-core wfplug-clock
libegl-mesa0 openssl-provider-legacy rpd-x-extras wfplug-connect
libgbm1 pipanel rpi-chromium-mods wfplug-ejecter
libgl1-mesa-dri piwiz rpi-connect wfplug-menu
libglx-mesa0 pplug-ejecter-data rpi-eeprom wfplug-netman
libgpiolib0 pplug-netman-schema rpi-firefox-mods wfplug-power
libgs-common pplug-power-data rpi-loop-utils wfplug-updater
libgs10 pplug-updater-data rpi-swap wfplug-volumepulse
libgs10-common pprompt rpi-userguide xserver-common
libpisp-common python3-libcamera rpicam-apps xserver-xorg-core
libpisp1 raindrop rpicam-apps-core
libpostproc58 raspberrypi-sys-mods rpicam-apps-encoder
librpicam-app1 raspi-config rpicam-apps-lite
Installing dependencies:
alacarte gir1.2-gmenu-3.0 gnome-menus libgnome-menu-3-0 qt6ct
Summary:
Upgrading: 129, Installing: 5, Removing: 0, Not Upgrading: 0
Download size: 463 MB
Space needed: 27.6 MB / 191 GB available
Update EEPROM
Then again, before moving forward, and especially because it was necessary to fix a
Failed Argon installation on Alfred,
use raspi-config to update the bootloader
and set it to Latest (without resetting config). This updated the EEPROM from a
May release to a November release, less than a week old:
pi@roach:~ $ sudo rpi-eeprom-update -l
/usr/lib/firmware/raspberrypi/bootloader-2712/default/pieeprom-2025-05-08.bin
pi@roach:~ $ ls -l /usr/lib/firmware/raspberrypi/bootloader-2712/default/
total 2152
-rw-r--r-- 1 root root 2097152 Nov 6 13:30 pieeprom-2025-05-08.bin
-rw-r--r-- 1 root root 102992 Nov 6 13:30 recovery.bin
pi@roach:~ $ sudo raspi-config
pi@roach:~ $ sudo rpi-eeprom-update -l
/usr/lib/firmware/raspberrypi/bootloader-2712/latest/pieeprom-2025-11-05.bin
Reboot after updating the EEPROM; and definitely before moving forward.
Argon case scripts
The instructions in page 10 of the Argon NEO 5 M.2 NVME PCIE case manual to install the scripts for FAN control seem simple enough:
curl https://download.argon40.com/argon-eeprom.sh | bash
pi@roach:~ $ curl https://download.argon40.com/argon-eeprom.sh | bash
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 1059 100 1059 0 0 16607 0 --:--:-- --:--:-- --:--:-- 16809
*************
Argon Setup
*************
Hit:1 http://deb.debian.org/debian trixie InRelease
Get:2 http://deb.debian.org/debian trixie-updates InRelease [47.3 kB]
Hit:3 http://archive.raspberrypi.com/debian trixie InRelease
Hit:4 http://deb.debian.org/debian-security trixie-security InRelease
Fetched 47.3 kB in 0s (485 kB/s)
Reading package lists... Done
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
Calculating upgrade... Done
0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
BOOTLOADER: up to date
CURRENT: Wed Nov 5 05:37:18 PM UTC 2025 (1762364238)
LATEST: Wed Nov 5 05:37:18 PM UTC 2025 (1762364238)
RELEASE: latest (/usr/lib/firmware/raspberrypi/bootloader-2712/latest)
Use raspi-config to change the release.
Updating bootloader EEPROM
image: /usr/lib/firmware/raspberrypi/bootloader-2712/latest/pieeprom-2025-11-05.bin
config_src: blconfig device
config: /tmp/tmp43cskz0p/boot.conf
################################################################################
[all]
WAKE_ON_GPIO=0
POWER_OFF_ON_HALT=1
PCIE_PROBE=1
BOOT_UART=1
BOOT_ORDER=0xf416
NET_INSTALL_AT_POWER_ON=1
################################################################################
*** To cancel this update run 'sudo rpi-eeprom-update -r' ***
*** CREATED UPDATE /tmp/tmp43cskz0p/pieeprom.upd ***
CURRENT: Wed Nov 5 05:37:18 PM UTC 2025 (1762364238)
UPDATE: Wed Nov 5 05:37:18 PM UTC 2025 (1762364238)
BOOTFS: /boot/firmware
'/tmp/tmp.rxzVUvjeh8' -> '/boot/firmware/pieeprom.upd'
UPDATING bootloader. This could take up to a minute. Please wait
*** Do not disconnect the power until the update is complete ***
If a problem occurs then the Raspberry Pi Imager may be used to create
a bootloader rescue SD card image which restores the default bootloader image.
flashrom -p linux_spi:dev=/dev/spidev10.0,spispeed=16000 -w /boot/firmware/pieeprom.upd
Verifying update
VERIFY: SUCCESS
UPDATE SUCCESSFUL
After a required reboot, run the argonneo5.sh script too:
curl https://download.argon40.com/argonneo5.sh | bash
pi@roach:~ $ curl https://download.argon40.com/argonneo5.sh | bash
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 2171 100 2171 0 0 46338 0 --:--:-- --:--:-- --:--:-- 47195
*************
Argon Setup
*************
Hit:1 http://deb.debian.org/debian trixie InRelease
Hit:2 http://archive.raspberrypi.com/debian trixie InRelease
Hit:3 http://deb.debian.org/debian trixie-updates InRelease
Hit:4 http://deb.debian.org/debian-security trixie-security InRelease
Reading package lists... Done
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
Calculating upgrade... Done
0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
BOOTLOADER: up to date
CURRENT: Wed Nov 5 05:37:18 PM UTC 2025 (1762364238)
LATEST: Wed Nov 5 05:37:18 PM UTC 2025 (1762364238)
RELEASE: latest (/usr/lib/firmware/raspberrypi/bootloader-2712/latest)
Use raspi-config to change the release.
EEPROM settings up to date
*********************
Setup Completed
*********************
Please reboot for changes to take effect
After another required reboot, the firware is ready and there is nothing to do.
Essential Software
Basic packages
Before moving forward, I like to install a few basics that make work easier, or on which subsequent packages depend:
$ sudo apt install -y bc git iotop-c netcat-openbsd rename speedtest-cli sysstat \
vim python3-pip python3-influxdb python3-numpy python3-absl python3-unidecode
Fail2Ban
Just in case this system ever gets its port 22 exposed to the Internet, Fail2Ban scans log files and bans IP addresses conducting too many failed login attempts. It is a rather basic protection mechanism, and this system is not intended to have its SSH port open to the Internet, but it is so easy to install and enable that there is no excuse not to.
The configuration in /etc/fail2ban/jail.conf can be spiced up to make a
little more trigger-happy:
# "bantime" is the number of seconds that a host is banned.
bantime = 12h
# A host is banned if it has generated "maxretry" during the last "findtime"
# seconds.
findtime = 90m
# "maxretry" is the number of failures before a host get banned.
maxretry = 3
# "bantime.increment" allows to use database for searching of previously banned ip's to increase a
# default ban time using special formula, default it is banTime * 1, 2, 4, 8, 16, 32...
bantime.increment = true
Then restart the service to pick the changes up:
SSH Server
As a general good practice, even if this system won't have its SSH port open to the
Internet, and on top of having Fail2ban enabled, SSH authetication should
be allowed only with
What is SSH Public Key Authentication?.
Once the system arrives as it final destination, its final owner should add their own
public keys are added to /home/pi/.ssh/authorized_keys and disable password
authentication by setting PasswordAuthentication no in /etc/ssh/sshd_config.
This tutorial explains several concrete methods to the this on different platforms: Set up SSH public key authentication to connect to a remote system.
Additional Software
Additional Debian packages
The following packages are installed based on experience setting up desktop environments in other PCs, most recently Ubuntu Studio 24.04 for myself and a young artist.
$ sudo apt install -y gkrellm gkrellm-cpufreq geeqie id3v2 btop sox exiv2 rename \
scrot python3-pip python3-selenium tor unrar ttf-mscorefonts-installer ffmpeg \
iotop-c xdotool redshift-gtk inxi screen code
Visual Studio Code
Installing the code package is the canonical method to install
VS Code on Raspberry Pi.
VS Code is not officially supported on Raspberry Pi, so it pays to keep an eye on their
community discussions
for update and known issues and workarounds. One notorious known issue has been freezes
on Raspberry Pi 4, for which the workaround is to disable use of the GPU by adding this
flag in /home/pi/.vscode/argv.json
This workaround may not be necessay for the more recent versions of VS Code, and the version installed at the time of writting is 1.105.1.
Raspberry Pi Connect
Raspberry Pi Connect provides secure access to your Raspberry Pi from anywhere in the world. While it is unsurprisingly a little laggy, it works well enough to use the desktop environment from any web browser anywhere without a complicated setup.
Following the instructions is simple and quick enough to access the desktop environment within a couple of minutes, it can be enabled and disabled any time through SSH and it can also be added to (and remove from) a Raspberry Pi Connect account very easily.
To connect, start the rpi-connect service and create a URL to sing in, then visit
that URL with the browser with an active session on https://connect.raspberrypi.com/
pi@roach:~ $ rpi-connect on
✓ Raspberry Pi Connect started
pi@roach:~ $ rpi-connect signin
Complete sign in by visiting https://connect.raspberrypi.com/verify/XEKA-TPFN
✓ Signed in
Once the device is signed in, it shows up at https://connect.raspberrypi.com/devices and it's just two clicks to open the desktop environment in a new browser window:
Once this access is no longer necessary, the service can be disabled on the Raspberry Pi
by simply running rpi-connect off and running rpi-connect signout before will
deassociated from the previously used Raspberry Pi Connect account.



