Font HOWTO: install, choose and tune fonts on Linux

Updated November 2026

On Linux, one library, fontconfig, decides which font every desktop program uses. To add a font, put the file in ~/.local/share/fonts (or install a package) and run fc-cache. To change which font is used, set your choice in the desktop settings or in a small fontconfig file. This page covers both, plus the usual fixes for missing emoji and boxes in place of Chinese, Japanese or Korean text.

The classic Font HOWTO dealt with X font paths, the xfs font server and converting TrueType to Type 1 for printing. None of that is needed any more. Programs now draw fonts themselves using fontconfig, FreeType (which draws the letters) and HarfBuzz (which places them correctly for each script).

Where fonts live

DirectoryWho uses it
/usr/share/fontsFonts installed by packages. Do not put your own files here.
/usr/local/share/fontsFonts an administrator adds by hand, for all users
~/.local/share/fontsYour own fonts (fontconfig's per-user directory)
~/.fontsOld per-user location. Still read, but fontconfig marks it for removal. Move fonts to ~/.local/share/fonts.

OpenType (.otf) and TrueType (.ttf, .ttc) files work everywhere, including variable fonts, where one file holds every weight. Web fonts (.woff2) are meant for browsers. For desktop use, get the .ttf or .otf version.

Install fonts from packages

Packages are the best choice: they update, and they include licenses. Useful sets:

# Debian, Ubuntu
sudo apt install fonts-noto-core fonts-noto-cjk fonts-noto-color-emoji fonts-liberation2

# Fedora
sudo dnf install google-noto-sans-fonts google-noto-sans-cjk-fonts \
  google-noto-color-emoji-fonts liberation-fonts-all

# Arch
sudo pacman -S noto-fonts noto-fonts-cjk noto-fonts-emoji ttf-liberation

Noto covers almost every script, and Noto Color Emoji provides emoji. Liberation fonts have the same letter widths as Arial, Times New Roman and Courier New, so documents from Windows keep their layout. Microsoft's own core fonts are in Debian and Ubuntu as ttf-mscorefonts-installer (Debian contrib, Ubuntu multiverse). It downloads the fonts from the Internet and asks you to accept Microsoft's license.

Install a font by hand

Say you downloaded a font family as a ZIP file:

mkdir -p ~/.local/share/fonts/inter
unzip ~/Downloads/Inter.zip -d /tmp/inter
cp /tmp/inter/*.ttf ~/.local/share/fonts/inter/
fc-cache -f ~/.local/share/fonts
fc-list | grep -i inter

The last command should list the new files. Restart programs that were already open, since most only read the font list at start-up. For every user on the machine, copy the files to /usr/local/share/fonts/ instead (with sudo), make them readable (sudo chmod 644), and run sudo fc-cache -f.

To remove a font, delete its files and run fc-cache -f again. Check the license of any font you download. Many good ones are free under the SIL Open Font License.

See what fontconfig knows

fc-list : family                  # every font family installed
fc-list : family style file       # with styles and file paths
fc-list :lang=ja family           # fonts that can show Japanese
fc-match sans-serif               # the font used for "sans-serif"
fc-match -s monospace | head      # fallback order for monospace
fc-match Helvetica                # what you get when a page asks for Helvetica

Typical output:

$ fc-match sans-serif
NotoSans-Regular.ttf: "Noto Sans" "Regular"

Programs ask fontconfig for a generic name (sans-serif, serif, monospace, emoji) or a specific family. fontconfig answers with the best installed match. If the font lacks a character, the program moves down the fallback list from fc-match -s until a font has it.

Choose your fonts

For interface fonts, start with your desktop settings. On GNOME, use GNOME Tweaks or the font options in Settings, depending on the version. KDE Plasma has them in System Settings, Text & Fonts. Those settings apply to that desktop's menus and windows.

To change the generic families for every program, create ~/.config/fontconfig/fonts.conf:

<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "urn:fontconfig:fonts.dtd">
<fontconfig>
  <!-- Preferred fonts for the generic families -->
  <alias>
    <family>sans-serif</family>
    <prefer>
      <family>Noto Sans</family>
      <family>Noto Sans CJK JP</family>
      <family>Noto Color Emoji</family>
    </prefer>
  </alias>
  <alias>
    <family>serif</family>
    <prefer><family>Noto Serif</family></prefer>
  </alias>
  <alias>
    <family>monospace</family>
    <prefer><family>DejaVu Sans Mono</family></prefer>
  </alias>
</fontconfig>

Use the family names exactly as fc-list : family prints them. Run fc-match sans-serif to check the result. The file takes effect for programs started afterward. The old location, ~/.fonts.conf, is deprecated.

Rendering: sharp or smooth

Three settings control how text looks on screen:

Set these in GNOME Tweaks or KDE's font settings where possible. To force them for all programs, add this inside <fontconfig> in the same file:

  <match target="font">
    <edit name="antialias" mode="assign"><bool>true</bool></edit>
    <edit name="hinting" mode="assign"><bool>true</bool></edit>
    <edit name="hintstyle" mode="assign"><const>hintslight</const></edit>
    <edit name="rgba" mode="assign"><const>none</const></edit>
  </match>

For subpixel rendering, replace none with rgb (the most common panel layout). Rendering edits always use target="font". Check the result with fc-match -v sans-serif | grep -E 'hintstyle|rgba|antialias'.

Emoji and CJK text

Empty boxes or "tofu" in place of characters mean no installed font has them. The fixes:

Troubleshooting

The text console uses its own bitmap fonts, not fontconfig. See Framebuffer HOWTO. The classic Font HOWTO is kept by the Linux Documentation Project at tldp.org.

Sources