Personal Arch Linux setup
This is how I have my computer set up. I don't expect this document to be useful for other people.
Installation
Follow Arch Linux with mirrored, encrypted ZFS root.
Connect to network:
dhcpcd
Non-root user
useradd -m -G wheel,network,sys,uucp me
chmod 700 /home/me
passwd me
useradd -m -G network guest
passwd guest
pacman -S sudo
visudo
Uncomment the line %wheel ALL=(ALL) ALL
and save. Log out and log back in as regular user.
Desktop environment
Install video drivers:
pacman -S nvidia nvidia-utils cuda cudnn
systemctl reboot
Install basic desktop environment:
pacman -S xfce4 xf86-input-{synaptics,wacom} firefox vim
cp /etc/X11/xinit/xinitrc .xinitrc
Replace the last few lines with
exec startxfce4
Remap caps lock to escape:
# ~/.Xmodmap
# Double check that ~/.xinitrc loads this file.
# If not, add `xmodmap "$HOME/.Xmodmap"` before the `exec` line.
clear Lock
!keycode 66 = Escape Caps_Lock ! <Shift>Escape for caps lock
keycode 66 = Escape
Run exec startx
to start DE.
Screen locker
Configure shortcuts in xfce4-keyboard-settings
:
Alt+Q xflock4
Install xautolock to lock the screen after 20 minute timeout:
pacman -S xautolock
In xfce4-session-settings
under "Application Autostart", add an entry for xautolock:
/bin/bash -c 'xset dpms 0 0 0; xautolock -time 20 -locker /usr/bin/xflock4 > ~/.xautolock.log 2>&1'
Confirm that screen lock works. Confirm that you can't bypass the lock with Ctrl-Alt-F7.
NetworkManager
pacman -S networkmanager network-manager-applet
systemctl enable NetworkManager systemd-resolved
systemctl start NetworkManager systemd-resolved
ln -sf /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf
The router provided by my ISP has a bug that causes DNS requests to hang for 5 seconds. To work around it:
nmcli con
nmcli con modify MyNetworkName ipv4.dns-options single-request
To revert, set ipv4.dns-options
to ''
instead of single-request
.
Sound
pacman -S pipewire pipewire-media-session pipewire-pulse xfce4-pulseaudio-plugin xfce4-notifyd pavucontrol clementine gst-libav gst-plugins-{base,good,bad,ugly}
Add PulseAudio applet to panel. Log out and log back in, then confirm sound works.
Bluetooth headset
$ pacman -S bluez-utils blueman-applet
Configure BlueZ to automatically power on Bluetooth adapter:
# /etc/bluetooth/main.conf
[Policy]
AutoEnable=true
Power on the headset. Start BlueZ and connect to the headset:
$ systemctl enable bluetooth
$ systemctl start bluetooth
$ bluetoothctl
[bluetooth]# power on
[bluetooth]# agent on
[bluetooth]# default-agent
[bluetooth]# scan on
[bluetooth]# devices
[bluetooth]# pair XX:XX:XX:XX:XX:XX
[bluetooth]# connect XX:XX:XX:XX:XX:XX
Confirm audio is working in headset. You may need to switch the output device in xfce4-pulseaudio-plugin/pavucontrol. Mark the headset trusted so that it can initiate the connection:
[bluetooth]# trust XX:XX:XX:XX:XX:XX
Create the following script to automatically switch to the headset when powered on:
# ~/.local/bin/btautoswitch
#!/bin/bash
while true; do
if pactl list sinks | fgrep bluez_output.XX_XX_XX_XX_XX_XX.a2dp-sink >/dev/null; then
if pactl info | fgrep 'Default Sink: alsa_output.pci-XXXX_XX_XX.X.analog-stereo' >/dev/null; then
pactl set-default-sink bluez_output.XX_XX_XX_XX_XX_XX.a2dp-sink
fi
fi
sleep 0.5
done
Add it to autostart in xfce4-session-settings
. You may also need to add blueman-applet
. Start btautoswitch
manually now:
$ btautoswtich
Power off the headset. Audio should go back to the previous audio sink. Power on the headset. Audio should move to the headset.
If something goes wrong, the following commands may be useful:
[bluetooth]# show # Show Bluetooth controller status
[bluetooth]# info # Show Bluetooth device status
$ journalctl -fu bluetooth # Watch BlueZ logs
$ journalctl -fk # Watch kernel messages for new devices
$ pactl list cards # See if headset is known by PulseAudio
$ pactl list sinks # See if headset is recognized as audio sink by PulseAudio
$ blueman-manager # Blueman GUI
Console utilities
pacman -S mlocate ncdu openssh parallel virtualbox virtualbox-host-modules-arch wget whois ripgrep the_silver_searcher moreutils bind-tools android-{tools,udev} cronie
gpasswd -a me vboxusers
systemctl enable man-db.timer systemd-timesyncd cronie
systemctl start man-db.timer systemd-timesyncd cronie
Ignore backups and directories with many files in /etc/updatedb.conf
:
PRUNEPATHS = "[...] /slow/backup /slow/bulk/datasets"
Development tools
pacman -S python base-devel python-{numpy,scipy,matplotlib,seaborn,scikit-learn,pandas,pip} python2-{pip,dbus} git pandoc ipython ipython2 jupyterlab tensorflow-opt-cuda tensorboard rustup texlive-most wireshark
gpasswd -a me wireshark
Docker
zfs create -o mountpoint=/var/lib/docker zroot/docker
pacman -S docker
gpasswd -a me docker
Desktop programs
pacman -S firefox xorg-xset redshift caja dmenu gvim maim dzen2 pidgin pidgin-libnotify thunderbird keepassx2 aspell-en eom gimp gnumeric inkscape picard liferea mpv soundconverter transmission-gtk mcomix engrampa youtube-dl ttf-dejavu ttf-liberation noto-fonts{,-cjk,-emoji,-extra}
Set units in Caja to IEC.
Install auracle-git
. Install the following:
auracle download anki freecad-weekly-appimage insect zotero-bin
cd $pkg; makepkg -sic # for each
Firefox
about:preferences settings:
- General:
- Tabs:
- Disable "Ctrl+Tab cycles through tabs in recently used order"
- Browsing:
- Enable "Use autoscrolling"
- Enable "Always show scrollbars"
- Disable "Recommend extensions as you browse"
- Disable "Recommend feaures as you browse"
- Tabs:
- Home:
- New Windows and Tabs: Set all to "Blank Page"
- Firefox Home Content: Disable all
- Search:
- Search Suggestions: Disable all
- Privacy & Security:
- Enhanced Tracking Protection: Strict
- Logins and Passwords:
- Disable "Autofill logins and passwords"
- Address Bar - Firefox Suggest: Disable all except "Bookmarks"
- Firefox Data Collection and Use:
- Disable "Allow Firefox to send technical and interaction data to Mozilla"
- Disable "Allow Firefox to make personalized extension recommendations"
- Disable "Allow Firefox to install and run studies"
about:config (or user.js) settings:
// Don't mangle URLs
user_pref("keyword.enabled", false);
user_pref("browser.fixup.alternate.enabled", false);
// Don't close the window when the last tab is closed.
user_pref("browser.tabs.closeWindowWithLastTab", false);
// Send origin but not full URL.
// Not sending the referrer at all breaks too many sites.
user_pref("network.http.referer.XOriginTrimmingPolicy", 2);
// Disable clipboard API to avoid exposing clipboard contents on middle click.
// This has been fixed for links in <https://bugzilla.mozilla.org/show_bug.cgi?id=1521396>,
// but middle clicking on other elements still exposes your clipboard contents.
user_pref("middlemouse.paste", false);
user_pref("dom.event.clipboardevents.enabled", false);
user_pref("dom.events.asyncClipboard", false);
// Service Workers can make requests even after a page is closed. This is a
// privacy risk.
user_pref("dom.serviceWorkers.enabled", false);
Theme: "Light". The "System theme" doesn't highlight the selected tab.
Extensions:
Vimium config:
unmapAll
map j scrollDown
map k scrollUp
map gg scrollToTop
map G scrollToBottom
map d scrollPageDown
map u scrollPageUp
map i enterInsertMode
map f LinkHints.activateMode
map F LinkHints.activateModeToOpenInNewTab
HDD ZFS pool
Create /etc/systemd/system/zfs-load-key.service
(see ZFS#Unlock at boot time: systemd):
[Unit]
Description=Load encryption keys
DefaultDependencies=no
Before=zfs-mount.service
After=zfs-import.target
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/bin/bash -c '/usr/bin/zfs load-key -a'
[Install]
WantedBy=zfs-mount.service
Place key in /etc/cryptfs.key
. Import the pool and enable services:
zpool import
zpool import slow
systemctl enable zfs-scrub@slow.timer
systemctl start zfs-scrub@slow.timer
systemctl enable zfs-load-key.service
systemctl start zfs-load-key.service
Backups
Snapshots to HDD
See Onsite backups with zrepl.
Offsite
Using Borg to back up to rsync.net.
In /usr/local/bin/rsyncnet-backup
:
#!/bin/bash
set -eu
if [ "$EUID" -ne 0 ]; then
echo 'Run as root'
exit 1
fi
# # /root/.ssh/config
# Host whatever.rsync.net
# User 12345
# IdentityFile ~/.ssh/rsyncnet
# ServerAliveInterval 10
# ServerAliveCountMax 30
export SSH_HOST='whatever.rsync.net'
export BORG_REPO="$SSH_HOST:borg/myhostname"
export BORG_PASSPHRASE="$(cat /path/to/borg.key)"
# Based on https://borgbackup.readthedocs.io/en/stable/quickstart.html#automating-backups
info() { printf "\n%s %s\n\n" "$( date )" "$*" >&2; }
trap 'echo $( date ) Backup interrupted >&2; exit 2' INT TERM
info "Checking quota"
ssh "$SSH_HOST" quota
info "Starting backup"
borg create \
--remote-path=borg1 \
--verbose \
--filter AME \
--list \
--stats \
--show-rc \
--compression lz4 \
--exclude-caches \
--one-file-system \
--exclude '/home/*/.cache' \
--exclude '/home/*/.cargo' \
--exclude '/home/*/.conda' \
--exclude '/home/*/.go' \
--exclude '/home/*/.julia' \
--exclude '/home/*/.npm' \
--exclude '/home/*/.platformio' \
--exclude '/home/*/.pyenv' \
--exclude '/home/*/.rustup' \
--exclude '/home/*/.vagrant.d/boxes' \
--exclude '/home/*/Code/3p' \
--exclude '/home/*/Downloads' \
--exclude '/home/*/Music' \
--exclude '/home/*/aur' \
--exclude '/var/cache/*' \
--exclude '/var/lib/docker' \
--exclude '/var/lib/prometheus' \
--exclude '/var/log/journal' \
--exclude '/var/tmp/*' \
::'{utcnow}' \
/etc \
/home \
/root \
/var
info "Pruning repository"
borg prune \
--remote-path=borg1 \
--list \
--show-rc \
--keep-daily 7 \
--keep-weekly 4 \
--keep-monthly 4
Set appropriate permissions:
sudo chown root:root /usr/local/bin/rsyncnet-backup /path/to/borg.key
sudo chmod 755 /usr/local/bin/rsyncnet-backup
sudo chmod 600 /path/to/borg.key
Add to /etc/anacrontab
:
1 120 rsyncnet-backup nice chronic /usr/local/bin/rsyncnet-backup
Prometheus
See Collecting local system stats with Prometheus on Arch Linux.