My Arch Linux Setup 2022
The most popular operating systems are Windows, MacOS and Linux. After going to university to study Software engineering I became interested in trying the Linux operating system. The main reason was the heavy use of WSL (Windows subsystem for Linux) which was sufficient to finish all the school assignments, but there came a point where I spent more time in WSL then in Windows.
Introduction
After deciding to install Linux as a dualboot I looked at the available Linux distributions. From using RaspberryPi computers, which use Debian as an operating system, I started using their cousin Ubuntu. On Ubuntu I became familiar with Gnome, theming and ricing. I also started watching YouTube videos related to Linux customisation and was introduced to not only different Linux distributions, but also different display mangers.
The Linux distribution basically packages a base operating system (kernel), all additional applications, drivers, etc. The display managers dictate how to display the information to the user and how they can use the system.
As I mentioned before, I started with Ubuntu and Gnome. I dont particularly like the Gnome feel as it looks plain and a little bit old. With extensive ricing I got it to the point where it looked similar to a more modern style, however I once again noticed, that I mainly spend time in the terminal launching tasks and navigating directories.
On YouTube I found a type of display managers called Tiling window manager as opposed to a Stacking window manager. The magic of a Tiling window manager is that it first opens the desired application in full-screen, then after opening another one the screen splits into two, so both apps then take half-screen, etc. Tiling window managers are heavily key-bind based, so the user rarely has to use the mouse to interact with the screen.
The first tiling window manager that I have tried was i3 which uses a dynamic layout where the user can specify if the next window opens to the right or below the current window. This gives me the most flexibility to structure my workflow.
After becoming used to i3 on the "frontend" I started to look at a better "backend". The problem with linux distributions for me comes to the package managers. First of all, Ubuntu is a point release, which means that its package manager apt
and apt-get
only installs stability fixes and security updates. It also uses flatpak
which is like an online repository for user packages.
The next most popular Linux distribution is Arch linux. Arch comes installed with only the backend, so the user can choose what frontend to install for themselves. Arch is also a rolling release which means that every package gets updated regularely. Arch also has two separate package managers pacman
and an AUR (Arch User Repository) store which allowes users to download packages from a central trusted place. The biggest benefit is the ArchWiki which contains detailed, regularely updated and very useful guides to nearly everyting there is to use on Arch.
Disk Partitions
I am using a DELL Inspiron 15 7000 laptop, with 512GB SSD and 1TB HDD. With this setup I have to logically structure the available disk space. The partition structure that I ended up with and I find the most comfortable is the following:
SSD
EFI boot | Windows C: (NTFS) | Windows D: (NTFS) |
---|---|---|
500 MB | 250 GB | 200 GB |
HDD
Linux / (ext4) | Linux /home (ext4) | Linux swap | Windows G: (NTFS) |
---|---|---|---|
100 GB | 60 GB | 3 GB | 400 GB |
My partition logic is the following:
- I use
C:
drive to install all Windows applications - I use
D:
drive to store all the user data, including Linux data (this is useful when jumping between the systems) - I use
G:
drive to install all the computer games - The
/
drive stores all the system data - the
/home
drive stores all the user data
Apps
From using the arch linux daily for some years now I have tried many apps and tools for the tasks that I do day-to-day. In the following list I would like to list the apps that are essential for me as a programmer.
Essentials
- alsa + volume-icon - Advanced Linux Sound Architecture
- dmenu with command history - app launcher and option picker
- bash-completion - better tab completion in bash
- blueman + blueman-applet - bluetooth support
- curl - make network requests from terminal
- dunst - notification handler
- ffmpeg - audio and video processor
- git - work with git repositiories
- grep - find and replace in files or text
- grub + os-prober - bootloader + disk partition scanner
- htop - view running processes and their resource consumption
- i3-battery-popup - low battery popup
- i3-gaps - tiling window manager with gaps modification
- i3-scrot - screenshot tool
- imagemagick - tools for image transformations
- mplayer - simple video player
- nautilus - graphical file browser
- NetworkManager + network-manager-applet - WiFi and Ethernet support
- nitrogen - desktop background manager
- noto-fonts - support for many popular fornts
- openssh - ssh connections
- pavucontrol - graphical sound controls
- pulseaudio - audio mixer
- polybar - cool status bar for i3 widow manager
- ranger - terminal file browser
- sudo - allow user to temporarily execute command with root privileges
- sxiv - simple image viewer
- tree - list directory in a tree structure
- zip + unzip - create a zip file and unzip it
- xarchiver - graphical unzipping tool
- xterm - terminal
- zathura - simple PDF viewer
Text editors
- visual-studio-code - popular graphical IDE and text editor
- neovim - modern version of the vim terminal text editor
- emacs - popular linux IDE
- nano - simple terminla text editor
- intellij-idea-ultimate-edition - editor for developing in Java
- android-studio - editor for developing for Android
Programming
- android-sdk - packages related to development for Android mobile devices
- ansible + vagrant + VirtualBox - tool for running automated scripts and creating vierual machines
- cloc - small utility for counting lines of code in a project
- dart + flutter - development in the Flutter framework
- docker + docker-compose - support for light-weight app containerisation
- dotnet-runtime - developemnt in C#
- make + gcc + cmake + gdb - developemnt in C
- ghc - developemnt in Haskell
- jre-openjdk + jdk-openjdk + java-runtime + maven - developemnt in Java
- python + pip + mypy - developemnt in Python
- nodejs + npm + yarn - web development
- texlive-core - LaTeX renderer
Other
- anydesk - remote desktop
- filezilla - file-transfer program
- firefox - browser
- inkscape - SVG image editor
- mc - Midnight Commander - file-transfer program
- mypaint or gimp - raster image editor
- nmap - network scanner
- obsidian - markdown editor
File structure
Filesystem Hierarchy Standard
Linux uses the Filesystem Hierarchy Standard which categorieses types of files and common use-cases and designates them standardised locations on the system.
/
- primary directory containing everyting on the system
/bin
- essential command binaries that need to be available in single user mode; for all users, e.g., cat, ls, cp
/boot
- boot loader files, e.g., kernels, initrd, grub.
/dev
- device files, e.g., /dev/null
, /dev/disk0
, /dev/sda1
, /dev/tty
, /dev/random
.
/etc
- host-specific system-wide configuration files.
/home
- users' home directories, containing saved files, personal settings, etc.
/lib
- libraries essential for the binaries in /bin
and /sbin
.
/media
- mount points for removable media such as CD-ROMs (appeared in FHS-2.3).
/mnt
- temporarily mounted filesystems. Temporary mount directory where sysadmins can mount filesystems.
/opt
- optional application software packages. Contains add-on applications from individual vendors.
/proc
- virtual filesystem providing process and kernel information as files. In Linux, corresponds to a procfs mount. Generally automatically generated and populated by the system, on the fly.
/root
- home directory of the root user
/sbin
- essential system binaries that are available to the system administrators, e.g., fsck, init, route.
/srv
- site-specific data served by this system, such as data and scripts for web servers, data offered by FTP servers, and repositories for version control systems.
/tmp
- temporary files. Often not preserved between system reboots, and may be severely size restricted.
/usr
- secondary hierarchy for read-only user data; contains the majority of (multi-)user utilities and applications.
/var
- variable files: files whose content is expected to continually change during normal operation of the system, such as logs, spool files, and temporary e-mail files.
Base Directory Specification
For use specific data there exists a standard called a Base Directory Specification which defines standard locations where user-specific files are located. These locations are customisable by environment variables.
XDG_DATA_HOME
- For user application's own data files (default $HOME/.local/share
)
XDG_CONFIG_HOME
- For user's app configuration files (default $HOME/.config
)
XDG_STATE_HOME
- For user-specific app session data, which should be stored for future reuse (default $HOME/.local/state
)
XDG_CACHE_HOME
- For user-specific apps cache files (default $HOME/.cache
)
XDG_RUNTIME_DIR
- For user-specific app runtime files like sockets which may survive reboot and logout cycles
A user home directory typically also contains folders such as Documents
, Downloads
, etc. These folders can be also customized using the XDG user directories which provides a command
$ xdg-user-dirs-update
which generates a file ~/.config/user-dirs.dirs
and updates the following variables
XDG_DESKTOP_DIR
- for files placed on user's desktop (default $HOME/Desktop
)
XDG_DOCUMENTS_DIR
- for user's personal documents (default $HOME/Documents
)
XDG_DOWNLOAD_DIR
- for files downloaded from the internet (default $HOME/Downloads
)
XDG_MUSIC_DIR
- for user's music files (default $HOME/Music
)
XDG_PICTURES_DIR
- for user's prictures (default $HOME/Pictures
)
XDG_PUBLICSHARE_DIR
- for files that other users can access (default $HOME/Public
)
XDG_TEMPLATES_DIR
- templates to use when creating a new file (default $HOME/Templates
)
XDG_VIDEOS_DIR
- for user's videos (default $HOME/Videos
)
Note that not all applications support the XDG user directory specification. Arch linux tracks these apps and sometimes also offers fixes on how to make the app comply with the specification https://wiki.archlinux.org/title/XDG_Base_Directory
Windows disk mounting
As I mentioned before, I store my user data on the Windows D: drive. This allows me to access the data from both Linux and Windows. To permanently mount the disk D: to Linux we need to first turn off Fast startup in WIndows because allows Windows to lock disk partitions as read-only and we can't modify them from Linux. So by unchecking the checkbox at Control Panel > Power Options > Choose what the power buttons do > Change settings that are currently unavailable > Turn on fast startup (recommended)
To mount a NTFS partition from Linux the de-facto standard is to use ntfs-3g implementation, however a new kernel-level implementation called ntfs3 is on the rise.
To mount the windows disk partition first create a user folder in the /media
directory. So for user tomas
create a directory /media/tomas/
and set appropriate permissions to the directroy. To mount the Windows D:
partition lets create a folder /media/tomas/d/
.
To mount the drive we first need to find its UUID, we can list the partitions with commands fdisk -l
, lsblk
and blkid
. Then we can add an entry into /etc/fstab
# <file system> <dir> <type> <options> <dump> <pass>
# /dev/nvme0n1p4
UUID=484480604480531C /media/tomas/d ntfs3 defaults 0 0
This will mount the NTFS partition with proper permissions.
Dotfiles
Linux denotes hidden files with a dot for example .bashrc
, .config/
, .profile
, etc. These are configuration files that the "common" user has not interest in. After using a lot of packages the home directory can become very cluttered and thats where the XDG user directories come in to standardise the file locations. This means that most of the configuration files would go to the .config
directory.
.bashrc
.bashrc
is a Bash shell script that Bash runs whenever it is started interactively. It initializes an interactive shell session. You can put any command in that file that you could type at the command prompt.
shopt
First we can set shopt (shell options) parameters. The one I really like is autocd which can execute a command as if it was a cd
parameter
shopt -s autocd
PS1
Then we can set the visual feel of the of the console. By setting the PS1 variable, we set the shell prompt to look like [folder]$
. With dircolors we can set custom colors in commands lie ls
export PS1="[\[$(tput sgr0)\]\[\033[38;5;33m\]\W\[$(tput sgr0)\]]\[$(tput sgr0)\]\[\033[38;5;33m\]\\$\[$(tput sgr0)\] \[$(tput sgr0)\]"
eval "$(dircolors -p | \
sed 's/ 4[0-9];/ 01;/; s/;4[0-9];/;01;/g; s/;4[0-9] /;01 /' | \
dircolors /dev/stdin)"
extensions
Sometimes we need to configure or add parameters to the commands. For this we can use environment variables and aliases. We declare these variables in .bashrc
file. To no clutter the .bashrc
file we can split these into ~/.config/aliasrc
and ~/.config/envvarrc
then we can source them inside the .bashrc
[ -f "$XDG_CONFIG_HOME/envvarrc" ] && source "$XDG_CONFIG_HOME/envvarrc"
[ -f "$XDG_CONFIG_HOME/aliasrc" ] && source "$XDG_CONFIG_HOME/aliasrc"
shared history
Sometimes it can be annoying trying to find a previous command from the terminal only to find out that it was overriden by another terminal that we have opened later. Using the following commands we can enable histroy sharing between terminals
shopt -s histappend
export HISTCONTROL=ignoredups:erasedups
export PROMPT_COMMAND="${PROMPT_COMMAND:+$PROMPT_COMMAND$'\n'}history -a; history -c; history -r"
.config/aliasrc
In this file I place all the aliases that I use on the system. I split these into categories of shortcuts, default arguments, redirections and colors.
#!/bin/bash
# shortcuts
alias e="emacs --no-window-system" \
v="vim"
# default arguments
alias valgrid="valgrid --leak-check=full --track-origins=yes --show-reachable=yes"
alias ls="ls -A -hN --group-directories-first"
alias mvn="mvn -gs \"$XDG_CONFIG_HOME/maven/settings.xml\""
alias yarn='yarn --use-yarnrc "$XDG_CONFIG_HOME/yarn/config"'
alias sxiv="sxiv -a"
alias teams="teams --disable-seccomp-filter-sandbox"
# substitutions
command -v nvim >/dev/null && alias vim="nvim" vimdiff="nvim -d"
# colors
alias ls="${BASH_ALIASES[ls]} --color=auto"
alias grep="grep --color=auto"
alias diff="diff --color=auto"
# enable aliases with sudo
alias sudo="sudo "
.config/envvarrc
In this file I place all the environment variables. Mainly the XDG fixes defined in the XDG user directories Wiki Page.
CDPATH
To quickly access common places on my system such as my data folder in /media/tomas/d/
I use the CDPATH environment variable. This variable tells cd
what directories to search. To support tab completion I use the package called bash-completion.
#!/bin/bash
# XDG variables
# ...
# extend cd paths
export CDPATH=".:/media/${USER}"
.profile
This file is source on startup. Bash sources .bash_profile
so we source .profile
from that file.
In this file I define the user preferred files like a terminal, editor and browser
export TERMINAL="xterm"
export EDITOR="vim"
export VISUAL="vim"
export BROWSER="firefox"
Here we can also load our Xorg configurations like Xresources and Xmodmap
xrdb -marge "$XDG_CONFIG_HOME/X11/Xresources"
xmodmap "$XDG_CONFIG_HOME/X11/Xmodmap"
.Xresources
Here we can configure the terminal "feel". Mailny the colors and fonts. To declutter the home directory, I have relocated the file into $XDG_CONFIG_HOME/X11/Xresources
.
.Xmodmap
I am using the i3 window manager and I am using Mod1 (Alt) key as the action key for i3. Linux associates both the left Alt and the right "Alt Gr" keys to the Mod1 key. However "Alt Gr" key is often used as a Multi_Key for using diacritics and letter combinations. That is why I remapped the "Alt Gr" key from Mod1 to Multi_key. To declutter the home directory, I have relocated the file into `$XDG_CONFIG_HOME/X11/Xmodmap.
remove mod1 = Alt_R
keycode 108 = Alt_R
keysym Alt_R = Multi_key
.Xauthority
The .Xauthority
file can be found in each user home directory and is used to store credentials in cookies used by xauth
for authentication of X sessions. Once an X session is started, the cookie is used to authenticate connections to that specific display. To move the file into a differnet directory we have to set the $XAUTHORITY
variable. To declutter the home directory, we have to set the variable to export XAUTHORITY="$XDG_CONFIG_HOME/X11/Xauthority"
Note that not all display managers accept the $XAUTHORITY vaiable and have hard-coded paths.
.config/git
git is an absolutely amazing version control tool. It allows us to track file changes with a very simple commands. Then we can upload our local git changes to cloud servers like GitHub or Gitlab. These online clouds usually require some form of authentication, weather it is an username and password or a token.
If we dont want to remebemr the passwords, git offers various solutions to store these credentials. To store only the usernames and passwords we can use a git Credential Helper.
git config --global credential.helper 'store --file=$XDG_CONFIG_HOME/git/credentials'
We can also move .gitconfig
to XDG_CONFIG_HOME/git/config
as it is an XDG-compliant alternative
.config/i3
As I mentioned in the introduction, i3 is my window manager of choice, more specifically the i3-gaps extension. i3 is a tiling window manager designed for X11, inspired by wmii and written in C. It supports tiling, stacking, and tabbing layouts, which it handles dynamically.
The best feature for me is the dynamic aspect of tiling windows. I havent spent much time with the static tiling window managers, but after getting used to the dynamic layout it is very hard to imagine using anything else.
Instead of making compile-time changes by modifying the literal source code of the window manager i3 uses a configuration file located in $XDG_CONFIG_HOME/i3/config
.
I structure the configuration file into the following sections: Basic configuration, Basic bindings, Letter key bindings, Workspace names, Workspace switching, Moving windows to workspaces, App autostart, Default settings, Function keys, Special modes
Basic configuration
In this section we set the global variables. For command combinations I use Mod1 (Alt)
rather then Mod4 (Win key)
. I find the Alt key position more natural but it also takes precedence over Alt shortcuts inside various applications like Intellij IDEA.
workspace_auto_back_and_forth yes
gaps inner 15
gaps outer 15
smart_gaps on
smart_borders on
set $mod Mod1
for_window [class="^.*"] border pixel 3
# class border backgr. text indicator child_border
client.focused #555555 #555555 #ffffff #4361ee #4895EF
Basic bindings
This section binds special non-letter keys. I use evironment variables to not hardcode the preferred default apps.
bindsym $mod+Return exec --no-startup-id $TERMINAL
bindsym $mod+Shift+Return exec --no-startup-id samedir
bindsym $mod+Shift+space floating toggle
bindsym $mod+space focus mode_toggle
bindsym $mod+F2 exec --no-startup-id $BROWSER
bindsym Print exec i3-scrot
bindsym --release Shift+Print exec i3-scrot -s
Letter key bindings
This section binds letter controls. There is some duplications as I support both the arrow keys and the vim (hjkl) navigation.
bindsym $mod+Shift+q [con_id="__focused__" instance="^(?!dropdown_).*$"] kill
bindsym $mod+r mode "resize"
bindsym $mod+Shift+r restart
bindsym $mod+t split toggle
bindsym $mod+Shift+t gaps inner current set 15; gaps outer current set 15
bindsym $mod+s sticky toggle
bindsym $mod+g gaps inner current plus 5
bindsym $mod+Shift+g gaps inner current minus 5
bindsym $mod+d exec --no-startup-id $HOME/.local/bin/dmenu_run_history
bindsym $mod+Shift+d gaps inner current set 0; gaps outer current set 0
bindsym $mod+f fullscreen toggle
bindsym $mod+h focus left
bindsym $mod+Shift+h move left 30
bindsym $mod+Ctrl+h move workspace to output left
bindsym $mod+j focus down
bindsym $mod+Shift+j move down 30
bindsym $mod+Ctrl+j move workspace to output down
bindsym $mod+k focus up
bindsym $mod+Shift+k move up 30
bindsym $mod+Ctrl+k move workspace to output up
bindsym $mod+l focus right
bindsym $mod+Shift+l move right 30
bindsym $mod+Ctrl+l move workspace to output right
bindsym $mod+Left focus left
bindsym $mod+Shift+Left move left 30
bindsym $mod+Ctrl+Left move workspace to output left
bindsym $mod+Down focus down
bindsym $mod+Shift+Down move down 30
bindsym $mod+Ctrl+Down move workspace to output down
bindsym $mod+Up focus up
bindsym $mod+Shift+Up move up 30
bindsym $mod+Ctrl+Up move workspace to output up
bindsym $mod+Right focus right
bindsym $mod+Shift+Right move right 30
bindsym $mod+Ctrl+Right move workspace to output right
bindsym $mod+z gaps outer current plus 5
bindsym $mod+Shift+z gaps outer current minus 5
Workspaces
This section handles workspaces and moving things between them
# ^v^v^v^ [ Workspace names ] ^V^V^V^ #
set $ws1 "1"
set $ws2 "2"
set $ws3 "3"
set $ws4 "4"
set $ws5 "5"
set $ws6 "6"
set $ws7 "7"
set $ws8 "8"
set $ws9 "9"
set $ws10 "10"
# ^v^v^v^ [ Switch to workspace ] ^V^V^V^ #
bindsym $mod+1 workspace $ws1
bindsym $mod+2 workspace $ws2
bindsym $mod+3 workspace $ws3
bindsym $mod+4 workspace $ws4
bindsym $mod+5 workspace $ws5
bindsym $mod+6 workspace $ws6
bindsym $mod+7 workspace $ws7
bindsym $mod+8 workspace $ws8
bindsym $mod+9 workspace $ws9
bindsym $mod+0 workspace $ws10
# ^v^v^v^ [ Move focused window to workspace ] ^V^V^V^ #
bindsym $mod+Shift+1 move container to workspace $ws1
bindsym $mod+Shift+2 move container to workspace $ws2
bindsym $mod+Shift+3 move container to workspace $ws3
bindsym $mod+Shift+4 move container to workspace $ws4
bindsym $mod+Shift+5 move container to workspace $ws5
bindsym $mod+Shift+6 move container to workspace $ws6
bindsym $mod+Shift+7 move container to workspace $ws7
bindsym $mod+Shift+8 move container to workspace $ws8
bindsym $mod+Shift+9 move container to workspace $ws9
bindsym $mod+Shift+0 move container to workspace $ws10
Autostart
In this section I define all the apps I want to run on startup. From the Apps section you probably already know what these apps do.
exec --no-startup-id nm-applet
exec_always --no-startup-id nitrogen --restore
exec_always --no-startup-id $HOME/.config/polybar/launch.sh
exec --no-startup-id i3-battery-popup -n -t 1m
Function keys
By default, some function keys do not work out of the box. In this section I define the way to handle audio (F1, F2, F3) and brightness keys (F11, F12)
bindsym XF86AudioRaiseVolume exec --no-startup-id pactl set-sink-volume @DEFAULT_SINK@ +10% && $refresh_i3status
bindsym XF86AudioLowerVolume exec --no-startup-id pactl set-sink-volume @DEFAULT_SINK@ -10% && $refresh_i3status
bindsym XF86AudioMute exec --no-startup-id pactl set-sink-mute @DEFAULT_SINK@ toggle && $refresh_i3status
bindsym XF86AudioMicMute exec --no-startup-id pactl set-source-mute @DEFAULT_SOURCE@ toggle && $refresh_i3status
bindsym XF86MonBrightnessUp exec --no-startup-id xbacklight +5
bindsym XF86MonBrightnessDown exec --no-startup-id xbacklight -5
Binding Modes
i3 supports being in different binding modes where we can bind keys only for that mode. For example I have a resize mode in which I rebind the arrow keys to resize the active window.
mode "resize" {
# These bindings trigger as soon as you enter the resize mode
bindsym j resize shrink width 10 px or 10 ppt
bindsym k resize grow height 10 px or 10 ppt
bindsym l resize shrink height 10 px or 10 ppt
bindsym semicolon resize grow width 10 px or 10 ppt
# same bindings, but for the arrow keys
bindsym Left resize shrink width 10 px or 10 ppt
bindsym Down resize grow height 10 px or 10 ppt
bindsym Up resize shrink height 10 px or 10 ppt
bindsym Right resize grow width 10 px or 10 ppt
# back to normal: Enter or Escape or $mod+r
bindsym Return mode "default"
bindsym Escape mode "default"
bindsym $mod+r mode "default"
}
.config/polybar
A window manager comes with only a way to manage windows. To give the user a context of what workspace he is on, what is his battery level, etc. he needs to use a status bar. By default i3 comes with a status bar called i3-status which is purely text-based.
Polybar aims to help users build beautiful and highly customizable status bars for their desktop environment, without the need of having a black belt in shell scripting. Polybar is a great, highly extensible status bar. It has a really nice feel, especially when using emojis.
Polybar uses a simple configuration file located in $XDG_CONFIG_HOME/polybar/config.ini
. I use the following configuration:
- on the left: xworkspaces i3
- on the right: filesystem battery backlight pulseaudio wlan date
colors
[colors]
background = #282A2E
background-alt = #373B41
foreground = #C5C8C6
primary = #F0C674
secondary = #8ABEB7
alert = #A54242
disabled = #707880
bottom/bar
In this section I create a bottom status bar and I specify the fonts to use in order of imporance and the module strucutre
[bar/bottom]
bottom = true
width = 100%
height = 24pt
radius = 6
background = ${colors.background}
foreground = ${colors.foreground}
line-size = 3pt
padding-left = 0
padding-right = 1
module-margin = 1
cursor-click = pointer
cursor-scroll = ns-resize
enable-ipc = true
tray-position = right
wm-restack = i3
font-0 = "monospace;2"
font-1 = NotoSans-Regular:size=8;-1
font-2 = MaterialIcons:size=10;0
font-3 = Termsynu:size=8:antialias=false;-2
font-4 = FontAwesome:size=10;0
modules-left = xworkspaces i3
modules-right = filesystem battery backlight pulseaudio wlan date
module/xworkspaces
This module displays i3 workspaces as neat buttons
[module/xworkspaces]
type = internal/xworkspaces
label-active = %name%
label-active-background = ${colors.background-alt}
label-active-underline= ${colors.primary}
label-active-padding = 1
label-occupied = %name%
label-occupied-padding = 1
label-urgent = %name%
label-urgent-background = ${colors.alert}
label-urgent-padding = 1
label-empty = %name%
label-empty-foreground = ${colors.disabled}
label-empty-padding = 1
module/i3
This module simply shows the active i3 mode
[module/i3]
type = internal/i3
format = <label-mode>
label-mode-padding = 1
label-mode-background = ${colors.background-alt}
label-mode-foreground = #F0C674
module/filesystem
This module shows the disk usage of the /home
directory
[module/filesystem]
type = internal/fs
interval = 25
mount-0 = /home
label-mounted = %{F#F0C674}%mountpoint%%{F-} %percentage_used%%
label-unmounted = %mountpoint% not mounted
label-unmounted-foreground = ${colors.disabled}
module/battery
This module shows the battery icon and the percentage remaining. The battery is represented by an icon that slowly drains and changes color from white to orange then red.
[module/battery]
type = internal/battery
full-at = 98
format-charging = <animation-charging> <label-charging>
format-discharging = <ramp-capacity> <label-discharging>
format-full = <ramp-capacity> <label-full>
ramp-capacity-0 =
ramp-capacity-0-foreground = #f53c3c
ramp-capacity-1 =
ramp-capacity-1-foreground = #ffa900
ramp-capacity-2 =
ramp-capacity-3 =
ramp-capacity-4 =
bar-capacity-width = 10
bar-capacity-format = %{+u}%{+o}%fill%%empty%%{-u}%{-o}
bar-capacity-fill = █
bar-capacity-fill-foreground = #ddffffff
bar-capacity-fill-font = 3
bar-capacity-empty = █
bar-capacity-empty-font = 3
bar-capacity-empty-foreground = #44ffffff
animation-charging-0 =
animation-charging-1 =
animation-charging-2 =
animation-charging-3 =
animation-charging-4 =
animation-charging-framerate = 750
module/backlight
This module tracks the brightness of the screen and displays it as a percentage. Again the sun changes from full-bright to less and less bright as the brightness drops.
[module/backlight]
type = internal/xbacklight
format = <ramp> <label>
ramp-0 =
ramp-1 =
ramp-2 =
module/pulseaudio
This module shows the current volume according to pulseaudio.
[module/pulseaudio]
type = internal/pulseaudio
format-volume = <ramp-volume> <label-volume>
label-muted = muted
label-muted-foreground = #66
ramp-volume-0 =
ramp-volume-1 =
ramp-volume-2 =
ramp-volume-3 =
module/wlan
This module displays the current connected WiFi nettwork name.
[network-base]
type = internal/network
interval = 5
format-connected = <label-connected>
format-disconnected = <label-disconnected>
label-disconnected = %{F#F0C674}%ifname%%{F#707880} disconnected
[module/wlan]
inherit = network-base
interface-type = wireless
label-connected = %essid%
module/date
This module displays the current time. After clicking on the time it expands to show also the current date and seconds.
[module/date]
type = internal/date
interval = 1
date = %H:%M
date-alt = %d.%m.%Y %H:%M:%S
label = %date%
label-foreground = ${colors.primary}
backup on git
After tweaking the dotfiles for so long it would be a shame to lose all our progress, especially after so much time put into it. To create a backup we can create a bare repository.
git init --bare $XDG_DATA_HOME/dotfiles
cd $XDG_DATA_HOME/dotfiles
git config --local status.showUntrackedFiles no
Now we can setup an alias that makes our home directory act as a git repository. As mentioned previously, I store the alias inside the $XDG_CONFIG_HOME/aliasrc
alias config="git --git-dir=$XDG_DATA_HOME/dotfiles" --word-tree=$HOME"
Now we can happily use config add
, config commit
, config push
instead of git add
, git commit
, git push
and the changes will be made to our dotfiles repo.
Text Editors [TODO]
Text editors are a large part of a progammers life. Most of the time we spend reading (and sometimes writing) code. For this it is crutial to have good text editors. For some tasks it is easier to use a dedicated Integrated Development Environment (IDE) and for others just a plain text editor. The text editors are usually so customisable that they can essecially become a personalized IDE built for our specific needs.
When it comes to Linux there are mainly three options:
- use a terminal-based solution like
vim
oremacs
- use a graphical text editor like
VS code
oremacs
- use a full-fledged IDE like
intellij idea
orandroid-studio
I usually have all installed and switch between them as I need; however, I would like to learn and gravitate towards the simpler options like emacs
or VS code
. The big difference between them is that emacs
is mainly shortcut oriented with lots of key combinations while VS code
has the more common workflow.
vim [TODO]
One of the most common terminal text editors is vim. Vim is a free and open-source, screen-based text editor program. It is an improved clone of vi. NeoVim is a vim fork focused on extensibility and usability with 30% less source-code than Vim.
As these programs share the common syntax we can reference vim to neovim so we share the same configuration. First in aliases I redirect the vim command to neovim.
command -v nvim >/dev/null && alias vim="nvim" vimdiff="nvim -d"
The configuration of vim can be found in $XDG_CONFIG_HOME/nvim/init.vim
set showmatch " show matching
set ignorecase " case insensitive
set mouse=v " middle-click paste with
set hlsearch " highlight search
set incsearch " incremental search
set tabstop=4 " number of columns occupied by a tab
set softtabstop=4 " see multiple spaces as tabstops so <BS> does the right thing
set expandtab " converts tabs to white space
set shiftwidth=4 " width for autoindents
set autoindent " indent a new line the same amount as the line just typed
set relativenumber " add line numbers
set wildmode=longest,list " get bash-like tab completions
filetype plugin indent on " allow auto-indenting depending on file type
syntax on " syntax highlighting
set mouse=a " enable mouse click
set clipboard=unnamedplus " using system clipboard
filetype plugin on
set ttyfast " Speed up scrolling in Vim
emacs [TODO]
VS code [TODO]
Virtual Private Server [TODO]
Every tech-savy person wants to have a VPS on some point in time. Weather it is for hosting game servers, self-hosting various services or just experimenting with the technology. At least if not a VPS, then at least a personal website.
When I wanted to make my personal website, I bought a web hosting for about 33€/month while the domain only costed 11€/month. A VPS would cost about 52€/month. Having a spare Raspberry Pi at home, I have decided to use it as a personal VPS and expose the port 80 to the internet via the home router.
A good tutorial is the following guide: VPS Beginner guide
Setup the router [TODO]
Setup the Raspberry Pi [TODO]
Setup the database
On the RPi I want to use PostgreSQL as it is one of the most popular databases. Using the command below we can install PostgreSQL.
sudo apt-get install postgresql
To configure the databse we will switch to the postgres user and create a new user
$ sudo su postgres
$ createuser pi -P --interactive
Enter password for new role:
Enter it again:
Shall the new user be a superuser? (y/n) y
Setup web hosting
For the webhosting I want to use the basic LAPP (Linux, Apache, PostgreSQL, PHP). In the previous step we have installed PostgreSQL. Using the command below we can install Apache and PHP.
$ apt-get install apache2
$ apt-get install php libapache2-mod-php php-pgsql
$ systemctl restart apache2
In /etc/php/7.3/apache2/php.ini
uncomment the line
extension=pdo_pgsql
On the website we want to expose multiple services with domains such as domain.com
, git.domain.com
, db.domain.com
, etc. For each exposed webserver we will create a separate folder inside the /var/www
folder. So we an create folders like domain.com, gogs, etc.
Setup a free domain
If you dont want to pay for your custom domain, but you are satified with a subdomain, you can pick one up for free at https://freedns.afraid.org/. It offers making a subdomain on domains like mooo.com, my.to, h4ck.me, 404.mn, play.ai, etc.
FreeDNS allows us to point the url to an ip address. If we dont have a static ip address we can use the Dynamic DNS which allows us to send our IP periodically from our server and the URL will reconfigure itself to point to that IP address.
To an active account on the FreeDNS we can send periodic updates to sign in. We can use the following two scripts from this repository: https://github.com/leemgs/auto-freedns-afraid-org.
The file /opt/free_dns/afraid-autoip.sh
will automatically update the IP on the dynamic DNS
TOKEN_KEY="xxxxxxxxxxxxxxxxxxxxxxxxxxx"
WGET_OPTION="-q --read-timeout=0.0 --waitretry=5 --tries=400 --background"
wget ${WGET_OPTION} http://freedns.afraid.org/dynamic/update.php?${TOKEN_KEY}
sleep 5
The file /opt/free_dns/afraid-autologin.sh
will sign in the user.
ID="[email protected]"
PASS="xxxxxxx"
URL="https://freedns.afraid.org/zc.php?/step=2&from=L3N1YmRvbWFpbi8=&action=auth&username=$ID&password=$PASS"
curl --silent --output /dev/null -I $URL
We can run these scripts periodically using chrontab
$ sudo vim /etc/crontab
30 * * * * root /opt/free_dns/afraid-autoip.sh
30 * * * * root /opt/free_dns/afraid-autologin.sh
Then just restart the cronjob with sudo service cron restart
Setup HTTPS
We will use SSL signed by https://letsencrypt.org/. To automatize the process we will use certbot.
apt install snap
snap install core
sudo snap refresh core
snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot
certbot --apache
Every time we want to re-generate or add new SSL certificates we just run certbot --apache
and follow the provided steps.
Setup git server
Setting up a git server on its own seems to be pretty easy. However I would prefer also a visual git server. Gogs is a self-hosted Git service. A very nice tutorial video can be found in https://www.youtube.com/watch?v=5ysGZoBJGVU.
The first step is obviously to istall git.
$ apt-get install git
Then we need to create a user that will hold the repositories
$ createuser -m git
To istall Gogs copy the latest version from https://gogs.io/docs/installation/install_from_binary
$ cd /var/www/gogs
$ wget https://dl.gogs.io/0.12.9/gogs_0.12.9_linux_armv7.tar.gz
$ tar xzvf gogs_0.12.9_linux_armv7.tar.gz
$ chown -R www-data:www-data /var/www/gogs
$ chmod -R 755 /var/www/gogs
Now we have to create database for gogs by issuing the following commands.
$ su postgres
$ psql
postgres=# CREATE USER gogs WITH PASSWORD 'jw8s0F4';
CREATE ROLE
postgres=# CREATE DATABASE gogs OWNER gogs;
CREATE DATABASE
Now we need to configure apache to serve the gogs service under git.domain.com
. To do this we need to create a new file /etc/apache2/sites-enabled/git.conf
<VirtualHost *:80>
ServerAdmin webmaster@localhost
ServerName git.domain.com
ProxyPreseveHost On
ProxyRequests Off
ProxyPass / http://localhost:29418/
ProxyPassReverse / http://localhost:29418/
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirualHost>
To activate apache proxy run the following commands
$ a2enmod proxy
$ a2enmod proxy_http
$ a2enmod proxy_balancer
$ systemctl restart apache2
Before running the server create a config file /var/www/gogs/custom/config/app.ini
[server]
HTTP_ADDR = 127.0.0.1
HTTP_PORT = 29418
EXTERNAL_URL = http://git.domain.com
To launch the script automatically create a service in vim /etc/systemd/system/gogs.service
[Unit]
Description=Gogs
After=syslog.target
After=network.target
After=mariadb.service mysqld.service postgresql.service memcached.service redis.service
[Service]
# Modify these two values and uncomment them if you have
# repos with lots of files and get an HTTP error 500 because
# of that
###
#LimitMEMLOCK=infinity
#LimitNOFILE=65535
Type=simple
User=git
Group=git
WorkingDirectory=/var/www/gogs
ExecStart=/var/www/gogs/gogs web
Restart=always
Environment=USER=git HOME=/home/git
# Some distributions may not support these hardening directives. If you cannot start the service due
# to an unknown option, comment out the ones not supported by your version of systemd.
ProtectSystem=full
PrivateDevices=yes
PrivateTmp=yes
NoNewPrivileges=true
[Install]
WantedBy=multi-user.target
Lastly, enable and start the service with
systemctl enable gogs.service
systemctl start gogs.service
After the successfull installation the Gogs service will be available under [git.domain.com]. As the last step after registering in the /var/www/gogs/custom/config/app.ini
we can set DISABLE_REGISTRATION=true
Setup website projects \w git submodules
My personal website acts as my portfolio on which I present some of my projects. Each project is a totally separate project and with the introduction of Gogs git server on my hosting I have decided to have each project a separate git repository. However my website is also hosted on git ,this creates a git-inside-git scenario. To work with these nested gits submodules come to help.
Git submodules allows us to keep a Git repository as a subdirectory of another Git repository. This lets us clone another repository into our project and keep the commits separate.
Using this technique I can have a repository for my personal website and inside /public/
folder I have all the projects linkes as submodules.
Setup website auto-deploys with CI/CD
Since I am not very used to transfering files via FTP or SCP transfering files to the server usually takes me quite a long time. Now that I am using my own git server as well I can use my git repository as the upload destination. I found this handy tutorial Deploying My Site With Gogs that uses Gog's git hooks to copy the repository data to the webhosting location.
#!/bin/bash
git --work-tree=/var/www/domain.com/ --git-dir=/home/git/repositories/zloutek1/domain.com.git checkout -f
Because I am using submodules, things werent so simple. The command above works, however it does not pull the contents of the submodules so if we add a new suvmodule to the website it would just be an empty directory. We need to add a few lines to force the submodule download.
#!/bin/bash
set -e
ARGS="--work-tree=. --git-dir=/home/git/repositories/zloutek1/domain.com.git -C /var/www/domain.com/"
git ${ARGS} checkout -f
git ${ARGS} submodule foreach git pull origin main
git ${ARGS} submodule update --init --recursive
Setup Minecraft server
The best Minecraft server that I know of is papermc. To setup the server create a directory /srv/minecraft
and set its permissions to your user.
mkdir /srv/minecraft
chown myuser:myuser /srv/minecraft
Download java 17.
$ curl -s "https://get.sdkman.io" | bash
$ source "$HOME/.sdkman/bin/sdkman-init.sh"
$ sdk list java
================================================================================
Available Java Versions
================================================================================
Vendor | Use | Version | Dist | Status | Identifier
--------------------------------------------------------------------------------
Liberica | | 17.0.1 | librca | | 17.0.1-librca
$ sdk install java 17.0.1-librca
Install the latest server jar.
$ cd /srv/minecraft
$ wget https://api.papermc.io/v2/projects/paper/versions/1.19/builds/29/downloads/paper-1.19-29.jar
$ echo "java -Xms256M -Xmx496M -jar paper-1.19-29.jar nogui" > run.sh
$ chmod +x run.sh
Now you can start the server at any time with /srv/minecraft/run.sh