Initial commit: Omeron modular Hyprland setup framework

- Modular installer with gum-based TUI
- Fresh-install detection with auto GPU driver selection
- Preflight module for system detection (Intel/AMD/NVIDIA)
- Core modules: packages, dotfiles, services, SDDM
- Optional software installer (Obsidian, Neovim, VS Code, etc.)
- Homelab config module with dynamic AGS integration
- Two complete themes: Forest Neon and Rose Night
- 19 Hyprland control scripts + 4 AGS widgets
- Idempotent dotfile deployment with automatic backup
- YAML-based configuration, extensible module system
- Full logging to ~/.local/share/omeron/
This commit is contained in:
2026-05-27 20:51:58 +02:00
commit be7bffc1e5
86 changed files with 9984 additions and 0 deletions

84
modules/core/dotfiles.sh Executable file
View File

@@ -0,0 +1,84 @@
#!/usr/bin/env bash
module_description() {
printf "Dotfiles - deploy configuration files to ~/.config\n"
}
module_required() { return 0; }
module_should_skip() { return 1; }
module_prereqs() {
return 0
}
module_main() {
log_section "Dotfile Deployment"
local dotfiles_dir="$OMERON_PROJECT_DIR/dotfiles"
local config_items=()
local backup_dir
if [[ -f "$OMERON_PROJECT_DIR/config/omeron.yaml" ]] && command -v python3 >/dev/null 2>&1; then
log_info "Loading config items from omeron.yaml"
config_items=()
local raw_items
raw_items="$(python3 -c "
import yaml
with open('$OMERON_PROJECT_DIR/config/omeron.yaml') as f:
data = yaml.safe_load(f)
items = data.get('dotfiles', {}).get('items', [])
print(' '.join(items))
" 2>/dev/null)"
if [[ -n "$raw_items" ]]; then
read -ra config_items <<< "$raw_items"
fi
fi
if ((${#config_items[@]} == 0)); then
config_items=(hypr waybar wofi swaync kitty gtk-3.0 gtk-4.0 qt5ct qt6ct)
fi
if ! tui_confirm "Deploy dotfiles to ~/.config? (existing files will be backed up)"; then
log_info "Dotfile deployment skipped by user"
return 0
fi
backup_dir="$(backup_file "$HOME/.config/hypr" "$HOME/.dotfiles-backup/$(date +%Y%m%d-%H%M%S)")"
backup_dir="$(dirname "$backup_dir" 2>/dev/null || printf '%s' "$HOME/.dotfiles-backup/$(date +%Y%m%d-%H%M%S)")"
for item in "${config_items[@]}"; do
local source="$dotfiles_dir/$item"
local target="$HOME/.config/$item"
if [[ ! -d "$source" ]] && [[ ! -f "$source" ]]; then
log_warn "Source not found: $source"
continue
fi
log_info "Deploying $item..."
copy_path "$source" "$target"
done
if [[ -f "$dotfiles_dir/starship.toml" ]]; then
copy_path "$dotfiles_dir/starship.toml" "$HOME/.config/starship.toml"
fi
local wallpaper_source="$dotfiles_dir/wallpapers"
local wallpaper_target="$HOME/Bilder/Wallpaper"
if [[ -d "$wallpaper_source" ]]; then
copy_path "$wallpaper_source" "$wallpaper_target"
fi
chmod +x "$HOME/.config/hypr/Scripts/"*.sh 2>/dev/null || true
chmod +x "$HOME/.config/hypr/Scripts/"*.py 2>/dev/null || true
chmod +x "$HOME/.config/waybar/scripts/"*.sh 2>/dev/null || true
replace_home_paths "$HOME/.config/hypr" "/home/pascal"
replace_home_paths "$HOME/.config/gtk-3.0" "/home/pascal"
replace_home_paths "$HOME/.config/gtk-4.0" "/home/pascal"
replace_home_paths "$HOME/.config/qt5ct" "/home/pascal"
replace_home_paths "$HOME/.config/qt6ct" "/home/pascal"
log_success "Dotfiles deployed (backup: $backup_dir)"
}

191
modules/core/packages.sh Executable file
View File

@@ -0,0 +1,191 @@
#!/usr/bin/env bash
module_description() {
printf "System Packages - install Hyprland, GPU drivers, and all dependencies\n"
}
module_required() { return 0; }
module_should_skip() { return 1; }
module_prereqs() {
require pacman pacman
is_arch || {
log_error "This module requires an Arch-based system"
return 1
}
}
module_main() {
log_section "Package Installation"
local groups=()
local all_packages=()
if ((OMERON_FRESH_INSTALL)); then
tui_format "#{bold}Fresh install mode — installing everything#{normal}"
groups=(
"hyprland"
"gpu"
"audio"
"network"
"fonts"
"tools"
"qt"
"development"
)
else
tui_format "#{bold}Existing system — checking for missing packages#{normal}"
groups=(
"hyprland"
"audio"
"network"
"tools"
)
fi
for group in "${groups[@]}"; do
local pkgs=()
mapfile -t pkgs < <(get_group_packages "$group")
all_packages+=("${pkgs[@]}")
done
all_packages=("$(remove_duplicates "${all_packages[@]}")")
local total=${#all_packages[@]}
local existing=0
local missing=0
local pkg
for pkg in "${all_packages[@]}"; do
if is_package_installed "$pkg"; then
((existing++))
else
((missing++))
fi
done
tui_format ""
tui_format "#{bold}Package Summary:#{normal}"
tui_format " Total packages: ${total}"
tui_format " Already installed: ${existing}"
tui_format " To install: ${missing}"
tui_format ""
if ((missing == 0)); then
log_success "All packages already installed"
return 0
fi
if ! tui_confirm "Install ${missing} missing packages?"; then
log_info "Package installation skipped by user"
return 0
fi
if ((OMERON_FRESH_INSTALL)); then
log_info "Running system update first..."
sudo_run pacman -Syu --noconfirm 2>&1 | tail -3 || true
fi
local pacman_pkgs=()
local aur_pkgs=()
local gpu_pkgs=()
for pkg in "${all_packages[@]}"; do
if is_package_installed "$pkg"; then
continue
fi
if pacman -Si "$pkg" >/dev/null 2>&1; then
pacman_pkgs+=("$pkg")
else
aur_pkgs+=("$pkg")
fi
done
if ((${#pacman_pkgs[@]})); then
log_info "Installing ${#pacman_pkgs[@]} pacman packages..."
tui_spin "Installing core packages..." sudo_run pacman -S --needed --noconfirm "${pacman_pkgs[@]}"
log_success "Core packages installed"
fi
if ((${#aur_pkgs[@]})); then
if have paru || have yay; then
log_info "Installing ${#aur_pkgs[@]} AUR packages..."
install_aur "${aur_pkgs[@]}" || log_warn "Some AUR packages may not have been installed"
else
log_warn "No AUR helper found. Install manually: ${aur_pkgs[*]}"
fi
fi
log_success "Package installation complete"
log_info "Installed: $((missing - ${#aur_pkgs[@]})) | AUR/optional: ${#aur_pkgs[@]}"
}
get_group_packages() {
local group="$1"
case "$group" in
hyprland)
printf '%s\n' \
hyprland hyprpaper hyprlock hypridle \
waybar wofi swaync kitty \
brightnessctl playerctl \
grim slurp swappy hyprshot \
wl-clipboard libnotify sshpass
;;
gpu)
gpu_packages
printf '%s\n' \
mesa mesa-utils \
vulkan-tools vulkan-icd-loader \
libva-utils
;;
audio)
printf '%s\n' \
pipewire pipewire-pulse pipewire-alsa pipewire-jack \
wireplumber pavucontrol helvum \
sof-firmware
;;
network)
printf '%s\n' \
networkmanager network-manager-applet \
bluez bluez-utils blueman
;;
fonts)
printf '%s\n' \
noto-fonts noto-fonts-emoji ttf-jetbrains-mono-nerd \
ttf-font-awesome ttf-nerd-fonts-symbols ttf-dejavu
;;
tools)
printf '%s\n' \
nautilus papirus-icon-theme starship \
python-gobject gtk3 gtk4 \
polkit-gnome xdg-desktop-portal xdg-desktop-portal-hyprland \
qt5ct qt6ct \
gum
;;
qt)
printf '%s\n' \
qt5-wayland qt6-wayland \
qt5-base qt6-base
;;
development)
printf '%s\n' \
git base-devel \
zip unzip unrar p7zip \
ripgrep fd bat lsd \
htop btop fastfetch
;;
esac
}
remove_duplicates() {
printf '%s\n' "$@" | sort -u
}

106
modules/core/preflight.sh Executable file
View File

@@ -0,0 +1,106 @@
#!/usr/bin/env bash
OMERON_FRESH_INSTALL=0
OMERON_DETECTED_GPU=""
module_description() {
printf "System Preflight - detect system state and missing dependencies\n"
}
module_required() { return 0; }
module_should_skip() { return 1; }
module_prereqs() {
require pacman pacman
is_arch || {
log_error "This module requires an Arch-based system"
return 1
}
}
module_main() {
log_section "System Preflight Check"
OMERON_DETECTED_GPU="$(detect_gpu)"
export OMERON_DETECTED_GPU
system_summary
if is_fresh_install; then
OMERON_FRESH_INSTALL=1
export OMERON_FRESH_INSTALL
tui_format ""
tui_format "#{bold}#{yellow}⚠ Fresh system detected!#{normal}"
tui_format "Hyprland is not installed and no desktop session is running."
tui_format ""
local gpu_name
gpu_name="$(lspci -nn 2>/dev/null | grep -i 'vga\|3d\|display' | sed 's/.*: //' | head -1 || echo "unknown")"
tui_format "#{bold}This installation will:#{normal}"
tui_format " • Hyprland compositor + tools"
tui_format " • GPU drivers for: ${gpu_name}"
tui_format " • Audio system (PipeWire)"
tui_format " • Network services (NetworkManager)"
tui_format " • Fonts and icon themes"
tui_format " • Dotfiles deployment"
tui_format ""
if ! tui_confirm "Proceed with full system setup?"; then
log_info "Fresh installation aborted by user"
exit 0
fi
if ! have paru && ! have yay; then
log_info "No AUR helper found. Installing paru..."
install_aur_helper
fi
if ! have gum; then
log_info "Installing gum for better TUI..."
sudo_run pacman -S --needed --noconfirm gum 2>/dev/null || true
tui_style
fi
log_success "Preflight complete — ready for full installation"
else
tui_format ""
tui_format "#{bold}#{green}✓ Existing Hyprland system detected#{normal}"
tui_format "Will check for missing packages and updates."
tui_format ""
fi
}
install_aur_helper() {
if have paru || have yay; then
return 0
fi
if ! command -v git >/dev/null 2>&1; then
sudo_run pacman -S --needed --noconfirm git base-devel
fi
local build_dir
build_dir="$(mktemp -d)"
log_info "Building paru from AUR..."
sudo_run pacman -S --needed --noconfirm rustup 2>/dev/null || true
if have rustup; then
rustup default stable >/dev/null 2>&1 || true
fi
if git clone https://aur.archlinux.org/paru.git "$build_dir/paru" 2>/dev/null; then
(cd "$build_dir/paru" && makepkg -si --needed --noconfirm) 2>&1 | tail -5 || {
log_warn "paru build failed, trying yay..."
if git clone https://aur.archlinux.org/yay.git "$build_dir/yay" 2>/dev/null; then
(cd "$build_dir/yay" && makepkg -si --needed --noconfirm) 2>&1 | tail -5 || {
log_warn "yay build failed too. Install manually: paru -S paru-bin"
}
fi
}
fi
rm -rf "$build_dir"
}

50
modules/core/sddm.sh Executable file
View File

@@ -0,0 +1,50 @@
#!/usr/bin/env bash
module_description() {
printf "SDDM Theme - install custom login theme\n"
}
module_required() { return 1; }
module_should_skip() {
if have sddm; then
return 1
fi
return 0
}
module_prereqs() {
if ! have sddm; then
log_warn "SDDM is not installed. Install with: sudo pacman -S sddm"
return 1
fi
}
module_main() {
log_section "SDDM Theme Installation"
local sddm_theme_dir="$OMERON_PROJECT_DIR/dotfiles/hypr/sddm-theme"
if [[ ! -d "$sddm_theme_dir/pascal-hypr" ]]; then
log_warn "SDDM theme not found at $sddm_theme_dir"
return 1
fi
log_info "Installing SDDM theme..."
sudo_run mkdir -p /usr/share/sddm/themes /etc/sddm.conf.d
if [[ -d "/usr/share/sddm/themes/pascal-hypr" ]]; then
sudo_run rm -rf "/usr/share/sddm/themes/pascal-hypr"
fi
sudo_run cp -a "$sddm_theme_dir/pascal-hypr" /usr/share/sddm/themes/
if [[ -f "$sddm_theme_dir/sddm.conf" ]]; then
sudo_run cp -a "$sddm_theme_dir/sddm.conf" /etc/sddm.conf.d/10-pascal-hypr.conf
fi
log_success "SDDM theme installed"
if tui_confirm "Enable SDDM as display manager?"; then
sudo_run systemctl enable sddm --now 2>/dev/null || log_warn "Could not enable SDDM"
fi
}

52
modules/core/services.sh Executable file
View File

@@ -0,0 +1,52 @@
#!/usr/bin/env bash
module_description() {
printf "System Services - enable and start NetworkManager and Bluetooth\n"
}
module_required() { return 0; }
module_should_skip() {
have systemctl || return 0
return 1
}
module_prereqs() {
require systemctl systemd
}
module_main() {
log_section "System Services"
local services=("NetworkManager.service" "bluetooth.service")
if [[ -f "$OMERON_PROJECT_DIR/config/omeron.yaml" ]] && command -v python3 >/dev/null 2>&1; then
local raw_services
raw_services="$(python3 -c "
import yaml
with open('$OMERON_PROJECT_DIR/config/omeron.yaml') as f:
data = yaml.safe_load(f)
svcs = data.get('services', [])
print(' '.join(svcs))
" 2>/dev/null)"
if [[ -n "$raw_services" ]]; then
read -ra services <<< "$raw_services"
for i in "${!services[@]}"; do
if ! [[ "${services[$i]}" == *".service" ]]; then
services[$i]="${services[$i]}.service"
fi
done
fi
fi
for svc in "${services[@]}"; do
log_info "Enabling $svc..."
if sudo_run systemctl enable --now "$svc" >/dev/null 2>&1; then
log_success "$svc enabled and started"
else
log_warn "Failed to enable $svc (may already be running)"
fi
done
log_success "Services configured"
}