💾 Archived View for ibert.tech › articles › install-ubuntu-for-raspberry-pi-headless.gmi captured on 2023-06-14 at 13:43:30. Gemini links have been rewritten to link to archived content
⬅️ Previous capture (2023-05-24)
-=-=-=-=-=-=-
The download and installation instructions[1] will tell you that you need an HDMI cable or a serial cable. With a bit of preparation, that is actually not necessary.
I am assuming that you have a Linux machine with a Micro SD card reader/writer available. In my case, this also runs Ubuntu. I am also assuming you want to connect your Raspberry Pi to your wired network.
Get the image you want. The link to the download page is above. I have tried this with the 32 bit image of Ubuntu 20.04 LTS "Focal Fossa", trying to revive an old Raspberry PI 2B I had lying around.
Uncompress the image to a work directory. Put your Micro SD card into the reader. Find out how big your SD card is (dmesg is your friend, or use lsblk -b). In your work directory, create a file that is the size of your card, like in this example (I already knew that the card would be /dev/sdg, your mileage may vary):
% lsblk -b /dev/sdg NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT sdg 8:96 1 15931539456 0 disk % fallocate -l 15931539456 my_sd_card_image
Now overwrite the beginning of the file with the uncompressed image you downloaded. The special form of output redirection prevents the truncation of the file.
% cat diskimage 1<>my_sd_card_image
Next, create a loop device so you can work with the image. The -f parameter looks for the first free loop device, and the -P parameter forces the kernel to read the partition table and create the appropriate devices. You will need to do a lot of things as root now, so you can get a root shell at this point.
% sudo -i # losetup -fP --show my_sd_card_image /dev/loop3 # ls /dev/loop3* /dev/loop3 /dev/loop3p1 /dev/loop3p2
First, make the data partition bigger so that it spans the whole image. Currently, most of the image is actually not allocated. GPartEd is my preferred tool for this. Start it on the loop device for the whole image, and re-size the second partition to its maximum size. You can use fdisk and resize2fs if you want; it isn't difficult either.
# mount /dev/loop3p2 /mnt
Now let's edit some files. Make sure you don't edit the files on your machine under /etc but the files on the image under /mnt/etc!
Add a user for yourself. You do this by adding a line to /mnt/etc/passwd:
martini:x:1001:1001:Martin Ibert:/home/martini:/bin/bash
And this to /mnt/etc/shadow. The number 18192 should be replaced by the days since the epoch (expr $(date +%s) / 86400).
martini:*:18192:0:99999:7:::
Now edit /mnt/etc/group and add yourself to the following groups: adm sudo. Also add the following line:
martini:x:1001:
Edit /mnt/etc/sudoers so that the middle section reads as follows. The file is read-only, so you need to write it out with :x!.
# Allow members of group sudo to execute any command %sudo ALL=(ALL:ALL) ALL # Members of the adm group may gain root privileges %adm ALL=(ALL) NOPASSWD: ALL
Finally, give yourself a rudimentary home directory (obviously, use the SSH key you want, or use your regular authorized_keys file):
# mkdir -p /mnt/home/martini/.ssh # cp ~martini/.ssh/id_rsa_np.pub /mnt/home/martini/.ssh/authorized_keys # chmod 700 /mnt/home/martini/.ssh # chmod 600 /mnt/home/martini/.ssh/authorized_keys # chown -R 1001:1001 /mnt/home/martini
Unmount the image.
# umount /mnt
If you write the image with dd, it will take forever for a big Micro SD card. So we will be doing it differently.
First, we'll put the partition table on the card. That is in the first megabyte of the image:
# dd if=/dev/loop3 of=/dev/sdg count=2048 # ls /dev/sdg* /dev/sdg /dev/sdg1 /dev/sdg2
You now need partclone. Install it if you don't have it yet. We use it to quickly put just the data that means something onto the card, rather than dump a ton of blocks that have no useful data in them. (Output not shown.) The boot partition can be dumped normally as it is not very big. Make sure it is actually the size shown.
# dd if=/dev/loop3p1 of=/dev/sdg1 bs=256M # sync # partclone.ext4 -b -s /dev/loop3p2 -o /dev/sdg2
Don't panic if it seems to hang after saying Syncing.... If your machine has ample RAM, this is when the actual writing to the card will take place. Everything before that happens in memory if there is enough of it.
In goes the card, and then connect your Raspberry PI to your LAN and power it up. Watch your DHCP server to find out its address (in my case, I knew the MAC beforehand and could configure DHCP ahead of time, but if you don't, you need to find the latest device to get an address). It still takes a few seconds for the SSH server to come up after the address is assigned. All my Respberry Pis have MAC addresses beginning with b8:27:eb. The internet says that dc:a6:32 is also a possibility.
When you power up the Raspberry Pi, pay attention to the yellow LED. It should light up briefly. After that, nothing appears to be happening for a while. Be patient.
You should now be able to ssh into your Raspberry Pi and sudo from there to complete the configuration of the system.
Don't forget to destroy the loop device.
# losetup -d /dev/loop3
1: https://ubuntu.com/download/iot/raspberry-pi