Installing Ubuntu on a Raspberry Pi
Ubuntu 20.04 has been finally certified for the Raspberry Pi 4. This article explains how to get it up and running.
Table of Contents
Raspberry Pi 4 have got some impressive hardware upgrades such as USB 3 support, real Gigabit Ethernet and up to 8 GB of RAM. These features attract many self-hosting enthusiasts who use Raspberry Pi 4 as a server, and it works pretty well for many use cases. This tiny computer can easily host things like personal websites, Nextcloud instances or even full Bitcoin nodes.
Raspberry Pi 4 features impressive production-ready hardware but having reliable hardware is only a part of a self-hosting equation. Hardware is useless without an operating system, and the default operating system for Raspberry Pi is Raspbian. Unfortunately, it lacks many tools that are often necessary to set up and maintain a server. Don’t get me wrong: Raspbian is a decent OS, it just has different goals and priorities.
Folks at Canonical saw that opportunity and decided to compliment Raspberry Pi 4 hardware with their enterprise-grade Ubuntu operating system. In my opinion, it’s one of the most important events in Raspberry Pi’s history. Finally, it’s possible to buy a cheap and reasonably performant server which is officially compatible with one of the most popular and well-tested operating systems on the market.
- Raspberry Pi 4
- SD card (Ubuntu 20.04)
- SD card or any USB-attached storage device (Ubuntu 20.10 or newer)
My recommendation is to use an A1-marked SD card. Those cards are usually faster when it comes to random access, and it can be a bottleneck for many kinds of workloads such as running an operating system. You might stumble upon A2 cards and assume that they would perform even better but its unlikely that you would notice any difference (except for the higher price, of course).
With the release of Ubuntu 20.10, it’s now possible to forget about SD cards and use faster and more reliable storage devices such as SSD drives. You can use any USB-attached storage, but don’t expect to see any significant performance gains. Fast SSDs also need fast CPUs in order to unlock their full capacity, so the only real benefits you might get are safety and durability. SSDs are more likely to survive power outages, and they generally last longer under sustained loads.
Step 1: Wipe Your SD Card
First, you have to find the device name of your SD card. My Dell XPS 13 has an internal card reader, so the SD cards always appear at
/dev/mmcblk0 but it can be different if you use an external card reader. You should also make sure that your SD card is unmounted (
umount it, if necessary).
sudo dd if=/dev/zero of=/dev/mmcblk0 bs=16M status=progress
Be patient, it can take a while. That’s why it’s good to use
status=progress, we can see the progress and be assured that
dd did not just hang for some reason. Tweaking block size can speed things up quite a bit but I’d advice against that unless you know exactly what you’re doing.
If you want to lower the chances that you left any traces of the old data, you might prefer to use
if=/dev/urandom instead of
Step 2: Download Ubuntu
The latest version of Ubuntu can be downloaded from the official website.
Ubuntu images ship in a compressed format so we need to
unxz the downloaded file in order to extract the actual Ubuntu image that can be written on an SD card.
unxz --keep ubuntu-20.04-preinstalled-server-arm64+raspi.img.xz ls -lh
668M ubuntu-20.04-preinstalled-server-arm64+raspi.img.xz 3.0G ubuntu-20.04-preinstalled-server-arm64+raspi.img
Step 3: Write Ubuntu Image on Your SD Card
In case you’re not familiar with
if is short of input file and
of is short from output file.
sudo dd status=progress \ if=ubuntu-20.04-preinstalled-server-arm64+raspi.img \ of=/dev/mmcblk0
Finally, we should see something like that:
3200717312 bytes (3.2 GB, 3.0 GiB) copied, 649 s, 4.9 MB/s 6255474+0 records in 6255474+0 records out 3202802688 bytes (3.2 GB, 3.0 GiB) copied, 649.853 s, 4.9 MB/s
That should be it. Let’s check what do we have now on that SD card:
NAME FSTYPE LABEL UUID FSAVAIL FSUSE% MOUNTPOINT mmcblk0 ├─mmcblk0p1 vfat system-boot xxx 191.5M 24% /media/user/system-boot └─mmcblk0p2 ext4 writable xxx 762.2M 66% /media/user/writable
You can re-insert your SD card in order to trigger auto-mounting, so you don’t have to mount partitions to directories manually.
It looks like we need two partitions: first one is used by Raspberry Pi to boot up, and the second one hosts the operating system and all the data owned by its users.
sudo fdisk -l
Disk /dev/mmcblk0: 29.7 GiB, 31914983424 bytes, 62333952 sectors Units: sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disklabel type: dos Disk identifier: 0x00000000 Device Boot Start End Sectors Size Id Type /dev/mmcblk0p1 * 2048 526335 524288 256M c W95 FAT32 (LBA) /dev/mmcblk0p2 526336 6255439 5729104 2.7G 83 Linux
Note that those partitions do not take up all the free space on the SD card. The second partition will be expanded automatically once you boot up your Raspberry Pi.
Step 4: Set Up Wi-Fi (Optional)
The official image knows nothing about your Wi-Fi and that’s a pain in the ass, especially if you have a few Pi boards. Making your own custom Ubuntu image with Wi-Fi settings baked in can simplify setting up new machines or giving a fresh start to the existing ones.
First, let’s set up Wi-Fi (change
/media/user/ to your actual mount path):
network: version: 2 ethernets: eth0: dhcp4: true dhcp4-overrides: route-metric: 100 optional: true wifis: wlan0: dhcp4: true dhcp4-overrides: route-metric: 200 optional: true access-points: "your_access_point_name": password: "your_strong_password"
Note that both network interfaces are optional and
eth0 has a higher priority (
route-metric is set to lower value). In my opinion, this is the best configuration for most of the use cases. If you need only one of those interfaces, just remove the other one.
Raspberry Pi will read this config file only once, so it’s a good idea to double-check the config before powering on your Pi with this boot drive.
Step 5: Create Customized Image (Optional)
And the last step is to clone our customized Ubuntu to a separate
img file for later use. We don’t want to clone the whole SD card, just the part with the actual data, so:
sudo fdisk -l
This tool can show us a lot of useful info about all the block storage devices. We’re interested in sector size and end sector in particular.
Disk /dev/mmcblk0: 29.7 GiB, 31914983424 bytes, 62333952 sectors Units: sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disklabel type: dos Disk identifier: 0x87c6153d Device Boot Start End Sectors Size Id Type /dev/mmcblk0p1 * 2048 526335 524288 256M c W95 FAT32 (LBA) /dev/mmcblk0p2 526336 6255439 5729104 2.7G 83 Linux
6255439 * 512 =
3202784768 bytes or ~3.2 GB
Looks legit. Check your output and put your own numbers, if necessary. So, let’s create our custom image:
sudo dd status=progress bs=512 count=6255439 \ if=/dev/mmcblk0 \ of=ubuntu-20.04-custom-network-config.img
668M ubuntu-20.04-preinstalled-server-arm64+raspi.img.xz 3.0G ubuntu-20.04-preinstalled-server-arm64+raspi.img 3.0G ubuntu-20.04-custom-network-config.img
Step 6: First Boot
First, let’s unmount the SD card:
sudo umount /media/user/system-boot sudo umount /media/user/writable
Now, remove that SD card and insert it into your Raspberry Pi 4 board.
If your SD card already “knows” your Wi-Fi (see step 4), you don’t need to use wires in order to start using your Raspberry Pi. Let’s connect to it:
You’ll need to change your password immediately. The default one is
Let’s see how our partitions look now:
NAME FSTYPE LABEL UUID FSAVAIL FSUSE% MOUNTPOINT mmcblk0 ├─mmcblk0p1 vfat system-boot xxx 154.7M 39% /boot/firmware └─mmcblk0p2 ext4 writable xxx 25.3G 8% /
sudo fdisk -l
Disk /dev/mmcblk0: 29.74 GiB, 31914983424 bytes, 62333952 sectors Units: sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disklabel type: dos Disk identifier: xxx Device Boot Start End Sectors Size Id Type /dev/mmcblk0p1 * 2048 526335 524288 256M c W95 FAT32 (LBA) /dev/mmcblk0p2 526336 62333918 61807583 29.5G 83 Linux
Filesystem Size Used Avail Use% Mounted on /dev/mmcblk0p1 253M 98M 155M 39% /boot/firmware /dev/mmcblk0p2 29G 2.5G 26G 9% /
All fine, I guess we’re done here.
Step 7: Updating Software
Outdated software is a security threat, and you can also miss on new features and performance optimizations if you don’t keep your OS up do date. First, let’s check for new software updates:
sudo apt update
Hit:1 http://ports.ubuntu.com/ubuntu-ports focal InRelease Hit:2 http://ports.ubuntu.com/ubuntu-ports focal-updates InRelease Hit:3 http://ports.ubuntu.com/ubuntu-ports focal-backports InRelease Hit:4 http://ports.ubuntu.com/ubuntu-ports focal-security InRelease Reading package lists... Done Building dependency tree Reading state information... Done 74 packages can be upgraded. Run 'apt list --upgradable' to see them.
Looks like our Ubuntu needs some updating, let’s do it:
sudo apt upgrade
Raspberry Pi 4 + Ubuntu is a match made in heaven. Ubuntu is as easy to install as the official Raspbian distribution, and it can offer you more stability, convenience and a wider array of professional tools that are necessary to set up and maintain a server.