Arch Linux config
Arch Linux config
I’ve decided to switch to Arch Linux and configure it declaratively with metapac.
System installation
Installation
On installation, see https://wiki.archlinux.org/title/Installation_guide and/or use archinstall.
Don’t forget to run
pacman -Sy archlinux-keyring
Before archinstall.
After installation
Update everything:
sudo pacman -Syyu
Install git, python and yadm:
sudo pacman -Syu python git pacman-contrib yadm
Select top-6 fastest mirrors to work with. Generate a mirrorlist file using this service: https://archlinux.org/mirrorlist/, then use rankmirrors from pacman-contrib (see Mirrors on Arch Wiki).
sudo -i
cp /etc/pacman.d/mirrorlist /etc/pacman.d/mirrorlist.backup
rankmirrors -n 6 /etc/pacman.d/mirrorlist.backup > /etc/pacman.d/mirrorlist
If there isn’t enough RAM (e.g. running in a VM), turn off mounting /tmp as tmpfs:
sudo systemctl mask tmp.mount
Install paru:
sudo pacman -S --needed base-devel
git clone https://aur.archlinux.org/paru.git
cd paru
makepkg -si
Install metapac:
paru -Syyu metapac
Enable multilib by uncommenting the [multilib] section in /etc/pacman.conf.
Then install Arch packages with metapac:
mkdir ~/00-Scratch/
git clone https://github.com/SqrtMinusOne/dotfiles.git ~/00-Scratch/dotfiles/
cp -r ~/00-Scratch/dotfiles/.config/metapac ~/.config/
metapac s
Then, install the ssh and gpg keys (put them into the ~/.ssh folder). To export gpg keys:
gpg --output private.pgp --armor --export-secret-keys <keyname>
And to import:
gpg --import private.pgp
gpg --edit-key <keyname>
trust
Also the following to ~/.ssh/config:
Host *
AddKeysToAgent yes
And run:
systemctl enable --user --now ssh-agent
It looks like it is necessary to run at least once.
Then, clone the dotfiles repo with yadm:
yadm clone git@github.com:SqrtMinusOne/dotfiles.git
Checkout the changed files.
Clone org-mode and passwords repos:
git clone ssh://git@git.sqrtminusone.xyz:222/sqrtminusone/org-mode.git "/home/pavel/30-39 Life/32 org-mode"
git clone ssh://git@git.sqrtminusone.xyz:222/sqrtminusone/passwords.git "/home/pavel/.password-store"
And don’t forget to configure git:
git config --global user.email "thexcloud@gmail.com"
git config --global user.name "SqrtMinusOne"
Install wakatime:
cd ~/00-Scratch/
git clone https://github.com/wakatime/wakatime-cli.git
cd ./wakatime-cli
go build
mv wakatime-cli ~/bin
And create the ~/.wakatime.cfg file with the following contents:
[settings]
api_key = <api-key>
Then run emacs and make sure it starts. Run:
M-x nerd-icons-install-fontsM-x all-the-icons-install-fontsM-x treesit-install-language-grammar
Run rclone config, configure the remotes. Then M-x my/index-commands-sync.
If everything works, login into EXWM.
Create some directories:
mkdir -p /home/pavel/Pictures/screenshots/
mkdir -p /home/pavel/.mpd/playlists/
Also run:
sudo chmod +s /usr/bin/light
For I’ve decided to use NetworkManager, but Arch Linux uses iwd by default, which causes issues. Disable it by:
sudo systemctl disable --now iwd
sudo systemctl disable --now systemd-networkd
sudo systemctl enable --now NetworkManager
And reboot. After the reboot, NetworkManager should run using wpa_supplicant as backend for Wi-Fi.
Don’t forget to sync mail and enable the sync timer.
sudo usermod -a -G libvirt pavel
sudo usermod -a -G kvm pavel
sudo virsh net-autostart default
Install zotero-better-bibtex manually.
Run init-nvm:
bash /usr/share/nvm/init-nvm.sh
Add flatpak remote:
flatpak remote-add --user --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
To install xrdp, configure an unpriviliged user:
sudo useradd xrdp -d / -c 'xrdp daemon' -s /usr/sbin/nologin
Then uncomment these lines in /etc/xrdp/xrdp.ini:
runtime_user=xrdp
runtime_group=xrdp
And in /etc/xrdp/sesman.ini:
SessionSockdirGroup=xrdp
Fix the permissions:
sudo chmod 640 /etc/xrdp/cert.pem /etc/xrdp/key.pem /etc/xrdp/rsakeys.ini
sudo chown root:xrdp /etc/xrdp/cert.pem /etc/xrdp/key.pem /etc/xrdp/rsakeys.ini
sudo systemctl enable --now xrdp
Set the default browser:
xdg-settings set default-web-browser glide-browser-bin.desktop
Disable systemd coredumps by editing /etc/systemd/coredump.conf
[Coredump]
Storage=none
ProcessSizeMax=0
systemctl --user enable --now gnome-keyring-daemon.service gnome-keyring-daemon.socket
Metapac configuration
metapac is a declarative wrapper around different package managers, including pacman and paru. This means the required packages can be listed in configuration files and checked into version control.
I’ve also tried decman, but it turned out to be too unstable because it ships its own logic for building AUR packages, which doesn’t always work. So wrapping paru seems like a saner approach. Also, sometimes AUR drops packets, and decman can’t handle it gracefully.
In metapac, packages are listed in “groups”, each group being a TOML file stating which package has to be installed by which package manager. I declare groups as Org tables, see the “System configuration” section in Emacs.org.
Below is the table enabling different groups on different hostnames:
| Profile | archlinux | weiss | violet | schwarz |
|---|---|---|---|---|
| browsers | + | + | + | + |
| console | + | + | + | + |
| desktop | + | + | + | + |
| desktop-misc | + | + | + | + |
| desktop-polybar | + | + | + | + |
| desktop-rofi | + | + | + | + |
| dev | + | + | + | + |
| emacs | + | + | + | + |
| latex | + | + | + | + |
| + | + | + | + | |
| music | + | + | + | + |
| nvidia | + | |||
| office | + | + | + | + |
| system | + | + | + | + |
| printer | + | |||
| games | + | |||
| geo | + | |||
| remote | + |
And the code to format it as TOML:
(let* ((hostnames (cdr (nth 0 groups)))
groups-by-hostname)
(cl-loop for row in (cdr groups)
for group = (nth 0 row)
do (cl-loop for i from 0
for sign in (cdr row)
for hostname = (nth i hostnames)
if (not (string-empty-p sign))
do (push group (alist-get hostname groups-by-hostname
nil nil #'equal))))
(cl-loop for (hostname . groups) in groups-by-hostname
concat (format "%s = [%s]\n" hostname
(mapconcat (lambda (g) (format "\"%s\"" g)) groups ","))))
Which is used in the config:
enabled_backends = ["arch", "flatpak"]
hostname_groups_enabled = true
[hostname_groups]
<<metapac-groups-format()>>
[arch]
package_manager = "paru"
paru configuration
Configuring paru to work with my custom Emacs build.
Include = /etc/paru.conf
[private]
Url = https://github.com/SqrtMinusOne/sqrt-emacs.git
GenerateSrcinfo
SkipReview
pacserve
https://wiki.archlinux.org/title/Pacserve
| Arch dependencies |
|---|
| pacserve |
systemctl enable --now pacserve
System packages
Some necessary Arch packages:
| Arch dependency |
|---|
| amneziavpn-bin |
| base |
| base-devel |
| debtap |
| gnome-keyring-daemon |
| grub |
| iwd |
| lightdm |
| lightdm-gtk-greeter |
| linux |
| linux-firmware |
| inetutils |
| nano |
| networkmanager |
| metapac |
| openssh |
| pacman-contrib |
| paru |
| pipewire |
| pipewire-audio |
| pipewire-alsa |
| pipewire-pulse |
| pipewire-jack |
| sof-firmware |
| smartmontools |
| vim |
| xterm |
| wget |
| wireless_tools |
| wireplumber |
| yadm |
| zram-generator |
Various drivers, I’m not sure which I actually need, so…
| Arch dependency |
|---|
| libva-intel-driver |
| intel-media-driver |
| vulkan-intel |
| vulkan-radeon |
| xf86-video-amdgpu |
| xf86-video-ati |
Also opensnitch, a firewall.
| Arch dependency |
|---|
| opensnitch |
| apparmor |
| firejail |
A tool to downgrade a package.
| Arch dependency |
|---|
| downgrade |
NVIDIA drivers & AI stuff for violet
| Category | Arch dependency |
|---|---|
| nvidia | cuda |
| nvidia | nvidia-utils |
| nvidia | nvidia-open |
| nvidia | llama.cpp-vulkan |
| nvidia | nvidia-container-toolkit |
Printer packages.
| Category | Arch dependency |
|---|---|
| printer | cups |
| printer | usbutils |
| printer | brlaser |
| printer | naps2-bin |
| printer | brscan4 |
Remote connectivity packages.
| Category | Arch dependency |
|---|---|
| remote | xorgxrdp |
To type stuff
| Arch dependency |
|---|
| xvkbd |
(my/format-arch-dependencies category)
<<packages("nvidia")>>
<<packages("printer")>>
<<packages("remote")>>
<<packages()>>
Notes on VMs
Linux
Install spice-vdagent and reboot to enable clipboard sharing.
Check View > Scale Display > Auto resize VM with window. Then, running
xrandr --output Virtual-1 --auto
Will resize the display to the VM window. This question has some info on how to automate that, I’m fine with executing the command manually.
To add a shared folder, do:
- Memory > Enable shared memory
- Add hardware > Filesystem with virtiofs, e.g.
<filesystem type="mount">
<source dir="/home/pavel/00-Scratch"/>
<target dir="shared"/>
<driver type="virtiofs"/>
</filesystem>
Then, in order to mount:
mkdir ~/00-Scratch/
sudo mount -t virtiofs shared /home/pavel/00-Scratch/
To make in permanent, add the following to /etc/fstab
shared /home/pavel/00-Scratch virtiofs defaults 0 0
Windows
References:
When creating a VM, check “Customize configuration before install”. Make the following changes:
-
In the CPUs tab, select “Copy host CPU configuration” and click Apply.
-
In the XML version edit the
<clock>section as follows:<clock offset='localtime'> <timer name='rtc' present='no' tickpolicy='catchup'/> <timer name='pit' present='no' tickpolicy='delay'/> <timer name='hpet' present='no'/> <timer name='kvmclock' present='no'/> <timer name='hypervclock' present='yes'/> </clock>The source says it will disable all timers except for the hypervclocks, reducing idle CPU usage.
Also enable Hyper-V enlightenments in
<hyperv>:<hyperv> <relaxed state='on'/> <vapic state='on'/> <spinlocks state='on' retries='8191'/> <vpindex state='on'/> <synic state='on'/> <stimer state='on'> <direct state='on'/> </stimer> <reset state='on'/> <frequencies state='on'/> <reenlightenment state='on'/> <tlbflush state='on'/> <ipi state='on'/> </hyperv>Add this device under
<devices>:<channel type='unix'> <source mode='bind'/> <target type='virtio' name='org.qemu.guest_agent.0'/> <address type='virtio-serial' controller='0' bus='0' port='2'/> </channel> -
In the SATA Disk 1 section, section set the Disk bus type to VirtIO.
-
In NIC section, set the device model to virtio.
-
Add a CD-ROM device with the VirtIO driver ISO.
During installation, load the VirtIO driver in \amd64\w11. The disk should appear.
After installation, open the VirtIO driver ISO and run virtio-win-guest-tools.exe. Then, the option at View > Scale Display / Auto resize VM with window should work.
Configure DNS to 1.1.1.1
To configure a shared folder:
- Toggle “Enable shared memory” in the memory tab.
- Click “Add hardware” -> Filesystem, select virtiofs as the driver and specify the paths.
- Install WinFSP on the VM.
- Run:
sc.exe create VirtioFsSvc binpath= "C:\Program Files\Virtio-Win\VioFS\virtiofs.exe" start=auto depend="WinFsp.Launcher/VirtioFsDrv" DisplayName="Virtio Filesystem Service" sc.exe start VirtioFsSvc - Reboot the VM.
Copying VMs between machines
To copy a VM, first, copy the image:
rsync -avP /var/lib/libvirt/images/debian12-vpn.qcow2 /run/media/pavel/A6E5-4138/vms/
Then, export the configuration:
virsh -c qemu:///system dumpxml debian12-vpn > debian12-vpn.xml
To restore, copy the image back:
sudo rsync -avP /run/media/pavel/A6E5-4138/vms/debian12-vpn.qcow2 /var/lib/libvirt/images/
And import the configuration:
sudo virsh define debian12-vpn.xml
Assign a static IP to a VM
To assign a static IP to a VM, run:
sudo EDITOR=vim virsh net-edit default
And inside the <dhcp> section, insert:
<host mac='52:54:00:58:7f:82' name='myvm' ip='192.168.122.50'/>
After which, restart the network:
sudo virsh net-destroy default
sudo virsh net-start default
Network
Don’t forget to set iptables in /etc/libvirt/network.conf:
firewall_backend = "iptables"
Notes on Software
Upgrading Python and AUR packages
After upgrading Python from 3.13 to 3.14, lieer has stopped working
$ gmi
Traceback (most recent call last):
File "/usr/bin/gmi", line 20, in <module>
from lieer import Gmailieer
ModuleNotFoundError: No module named 'lieer'
The issue is that the package has been installed for Python 3.13:
pacman -Ql lieer-git | grep -E '\.py$|site-packages'
lieer-git /usr/lib/python3.13/site-packages/
lieer-git /usr/lib/python3.13/site-packages/lieer-1.6.dist-info/
lieer-git /usr/lib/python3.13/site-packages/lieer-1.6.dist-info/METADATA
lieer-git /usr/lib/python3.13/site-packages/lieer-1.6.dist-info/RECORD
lieer-git /usr/lib/python3.13/site-packages/lieer-1.6.dist-info/WHEEL
lieer-git /usr/lib/python3.13/site-packages/lieer-1.6.dist-info/licenses/
lieer-git /usr/lib/python3.13/site-packages/lieer-1.6.dist-info/licenses/COPYING.GPL-3.0+
lieer-git /usr/lib/python3.13/site-packages/lieer-1.6.dist-info/licenses/LICENSE.md
lieer-git /usr/lib/python3.13/site-packages/lieer-1.6.dist-info/top_level.txt
lieer-git /usr/lib/python3.13/site-packages/lieer/
lieer-git /usr/lib/python3.13/site-packages/lieer/__init__.py
lieer-git /usr/lib/python3.13/site-packages/lieer/__pycache__/
lieer-git /usr/lib/python3.13/site-packages/lieer/__pycache__/__init__.cpython-313.opt-1.pyc
lieer-git /usr/lib/python3.13/site-packages/lieer/__pycache__/__init__.cpython-313.pyc
lieer-git /usr/lib/python3.13/site-packages/lieer/__pycache__/gmailieer.cpython-313.opt-1.pyc
lieer-git /usr/lib/python3.13/site-packages/lieer/__pycache__/gmailieer.cpython-313.pyc
lieer-git /usr/lib/python3.13/site-packages/lieer/__pycache__/local.cpython-313.opt-1.pyc
lieer-git /usr/lib/python3.13/site-packages/lieer/__pycache__/local.cpython-313.pyc
lieer-git /usr/lib/python3.13/site-packages/lieer/__pycache__/nobar.cpython-313.opt-1.pyc
lieer-git /usr/lib/python3.13/site-packages/lieer/__pycache__/nobar.cpython-313.pyc
lieer-git /usr/lib/python3.13/site-packages/lieer/__pycache__/remote.cpython-313.opt-1.pyc
lieer-git /usr/lib/python3.13/site-packages/lieer/__pycache__/remote.cpython-313.pyc
lieer-git /usr/lib/python3.13/site-packages/lieer/__pycache__/resume.cpython-313.opt-1.pyc
lieer-git /usr/lib/python3.13/site-packages/lieer/__pycache__/resume.cpython-313.pyc
lieer-git /usr/lib/python3.13/site-packages/lieer/gmailieer.py
lieer-git /usr/lib/python3.13/site-packages/lieer/local.py
lieer-git /usr/lib/python3.13/site-packages/lieer/nobar.py
lieer-git /usr/lib/python3.13/site-packages/lieer/remote.py
lieer-git /usr/lib/python3.13/site-packages/lieer/resume.py
And the Python version is 3.14:
$ python --version
Python 3.14.2
Simply rebuilding the package doesn’t help because something has been cached. It is neccessary to use the --rebuild tag:
$ paru -S lieer-git --rebuild
Installing MS Office 2007
MS Office 2007, which I need for work, installs reasonably well on PlayOnLinux, except for one library that can be downloaded with winetricks:
WINEPREFIX=~/.PlayOnLinux/wineprefix/Office2007 WINE=~/.PlayOnLinux/wine/linux-x86/4.0/bin/wine winetricks msxml3
Issues with DBeaver
In /usr/lib/jvm/java-21-openjdk/conf/security/java.security, in jdk.tls.disabledAlgorithms in lines:
ECDH, TLS_RSA_*, rsa_pkcs1_sha1 usage HandshakeSignature, \
ecdsa_sha1 usage HandshakeSignature, dsa_sha1 usage HandshakeSignature
Leave only ECDH
Running MAX in Firejail
Firejail config:
include disable-common.inc
include disable-devel.inc
include disable-programs.inc
private ~/.sandbox/max
private-tmp
private-cache
private-dev
caps.drop all
nonewprivs
[Desktop Entry]
Type=Application
Terminal=false
Name=MAX
Exec=firejail --profile=max /usr/share/max/bin/max %U
DBusActivatable=false
Icon=/usr/share/pixmaps/max.png
MimeType=x-scheme-handler/max;
Comment=MAX Messenger Client Application
Comment[ru]=Клиентское приложение мессенджера MAX
StartupWMClass=max
Categories=Chat;Network;InstantMessaging;Qt;
Keywords=max;chat;im;messaging;messenger;sms;
SingleMainWindow=true
X-GNOME-UsesNotifications=true
X-GNOME-SingleWindow=true
Don’t forget to run:
mkdir -p ~/.sandbox/max
update-desktop-database ~/.local/share/applications