Arch Linux (in dual boot)
Since my consulting work relies heavily on Microsoft tools like Office and Power BI, I have primarily been using Windows as my operating system.
I still do a lot of programming, and to my surprise, developing on Windows has been very good. When I need to run something dependent on Linux like Airflow and Redmine, I can use WSL and Docker.
One of the issues with virtualizing Linux is the loss of performance. For this reason, I allocated about 60GB to install Arch in dual boot on my laptop.
I wrote on Twitter that I was installing Arch, and someone suggested updating my old guide because a lot has changed in 8 years. So, I decided to break the hiatus of over 3 years on this blog to document my new installation process.
When I wrote my post in 2012, the official wiki was not up to date. Nowadays, it is very comprehensive, and I recommend following it for possible updates and more details.
As in previous posts, I want to make it clear that these are the configurations I chose for my
computers (a Dell Latitude 3480 and an Acer Predator Helios 300).
Some configurations listed here may be incompatible with your system or simply unnecessary depending
on the Desktop Environment you will be using.
I will not go into many details about the commands used. More information about them can be found on
the internet and in the official wiki.
If you have any questions or suggestions, feel free to leave a comment here or send me a DM on
Twitter.
Update: Since May 2021, the Arch ISO image includes a guided installer called Archinstall. As I am already used to it, I will continue to perform the manual installation process.
Disk partitioning
I installed Windows first and, during the installation, I partitioned the 240GB SSD as follows:
- 529 MB: Windows Recovery
- 500 MB: EFI (larger than the default)
- 150 GB: Windows
- 60 GB: Arch Linux
- Remaining: Encrypted NTFS partition with Veracrypt to access from both Linux and Windows
I did not create a partition for Swap. If I ever need it, I can create a swap file on the disk, in memory, or on the video card memory.
I also left /
, /home
, and /var
on the same partition. /boot
will be the 500 MB EFI
partition. By default, Windows creates this partition with 100MB, but this may not be enough if you
want to load many modules or have more than one kernel.
If I had not created the partitions through Windows, I could use some tool in Linux like cgdisk or parted.
Installation USB
I downloaded the ISO image via BitTorrent and created the bootable USB using the default options of Rufus Portable. I restarted the computer and kept pressing F12 until the list with the option to boot from the USB drive appeared. When selecting the option to install Arch, a message appeared waiting for a disk with LABEL=ARCH202008. I simply reconnected the USB drive to the USB port and the system loaded correctly.
Keyboard layout
When dropping into the terminal, the first step is to configure the keyboard. As I use a Brazilian keyboard, I ran the following command:
-
For Brazilian keyboard:
loadkeys br-abnt2
-
For American keyboard:
loadkeys us-acentos
Other options can be found at ls /usr/share/kbd/keymaps/**/*.map.gz
.
System clock update
timedatectl set-ntp true
The Linux default is to keep the hardware clock in UTC, but Windows default is to use local time. I prefer to keep it in UTC and configure Windows through Regedit.
Disk encryption
lsblk # To find out the partition. /dev/sda5 in my case
cryptsetup -v luksFormat /dev/sda5
I found the default settings OK. More options can be found in the wiki.
If lsblk
does not list your SSD (M.2 PCIe NVMe), check in the BIOS if the SATA Mode is set to
AHCI. If Windows was installed in RAID mode, you will need to restart it in safe mode and change the
SATA Mode in the BIOS.
Root partition formatting
cryptsetup luksOpen /dev/sda5 arch
mkfs.ext4 -L arch /dev/mapper/arch
Mounting partitions
mount /dev/mapper/arch /mnt
mkdir /mnt/boot
mount /dev/sda2 /mnt/boot
Internet connection
-
Wifi
Connect to wifi using iwd
iwctl --passphrase YOUR_PASSWORD station wlan0 connect YOUR_SSID
-
Ethernet
Wired networks should work automatically. If not:
Mirrorlist
Pacman reads the file /etc/pacman.d/mirrorlist
to determine from which
mirrors to download packages. It’s good to keep the
most up-to-date and fastest mirrors at the top to avoid long download times.
The new Arch installer should do this automatically using Reflector as soon as the internet connection is detected. Just make sure everything is OK. Since I’m in São Paulo, the mirrors from UFSCar and UFPR were at the top.
Installation of main packages
In this step, I install the base system and all the packages I will need, such as network tools, text editor, manual pages, Xorg, and PulseAudio.
pacstrap /mnt \
base{,-devel} \
linux{,-firmware} \
intel-ucode \
iwd \
dhcpcd \
iputils \
zsh \
go \
git \
neovim \
python{,-pip,-pynvim} \
man-db \
man-pages \
texinfo \
xorg-server \
xorg-xinit \
xf86-video-intel \
xf86-input-synaptics \
alsa-utils \
pipewire{,-pulse}
wireplumber
# pulseaudio{,-alsa,-bluetooth} \
# pavucontrol
Fstab
genfstab -U -p /mnt >> /mnt/etc/fstab
Chroot
arch-chroot /mnt
Timezone
-
Brazil
ln -sf /usr/share/zoneinfo/America/Sao_Paulo /etc/localtime
-
Germany
ln -sf /usr/share/zoneinfo/Europe/Berlin /etc/localtime
Save the time:
hwclock --systohc
Localization
I use the system in English, but I also enable pt_BR
and de_DE
. I tend to prefer en_GB
over
en_US
, but that’s a matter of taste.
sed -i -e 's/#en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen
sed -i -e 's/#en_GB.UTF-8 UTF-8/en_GB.UTF-8 UTF-8/' /etc/locale.gen
sed -i -e 's/#pt_BR.UTF-8 UTF-8/pt_BR.UTF-8 UTF-8/' /etc/locale.gen
sed -i -e 's/#de_DE.UTF-8 UTF-8/de_DE.UTF-8 UTF-8/' /etc/locale.gen
locale-gen
echo LANG=en_US.UTF-8 > /etc/locale.conf
Virtual Console
Configures the keyboard layout and font.
echo -e "KEYMAP=br-abnt2\nFONT=latarcyrheb-sun16" > /etc/vconsole.conf
or
echo -e "KEYMAP=us-acentos\nFONT=latarcyrheb-sun16" > /etc/vconsole.conf
Network Configuration
Adds the computer’s name to /etc/hosts
and also blocks some malicious and advertising sites.
echo "computer_name" > /etc/hostname
curl --output /etc/hosts --url "https://someonewhocares.org/hosts/zero/hosts"
echo -e "127.0.1.1\tcomputer_name.localdomain\tcomputer_name" >> /etc/hosts
Initramfs
I added encrypt
because the system partition is encrypted.
I also load the Nvidia modules, as explained below.
$ nvim /etc/mkinitcpio.conf
HOOKS=(base udev autodetect modconf block encrypt filesystems keyboard keymap consolefont fsck)
mkinitcpio -p linux
Pacman
Adds the repository multilib, colors pacman, and adds the Pac-Man animation.
sed -i -e '/^#\[multilib\]$/,+1s/#//' /etc/pacman.conf
sed -i -e '/# Misc options/a ILoveCandy' /etc/pacman.conf
sed -i -e 's/^# Color/Color/' /etc/pacman.conf
Root password
passwd
DNS and network
It is possible to use Iproute2, wpa_supplicant, or Iwd directly to connect to wired and wireless networks, but a connection manager simplifies the process.
Some configurations I have used:
-
NetworkManager was created by RedHat and is now part of the GNOME project.
It allows configuring wired networks, wifi, modems, and VPNs both through the command line and through graphical interfaces (very well integrated with Gnome and KDE).
sudo pacman -S networkmanager sudo systemctl enable NetworkManager.service
$ nmcli device DEVICE TYPE STATE CONNECTION enp7s0 ethernet disconnected -- wlp0s20f3 wifi disconnected -- p2p-dev-wlp0s20f3 wifi-p2p disconnected -- lo loopback unmanaged --
$ nmcli connection add type ethernet con-name Home ifname enp7s0 Connection 'Home' (0acb09e3-40a4-479f-9532-a154d8d65dfc) successfully added.
$ nmcli connection up Home Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/1)
$ nmcli device disconnect enp7s0 Device 'enp7s0' successfully disconnected.
Note: It is possible to keep both the cable and wifi connected at the same time so that if you disconnect the cable, there will be no downtime.
$ nmcli device wifi list IN-USE BSSID SSID MODE CHAN RATE SIGNAL BARS SECURITY 7C:05:07:04:38:52 MEU_SSID Infra 4 130 Mbit/s 80 ▂▄▆_ WPA2 A4:33:D7:A7:EA:10 Vizinho 1 Infra 6 130 Mbit/s 70 ▂▄▆_ WPA2 C0:3D:D9:88:1E:00 Vizinho 2 Infra 1 130 Mbit/s 65 ▂▄▆_ WPA2 68:02:B8:28:9A:60 Vizinho 3 Infra 6 195 Mbit/s 60 ▂▄▆_ WPA1 WPA2 00:26:F2:6B:D6:F2 Vizinho 4 Infra 11 54 Mbit/s 59 ▂▄▆_ WPA1 WPA2
$ nmcli device wifi connect MY_SSID password MY_PASSWORD Device 'wlp0s20f3' successfully activated with '3eafc7d7-8a89-40ae-8b01-ade3ba474de0'.
$ nmcli connection show NAME UUID TYPE DEVICE MEU_SSID 3eafc7d7-8a89-40ae-8b01-ade3ba474de0 wifi wlp0s20f3 Casa 0acb09e3-40a4-479f-9532-a154d8d65dfc ethernet --
ls /etc/NetworkManager/system-connections/ Home.nmconnection MY_SSID.nmconnection
-
systemd-networkd + systemd-resolved + iwd
ln -sf /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf
$ nvim /etc/iwd/main.conf [General] EnableNetworkConfiguration=true [Network] NameResolvingService=systemd
The network can be started when the computer is turned on:
sudo systemctl enable systemd-resolved iwd
Users
~# useradd -m -g users -G wheel,storage,power,video,audio,rfkill -s /bin/zsh julio
~# passwd julio
~# EDITOR=nvim visudo
Descomente a linha `%wheel ALL=(ALL) ALL`
Bootloader
I am using systemd-boot. Since my processor is Intel, I also load its microcode.
~# bootctl install
~# nvim /boot/loader/entries/arch.conf
title Arch Linux
linux /vmlinuz-linux
initrd /intel-ucode.img
initrd /initramfs-linux.img
options cryptdevice=UUID=0a1b2c3d-…-4e5f6g:arch root=/dev/mapper/arch rootfstype=ext4 add_efi_memmap
sudo nvim /boot/loader/loader.conf
timeout 3
The UUID of the encrypted partition (/dev/sda5
) can be seen by running the command
lsblk -o +UUID
.
With the bootloader configured, we can now restart the computer. If all goes well, a menu will appear to choose the operating system.
sudo umount /mnt/boot
sudo umount /mnt
sudo systemctl reboot
If no display manager was installed, Arch will start in the terminal. Log in with the user created in the previous step.
Dotfiles
My dotfiles are available on Github. I clone the repository and create the appropriate symlinks. When I have time, I will use rcm, chezmoi, or GNU Stow to automate this.
~$ git clone https://github.com/jbsilva/dotfiles.git
~$ ln -s dotfiles/.config ~/.config
~$ ln -s dotfiles/.zsh ~/.zsh
~$ ln -s dotfiles/.zshrc ~/.zshrc
~$ ln -s dotfiles/.gitconfig ~/.gitconfig
~$ ln -s dotfiles/.p10k_console.zsh ~/.p10k_console.zsh
~$ ln -s dotfiles/.p10k.zsh ~/.p10k.zsh
~$ ln -s dotfiles/.xinitrc ~/.xinitrc
~$ ln -s dotfiles/XCompose/.XCompose ~/.XCompose
~$ ln -s dotfiles/bin ~/bin
Shell
There are many options for command-line shells, such as
Bash, Zsh,
KornShell, and
Fish. To list the installed shells, run the command
chsh -l
.
I have been using Zsh for years. It is POSIX compliant and becomes extremely friendly with some plugins (PowerLevel10k, etc.), which my dotfile installs and configures automatically with zplug.
I created my user with the parameter -s /bin/zsh
, but it is possible to change the default shell
with the command chsh -s full-path-to-shell
.
Terminal Emulators
There are many terminal emulators available for Linux, each with its own advantages and disadvantages.
I used to use urxvt because startup time and memory usage were the main factors for me in the past. Now that I have more powerful computers, other features stand out:
- Cross-platform (at least Linux and macOS)
- Unicode
- Truecolor
- Ligatures
- Tabs
- GPU accelerated
- Good documentation
Of all the ones I’ve tested, Kitty is the one with the most features. Unfortunately, it’s not perfect, it has phone home features, uses its own terminfo causing issues, and the developer often behaves rudely towards users.
Alacritty is good, but it doesn’t have tabs and may never have.
Terminal Multiplexers
Terminal emulators like Kitty allow splitting a single window into multiple terminals, but most terminal multiplexers do this and much more, such as allowing a session to continue running even after closing the terminal.
Some that I have used:
- GNU Screen
- It is the simplest and comes pre-installed in several distributions.
- Tmux
- More comprehensive than Screen.
- Some projects like .tmux make it much more visually appealing and usable.
- Other projects: https://github.com/rothgar/awesome-tmux
- Byobu
- It is a layer on top of Screen or Tmux. I quite like it, but the project was discontinued in February 2020.
- Zellij
- My current favorite. It is a new project (in 2020 it was called Mosaic) written in Rust and with many interesting features.
Yay
Yay is an AUR helper/Pacman wrapper written in Go that greatly assists in package installation.
$ git clone https://aur.archlinux.org/yay.git && \
cd yay && \
makepkg -sri && \
cd .. && \
rm -rf yay
Some additional packages I install, including the Kitty terminal, Gimp image editor, VS Code, and various utilities:
$ yay -S \
ack \
aws-cli-v2-bin \
bleachbit \
bluez \
bluez-utils \
calibre \
chromium \
code \
ctags \
dbeaver \
digikam \
discord \
docker-compose \
duf \
dust \
fcitx5-chinese-addons \
fcitx5-im \
ffmpeg \
firefox \
gimp \
gitahead \
goldendict \
gparted \
htop \
hugo \
imagemagick \
insomnia-bin \
jq \
kitty \
lens-bin \
libreoffice-fresh \
make \
meld \
neofetch \
nerd-fonts-hack \
noto-fonts-emoji \
npm \
ntfs-3g \
oath-toolkit \
obs-studio \
okular \
openssh \
p7zip \
polkit \
qalculate-gtk \
renameutils \
rsync \
rust-analyzer \
slack-desktop \
spotify \
sshfs \
telegram-desktop \
texlive-core \
texlive-latexextra \
thunderbird \
transmission-remote-gtk \
tree \
ttf-joypixels \
usbutils \
veracrypt \
vlc \
wget \
xclip \
xorg-xrandr \
# audacity \
# awesome-git \
# aws-cli \
# blueman \
# byobu \
# copyq \
# feh \
# gnome-keyring \
# graphviz \
# hdparm \
# ibus \
# ibus-libpinyin \
# kdenlive \
# light-git \
# macchanger \
# maim \
# picom-git \
# postman-bin \
# redshift \
# rofi-git \
# sshpass \
# teams \
# unrar \
# unzip
Firewall
sudo pacman -S nftables
sudo systemctl enable nftables.service
sudo nft list ruleset
Fonts
Install the fonts available in the official repository or in the AUR:
$ yay -S \
inter-font \
nerd-fonts-fantasque-sans-mono \
noto-fonts \
noto-fonts-cjk \
noto-fonts-emoji \
otf-san-francisco \
otf-sfmono-patched \
ttf-dejavu \
ttf-liberation \
ttf-meslo-nerd-font-powerlevel10k
Manual Installation
Fonts not available as packages can be installed manually. Just add the files to a subfolder of
/usr/local/share/fonts
(for all users) or ~/.local/share/fonts/
(just for your user).
Example:
sudo mkdir -p /usr/local/share/fonts/{otf,ttf}
wget http://www.exljbris.com/dl/fontin2_pc.zip
sudo 7z x fontin2_pc.zip -o/usr/local/share/fonts/ttf/Fontin
sudo find /usr/local/share/fonts -type d -exec chmod 755 {} \;
sudo find /usr/local/share/fonts -type f -exec chmod 644 {} \;
$ tree /usr/local/share/fonts
/usr/local/share/fonts
├── otf
│ └── Example_Sans
│ ├── Example_Sans_B.otf
│ ├── Example_Sans_BI.otf
│ ├── Example_Sans_I.otf
│ └── Example_Sans_R.otf
└── ttf
└── Fontin
├── Fontin-Bold.ttf
├── Fontin-Italic.ttf
├── Fontin-Regular.ttf
├── Fontin-SmallCaps.ttf
└── ReadMe.txt
fc-cache
fc-list
…
If you want to set specific fonts to be
used, edit the file $XDG_CONFIG_HOME/fontconfig/fonts.conf
.
Windows Fonts
You can obtain the fonts from the ISO or the C:\Windows\Fonts
folder of an installed Windows.
Copy the fonts to /usr/share/fonts/WindowsFonts
:
sudo mkdir /usr/share/fonts/WindowsFonts
sudo cp /c/Windows/Fonts/* /usr/share/fonts/WindowsFonts/
sudo chmod 644 /usr/share/fonts/WindowsFonts/*
Alternatively, use a package like ttf-ms-win10 or ttf-ms-win11.
git clone https://aur.archlinux.org/ttf-ms-win11
cd ttf-ms-win11
cp /c/Windows/System32/Licenses/neutral/_Default/Core/license.rtf .
cp /c/Windows/Fonts/* .
makepkg -si
Keyboards
The keyboard on my laptop is ABNT2, but sometimes I connect keyboards with other layouts.
It is possible to configure each keyboard individually by device id or switch between pre-configured profiles.
-
Get the keyboard device id
sudo pacman -S xorg-xinput
$ xinput -list | grep -i Keychron ⎜ ↳ Keychron Keychron K2 id=11 [slave pointer (2)] ↳ Keychron Keychron K2 id=10 [slave keyboard (3)] ↳ Keychron Keychron K2 id=19 [slave keyboard (3)]
$ xinput list-props 10 Device 'Keychron Keychron K2': Device Enabled (189): 1 Device Node (313): "/dev/input/event5"
$ ls -l /dev/input/by-id/usb-Keychron* … /dev/input/by-id/usb-Keychron_Keychron_K2-event-if01 -> ../event6 … /dev/input/by-id/usb-Keychron_Keychron_K2-event-kbd -> ../event5
-
Configure with
setxkbmap
$ setxkbmap -device `xinput -list | \ grep "Keychron K2.*keyboard" | \ sed -e 's/^.*id=\([0-9]\+\).*/\1/' | \ head -1` \ -layout us \ -variant intl \ -option lv3:ralt_switch \ -option compose:rctrl \ -option caps:swapescape
Use the commands
localectl list-x11-keymap-layouts
,localectl list-x11-keymap-variants us
,localectl list-x11-keymap-options
, and the file/usr/share/X11/xkb/rules/base.lst
to set the appropriate configuration.My example swaps CapsLock with Esc, uses the right control as the compose key (Multi_Key), and the right Alt as the third level.
-
Run the command at system startup
$ nvim ~/bin/keyboards.sh #!/bin/sh # Notebook keyboard keyboard_id=$( xinput -list | grep "AT Translated Set 2 keyboard.*keyboard" | sed -e 's/^.*id=\([0-9]\+\).*/\1/' | head -1 ) if [ ! -z "$keyboard_id" ]; then setxkbmap -device $keyboard_id \ -layout br \ -option lv3:ralt_switch \ -option compose:menu \ -option caps:swapescape fi # Keychron K2 keyboard_id=$( xinput -list | grep "Keychron K2.*keyboard" | sed -e 's/^.*id=\([0-9]\+\).*/\1/' | head -1 ) if [ ! -z "$keyboard_id" ]; then setxkbmap -device $keyboard_id \ -layout us \ -variant intl \ -option lv3:ralt_switch \ -option compose:rctrl \ -option caps:swapescape fi
$ nvim ~/.config/autostart/keyboards.sh.desktop [Desktop Entry] Exec=/home/julio/bin/keyboards.sh Icon=dialog-scripts Name=keyboards.sh Path= Type=Application X-KDE-AutostartScript=true
-
Compose: c-cedilla
In the
US International with Dead Keys
layout,ç
can be obtained withAltGr + ,
, but I prefer to use´ + c
orcompose + c
.Create a
~/.XCompose
(or~/.config/ibus/Compose
) based on/usr/share/X11/locale/en_US.UTF-8/Compose
:# UTF-8 (Unicode) compose sequence include "%L" <Multi_key> <c> : "ç" ccedilla <Multi_key> <C> : "Ç" Ccedilla <dead_acute> <c> : "ç" ccedilla <dead_acute> <C> : "Ç" Ccedilla <Multi_key> <t> <o> <w> <e> <r> : "🗼"
Oriental Characters
You can type characters not available on your keyboard through an input method framework like IBUS or Fcitx5.
I will show how to use ibus-libpinyin
and fcitx5-chinese-addons
to type in Chinese. Configuring
other languages using other IMEs (input method editors) is similar.
IBUS
IBus (Intelligent Input Bus) is quite popular. It is already integrated with GNOME, but also works well with other Desktop Environments.
-
Install IBus
sudo pacman -S ibus ibus-libpinyin
-
Set the following environment variables:
sudo nvim /etc/environment GTK_IM_MODULE=ibus QT_IM_MODULE=ibus XMODIFIERS=@im=ibus GLFW_IM_MODULE=ibus
-
Configure IBus to start with the DE
$ nvim ~/.config/autostart/ibus-daemon.desktop [Desktop Entry] Comment=IBus Daemon #Exec=ibus-daemon -drx --panel=/usr/lib/kimpanel-ibus-panel Exec=ibus-daemon -drx GenericName=IBus Daemon Icon=ibus-engine Name=IBus Daemon StartupNotify=true Terminal=true Type=Application X-KDE-SubstituteUID=false
KDE has a widget called Input Method Panel, but I prefer to use the default IBus panel.
-
Configure IBus
ibus-setup
Under Input Method, choose Portuguese (Brazil), Chinese-Intelligent Pinyin, and English (US, intl., with dead keys).
Under General, set the shortcut
<Super>space
to switch between input methods.Under Advanced, check the option to use the system layout so that IBus does not override the layout set using
setxkbmap
. -
Change the panel color to match your taskbar
gsettings set org.freedesktop.ibus.panel xkb-icon-rgba '#ffffff'
Fcitx5
Fcitx (Flexible Context-aware Input Tool with eXtension support) is the input method framework I use.
It is very flexible, has many features, and integrates well with KDE.
-
Install Fcitx5
sudo pacman -S fcitx5-im fcitx5-chinese-addons
-
Set the following environment variables:
sudo nvim /etc/environment GTK_IM_MODULE=fcitx QT_IM_MODULE=fcitx XMODIFIERS=@im=fcitx DefaultIMModule=fcitx SDL_IM_MODULE=fcitx GLFW_IM_MODULE=ibus
The last line is for Kitty. It remains as ibus.
-
Configure Fcitx5 to start with the DE
$ nvim ~/.config/autostart/fcitx5.desktop [Desktop Entry] Name=Fcitx5 GenericName=Fcitx5 Input Method Comment=Start Fcitx5 Exec=fcitx5 Icon=fcitx Terminal=false Type=Application Categories=System;Utility; StartupNotify=false X-GNOME-Autostart-Phase=Applications X-GNOME-AutoRestart=false X-GNOME-Autostart-Notify=false X-KDE-autostart-after=panel X-KDE-StartupNotify=false X-GNOME-Autostart-enabled=true
-
Configure Fcitx5
I recommend making the configurations through the graphical interface
fcitx5-configtool
(in KDE, it is integrated into the system settings atSystem Settings » Personalization » Regional Settings » Input Method
).In my tests, manually edited files ended up being overwritten with the values configured by the graphical interface.
-
Config
$ nvim ~/.config/fcitx5/config [Hotkey/TriggerKeys] 0=Super+space [Behavior/DisabledAddons] 0=cloudpinyin 1=wayland 2=waylandim
-
Layouts
$ nvim ~/.config/fcitx5/profile [Groups/0] # Group Name Name="Group 1" # Layout Default Layout=us-intl # Default Input Method DefaultIM=keyboard-us-intl [Groups/0/Items/0] # Name Name=keyboard-us-intl # Layout Layout= [Groups/0/Items/1] # Name Name=pinyin # Layout Layout= [GroupOrder] 0="Group 1"
Note: the last entry in the
configtool
will be theDefaultIM
. -
XCB
$ nvim ~/.config/fcitx5/conf/xcb.conf Allow Overriding System XKB Settings=False
-
UI
pacman -S fcitx5-material-color fcitx5-nord
$ nvim ~/.config/fcitx5/conf/classicui.conf # Use Per Screen DPI PerScreenDPI=False # Font Font="Noto Sans Black 10" # Menu Font MenuFont="Sans 10" # Theme Theme=Material-Color-Blue
-
- Cloud Pinyin
$ nvim ~/.config/fcitx5/conf/pinyin.conf
CloudPinyinEnabled=False
Keychron Keyboard
To make the F1,…,F12 keys work correctly:
sudo nvim /etc/modprobe.d/hid_apple.conf
options hid_apple fnmode=2
sudo mkinitcpio -P
XDG user directories
Install xdg-user-dirs to create the folders.
sudo pacman -S xdg-user-dirs
$ xdg-user-dirs-update --force
Power Management
There are many tools for power management. I use the following:
sudo pacman -S tlp acpid acpi_call upower xfce4-power-manager
sudo systemctl enable tlp.service
sudo systemctl enable acpid.service
Bluetooth
After installing bluez
, start the bluetooth.service
:
sudo systemctl start bluetooth.service
The Bluez configuration is in /etc/bluetooth/main.conf
. I use the default settings.
Most desktop environments include some GUI to facilitate the connection, like Bluedevil in KDE, but
I also like to install bluez-utils
to connect Bluetooth devices via the command line with
bluetoothctl
.
Example connecting two keyboards and a headset:
((((06ef2b337b12f8a5))))
Tip: Use FN+Z+J
to reset the Keychron keyboard and reset the connections.
asdf
asdf has plugins for almost anything. It can replace pyenv
, rbenv
, goenv
, and
nvm
. There is even a plugin to manage different versions of Poetry.
git clone https://github.com/asdf-vm/asdf.git ~/.asdf --branch v0.11.3
Use the oh-my-zsh plugin to enable and add completions.
-
pacman -S --needed base-devel openssl zlib xz tk
asdf plugin add python asdf install python latest:3 asdf global python latest
asdf install python latest:3.10 asdf local python latest:3.10 asdf uninstall python <python-version>
-
Ruby
asdf plugin add ruby asdf install ruby latest asdf local ruby latest
-
Go
asdf plugin add golang asdf install golang latest asdf global golang latest
-
Node.js
asdf plugin add nodejs asdf install nodejs latest
Global versions are defined in the ~/.tool-versions
file.
Python
I had my first contact with Python over 10 years ago and today, besides being my favorite programming language, it is the language I use the most for work and personal projects.
The [Zen of Python][PEP 20] says:
“There should be one– and preferably only one –obvious way to do it.”
Which is valid for code, but for packaging, the story is quite different. My feelings are well portrayed in this sequence of xkcd comics: [xkcd 353], [xkcd 927], [xkcd 1987].

My current preferences are as follows, in order:
-
To manage different versions of Python: asdf or [Pyenv].
-
To manage virtual environments, control dependencies, and facilitate package publishing: PDM or [Poetry].
-
For more complex cases of machine learning or projects that depend on packages and binaries not available on [pypi]: [Mambaforge].
-
IDE: [VSCode] with the official extension or [PyCharm].
The issue with [PyCharm] is that some important features (framework integration, SQL editing, Docker integration, etc.) are paid.
Pyenv
Pyenv allows you to install and use different versions of Python.
It is like asdf, but exclusive to Python. If you already use asdf for other languages, it may not make much sense to install Pyenv.
-
Install Pyenv:
sudo pacman -S pyenv
-
Optionally, also install pyenv-virtualenv:
yay -S pyenv-virtualenv
-
Add the following lines to
~/.zshrc
:if (( $+commands[pyenv] )); then eval "$(pyenv init --path)"; fi if (( $+commands[pyenv-virtualenv-init] )); then eval "$(pyenv virtualenv-init -)"; fi
-
Check which versions are available and install the ones you will use:
pyenv install --list pyenv install 3.8.12 pyenv install mambaforge
-
List the installed versions:
pyenv versions
-
In a project folder, set the version to be used:
pyenv local 3.8.12
A file named
.python-version
will be created:$ cat .python-version 3.8.12
Poetry
Update: section updated for version 1.2.
-
Install Poetry
I prefer not to use the system package manager for Poetry, there are some good alternatives:
-
Script:
wget -O install-poetry.py https://install.python-poetry.org python install-poetry.py --preview
Note: The old installer (
get-poetry.py
) has been replaced byinstall-poetry.py
. Do not pass the--preview
parameter if you want the latest stable version. -
asdf:
asdf plugin add poetry asdf install poetry latest asdf global poetry latest
-
pipx:
pipx install poetry
-
-
Add to PATH
The old installer used the folder
$HOME/.poetry/bin
. The new one uses$HOME/.local/bin
.Using my function in
.zshrc
:addToPathStart $HOME/.local/bin
-
Install completions
poetry completions zsh > ~/.zprezto/modules/completion/external/src/_poetry
The above command is because I use Prezto. The important thing is to install in a folder listed in
$fpath
. -
Create a new project
poetry new my-project cd my-project
-
Set the Python version using Pyenv or asdf
pyenv local 3.8.12
or
asdf local 3.8.12
$ nvim pyproject.toml … [tool.poetry.dependencies] python = "^3.8" …
poetry env use -- /home/julio/.pyenv/versions/3.10.3/bin/python
or
poetry env use -- /home/julio/.asdf/installs/python/3.10.3/bin/python
poetry run python --version poetry debug info
-
Add dependencies
Development dependencies are passed with
--dev
.$ poetry add --group dev \ bandit \ black \ codecov \ coverage \ flake8 \ gitchangelog \ isort \ mkdocs \ mypy \ pydocstyle \ pytest \ pytest-cov
poetry add typer\[all\]
-
Update Poetry
poetry self update
Remember to generate the completions again.
-
Install poetry-plugin-up
poetry self add poetry-plugin-up poetry up --latest
This plugin updates the packages in
pyproject.toml
to the latest version.
If Poetry gets stuck on “Resolving dependencies,” try the following:
find ~/.cache/pypoetry -name '*.lock' -type f -delete
poetry env remove --all
poetry cache clear --all .
rm -rf $(poetry config cache-dir)/artifacts
Mambaforge
Mambaforge combines Mamba and Conda-Forge.
Mamba is a reimplementation of the Conda package manager in C++. It resolves dependencies very quickly and downloads in parallel.
Conda-Forge Channel contains recipes written by the community for Conda. It has many more packages than the official Conda repository.
-
If you do not want to use Pyenv, it is possible to install Mambaforge manually:
wget https://github.com/conda-forge/miniforge/releases/latest/download/Mambaforge-Linux-x86_64.sh bash Mambaforge-Linux-x86_64.sh
-
Update base packages
mamba update mamba mamba update --all
-
Create and activate a virtual environment
mamba create -n env_name python=3.10 jupyterlab … conda activate env_name
-
Install some additional packages
$ mamba install \ azure-identity \ bandit \ black \ bokeh \ dask \ flake8 \ ipywidgets \ isort \ jupyterlab_code_formatter \ kafka-python \ keras \ koalas \ matplotlib \ mypy \ numpy \ openpyxl \ pandas \ plotly \ pyarrow \ pycodestyle \ pydocstyle \ pylama \ pylint \ pyspark \ pytest \ python-graphviz \ python-wget \ scikit-learn \ seaborn \ sqlalchemy \ tenacity \ tensorflow \ unidecode \ xgboost
PDM
Like Poetry, PDM is a package and dependency manager.
The difference is that it follows the new PEPs (PEP 582, PEP 517, and PEP 621).
You can use a virtualenv or follow PEP 582 and use a folder called __pypackages__
. This folder is
equivalent to node_modules
, it is added to sys.path
.
Installation
-
Via script:
curl -sSL https://raw.githubusercontent.com/pdm-project/pdm/main/install-pdm.py | python3 -
-
Via asdf:
asdf plugin add pdm asdf install pdm latest asdf local pdm latest
-
Completions in ZSH
pdm completion zsh > ~/.zprezto/modules/completion/external/src/_pdm
Usage
-
Create a project
pdm init
-
Add dependencies
pdm add requests flask
-
Add development dependencies
pdm add -dG dev jupyterlab jupyterlab-code-formatter black isort pylint mypy
-
Remove dependencies
pdm remove flask
-
List dependencies
pdm list --graph
-
Install project
pdm install
-
Install based on the .lock file
pdm sync
-
Update dependencies
-
All packages
pdm update
-
Specific package
pdm update <package>
-
Packages from a group
pdm update -G <group>
-
Force update pinned packages
pdm update --update-eager
-
-
-
Remove unlisted packages
pdm sync --clean
-
Run binary in the environment
pdm run jupyter lab
Update
pdm self update
Rust
The recommended way to develop in Rust is to use rustup, which can be installed in two ways:
-
Official script:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
-
Pacman:
sudo pacman -S rustup rustup default stable
This method is more convenient in Arch, as it keeps Rust and its dependent packages constantly updated.
Test the installation:
$ rustc --version
rustc 1.53.0 (53cb7b09b 2021-06-17)
$ cargo --version
cargo 1.53.0 (4369396ce 2021-04-27)
$ rustdoc --version
rustdoc 1.53.0 (53cb7b09b 2021-06-17)
$ cargo new hello
Created binary (application) `hello` package
$ cd hello
$ cargo run
Compiling hello v0.1.0 (/home/julio/hello)
Finished dev [unoptimized + debuginfo] target(s) in 0.43s
Running `target/debug/hello`
Hello, world!
My Neovim is configured to use the rust-analyzer as LSP Server. Just install the binary:
sudo pacman -S rust-analyzer
Nvidia
One of the notebooks has an integrated Intel GPU and an Nvidia GeForce RTX 2070 Max-Q, which has better performance than the Intel GPU but consumes more power.
It is possible to permanently disable one of the cards or use Nvidia Optimus technology to switch between the cards according to the need.
Install drivers and utilities:
sudo pacman -S nvidia nvidia-utils nvidia-settings opencl-nvidia
Running a specific program on Nvidia
To perform the so-called
PRIME render offload just start the
program with the prime-run
command. Ex.:
sudo pacman -S nvidia-prime
prime-run kdenlive
Using only the Nvidia card
sudo nvim /etc/X11/xorg.conf.d/10-nvidia-drm-outputclass.conf
Section "OutputClass"
Identifier "intel"
MatchDriver "i915"
Driver "modesetting"
EndSection
Section "OutputClass"
Identifier "nvidia"
MatchDriver "nvidia-drm"
Driver "nvidia"
Option "AllowEmptyInitialConfiguration"
Option "PrimaryGPU" "yes"
ModulePath "/usr/lib/nvidia/xorg"
ModulePath "/usr/lib/xorg/modules"
EndSection
$ nvim ~/.xinitrc (ou /usr/share/sddm/scripts/Xsetup para o SDDM)
xrandr --setprovideroutputsource modesetting NVIDIA-0
xrandr --auto
setxkbmap br -option caps:swapescape
To ensure that the module will be loaded before the graphical interface.
sudo nvim /etc/modprobe.d/nvidia-drm-nomodeset.conf
options nvidia-drm modeset=1
sudo nvim /etc/mkinitcpio.conf
MODULES=(nvidia nvidia_modeset nvidia_uvm nvidia_drm)
sudo mkinitcpio -P
(Note: If the /boot
partition has little free space, it is possible to disable the generation of
the fallback image by commenting out the related lines in /etc/mkinitcpio.d/linux.preset
. If this
is not enough, it will be necessary to resize the partitions.)
sudo systemctl reboot
nvidia-smi
sudo pacman -S virtualgl
glxspheres64
Tearing
Screen tearing is when parts of different frames are displayed on the screen at the same time.
This problem was quite noticeable when watching videos on the monitor connected via HDMI. Test with the video https://youtu.be/MfL_JkcEFbE and with the site https://www.vsynctester.com.
-
Browser Configuration
Check if enabling
layers.acceleration.force-enabled
in Firefox’sabout:config
improves anything. -
Force composition
This option may increase latency, but it was what solved my problem.
Check the current settings:
$ nvidia-settings --query CurrentMetaMode Attribute 'CurrentMetaMode' (Predator:0.0): id=50, switchable=yes, source=RandR :: DPY-2: nvidia-auto-select @1920x1080 +1920+0 {ViewPortIn=1920x1080, ViewPortOut=1920x1080+0+0}
Enable
ForceCompositionPipeline
(orForceFullCompositionPipeline
):nvidia-settings --assign CurrentMetaMode="nvidia-auto-select +1920+0 { ForceCompositionPipeline = On }"
The
+1920+0
offset is because the laptop screen is full HD and is positioned to the left of the external monitor.Check the new settings:
$ nvidia-settings --query CurrentMetaMode Attribute 'CurrentMetaMode' (Predator:0.0): id=50, switchable=no, source=nv-control :: DPY-2: nvidia-auto-select @1920x1080 +1920+0 {ViewPortIn=1920x1080, ViewPortOut=1920x1080+0+0, ForceCompositionPipeline=On}
Add this command to a file that is executed at startup, such as
autostart
,xinit
, orXsetup
.~/bin/nvidia-force_comp_pipeline.sh
:#!/bin/sh s="$(nvidia-settings -q CurrentMetaMode -t)" echo "$s" if [[ "${s}" != "" ]]; then s="${s#*" :: "}" echo "$s" if [[ "${s}" != "NULL" ]]; then nvidia-settings -a CurrentMetaMode="${s//\}/, ForceCompositionPipeline=On\}}" fi fi
/usr/share/sddm/scripts/Xsetup
:#!/bin/sh # Xsetup - run as root before the login dialog appears # Keyboards kb_script="/home/julio/bin/keyboards.sh" [ -s "$kb_script" ] && \. "$kb_script" # Nvidia xrandr --setprovideroutputsource modesetting NVIDIA-0 xrandr --auto # Force Composition Pipeline nfcp_script="/home/julio/bin/nvidia-force_comp_pipeline.sh" [ -s "$nfcp_script" ] && \. "$nfcp_script"
If your monitors are fixed, you can use
/etc/X11/xorg.conf.d/20-nvidia.conf
:Section "Screen" … Option "MetaModes" "nvidia-auto-select +0+0 {ForceFullCompositionPipeline=On}" … EndSection
Window Managers and Desktop Environments
Awesome
For AwesomeWM, I like the configurations from Gerome Matilla. They are a bit bloated, but the layouts are very nice and have interesting features.
KDE
KDE Plasma is a very good DE with default settings that I really like.
I used to avoid using KDE on my old computers because it wasn’t light enough, but with my current hardware, this is no longer a big issue.
I recommend installing the following packages:
sudo pacman -S ark \
dolphin \
gwenview \
packagekit-qt5 \
plasma-browser-integration \
sddm \
spectacle
You can swap Caps Lock for ESC in
System Settings » Keyboard » Advanced » Caps Lock behavior » Swap Esc and Caps Lock
.
Install kdeconnect
on the computer and on Android devices to sync notifications, share files,
share the clipboard, use Android as a mouse and keyboard, among other functions.
Test the OpenGL and XRender options in
System Settings » Hardware » Display and Monitor » Compositor » Rendering backend
. The best option
is probably OpenGL, but I have seen reports of issues with Nvidia cards.```
If you don’t want to display media controls on the lock screen, run the following command:
kwriteconfig5 --file kscreenlockerrc --group Greeter --group LnF --group General --key showMediaControls --type bool false
If the fonts are too large, force the DPI in System Settings » Fonts » Force font DPI: 96
.
Tiling in KDE: Kröhnkite
-
Move the taskbar to the top of the screen;
-
Decrease the size of the bar (set to 30);
-
Right-click on the taskbar, click on Show Alternatives, and choose “Icons-only Task Manager”;
-
Right-click on the Pager » Configure Pager
- Show application icons on window outlines
- Text display: Desktop number
-
System Settings » Workspace » Window Management » KWin Scripts » Get New Scripts…
-
Activate Kröhnkite settings
mkdir -p ~/.local/share/kservices5/ ln -s ~/.local/share/kwin/scripts/krohnkite/metadata.desktop ~/.local/share/kservices5/krohnkite.desktop
A configure button for Kröhnkite will appear on the KWin Scripts screen. There, I do the following:
- Activate the Quarter layout
- Gaps between tiles: 3 px
- Prevent windows from minimizing
Remove borders of tiled windows
-
System Settings » Appearance » Window Decorations » Edit Theme » Window-Specific Overrides » Add
- Regular expression to match:
.*
- Border size: Tiny
- Hide window title bar
- Regular expression to match:
-
Go to System Settings » Workspace » Workspace Behavior » Virtual Desktops and add as many desktops as you want (I set it to 8, displayed in two rows);
-
System Settings » Workspace » Workspace Behavior » Desktop Effects » Focus » Dim Inactive;
-
System Settings » Workspace » Window Management » Window Behavior » Focus » Multiscreen behavior: Separate screen focus;
-
Border colors
kwriteconfig5 --file ~/.config/kdeglobals --group WM --key frame 61,174,233 kwriteconfig5 --file ~/.config/kdeglobals --group WM --key inactiveFrame 239,240,241
-
Remove minimum window size
- System Settings » Workspace » Window Management » Window Rules
- Add New…
- Window class: Unimportant
- Window types: Normal Window
- Add Properties…
- Minimum Size: Force 0 x 0
-
Change shortcuts in System Settings » Workspace » Shortcuts » KRunner
- KRunner:
Meta + R
- KRunner:
-
Change shortcuts in System Settings » Workspace » Shortcuts » KWin
- Switch to Desktop n:
Meta + n
- Switch to Previous Screen:
Meta + ,
- Switch to Next Screen:
Meta + .
- Window to Desktop n:
Meta+Shift+Fn
(UsingMeta + F1,…,F8
, becauseMeta+Shift+6
doesn’t work with US intl. keyboard) - Window to Previous Screen:
Meta + <
- Window to Next Screen:
Meta + >
- Krohnkite: Float All:
Meta+Shift+F
- Krohnkite: Right: Meta+L (use
ctrl+alt+L
to lock the screen)
- Switch to Desktop n:
Android Integration
MTP devices can only be accessed by one program.
To sync a tablet with Calibre, KDE must not have mounted the device before.
Kill the kiod5
process.
Gnome
Gnome is a complete and quite popular DE. I don’t like the default settings much, but after some quick adjustments, it becomes quite usable:
sudo pacman -S gnome gnome-tweaks gnome-shell-extension-appindicator evolution
sudo systemctl enable gdm
dconf write /org/gnome/desktop/input-sources/xkb-options "['caps:swapescape']"
Through Tweaks, enable the app indicator extension and the minimize and maximize buttons.
Install Pipewire for screen sharing to work on Wayland:
sudo pacman -S pipewire xdg-desktop-portal-gtk
Wine
- Install some of the following packages (not all are necessary)
$ sudo pacman -S \
wine-staging \
wine-gecko \
wine-mono \
winetricks \
zenity \
playonlinux
$ sudo pacman -S \
giflib \
lib32-giflib \
libpng \
lib32-libpng \
libldap \
lib32-libldap \
gnutls \
lib32-gnutls \
mpg123 \
lib32-mpg123 \
openal \
lib32-openal \
v4l-utils \
lib32-v4l-utils \
libpulse \
lib32-libpulse \
alsa-plugins \
lib32-alsa-plugins \
alsa-lib \
lib32-alsa-lib \
libjpeg-turbo \
lib32-libjpeg-turbo \
libxcomposite \
lib32-libxcomposite \
libxinerama \
lib32-libxinerama \
ncurses \
lib32-ncurses \
opencl-icd-loader \
lib32-opencl-icd-loader \
libxslt \
lib32-libxslt \
libva \
lib32-libva \
gtk3 \
lib32-gtk3 \
gst-plugins-base-libs \
lib32-gst-plugins-base-libs \
vulkan-icd-loader \
lib32-vulkan-icd-loader \
cups \
samba \
dosbox
-
Install the Windows fonts as explained previously
-
Run
winetricks
With
zenity
installed, a GUI will appear to help create prefixes, install dependencies, install and uninstall programs.
Prefixes are created in ~/.local/share/wineprefixes/
.
-
Call a program from the command line
WINEPREFIX="~/.local/share/wineprefixes/nome_prefixo" wine ~/.local/share/wineprefixes/nome_prefixo/drive_c/Programa.exe
VPNs
Most VPNs have their own installer (which is often available in the AUR).
Prefer WireGuard over OpenVPN when possible.
Links
- https://wiki.archlinux.org/title/NVIDIA
- https://wiki.archlinux.org/title/NVIDIA_Optimus
- https://wiki.archlinux.org/title/PRIME
- https://www.dell.com/community/Laptops-General-Read-Only/Dell-M-2-FAQ-regarding-AHCI-vs-RAID-ON-Storage-Drivers-M-2-Lanes/m-p/5072571/highlight/true#M903278
- https://jeffreytse.net/computer/2020/11/19/how-to-use-fcitx5-elegantly-on-arch-linux.html
- https://wiki.archlinux.org/title/Private_Internet_Access