Milestone 2: Alpine Linux
For this milestone, you will obtain a customized version of Alpine Linux, copy it onto a MicroSD card, boot your Raspberry Pi from that card, and perform a basic Alpine Linux installation onto the card.
- Milestone Worksheet
- Background
- Procedure
- Materials
- Step 1: Access the MicroSD Card
- Step 2: Download and Extract the ZIP File
- Step 3: Copy Files onto the MicroSD Card
- Step 4: Properly Eject the MicroSD Card
- Step 5: Insert the MicroSD Card into the Pi
- Step 6: Boot the Raspberry Pi
- Step 7: Adjust Keyboard Layout
- Step 8: Set Hostname
- Step 9: Configure Timezone
- Step 10: Set the Root Password
- Step 11: Copy Files into RAM
- Step 12: Change Repository Location
- Step 13: Repartition the MicroSD Card
- Step 14: Create the File Systems
- Step 15: Mount the MicroSD Card
- Step 16: Install the System
- Step 17: Reboot Onto the New System
- Submission Checklist
- ABET Assessment
Milestone Worksheet
Please download the following worksheet Milestone 2. To be sure your browser downloads the file instead of trying to open it, right-click the following link and choose “Save As,” “Save Link As,” or similar language from the menu. (Each browser is a little different in what wording it uses.)
Background
Please read Overview of Alpine Linux for a basic overview of Alpine Linux. As you read through the background material, complete the top part of the Milestone Worksheet.
Note that you will be using a customized distribution of Alpine Linux that I have created especially for this course. The stock version of Alpine Linux doesn’t support offline installs, and its default wireless networking stack does not work well with newer WiFi standards or with eduroam on campus. My customized version fixes these issues.
The basic process we’ll be using to obtain and install Alpine Linux is as follows:
- Download the customized Alpine Linux distribution from Moodle.
- Extract the downloaded ZIP file, and copy its contents onto a blank MicroSD card.
- Boot the Raspberry Pi from the MicroSD card.
- Perform basic configuration of Alpine Linux while running from RAM.
- Use the RAM-based environment to re-partition the MicroSD card and install Alpine into it.
- Reboot onto the installed version of Alpine Linux.
Procedure
This milestone procedure is structured as a step-by-step tutorial. It is important to complete the steps in order and carefully. Missing a step or performing a step incorrectly will likely lead to problems in later steps and/or later milestones.
Materials
For this procedure, you need:
- Your assembled Raspberry Pi 5 kit, connected to a monitor or TV, keyboard, and mouse.
- The Raspberry Pi 5 power supply (do NOT plug it in yet).
- A blank MicroSD card.
- A MicroSD card reader attached to your computer.
Note that a “blank” MicroSD card actually contains a single partition formatted with the FAT32 file system. Notes are included below in case you need to reuse a MicroSD card or find that your computer doesn’t recognize it when you plug in the card via the USB MicroSD card reader.
Step 1: Access the MicroSD Card
Put the MicroSD card into the card reader, checking that the side with the metal contacts is facing the contacts inside the card reader. Plug the card reader into your computer. You should see a single, empty drive appear, as illustrated in Figure 1. Note that your operating system’s file explorer may look different.
Troubleshooting Step 1
If you don’t see a single drive appear when you plug in your MicroSD card, or if you need to reuse an existing MicroSD card, follow the steps below for your operating system. Be sure to back up any data you need to save from an existing MicroSD card if you are reusing one, since this process is destructive. Be sure to use the FAT32 or MS-DOS format! Do not use the exFAT format, as the Raspberry Pi 5 hardware doesn’t support booting from an exFAT file system.
- Formatting a MicroSD Card in Linux
- How to Format Any SD Card to FAT32 on Mac
- Lifewire: How to Format an SD Card on Windows
Step 2: Download and Extract the ZIP File
Download this semester’s Alpine Linux ZIP file from the course Moodle site. The file is linked directly under the Milestone 2 assignment activity. Extract the contents of the ZIP file into a new folder on your system.
Step 3: Copy Files onto the MicroSD Card
Copy the extracted files, but not the ZIP file itself, into the root of the MicroSD card (not into a folder on the card!). The copied files should resemble Figure 2.
Step 4: Properly Eject the MicroSD Card
Safely eject the MicroSD card device using the tools provided by your operating system. On macOS, there is usually an eject button in the Finder. Windows machines will normally have a removable drives icon in the system tray with a menu for safe removal of the drive. Failure to eject the drive properly may cause it not to work on the Pi.
Step 5: Insert the MicroSD Card into the Pi
Carefully remove the MicroSD card from the card reader and insert it into the slot on the bottom of the Raspberry Pi. The metal contacts on the MicroSD card should be facing the Raspberry Pi circuit board. Insert the card gently, and do not try to force it.
Step 6: Boot the Raspberry Pi
Connect the Raspberry Pi 5 power supply to the Pi, and plug it into an AC outlet. The Pi should start up automatically and boot from the MicroSD card. You should reach a login prompt. Type:
root
and press Enter to log in as root. There is no password set at this time, and Alpine Linux is running entirely from RAM. Changes you make in the following steps will not be persistent until you start changing the MicroSD card in Step 13, so you need to re-run all steps starting from this one if you need to shut down the Pi or lose power before Step 13.
Step 7: Adjust Keyboard Layout
We need to be sure we’re using the “us” keyboard layout so that the keys generate the correct characters when pressed. Run:
setup-keymap us us
You shouldn’t see any error messages.
Step 8: Set Hostname
The next step is to configure the system hostname. For this step, use your CCU username followed by a dash (-) followed by csci311 as the base hostname, with coastal.edu as the domain. For example, my installation would have hostname mmurphy2-csci311, giving a fully-qualified domain name (FQDN) of mmurphy2-csci311.coastal.edu. Substitute your own username accordingly.
There are 3 steps to setting the hostname. First, run:
setup-hostname mmurphy2-csci311.coastal.edu
Again, substitute your username accordingly.
Then, you will need to use the vi editor to edit the /etc/hosts file:
vi /etc/hosts
Add both the hostname and the FQDN to each line of the hosts file. The result should look like the following (with your hostname substituted, of course):
127.0.0.1 localhost localhost.localdomain mmurphy2-csci311 mmurphy2-csci311.coastal.edu
::1 localhost localhost.localdomain mmurphy2-csci311 mmurphy2-csci311.coastal.edu
Once you’ve made the changes in vi, save the file and exit the editor. Make the new hostname effective by running:
rc-service hostname restart
You can ignore the warning about stopping a boot service. This warning is normal for any service that is configured to start early.
Step 9: Configure Timezone
Alpine Linux uses the musl C library instead of the glibc library used on most other Linux distributions. To map the UTC time used by the RTC on the Raspberry Pi to the current Eastern wall clock time, the musl library uses the TZ environment variable. This variable specifies the name of the timezone to use. Our timezone is known as “America/New_York” in Linux timezone data.
First, be sure the timezone data is available in the live environment by running:
apk add tzdata
To set the timezone in the installation environment, we just need to set and export the TZ environment variable. Note the single quotes around the timezone name:
export TZ='America/New_York'
When the actual installation step occurs, certain files in the installation environment are copied onto the installed system. One of these files is a persistent file to set the timezone each time you log into the system. Go ahead and create this file by running:
vi /etc/profile.d/timezone.sh
In this file, we just need to put in the same command we ran by hand above:
export TZ='America/New_York'
Save the file and exit vi. The timezone step is now complete.
Step 10: Set the Root Password
The root password from the installer environment will be copied onto the installed system. However, as you may recall from a few minutes ago, you could log into the root account with no password. This is bad from a security perspective, so we definitely want to set a root password by running:
passwd
Note that you won’t see any text while typing in the password, not even placeholder characters like *. This is a security feature, as it prevents someone looking over your shoulder from knowing the length of your password.
Try to choose a good password, but be sure it’s one that you can remember! You will need to be able to log in as root for the next several assignments.
Step 11: Copy Files into RAM
We’re going to use the live environment into which the Pi has been booted in order to repartition the MicroSD card and install Alpine Linux onto that card. Since we’re reusing the same card from which we booted, we first need to copy important files into our live environment, which is running on a ramdisk, which is a storage device that exists entirely in the Pi’s Random Access Memory (RAM). Remember that RAM is volatile, and its contents will be lost if the Pi loses power! Be especially careful not to bump the power adapter while you perform the rest of the steps in this milestone. If you should lose power, it is unfortunately necessary to restart the whole procedure from Step 1.
First, we need to stop the modloop service, which is used to hold kernel modules and firmware. Since we’ve already booted the system, these modules and firmware files have already been loaded, so it is now safe to unmount their persistent storage location. To do so, run:
rc-service modloop stop
Before we unmount the MicroSD card completely, we need to copy the Alpine Linux packages that the installer requires into our ramdisk. Run:
cp -r /media/mmcblk0p1/apks /root
Now we can unmount the MicroSD card:
umount /media/mmcblk0p1
Check for any errors in the above command. If you didn’t successfully stop the modloop service first, you will get a “device busy” message, and the unmount will fail. Re-run the command to stop the modloop, then retry unmounting.
Verify that /dev/mmcblk0p1 is unmounted by running:
mount
Scan the output of the mount command, and be sure that there are no references to /dev/mmcblk0 in that output.
Step 12: Change Repository Location
At boot time, Alpine Linux set up the package repository on the MicroSD card automatically. We copied that repository into the root user’s home directory (/root/apks), so we need to fix the repository location. Run:
vi /etc/apk/repositories
Change the contents of that file to a single line that reads:
/root/apks
Save the file and exit vi.
To test our changes, run:
apk update
You should not see any error messages in the output.
Step 13: Repartition the MicroSD Card
Up to this point, all the changes we have made exist only in RAM. We’re now going to start making changes to the MicroSD card itself. If anything does wrong with these changes, you will no longer be able to boot the Pi from this MicroSD card and will have to restart the procedure at Step 1. Be careful!
To repartition the MicroSD card, we’re going to use the fdisk program, which is an interactive program that presents menus and uses typed commands to operate. Start it by running:
fdisk /dev/mmcblk0
Carefully do the following in fdisk:
- Type p and press Enter to show the starting partition table. You likely have a single partition on the MicroSD card.
- Type o and press Enter to create a new DOS-style partition table.
- Type n and press Enter to create a new partition in the new table.
- We want a primary partition, so type p and press Enter.
- This new partition will be partition number 1 (so type 1 and press Enter).
- Just press Enter to accept the default starting sector (2048). This starting sector aligns the partition with the storage device for performance reasons.
- For the ending sector, type +750M to create a partition that is 750 MiB in size.
- If you are asked a question like “Do you want to remove the signature?”, answer y for yes.
- The new partition should have been created. Type p and press Enter to show it.
- Now we need to create a second partition. Run the “n” command again.
- This second partition is also a primary partition.
- The partition number is 2.
- Press Enter to accept the default starting sector.
- Press Enter to accept the default ending sector, which will cause the partition to fill up the rest of the MicroSD card.
- Display the partition table again with the p command. You should have two partitions: one of them 750 MiB in size and the other one using the rest of the MicroSD card.
- The Raspberry Pi requires that the first partition contain a FAT, or MS-DOS, file system in order to be able to boot. We need to change the partition type away from a Linux partition for this purpose. Run the t command to change the partition type.
- Select partition 1.
- For the type code, enter c and press Enter. This is the partition type code for “W95 FAT32 (LBA),” which is what we want in this case.
- Verify the new partition table one more time with the p command. You should have a 750 MiB partition of type W95 FAT32 (LBA) and a partition of type Linux that uses up the rest of the MicroSD card. If something doesn’t look right, go back to #2 and recreate your table.
- To save the partition table and exit fdisk, run the w command.
Once you’re out of the fdisk program, it is necessary to ask the device manager to rescan for hardware changes so that the partitions we created become available. Run:
mdev -s
Before going on to the next step, run:
ls /dev/mmcblk0*
You should see /dev/mmcblk0, /dev/mmcblk0p1, and /dev/mmcblk0p2 in the output. If not, something went wrong with this step. Simply redo this step from the beginning to fix it.
Step 14: Create the File Systems
When we created the partitions on the MicroSD card in the previous step, we created them as blank partitions. In order to store files in them, we need to create file systems first. For our first partition, we need a FAT32 file system. Create that using:
mkfs.vfat -n CSCI311 /dev/mmcblk0p1
Note that vfat is another name for FAT32 (technically, mkfs.vfat can choose a different FAT file system type for smaller devices, but for any modern device, it will select FAT32). We name this partition CSCI311, just in case you ever need to put the MicroSD card back into your computer. Windows and macOS can see this partition, since they both support FAT32 file systems. However, they won’t be able to see the next file system we’ll be creating by running:
mkfs.ext4 -L fs_root /dev/mmcblk0p2
This command creates a Linux 4th Extended File System (ext4) on the second partition of the MicroSD card.
Step 15: Mount the MicroSD Card
First, we need to mount the device that we will be using as the root (/) of our new installation. This device will be the one that contains the ext4 file system, or /dev/mmcblk0p2. Mount it to /mnt using the command:
mount -t ext4 -o noatime /dev/mmcblk0p2 /mnt
Since the BusyBox mount command defaults to a FAT32 file system, we need to tell it that we want to mount an ext4 file system with the -t ext4 option. We also give the mount option -o noatime, which turns off file access times. File access times aren’t really needed on a modern Linux system, and they contribute excess writes to our MicroSD card, which will wear it out more quickly. Turning them off prolongs the life of the card.
Now we need to create a directory (also known as a folder) into which we will mount our other partition. This directory will be located at /boot in our installed system. However, the root directory (/) of our installed system is mounted at /mnt in our running live environment. Therefore, we need to create this directory at /mnt/boot like so:
mkdir /mnt/boot
Mount the first partition at /mnt/boot like so:
mount -o noatime /dev/mmcblk0p1 /mnt/boot
We didn’t need to specify the file system type, since FAT32 is the default. However, we still needed to turn off access times.
Before going to the next step, verify that the partitions are mounted correctly by running:
mount
You should see /dev/mmcblk0p2 mounted to /mnt, and /dev/mmcblk0p1 should be mounted to /mnt/boot. If this isn’t the case, stop and fix your mounts now, or the next step will either fail outright or create a broken system. (If you need to unmount something as part of the fix, the command to do so is umount - unmount without the letter “n” after the starting “u”.)
Step 16: Install the System
Now that we have the target partitions mounted, we can use Alpine’s installer script to perform the installation for us:
setup-disk -m sys /mnt
This command instructs the installer to create a sys-mode installation of Alpine Linux on the target mounted at /mnt.
Check that the installation was successful. First, run:
ls /mnt
You should see the usual top-level Linux system directories present (like /boot, /etc, /home, /usr, etc.).
Run:
ls /mnt/boot
Be sure that you see the files vmlinuz-rpi, initramfs-rpi, config.txt, and cmdline.txt. Take a look at these latter two files:
cat /mnt/boot/config.txt
cat /mnt/boot/cmdline.txt
Note that the cmdline.txt file should have an entry that begins with root=UUID=, followed by the UUID of your second partition’s file system.
Run:
cat /mnt/etc/fstab
Verify that the UUID in cmdline.txt matches the one for the / (root) file system in the file system table (fstab). This UUID will the longer of the two UUIDs that should be present in the fstab file, since ext4 UUIDs are longer than FAT32 ones.
Step 17: Reboot Onto the New System
Once your installation looks right, reboot into it by running:
reboot
After a delay, you should see a login prompt if everything went well. Log in as root with the password that you set, and note that you won’t see anything while typing the password (for security).
Submission Checklist
Once you’ve logged into your newly installed system, run the following commands:
uname -a
hostname
cat /etc/alpine-release
mount
Check Your Work
Verify the following based on the commands you just ran:
- The Alpine release is 3.21.
- Your hostname is in the form username-csci311.coastal.edu, where username is the part of your CCU email address before the @ sign.
- /dev/mmcblk0p2 is mounted at / with the rw and noatime options.
- /dev/mmcblk0p1 is mounted at /boot with the rw and noatime (among other) options.
Double-check that /dev/mmcblk0p1 is mounted at /boot! If it isn’t correctly mounted at that location, updating the kernel will fail in a later milestone.
Prepare Your Submission
Use your phone to take a photo of your screen, since you don’t yet have a screenshot tool available on the Pi. Transfer the photo to your computer, and replace the placeholder image in the Milestone Worksheet with your photo. Export the worksheet to PDF format, and upload the PDF to Moodle as the submission for the Milestone 2 assignment activity.
As a reminder, here are the instructions for editing the worksheet in either LibreOffice or Word Online:
Turn Off the Pi
When you’re finished working on the milestone, shut down the Raspberry Pi properly by running the following command:
poweroff
The Pi is shut down correctly when its status light changes from green to red. You may unplug the Pi after it has shut down, and it will start up again the next time you plug it in. Alternatively, you can leave the Pi plugged in. The status light (which should be red at this point) is also the power button on the official Pi case, so pressing it will turn on the Pi if power is connected.
ABET Assessment
Successful completion of this assignment satisfies the following performance indicator:
- 1.6. Analyze a component of a complex problem.