Assignment 5: Install Alpine Linux
For this assignment, you will complete a “sys” mode installation of Alpine Linux on your second MicroSD card. This sequence of steps will replace the Alpine Linux installation environment you created in Assignment 4 with a standard installation that reuses the same MicroSD card.
- Background
- Procedure
- Step 0: Start the Pi
- Step 1: Adjust Keyboard Layout
- Step 2: Set Hostname
- Step 3: Connect to the Network
- Step 4: Configure Software Repositories
- Step 5: Configure Timezone
- Step 6: Configure Network Time Protocol (NTP)
- Step 7: Set the Root Password
- Step 8: Format the Linux Partition
- Step 9: Mount the Root Partition
- Step 10: Install the Base System
- Step 11: Clean Up the Boot Partition
- Step 12: Configure the File System Table (fstab)
- Submission Checklist
- ABET Assessment
Background
In the previous assignment, we copied the Alpine Linux installation files from the downloaded tarball onto our FAT32 partition at the start of the MicroSD card. Using these files, we were able to boot Alpine Linux into an environment that runs entirely from RAM. Alpine Linux is unique in that it supports several modes of operation from a single distribution. It can run from RAM in Diskless Mode, in which any runtime changes are lost when shutting down or rebooting. Some runtime changes can instead be written to a small storage partition that is created for this purpose in Data Disk Mode, which has the advantage of running from RAM (and is therefore quite fast) but allowing important files to be saved.
For a general-purpose computer, however, we usually want the third mode, which is called System Disk Mode or “sys” mode for short. Since we’re using our Pi as a general-purpose computer in this class, we’re going to convert our current Diskless Mode installation on our MicroSD card into a sys mode installation. We can perform this conversion in place, which is effectively our “installation” step for Alpine Linux.
Procedure
The procedure for this assignment is structured as a tutorial. We’re going to perform many of the same procedures that are documented in the Semi-Automatic Installation section of the Alpine User Handbook, although there are a few deviations based on experience using Alpine Linux as a desktop system. It is critically important that you follow the steps of this procedure in order and without interruption. If you miss a step, or if the Pi loses power during the procedure, you may have an unbootable MicroSD card. Should this situation occur, you will need to go back and re-do the previous assignment.
Remember that it can be difficult to distinguish a running sys mode installation from the Diskless Mode installation environment! You haven’t magically completed this assignment by simply booting into Alpine Linux from the MicroSD card. The steps in the Submission Checklist will verify that the installation has been successful.
Step 0: Start the Pi
If you are continuing from the previous assignment and did not shut down the Pi after logging into the installation environment, you can skip this step. Otherwise, be sure your Alpine Linux MicroSD card is plugged into the Pi, and plug in the USB power supply. When the Pi finishes booting, log in as root (no password is required).
Step 1: 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
Step 2: 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 3: Connect to the Network
As of Alpine Linux version 3.20.3, the installer is not able to perform an offline sys mode installation on the Raspberry Pi, since the Raspberry Pi firmware apk packages were omitted from the on-card package set. We therefore need a network connection to be able to proceed.
Wired Connection
If you have access to a wired connection, plug in the cable. Run the following command:
setup-interfaces
When asked which interface to initialize, answer with: eth0
Note that eth0 should be the default answer to the question (shown in square brackets next to the prompt), so you can just press Enter.
For the IP address, press Enter to accept the default (dhcp).
When prompted for the next interface (wlan0), type done and press Enter. Answer n to the prompt for doing manual configuration.
Once you’re back to the command prompt, run:
rc-service networking start
rc-update add networking
You should see your Pi pull an IP address when starting the network service. If not, check that the cable is plugged in properly, and run:
rc-service networking restart
If your router is being slow, it might be necessary to wait a bit for the IP address to be pulled successfully. You can run:
ip a s
to see the current IP address.
Off Campus or Cell Phone WiFi
If you don’t have a wired connection and are off campus or using your cell phone for as a WiFi hotspot, begin by running:
setup-interfaces
When asked which interface to initialize, type in wlan0 and press Enter. You will then be presented with a list of detected networks. Type in either the network name (SSID) or the number next to the network name in the scan results, then press Enter again.
You will be asked for the pre-shared key for the network (often called the “WiFi password”). Type it in. For security, you will not see anything displayed as you type, so type carefully. Press Enter when finished typing.
When prompted for the ip address, press Enter to accept the default (dhcp).
You will then be asked which additional interface to initialize. Type done and press Enter. Answer n (followed by Enter) when asked to do any manual network configuration.
Once you’re back to the command prompt, it will be necessary to set the wireless regulatory domain properly. To do so, run:
vi /etc/wpa_supplicant/wpa_supplicant.conf
Type shift+O to open a new line at the top of the file. Add the following text:
country=US
Save and exit vi. Back at the command prompt, run:
rc-service wpa_supplicant restart
Wait a minute or two, then run:
rc-service networking start
rc-update add networking
You should see the Pi pull an IP address during network service startup. If not, there are several things to troubleshoot. I had some difficulty with my wireless network at home but was able to get it to work with my cell phone hotspot, so you might try that. To change the wireless setup, you can re-run:
setup-interfaces
rc-service wpa_supplicant restart
rc-service networking restart
If you still have problems connecting to WiFi, try running an Ethernet cable and do the wired setup. Alternatively, you can try connecting from campus, but you’ll need to restart the steps of this assignment from the beginning, since you’ll have to turn off the Pi to transport it.
On Campus (eduroam)
Start by running:
setup-interfaces
When asked which interface to initialize, type in wlan0 and press Enter. You will then be presented with a list of detected networks. Type in either the network name (eduroam) or the number next to “eduroam” in the scan results, then press Enter again.
When prompted for the ip address, press Enter to accept the default (dhcp).
You will then be asked which additional interface to initialize. Type done and press Enter. Answer n (followed by Enter) when asked to do any manual network configuration.
To connect to eduroam, we need to do some additional manual setup. First, we need to edit the wpa_supplicant.conf file:
vi /etc/wpa_supplicant/wpa_supplicant.conf
Change the file to look like the following, replacing CCU_EMAIL_ADDRESS with your CCU email address and CCU_PASSWORD with your CCU password.
country=US
network={
ssid="eduroam"
key_mgmt=WPA-EAP
eap=PEAP
identity="CCU_EMAIL_ADDRESS"
password="CCU_PASSWORD"
phase2="autheap=MSCHAPV2"
}
Since your password is stored in cleartext, let’s restrict access to this file to the root user:
chmod 600 /etc/wpa_supplicant/wpa_supplicant.conf
Now you should be able to get connected by running:
rc-service wpa_supplicant restart
Wait a minute or two, then try to get an IP address by running:
rc-service networking start
rc-update add networking
You should receive an IP address when starting the networking service. If not, check the wpa_supplicant.conf file to be sure you’ve properly configured the network (restart the wpa_supplicant service if you need to make changes). Outside Penny Hall, you might also encounter a slow access point. In this case, wait a bit and then try running:
rc-service networking restart
You can check your IP address using:
ip a s
Step 4: Configure Software Repositories
We now need to configure the software repositories to perform our base installation. Run:
setup-apkrepos
Just press Enter for option 1. We need to edit the file /etc/apk/repositories using vi, so start the editor on that file and change it to look like the following:
http://dl-cdn.alpinelinux.org/alpine/v3.20/main
http://dl-cdn.alpinelinux.org/alpine/v3.20/community
@testing http://dl-cdn.alpinelinux.org/alpine/edge/testing
Be sure to delete the /media/mmcblk0p1/apks line. There should be a comment symbol (#) at the start of the community repository line, which you can simply remove. You’ll need to add the line that begins with @testing manually.
Once you’ve edited the file, save it and exit vi. Run:
apk update
Check that the output shows that repository information is being downloaded successfully and ends with an OK message. If not, then you either have a network connection issue or an error in your /etc/apk/repositories file. Don’t try to proceed until you have this part working, or everything else will fail!
Step 5: 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, we need to install the timezone data into the running environment:
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 6: Configure Network Time Protocol (NTP)
Speaking of time, the real-time clock on the Raspberry Pi will drift, as all computer clocks do. Go ahead and enable the Network Time Protocol client by running:
setup-ntp chrony
Step 7: 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 8: Format the Linux Partition
Now that we have the basic configuration finished, we need to format that second partition we created in Raspberry Pi OS. We’re going to use the ext4 Linux filesystem for this purpose. First, we need to add the formatting program into our installation environment:
apk add e2fsprogs
Since we now have the mkfs.ext4 command available, our next step is to format the partition. Remember that this partition was /dev/sda2 under Raspberry Pi OS? The MicroSD card was located at /dev/sda, and this was partition number 2.
Well, things have now changed! When we plugged the MicroSD card into the USB adapter, the USB adapter made the MicroSD card look like a SCSI or ATA hard drive, which is why the card showed up at /dev/sda. Now, however, we have plugged the card directly into the MicroSD slot on the Raspberry Pi. As such, the card is now located at /dev/mmcblk0. The mmc part of the name refers to the MultiMediaCard standard, which was the predecessor of Secure Digital (SD) cards. MicroSD is simply an SD card in a smaller form factor.
The blk part of /dev/mmcblk0 refers to the block device interface of the MMC/SD card, since these kinds of cards can have other interfaces (for example, there are WiFi adapters in this form factor for some types of digital camera). Block storage is the generic term for persistent storage, whether it be on a disk, SSD, or flash memory card like we’re using. The number 0 means that is the first interface, counting from zero.
Since the MicroSD card device node ends in a number, the device manager puts the letter p between the device number and the partition number. However, while device numbers are counted from zero, partition numbers are always counted from 1 due to a longstanding historical convention. For this reason, the partition we need to format is now located at /dev/mmcblk0p2
To run the format command, we type:
mkfs.ext4 /dev/mmcblk0p2
Step 9: Mount the Root Partition
Our new installation will have its root partition (the one where / is mounted) located on our newly formatted partition. In order to perform the installation step, we need this partition to be mounted at /mnt, which we can do like so:
mount -t ext4 -o noatime /dev/mmcblk0p2 /mnt
Notice here that we need to specify the filesystem type when performing the mount, which we do with the -t ext4 bit. In addition to using a different C library, Alpine Linux uses the BusyBox tool set instead of GNU binutils. BusyBox doesn’t really do partition or file system type detection in its mount command. Instead, it defaults to FAT32, and we have to override the file system type. Notice also that we give the noatime option to minimize writes to the MicroSD card.
Step 10: Install the Base System
We’re finally ready to do the installation itself. To inform the install script that we want “sys” mode, we need to include a flag on the command line for that purpose. Due to the Raspberry Pi hardware’s special boot process, we also have to set an environment variable to tell the Alpine installer script to force the installation to a partition that isn’t bootable. A warning will be displayed, but it can be safely ignored.
The command to run is:
FORCE_BOOTFS=1 setup-disk -m sys /mnt
The above command is a shorthand way to set the FORCE_BOOTFS environment variable to 1 for only the command being executed. We’re executing the setup-disk command, telling it to install in sys mode to the partition mounted at /mnt (which is our /dev/mmcblk0p2 from the prior step).
Step 11: Clean Up the Boot Partition
The reason we had to use the FORCE_BOOTFS flag in the above step is that the Raspberry Pi always boots from the FAT32 partition, which we find at /dev/mmcblk0p1 inside our Alpine Linux environment. The expectation of finding the boot files in a FAT32 partition at the start of the drive is part of the Raspberry Pi’s hardware design.
If we just reboot now, the Pi will still boot from the existing FAT32 partition, but it will boot back into the Diskless Mode installation environment. To prevent this behavior, we need to clean up the boot partition and move the sys mode boot files into it.
Since we’re still in Diskless Mode, the files from /dev/mmcblk0 are made available to the system at the mount path /media/mmcblk0p1 in a read-only state. We need to remount this filesystem in rewrite mode by running the mount command with the remount and rw options. Of course, we also add noatime to reduce unneeded writes:
mount -o remount,rw,noatime /media/mmcblk0p1
Now we can clean up all the files we used to boot into Diskless Mode. BE CAREFUL to type the following commands correctly, or Bad Things Will Happen:
rm -rf /media/mmcblk0p1/*
rm -f /media/mmcblk0p1/.alpine-release
We currently do not have any files in /media/mmcblk0p1, meaning that we couldn’t reboot the Pi at this point. We need to get the files that are currently in the boot directory of the new installation into the boot partition. The boot directory of the new installation is located at /mnt/boot at the moment.
Let’s start by removing an unnecessary symbolic link:
unlink /mnt/boot/boot
Now we can move the boot files from /mnt/boot to /media/mmcblk0p1:
mv /mnt/boot/* /media/mmcblk0p1
Step 12: Configure the File System Table (fstab)
Whenever a Linux system is booted, part of the startup process is mounting all the various filesystems used by the OS. The file that controls which of these filesystems to mount is called the file system table, and it is located at /etc/fstab on the booted system. Since we haven’t yet booted into our new system, the file we want to edit is currently located at /mnt/etc/fstab instead.
There are several ways to specify partition names in the file system table, but the most reliable way is to use the Universally Unique Identifier (UUID) of each filesystem. That way, even if the disks on the system are somehow labeled out of order at boot time, the correct filesystems will be mounted at the correct mount points. This isn’t too big an issue on the Raspberry Pi 5, since there is only one MicroSD card slot, and the card will always be at /dev/mmcblk0. However, it’s still a good practice to get in the habit of using UUIDs, since server systems (in particular) often have multiple disks of the same type. An unexpected system change might cause the disk order to change, resulting in problems if the partitions are specified using /dev entries.
To get the UUID of our boot partition, which is /dev/mmcblk0p1, we can use the blkid program like so:
blkid /dev/mmcblk0p1
Notice that the UUID is the second field in the output. Now, we could write this down somewhere and type it into the file system table manually, but there is a quicker way. We can start by using the awk command to get just the UUID part of the output like so:
blkid /dev/mmcblk0p1 | awk '{print $2}'
We need to make one more quick change, since we don’t use the double quotes around the UUID value in the file system table. Press the Up arrow on your keyboard, and edit the command to the following:
blkid /dev/mmcblk0p1 | awk '{print $2}' | sed 's/"//g'
This version of the command pipes the output of blkid into the awk command, which selects only the second field of the output. We then pipe that second field into the sed command, and we tell it to replace all occurrences of the double-quote symbol with an empty value.
Now for the neat trick: we can take the above command and append it to the end of the /mnt/etc/fstab file using the following code. BE CAREFUL that you put TWO angle brackets (>>)! A single angle bracket will break everything.
blkid /dev/mmcblk0p1 | awk '{print $2}' | sed 's/"//g' >> /mnt/etc/fstab
Now open /mnt/etc/fstab in vi and make it look a bit like the following. Since UUIDs are unique, the values of each one will be different for each person. The first one (that says dont_change_this_one in the sample below) is for your root (/) partition, which is /dev/mmcblk0p2. The second one (using move_from_bottom as a placeholder in the example) needs to be moved up from the bottom of the file, which is easy to do by going to the bottom line of the file and giving the dd command to vi. Move the cursor back to the top line and press p to paste the line you just cut to the line below the line containing the cursor. Edit that line to mount the boot partition at /boot, with filesystem type vfat, read-write, and noatime. The two zeroes at the end are the dump and pass flags for file system checks, which we can ignore for now (but they have to be present in the file).
UUID=dont_change_this_one / ext4 rw,noatime 0 1
UUID=move_from_bottom /boot vfat rw,noatime 0 0
tmpfs /tmp tmpfs nosuid,nodev 0 0
Remove any lines in the file that refer to CD and floppy drives, since the Raspberry Pi doesn’t have those. You can also remove the line for a usbdisk, since we’ll eventually be using a desktop environment that will mount removable devices to another location anyway. Once you’ve double-checked your fstab file, save it and exit vi.
Now type the following command and cross your fingers:
reboot
If all goes well, you will get a login prompt after a period of time. Log in as root, using the password you set in the previous steps. You won’t see anything while typing in your password.
Submission Checklist
Once you’ve logged into the newly installed system, run the following commands:
date
ip a s
uname -a
cat /etc/alpine-release
mount
How to Check Your Work
To verify that you have everything working properly, look at the output of the above commands:
- Be sure that your CCU username is part of your hostname.
- Be sure that the date shows a time during the period for this assignment this semester.
- Look at the output of
ip a s
. Either your eth0 or your wlan0 should show an IP address indented underneath it. This IP address will be on a line starting with “inet”, and it should have global scope. Unless you’re sure you have an IPv6-only network (unlikely), you should have an IPv4 address assigned to one of these interfaces. If not, check your network settings. - The Alpine release version should be up to date with the current release.
- In the output of the
mount
command, check that /dev/mmcblk0p2 is mounted to / AND that /dev/mmcblk0p1 is mounted to /boot. Both mounts should have the “noatime” option shown. If there are any issues, take a look at your /etc/fstab file. Check that you don’t have stray spaces in it, and that your UUIDs are correct.
Final Steps
Use your phone to take a photo of your screen, showing the output of your above commands. Upload the photo to Moodle as the submission for this assignment.
To turn off the Pi properly, run:
poweroff
Once the screen has gone blank and the green light on the Pi next to the MicroSD slot has changed to red, unplug the USB power supply.
ABET Assessment
Successful completion of this assignment satisfies the following performance indicator:
- 1.6. Analyze a component of a complex problem.