Tuesday, July 13, 2021

Setting the default monospace font on Raspberry Pi OS: An exercise in frustration

Many Linux distributions, including Debian GNU/Linux and Raspberry Pi OS (which is derived from Debian), use a system-wide font configuration framework called fontconfig. This uses a series of XML files to set default fonts, fine-tune font rendering, automatically detect new fonts, and more. By providing a centralized mechanism to manage fonts, fontconfig helps ensure a consistent look and feel across applications.

CUPS, the standard printing system on most Linux distributions as well as on Apple macOS, is among the numerous applications that use fontconfig. The configuration determines how CUPS renders documents that do not specify fonts, such as plain text files, for printing. For example, plain text files are printed using the default monospace font.

I followed the Arch Linux documentation for font configuration and Angelos Orfanakos's blog post on setting fonts in Debian to edit the font configuration manually. System-wide settings can be placed in ~/.config/fontconfig/fonts.conf, while per-user settings use ~/.config/fontconfig/fonts.conf.

On my Raspberry Pi 4, I was trying to change the default monospace font because the font it normally uses (Liberation Mono) looked very ugly when printed. Instead, I wanted it to use Courier New, from the Microsoft TTF Core Fonts, using the following configuration in /etc/fonts/local.conf:

<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<fontconfig>
    <alias>
        <family>monospace</family>
        <prefer>
            <family>Courier New</family>
        </prefer>
    </alias>
</fontconfig>

However, the system wouldn't honor the setting, and it took a lot of fiddling to get it to work. I tried placing the configuration in both /etc/fonts/local.conf and ~/.config/fontconfig/fonts.conf and nothing worked. After extensive fiddling, it turns out that in Raspberry Pi OS, the monospace font is explicitly defined in /etc/fonts/conf.d/31-mono-substitute.conf. The way this is set up causes it to not accept manual changes to the monospace font in local configuration files. This is specific to Raspberry Pi OS, and is presumably there to match official documentation and educational materials released by the Raspberry Pi Foundation.

Renaming the 31-mono-substitute.conf file to disabled-31-mono-substitute.conf worked. I'd suspect it won't be kept during updates, so I subsequently created a file containing no configuration data (as above, but with nothing between the fontconfig tags) in its place to ensure that it's preserved during updates.

Now the system accepts the local font settings and plain text documents are printed with the much cleaner Courier New font. It took me two hours for me to sort this out and it frustrated me to no end.

Draco

Sunday, March 28, 2021

Running a Raspberry Pi 4 from a USB portable SSD

I've been experimenting with the Raspberry Pi 4 as both a low-cost Linux desktop computer and a server. As inexpensive as it may be, there's lots of potential in the hardware and plenty of ways to make the most out of the miniature computer. One way of doing this is to use a portable SSD instead of a microSD card.

Newer Raspberry Pi boards, starting from revision 1.2 of the Raspberry Pi 2 Model B+, have the ability to boot directly from a USB storage device such as a flash drive or portable SSD, eliminating the need to use a microSD card. The use of an SSD can greatly increase storage performance, capacity, and reliability over a microSD card (more on this below).

There are a number of considerations to doing this, some of which are specific to the Pi 4:

  • The process is relatively simple. Raspberry Pi OS ships with an "SD Card Copier" utility, listed under Accessories in the main menu, which can be used to copy the running system to another storage device.
    • This process will erase all data on the target drive, so be sure you've selected the correct drive and backed up any important data on it.
    • The target drive must use an MBR partition table. If it uses GPT partitioning, the copy process will fail, and the drive will need to be repartitioned and reformatted with an MBR.
    • After copying, the target drive will contain both a small boot partition and a large Linux ext4 partition containing the full root filesystem outside of /boot. If you'd prefer to have a smaller root partition, run resize2fs on the second partition of the target drive (usually /dev/sda2) to shrink the ext4 filesystem to the desired size, then use cfdisk on the whole disk (usually /dev/sda) to shrink the partition to that same size.
    • It should be noted that there is no snapshot functionality involved, so copies are inconsistent and will not reflect the system state at any one point in time. As a result, I'd recommend rebooting the Pi and having no other applications running before beginning this process. Any services that are particularly sensitive to data consistency, such as database servers, should be stopped as well.
  • Enabling this feature on earlier generations of the Raspberry Pi may require writing to a one-time programmable memory on the board, a permanent and irreversible process. On the Raspberry Pi 4 Model B, an EEPROM firmware update may be required to enable USB booting. For more details, see the official documentation.
  • Some SSDs can require too much power for the USB ports on a Raspberry Pi. In particular, if the drive internally uses NVMe technology, such as an M.2 NVMe drive inside a USB enclosure or a retail portable SSD rated at more than 600 MB/s, it may require large bursts of power, which can cause the drive to disconnect while in use. SATA-based drives are less likely to experience this issue.
    • I learned this the hard way while trying to use a Plugable USB-C to NVMe enclosure containing a 1TB Samsung SSD 970 EVO Plus. The system simply could not finish copying the operating system without the drive disconnecting during the copy. This issue did not occur with a 500GB Samsung SSD 850 EVO in a StarTech USB 3.1 Gen 2 enclosure.
  • Trim, which is needed to maintain optimal performance on SSDs, will not work without some manual configuration, even if the drive otherwise supports it. Jeff Geerling has a detailed blog post on how to enable it; it's a rather complicated procedure and I won't be repeating it here.

Why use an SSD instead of a microSD card?

Raspberry Pi computers are designed primarily to use inexpensive SD or microSD memory cards for system storage. However, most microSD cards are not designed to be used as the boot drive or primary storage device for a computer. Instead, they are typically optimized for sequential or streaming I/O where data is read from or written to the card in large chunks. This makes sense given that these memory cards are primarily used to store pictures, videos, music, and other media files on devices like smartphones and cameras.

But computer operating systems rely much more on random I/O, where small bits and pieces of data are read and written in many different places on the storage media. A typical SD card, with a low-power controller tuned for optimal sequential I/O performance, will often perform poorly when asked to process many small random reads and writes. SSDs can deliver much higher performance than memory cards, especially in random I/O.

An SSD will also be much more durable than a memory card when used as an operating system drive. I won't go into detail here, but suffice it to say that due to differences in flash memory controllers, firmware features and optimizations, storage capacities, and the underlying NAND flash memories themselves, an SSD will be much less prone to failure than a microSD card over extended usage in a Raspberry Pi. They also provide valuable S.M.A.R.T. information which can be used to monitor usage statistics and possibly detect imminent failure, making it easier to avoid data loss. (On Raspberry Pi OS, you'll need to install the smartmontools package to use the smartctl command and read S.M.A.R.T. data.) Of course, any storage device can fail without warning, so it's always important to maintain current backups.