1
opensuse-setup/opensuse-personalizer.sh

526 lines
19 KiB
Bash
Executable File

#!/bin/bash
################################################################################
#
# opensuse-personalizer.sh
# Interactive post-install setup script for OpenSUSE installations
#
################################################################################
################################################################################
#
# Constants
#
################################################################################
########################################
# Zypper packages
# To remove
RM=(
libreoffice gedit
)
# To remove (and prevent reinstallation of)
AL=(
gnome-clocks gnome-packagekit gnome-software tigervnc vlc-noX xterm yast2
)
# To install
IN=(
# (Necessary packages)
wget nano git-core flatpak opi
# (Theming)
papirus-icon-theme fira-code-fonts gdouros-symbola-fonts
# (Shell utilities)
fish fzf fortune toilet cowsay wmctrl libnotify-tools
# (Programs)
emacs inkscape gimp shotcut audacity geary nextcloud-desktop steam blender
# (GNOME utilities)
gnome-session-wayland gnome-characters gnome-disk-utility gnome-font-viewer gnome-dictionary gnome-logs gnome-screenshot gnome-text-editor gnome-weather gnome-tweaks eog dconf-editor baobab totem menulibre Fragments
# (Misc.)
distribution-logos-openSUSE distribution-logos-openSUSE-icons distribution-logos-openSUSE-Tumbleweed
)
########################################
# Flatpak packages
FLATPAK_PACKAGES=(
com.discordapp.Discord
com.spotify.Client
com.github.tchx84.Flatseal
org.nickvision.tagger
)
########################################
# GNOME extensions
GNOME_EXTENSIONS=(
AlphabeticalAppGrid@stuarthayhurst
color-picker@tuberry
places-menu@gnome-shell-extensions.gcampax.github.com
)
########################################
# Directories
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
TMP_WORKDIR="/tmp/opensuse-setup-script-workdir/"
################################################################################
#
# Pre-setup prompts
#
################################################################################
########################################
# Pre-setup
# Ensure we're not running as root
if [ "${EUID}" == 0 ]; then
echo "DO NOT RUN THIS SCRIPT AS ROOT!"
echo "Please run this script as a regular user."
exit 1
fi
# Ensure zenity is installed
echo "Ensuring zenity is installed..."
sudo zypper --non-interactive in zenity
########################################
# Prompt for system chassis
system_chassis=$(hostnamectl chassis)
function string_eq ()
{
[[ "${1}" == "${2}" ]] && echo TRUE || echo FALSE
}
function prompt_chassis_type ()
{
entry=$(zenity --title="Chassis Type" --list --radiolist --width=200 --height=400 \
--text="Confirm the chassis type for this system:\n" \
--column="Selected" --column="Chassis Type" \
$(string_eq "${system_chassis}" "desktop") "Desktop" \
$(string_eq "${system_chassis}" "laptop") "Laptop" \
$(string_eq "${system_chassis}" "tablet") "Tablet" \
$(string_eq "${system_chassis}" "convertible") "Convertible")
# Ensure entry is lowercase
entry=${entry,,}
case "${entry}" in
"desktop"|"laptop"|"convertible"|"tablet")
if
zenity --question --title="Chassis Type" --text="Use ${entry} as chassis type?" --default-cancel --no-wrap
then
system_chassis="${entry}"
return 0
else
return 1
fi
;;
*)
zenity --warning --title="Chassis Type" --text="Please choose a chassis type for this system." --no-wrap
return 1
;;
esac
}
# Repeatedly show the prompt until we receive valid input
until prompt_chassis_type; do : ; done
# Set chassis type
echo "Setting chassis type to ${system_chassis}"
sudo hostnamectl chassis "${system_chassis}"
########################################
# Prompt for system name
system_name=$(hostnamectl hostname)
function prompt_system_name ()
{
entry=$(zenity --entry --title="System Name" --text="All lowercase letters, no spaces or symbols:" --entry-text="${system_name}")
# Filter all non-letter characters out of the user's entry
entry=${entry//[^[:alpha:]]/}
# Ensure entry is lowercase
entry=${entry,,}
case "${entry}" in
"")
zenity --warning --title="System Name" --text="Please enter a name for this system." --no-wrap
return 1
;;
*)
if
zenity --question --title="System Name" --text="Use ${entry} as system name?" --default-cancel --no-wrap
then
system_name="${entry}"
return 0
else
return 1
fi
;;
esac
}
# Repeatedly show the prompt until we receive valid input
until prompt_system_name; do : ; done
# Set hostname and pretty hostname
echo "Setting hostname to ${system_name}..."
sudo hostnamectl hostname "${system_name}"
echo "Setting pretty hostname to ${system_name^}"
sudo hostnamectl hostname --pretty "${system_name^}"
########################################
# Prompt for optional additions
optional_additions=""
function prompt_optional_additions ()
{
ENTRY=$(zenity --title="Optional Additions" --list --checklist --width=600 --height=440 \
--text="Select any additional configuration changes that you would like applied to the system:\n" \
--column="Apply" --column="Title" --column="Description" \
FALSE "Xournal++" "Install Xournal++ for taking handwritten notes" \
FALSE "EasyEffects" "Install EasyEffects for applying effects (e.g. equalizers) to system audio devices" \
FALSE "Media Control Key Shortcuts" "Set up media control keyboard shortcuts (for keyboards without dedicated media control keys)" \
FALSE "Touchpad Lock Toggle Shortcut" "Set up a touchpad lock toggle keyboard shortcut (for systems with touchpads)" \
FALSE "Power Button Screen Lock Override" "Override the power button's default behavior with a screen lock shortcut (for tablets or convertibles)" \
FALSE '"Reboot to Windows" Launcher' "Install a desktop entry that reboots the system to Microsoft Windows (for systems that multi-boot with Windows)")
case "${ENTRY}" in
"")
if
zenity --question --title="Optional Additions" --text="Apply only baseline system configuration?" --default-cancel --no-wrap
then
return 0
else
return 1
fi
;;
*)
if
ADDITIONS_LIST=$(echo "${ENTRY}" | sed "s/|/\n • /g")
zenity --question --title="Optional Additions" --text="Confirm your selection of the following additions:\n${ADDITIONS_LIST}" --default-cancel --no-wrap
then
optional_additions="${ENTRY}"
return 0
else
return 1
fi
;;
esac
}
# Repeatedly show the prompt until we receive valid input
until prompt_optional_additions; do : ; done
################################################################################
#
# Package setup
#
################################################################################
########################################
# Package operations
echo "Setting up packages..."
sudo zypper --non-interactive rm ${RM[@]} ${AL[@]}
sudo zypper --non-interactive al ${AL[@]}
sudo zypper --non-interactive in ${IN[@]}
########################################
# Flatpak operations
echo "Setting up Flatpak remotes..."
FLATHUB_REMOTE=https://flathub.org/repo/flathub.flatpakrepo
sudo flatpak remote-add --if-not-exists flathub "${FLATHUB_REMOTE}"
echo "Setting up Flatpak packages..."
sudo flatpak install --noninteractive ${FLATPAK_PACKAGES[@]}
########################################
# Codec installation
echo "Setting up codecs..."
opi codecs
########################################
# (OPTIONAL) Extra packages
if [[ "${optional_additions}" == *"Xournal++"* ]]; then
echo "Installing Xournal++..."
sudo zypper al texlive
sudo zypper in xournalpp
fi
if [[ "${optional_additions}" == *"EasyEffects"* ]]; then
echo "Installing EasyEffects..."
sudo zypper in easyeffects
fi
################################################################################
#
# System configuration
#
################################################################################
########################################
# GRUB configuration
# Silence GRUB
echo "Configuring GRUB..."
echo "# Automatically added by personal-opensuse-setup.sh
GRUB_TIMEOUT=0
GRUB_HIDDEN_TIMEOUT=0
GRUB_QUIET=true
GRUB_HIDDEN_TIMEOUT_QUIET=true" | sudo tee --append /etc/default/grub
sudo grub2-mkconfig -o /boot/grub2/grub.cfg
########################################
# PolicyKit configuration
# Create a local policy that unlocks basic networking settings for users
echo "Configuring PolicyKit..."
sudo mkdir -p /etc/polkit/localauthority/50-local.d/
echo "[Allow users to modify system network settings]
Identity=unix-group:users
Action=org.freedesktop.NetworkManager.settings.modify.system
ResultAny=auth_admin_keep
ResultInactive=auth_admin_keep
ResultActive=yes" | sudo tee /etc/polkit/localauthority/50-local.d/10-NetworkManager.pkla
################################################################################
#
# GNOME keyboard shortcuts
#
################################################################################
echo "Configuring GNOME keyboard shortcuts..."
########################################
# Navigation
gsettings set org.gnome.desktop.wm.keybindings switch-to-workspace-left "['<Primary><Super>Left']"
gsettings set org.gnome.desktop.wm.keybindings switch-to-workspace-left "['<Primary><Super>Right']"
gsettings set org.gnome.desktop.wm.keybindings move-to-workspace-left "['<Primary><Shift><Super>Left']"
gsettings set org.gnome.desktop.wm.keybindings move-to-workspace-left "['<Primary><Shift><Super>Right']"
# Swap "switch applications" (grouped alt+tab) for "switch windows" (non-grouped alt+tab) shortcuts
gsettings set org.gnome.shell.window-switcher current-workspace-only false
gsettings set org.gnome.desktop.wm.keybindings switch-windows $(gsettings get org.gnome.desktop.wm.keybindings switch-applications)
gsettings set org.gnome.desktop.wm.keybindings switch-windows-backward $(gsettings get org.gnome.desktop.wm.keybindings switch-applications-backward)
gsettings set org.gnome.desktop.wm.keybindings switch-applications []
gsettings set org.gnome.desktop.wm.keybindings switch-applications-backward []
########################################
# (OPTIONAL) Media
if [[ "${optional_additions}" == *"Media Control Key Shortcuts"* ]]; then
gsettings set org.gnome.settings-daemon.plugins.media-keys mic-mute "['<Super>Home']"
gsettings set org.gnome.settings-daemon.plugins.media-keys next "['<Control><Super>Page_Down']"
gsettings set org.gnome.settings-daemon.plugins.media-keys previous "['<Control><Super>Page_Up']"
gsettings set org.gnome.settings-daemon.plugins.media-keys volume-down "['<Super>Page_Down']"
gsettings set org.gnome.settings-daemon.plugins.media-keys volume-mute "['<Super>End']"
gsettings set org.gnome.settings-daemon.plugins.media-keys volume-up "['<Super>Page_Up']"
fi
########################################
# Windows
gsettings set org.gnome.desktop.wm.keybindings close "['<Super>w']"
gsettings set org.gnome.desktop.wm.keybindings toggle-fullscreen "['<Super>f']"
########################################
# Custom shortcuts
# Helper function (because gsettings doesn't make this simple)
function add_custom_gnome_keybinding ()
{
EXISTING_KEYBINDINGS=$(gsettings get org.gnome.settings-daemon.plugins.media-keys custom-keybindings)
KEYBINDING_INDEX=$(expr $(echo $EXISTING_KEYBINDINGS | grep -oE '[0-9]+' | sort -n | tail -n 1) + 1)
KEYBINDING_PATH=/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom${KEYBINDING_INDEX}/
if [[ "$EXISTING_KEYBINDINGS" == "@as []" ]]; then
gsettings set org.gnome.settings-daemon.plugins.media-keys custom-keybindings "['${KEYBINDING_PATH}']"
else
gsettings set org.gnome.settings-daemon.plugins.media-keys custom-keybindings "$(echo ${EXISTING_KEYBINDINGS} | sed s/.$//), '${KEYBINDING_PATH}']"
fi
gsettings set org.gnome.settings-daemon.plugins.media-keys.custom-keybinding:${KEYBINDING_PATH} name "${1}"
gsettings set org.gnome.settings-daemon.plugins.media-keys.custom-keybinding:${KEYBINDING_PATH} command "${2}"
gsettings set org.gnome.settings-daemon.plugins.media-keys.custom-keybinding:${KEYBINDING_PATH} binding "${3}"
}
# Add custom shortcuts
add_custom_gnome_keybinding "Launch Terminal" "gnome-terminal" "<Super>Return"
add_custom_gnome_keybinding "Toggle Night Light" "gnome-toggle-night-light" "<Alt><Super>n"
# (OPTIONAL) Add custom shortcuts
if [[ "${optional_additions}" == *"Touchpad Lock Toggle Shortcut"* ]]; then
add_custom_gnome_keybinding "Toggle Touchpad Lock" "gnome-toggle-touchpad-lock" "<Alt><Super>t"
fi
if [[ "${optional_additions}" == *"Power Button Screen Lock Override"* ]]; then
add_custom_gnome_keybinding "Lock Screen" "gdm-lock-screen" "PowerOff"
fi
################################################################################
#
# GNOME appearance configuration
#
################################################################################
echo "Configuring GNOME appearance settings..."
gsettings set org.gnome.desktop.interface icon-theme "Papirus"
gsettings set org.gnome.desktop.interface clock-format '24h'
gsettings set org.gnome.desktop.interface clock-show-date true
gsettings set org.gnome.desktop.interface clock-show-weekday true
gsettings set org.gnome.desktop.interface font-antialiasing "rgba"
gsettings set org.gnome.desktop.interface font-name "Cantarell 10"
gsettings set org.gnome.desktop.interface document-font-name "Cantarell 10"
gsettings set org.gnome.desktop.interface monospace-font-name "Fira Code 10"
gsettings set org.gnome.settings-daemon.plugins.color night-light-enabled true
gsettings set org.gnome.settings-daemon.plugins.color night-light-temperature 3700
gsettings set org.gnome.settings-daemon.plugins.color night-light-schedule-automatic false
gsettings set org.gnome.settings-daemon.plugins.color night-light-schedule-from 22
gsettings set org.gnome.settings-daemon.plugins.color night-light-schedule-to 6
################################################################################
#
# GNOME app folder configuration
#
################################################################################
echo "Configuring GNOME app folders..."
########################################
# Favorites
gsettings set org.gnome.shell.favorite-apps "['org.gnome.Terminal.desktop', 'firefox.desktop', 'emacsclient.desktop', 'org.gnome.Geary.desktop', 'org.gnome.Nautilus.desktop']"
########################################
# Utilities folder
UTILITIES_FOLDER_PATH=/org/gnome/desktop/app-folders/folders/Utilities/
gsettings set org.gnome.desktop.app-folders folder-children "['Utilities']"
gsettings set org.gnome.desktop.app-folders.folder:${UTILITIES_FOLDER_PATH} name "X-GNOME-Utilities.directory"
gsettings set org.gnome.desktop.app-folders.folder:${UTILITIES_FOLDER_PATH} translate true
gsettings set org.gnome.desktop.app-folders.folder:${UTILITIES_FOLDER_PATH} categories "[]"
gsettings set org.gnome.desktop.app-folders.folder:${UTILITIES_FOLDER_PATH} apps "['org.gnome.FileRoller.desktop', 'org.gnome.Characters.desktop', 'ca.desrt.dconf-editor.desktop', 'org.gnome.Dictionary.desktop', 'org.gnome.baobab.desktop', 'org.gnome.DiskUtility.desktop', 'org.gnome.Evince.desktop', 'com.github.wwmm.easyeffects.desktop', 'org.gnome.Extensions.desktop', 'com.github.tchx84.Flatseal.desktop', 'org.gnome.font-viewer.desktop', 'de.haeckerfelix.Fragments.desktop', 'org.gnome.eog.desktop', 'org.gnome.Logs.desktop', 'menulibre.desktop', 'org.gnome.Screenshot.desktop', 'gnome-system-monitor.desktop', 'org.nickvision.tagger.desktop', 'org.gnome.tweaks.desktop', 'uefi-firmware-settings.desktop', 'org.gnome.Totem.desktop']"
################################################################################
#
# GNOME extension setup
#
################################################################################
echo "Setting up GNOME extensions..."
for EXTENSION in "${GNOME_EXTENSIONS[@]}"; do
busctl --user call org.gnome.Shell.Extensions /org/gnome/Shell/Extensions org.gnome.Shell.Extensions InstallRemoteExtension s ${EXTENSION}
done
################################################################################
#
# Personal configuration files and scripts
#
################################################################################
########################################
# Emacs
echo "Setting up Emacs..."
# Remove any vendor-provided Emacs configuration files
rm ${HOME}/.emacs ${HOME}/.emacs.d/init.el
# Download Emacs configuration
EMACS_CONFIG_DIR=${HOME}/.config/emacs
mkdir -p ${EMACS_CONFIG_DIR}
wget https://jessieh.net/emacs -O ${EMACS_CONFIG_DIR}/init.el
# Enable and start Emacs daemon
systemctl --user enable emacs.service
systemctl --user start emacs.service
########################################
# Fish
echo "Setting up Fish..."
# Download Fish configuration
FISH_CONFIG_DIR=${HOME}/.config/fish
mkdir -p ${FISH_CONFIG_DIR}
wget https://jessieh.net/fish -O ${EMACS_CONFIG_DIR}/config.fish
# Set Fish as default shell
sudo chsh ${USER} -s $(which fish)
########################################
# Utility scripts
echo "Installing scripts..."
if [[ "${optional_additions}" != *'Touchpad Lock Toggle Shortcut'* ]]; then
rm ${SCRIPT_DIR}/scripts/gnome-toggle-touchpad-lock
fi
if [[ "${optional_additions}" != *'"Reboot to Windows" Launcher'* ]]; then
rm ${SCRIPT_DIR}/scripts/reboot-windows
fi
chmod +x ${SCRIPT_DIR}/scripts/*
sudo cp ${SCRIPT_DIR}/scripts/* /usr/bin
########################################
# Desktop entries
echo "Installing desktop entries..."
if [[ "${optional_additions}" != *'"Reboot to Windows" Launcher'* ]]; then
rm ${SCRIPT_DIR}/desktop_entries/windows.desktop
fi
mkdir -p ${HOME}/.local/share/applications/
cp ${SCRIPT_DIR}/desktop-entries/* ${HOME}/.local/share/applications/
################################################################################
#
# Post-setup suggestions
#
################################################################################
echo
echo "Personalization complete!"
echo
echo "Recommended next steps:"
echo " • Log in to Firefox Sync"
echo " • Configure Nextcloud client"
if [[ "${optional_additions}" == *"EasyEffects"* ]]; then
echo " • Install an audio device profile from"
echo " https://autoeq.app"
fi
echo " • Install a Wireguard VPN profile from"
echo " https://mullvad.net/en/account/#/wireguard-config/?platform=linux"
echo " • Configure display settings and run 'gdm-update-display-settings'"
echo " • Run 'themer' to install/update unofficial libadwaita themes"