Sway Desktop Environment in Arch Linux

Sway Desktop Environment in Arch Linux

October 19, 2022(August 24, 2023)
sway, arch-linux

This note is recorded when I configure Arch Linux with sway Desktop Environment.

User #

“User” section operations are performed on the root account.

Create general user #

Add general user:

useradd -m -G wheel "user name"

Set up a password:

passwd "user name"

Enable Sudo #

Enable sudo on wheel group.

EDITOR=vim visudo

To allow members of group wheel sudo access:

%wheel      ALL=(ALL:ALL) ALL

Subsequent operations are performed by the created general user.

Network #

Resolve #

Enable resolve with systemed-resolved:

sudo systemctl start systemd-resolved.service
sudo systemctl enable systemd-resolved.service

# replace resolve.conf
sudo mv /etc/resolv.conf /etc/resolv.conf.org
sudo ln -s /run/systemd/resolve/resolv.conf /etc/resolv.conf

NetworkManager #

Install NetworkManager.
Use NetworkManager instead of systemd-netwokrd for vpn connection:

sudo systemctl start NetworkManager.service
sudo systemctl enable NetworkManager.service

Date #

Enable systemd-timesyncd:

sudo systemctl start systemd-timesyncd.service
sudo systemctl enable systemd-timesyncd.service

Pacman #

Comparing versions before updating #

To see old and new versions of available packages, uncomment the \(VerbosePkgLists\) line in /etc/pacman.conf.

Enabling parallel downloads #

To download packages in parallel, uncomment the “ParallelDownloads = 5” line in /etc/pacman.conf.

Coloring #

To colorize the output, uncomment the “Color” line in /etc/pacman.conf.

Pacman #

To Make Pacman appear in the output of pacman. Add “ILoveCandy” under [options] in /etc/pacman.conf.

Cleaning the package cache #

To clean the package cache, install paccache privided within the pacman-contrib

sudo pacman -S pacman-contrib

Enable and start paccache.timer to discard unused packages weekly:

sudo systemctl enable paccache.timer
sudo systemctl start paccache.timer

Useful packages #

Install useful packages:

sudo pacman -S git wget man-db man-pages unarchiver duf htop iotop sysstat jq neofetch rsync httpie cmake

Zsh #

Install Zsh as shell:

sudo pacman -S zsh

Change login shell Zsh:

chsh -s /bin/zsh

Configure Zsh. My Zsh config is as follows.

Append the following line to ~/.zshenv:

# Language
export LANGUAGE="en_US.UTF-8"
export LANG="${LANGUAGE}"
export LC_ALL="${LANGUAGE}"
export LC_CTYPE="${LANGUAGE}"

# Editor
export EDITOR=vim
export CVSEDITOR="${EDITOR}"
export SVN_EDITOR="${EDITOR}"
export GIT_EDITOR="${EDITOR}"

# Pager
export PAGER=less

# zsh
export ZDOTDIR="${HOME}/.config/zsh"
export ZSH_COMPLETION_DIR="${HOME}.local/share/zsh/completion"
export PATH="${HOME}/.local/bin:$PATH"

Create directories and git clone:

# zsh state directory
mkdir -p ~/.local/state/zsh
# zsh completion directory
mkdir -p ~/.local/share/zsh/completion
# zinit repository directory
mkdir -p ~/.local/share/zinit/zinit.git
# zinit clone
git clone https://github.com/zdharma-continuum/zinit.git ~/.local/share/zinit/zinit.git

XDG Base Directory #

Append the following line to ~/.zshenv:

export XDG_CONFIG_HOME="${HOME}/.config"
export XDG_CACHE_HOME="${HOME}/.cache"
export XDG_DATA_HOME="${HOME}/.local/share"
export XDG_STATE_HOME="${HOME}/.local/state"

Source ~/.zshenv:

source ~/.zshenv

Make XDG Base Directories:

mkdir -p $XDG_CONFIG_HOME
mkdir -p $XDG_CACHE_HOME
mkdir -p $XDG_DATA_HOME
mkdir -p $XDG_STATE_HOME
mkdir -p "${HOME}/.local/bin"
mkdir -p "${HOME}/.local/src"

go #

Install go for libraries:

sudo pacman -S go

Append the following line to ~/.zshenv:

export GOPATH="${XDG_DATA_HOME}/go"
export PATH="${PATH}:${GOPATH}/bin"

Source ~/.zshenv:

source ~/.zshenv

AUR Helper #

Install yay as AUR Helper:

cd ~/.local/src
git clone https://aur.archlinux.org/yay.git
cd yay
makepkg -si

fzf #

fzf is a general-purpose command-line fuzzy finder.

Install fzf:

# clone fzf
git clone --depth 1 "https://github.com/junegunn/fzf.git" "${XDG_DATA_HOME}/fzf"
# install fzf
"${XDG_DATA_HOME}/fzf/install" --xdg --completion --key-bindings --no-update-rc --no-bash --no-fish

tmux #

tmux is a terminal multiplexer.

Install tmux:

sudo pacman -S tmux

Install tmux plugin manager:

git clone https://github.com/tmux-plugins/tpm ~/.config/tmux/plugins/tpm

Configure tmux. My tmux config is as follows.

To fetch the tmux plugins, press “tmux prefix” + I in terminal.

git #

Create ~/.config/git/config:

mkdir -p ~/.config/git
# if ~/.gitconfig exists
mv .gitconfig ~/.config/git/config
# if ~/.gitconfig does not exist
touch ~/.config/git/config

Set up git:

git config --global pull.rebase false
git config --global init.defaultBranch main

# delta
git config --global delta.navigate true
git config --global delta.light false
git config --global delta.line-numbers true

# user name and mail for git
git config --global user.name "<your name>"
git config --global user.email "<your email>"

# optional
# git config --global [email protected]:.insteadOf https://github.com/

Emacs #

Install Emacs:

sudo pacman -S emacs-nativecomp

Configure Emacs. My Emacs config is as follows.

Vim #

Append the following line to ~/.zshenv:

export VIMINIT="set nocp | source ${XDG_CONFIG_HOME:-$HOME/.config}/vim/vimrc"

Source ~/.zshenv:

source ~/.zshenv

Configure Vim. My Vim config is as follows.

RUSTUP and CARGO #

Append the following line to ~/.zshenv:

export RUSTUP_HOME="${XDG_DATA_HOME}/rustup"
export CARGO_HOME="${XDG_DATA_HOME}/cargo"
[ -d "$CARGO_HOME" ] && . "$CARGO_HOME/env"

Source ~/.zshenv:

source ~/.zshenv

Install rustup:

# Make the directory for cargo
mkdir -p $CARGO_HOME
# Install rustup
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- --no-modify-path -y

Install useful packages:

"${CARGO_HOME}/bin/rustup" run stable cargo install bat fd-find ripgrep git-delta grex lsd bottom du-dust csview

ghq #

ghq provides a way to organize remote repository clones.

Install ghq:

# Install ghq
go install github.com/x-motemen/ghq@latest
# Set up my ghq.root
git config --global ghq.root "${HOME}/workspace/ghq"

navi is an interactive cheatsheet tool for the command-line.

Install navi:

"${CARGO_HOME}/bin/rustup" run stable cargo install navi

Append the following line to ~/.zshenv:

export NAVI_CONFIG="${HOME}/.config/navi/config.yaml"

Source ~/.zshenv:

source ~/.zshenv

Configure navi. My navi config is as follows.

lazygit #

lazygit is A simple terminal UI for git commands.
Install lazygit:

go install github.com/jesseduffield/lazygit@latest

Configure lazygit. My lazygit config is as follows.

Maintenance of file system #

SSD #

Enable fstrim.timer:

sudo systemctl enable fstrim.timer

Btrfs #

Enable btrfs scrub:

# root(/)
sudo systemctl enable [email protected]

# /home (if mount)
sudo systemctl enable [email protected]

GUI #

Display Server protocol #

Install GUI libraries for wayland:

sudo pacman -S xorg-xwayland qt5-wayland

Display Manager #

Install lightDM as a Display Manager:

sudo pacman -S lightdm lightdm-gtk-greeter

To change LightDM background, edit /etc/lightdm/lightdm-gtk-greeter.conf and define the background variable under the [greeter] section:

[greeter]
background=/usr/share/backgrounds/archlinux/small.png

Enable lightDM:

sudo systemctl enable lightdm

Sway #

Install sway as a Wayland compositor:

sudo pacman -S sway swaylock swayidle swaybg waybar noto-fonts

Configure sway. My sway config is as follows.

Configure waybar. My waybar config is as follows.

Manage Sway-specific daemons with systemd.
Edit ~/.config/systemd/user/sway-session.target as follows:

[Unit]
Description=Sway compositor session
Documentation=man:systemd.special
BindsTo=graphical-session.target
Wants=graphical-session-pre.target
After=graphical-session-pre.target

Then, Append the following line to ~/.config/sway/config:

exec_always "systemctl --user import-environment; systemctl --user start sway-session.target"

With the above line in the configuration file, whenever Sway starts, it also activates sway-session.target.

xprofile #

Edit ~/.xprofile as follows:

#!/bin/sh

export XDG_SESSION_TYPE=wayland
export XDG_CURRENT_DESKTOP=sway
export XDG_CURRENT_SESSION=sway
export LIBSEAT_BACKEND=logind
export QT_QPA_PLATFORM="wayland;xcb"
export GDK_DPI_SCALE=1
export QT_SCALE_FACTOR=1.5
export MOZ_ENABLE_WAYLAND=1
export WINIT_UNIX_BACKEND=x11
export WLR_DRM_NO_MODIFIERS=1

sleep 5

Xdefaults #

Edit ~/.Xdefaults as follows:

Xft.dpi: 144

! These might also be useful depending on your monitor and personal preference:
Xft.autohint: 0
Xft.lcdfilter:  lcddefault
Xft.hintstyle:  hintfull
Xft.hinting: 1
Xft.antialias: 1
Xft.rgba: rgb

Notification #

mako is a lightweight notification daemon for Wayland.
Install mako:

sudo pacman -S mako

Configure mako. My mako config is as follows.

Append the following line ~/.config/sway/config to execute mako:

exec mako

Clipboard #

Install wl-clipboard and clipman as a clipboard manager:

sudo pacman -S wl-clipboard
yay -S clipman

Keep secrets secret with enpass:
https://www.reddit.com/r/swaywm/comments/ljl0dh/keeping_secrets_secret_with_keepassxc_clipman_and/

Make bash script ~/.config/sway/scripts/myclipman:

#!/usr/bin/env bash

app_id=$( swaymsg -t get_tree | jq -r '.. | select(.type?) | select(.focused==true) | .window_properties.class'  )
if [[ $app_id != "Enpass" ]]; then
    # --no-persist so that we preserve rich text:
    clipman store --no-persist
fi

Append the following line to ~/.config/sway/config:

exec wl-paste -t text --watch ~/.config/sway/scripts/myclipman
bindsym Control+semicolon  exec clipman pick -t rofi

Screen lock #

Append the following line to ~/.config/sway/config:

exec swayidle -w \
  timeout 300 'swaylock -f -C ~/.config/swaylock/config' \
  timeout 600 'swaymsg "output * dpms off"' \
  resume 'swaymsg "output * dpms on"' \

bindsym $super+Shift+l exec swaylock -f -C ~/.config/swaylock/config

Opacity #

The transparent script depends on python i3ipc, so install it.

sudo pacman -S python python-pip
pip install i3ipc

Append the following line to ~/.config/sway/config:

exec /usr/share/sway/scripts/inactive-windows-transparency.py --opacity 0.8

Multiple monitor #

kanshi is Automatically selector a display configuration based on connected devices.

Install kanshi:

sudo pacman -S kanshi

Configure kanshi. My kanshi config is as follows.

Link to sway-session.target and start kanshi.
Edit ~/.config/systemd/user/kanashi.service as follows:

[Unit]
Description=Dynamic output configuration for Wayland compositors
Documentation=https://sr.ht/~emersion/kanshi
BindsTo=sway-session.target

[Service]
Type=simple
ExecStart=/usr/bin/kanshi

[Install]
WantedBy=sway-session.target

If multiple monitors, enable kanshi:

systemctl --user enable kanshi.service

Custom keybindings #

Append the following line to ~/.config/sway/config:

bindsym XF86AudioRaiseVolume exec pactl set-sink-volume @DEFAULT_SINK@ +1%
bindsym XF86AudioLowerVolume exec pactl set-sink-volume @DEFAULT_SINK@ -1%
bindsym XF86AudioMute exec pactl set-sink-mute @DEFAULT_SINK@ toggle
bindsym XF86AudioMicMute exec pactl set-source-mute @DEFAULT_SOURCE@ toggle
bindsym XF86MonBrightnessDown exec brightnessctl set 5%-
bindsym XF86MonBrightnessUp exec brightnessctl set 5%+
bindsym XF86AudioPlay exec playerctl play-pause
bindsym XF86AudioNext exec playerctl next
bindsym XF86AudioPrev exec playerctl previous

Screen shot #

Install grim and slurp:

sudo pacman -S grim slurp

Append the following line to ~/.config/sway/config:

bindsym $super+Shift+2 exec /usr/share/sway/scripts/grimshot --notify save window $HOME/Downloads/screenshot_$(date "+%y%m%d%H%M%S").png
bindsym $super+Shift+3 exec /usr/share/sway/scripts/grimshot --notify save output  $HOME/Downloads/screenshot_$(date "+%y%m%d%H%M%S").png
bindsym $super+Shift+4 exec /usr/share/sway/scripts/grimshot --notify save area  $HOME/Downloads/screenshot_$(date "+%y%m%d%H%M%S").png

Backlight #

Install brightnessctl:

sudo pacman -S brightnessctl

External monitor #

Install ddcci-driver-linux-dkms to expose external monitors in sysfs:

yay -S ddcci-driver-linux-dkms

Load ddcci kernel module:

sudo vim /etc/modules-load.d/ddcci.conf

# /etc/modules-load.d/ddcci.conf
ddcci

Font #

Noto font #

Install Noto font:

sudo pacman -S noto-fonts noto-fonts-cjk noto-fonts-emoji noto-fonts-extra

Awesome font #

Install Awesome font:

sudo pacman -S ttf-font-awesome

Cica font #

Install Cica font as a programming font.

Download latest Cica font:

wget https://github.com/miiton/Cica/releases/download/v5.0.3/Cica_v5.0.3.zip

Extract zip file:

unar Cica_v5.0.3.zip -D -o "${XDG_DATA_HOME}/fonts/Cica"

Update font cache:

fc-cache -vf

Sound #

Install sound server:

sudo pacman -S pipewire wireplumber pipewire-alsa pipewire-pulse pavucontrol playerctl

Bluetooth #

Install bluetooth libraries.

sudo pacman -S bluez bluez-utils blueman

Enable bluetooth.service

sudo systemctl start bluetooth.service
sudo systemctl enable bluetooth.service

Append the following line ~/.config/sway/config to execute blueman:

exec blueman-applet
for_window [app_id="blueman-manager"] floating enable

Keyboard Input #

key repeat #

Append the following line to ~/.config/sway/config:

input type:keyboard {
    repeat_delay 300
    repeat_rate 50
}

key remap #

Xremap is a key remapper for Linux.

Install Xremap for sway:

"${CARGO_HOME}/bin/rustup" run stable cargo install xremap --features sway

Configure Xremap. My Xremap config is as follows.

Run xremap without sudo as follows.
Running xremap without sudo

And, the following is also required:

sudo gpasswd -a "USER_NAME" input

Link to sway-session.target and start Xremap.
Edit ~/.config/systemd/user/xremap.service as follows:

[Unit]
Description=xremap
BindsTo=sway-session.target

[Service]
KillMode=process
ExecStart=%h/.local/share/cargo/bin/xremap %h/.config/xremap/config.yml
ExecStop=/usr/bin/killall xremap
Type=simple
Restart=always

[Install]
WantedBy=sway-session.target

Enable xremap.service:

systemctl --user enable xremap.service

Touchpad #

Append the following line to ~/.config/sway/config:

input type:touchpad {
    tap enabled
    dwt enabled
    natural_scroll enabled
    pointer_accel 1
}

Input Method #

I’m skk(Japanese input system) user.
So, install fcitx5-skk:

sudo pacman -S fcitx5 fcitx5-skk fcitx5-im fcitx5-configtool

Append the following line to ~/.xprofile:

export GTK_IM_MODULE=fcitx
export QT_IM_MODULE=fcitx
export XMODIFIERS=@im=fcitx

Append the following line ~/.config/sway/config to start fcitx5:

exec fcitx5 -d

wallpaper #

Install wallpaper:

sudo pacman -S archlinux-wallpaper

Append the following line ~/.config/sway/config:

output "*" bg /usr/share/backgrounds/archlinux/small.png fill

Firewall #

Install ufw as Firewall:

sudo pacman -S ufw

sudo systemctl start ufw.service
sudo systemctl enable ufw.service

sudo ufw enable
sudo ufw default deny

# for kde-connect
sudo ufw allow 1714:1764/udp
sudo ufw allow 1714:1764/tcp
sudo ufw reload

Required GUI Applications #

thunar #

Install thunar as a file manager:

sudo pacman -S thunar gvfs gvfs-smb sshfs tumbler

rofi #

Install rofi as a clone of a simple switcher.
But, rofi is package for user under Xorg display servers, and merging support for Wayland compositors in the main branch has indefinitely stalled.
So I use rofi-lbonn-wayland for Wayland support.

yay -S rofi-lbonn-wayland

Configure rofi. My fori config is as follows.

As noted in Difference with rofi, rofi-lbonn-wayland has no windows mode.
So, I wrote a script for window selector and set as window mode as follows.

And, append the following line to ~/.config/rofi/config.rasi:

configuration {
    modes: "windows:~/.config/rofi/scripts/window-select.sh,drun,combi";
    combi-modes: [windows,drun];
}

Append the following line to ~/.config/sway/config:

# Window toggle
bindsym $super+Tab exec "rofi -show window"

# start rofi (a program launcher)
bindsym $super+space exec "rofi -show combi"

wezterm #

Install wezterm as a Terminal:

sudo pacman -S wezterm

Configure wezterm. My wezterm config is as follows.

OpenVPN #

Install OpenVPN support:

sudo pacman -S networkmanager-openvpn

Install nm-applet as GUI:

sudo pacman -S network-manager-applet

Append the following line ~/.config/sway/config to execute nm-applet:

exec nm-applet --indicator

Click the plus sign to add a new connection and choose OpenVPN In desktop environment network setting.
Import The client configuration profile by selecting Import a saved VPN configuration… and selecting the appropriate file(xxx.ovpn file).

Set only certain network connections via vpn.
Click IPv4 Settings -> Routes… in vpn config.
Add certain network, and check Use this connection only for resources on it network.

Reboot #

Reboot:

sudo reboot

GUI setting #

login sway desktop environment.
And, to execute wezterm, enter $super+space.

Google Chrome #

Install Google Chrome:

yay -S google-chrome

NextCloud #

Install NextCloud client:

sudo pacman -S nextcloud-client

Install libraries for NextCloud Auto login:

sudo pacman -S qtkeychain-qt5 libsecret gnome-keyring seahorse

LightDM already has the necessary PAM configuration.
The password for the user account should be the same as the default keyring.

Append the following line ~/.config/sway/config to execute NextCloud:

exec nextcloud --background

Enpass #

Install Enpass as password manager:

yay -S enpass-bin

Append the following line ~/.config/sway/config to execute enpass:

for_window [class="Enpass"] {
    floating enable
    sticky enable
}

exec enpass -minimize

fcitx-skk #

Execute fcitx5-configuretool:

fcitx5-configuretool

Set Current Input Method to SKK in Input Method tab.
Set Trigger Key of Clipboard to Empty in Addons tab.
Set Initial Input Mode of SKK to Latin in Addons tab.
Check Return-key does not insert new line on commit checkbox of SKK in Addons tab.
Set user-dictionary path.
Enable sticky-shift as follows.
https://mako-note.com/ja/ibus-skk-stickyshift/