Last active
December 1, 2025 14:37
-
-
Save tuxerrante/4d4693a44abd56627ecf2c6526313adc to your computer and use it in GitHub Desktop.
fedora workstation 43 devops setup
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| set -euo pipefail | |
| # ==================================================================== | |
| # Fedora 43 Hyprland + ML4W Development Environment Setup | |
| # https://www.fedoraproject.org/misc#everything | |
| # ==================================================================== | |
| # Configuration Version: 2025.11.28 | |
| # This script sets up: | |
| # - Hyprland wayland compositor with ML4W dotfiles | |
| # - Modern shell utilities (fzf, bat, eza, zoxide, starship, fd, ripgrep) | |
| # - DevOps tools (Go, Helm, K9s, kubectl, etc.) | |
| # - Neovim Nightly with LazyVim | |
| # - Custom Hyprland keybindings for Windows-like behavior | |
| # ==================================================================== | |
| # ==================================================================== | |
| # CONFIGURABLE SETTINGS | |
| # ==================================================================== | |
| readonly CONFIG_VERSION="2025.11.28" | |
| readonly GO_VERSION="1.25.3" | |
| readonly HELM_VERSION="4.0.1" | |
| # readonly K9S_VERSION="0.50.16" | |
| readonly GOLANGCI_VERSION="latest" | |
| readonly GITLEAKS_VERSION="8.30.0" | |
| readonly KUBECONFORM_VERSION="latest" | |
| readonly KUBECTL_VERSION="stable" | |
| readonly NERDFONT_VERSION="v3.4.0" | |
| readonly KEYBOARD_LAYOUT="${KEYBOARD_LAYOUT:-it}" | |
| # Logging Setup | |
| readonly LOG_FILE="$HOME/fedora_setup_$(date +%Y%m%d_%H%M%S).log" | |
| readonly SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" | |
| # Redirect all output to both terminal and log file | |
| exec > >(tee -a "$LOG_FILE") | |
| exec 2>&1 | |
| # ==================================================================== | |
| # LOGGING FUNCTIONS | |
| # ==================================================================== | |
| log_info() { | |
| echo -e "\033[0;34m[INFO]\033[0m $*" | |
| } | |
| log_success() { | |
| echo -e "\033[0;32m[OK]\033[0m $*" | |
| } | |
| log_warn() { | |
| echo -e "\033[1;33m[WARN]\033[0m $*" | |
| } | |
| log_error() { | |
| echo -e "\033[0;31m[ERROR]\033[0m $*" | |
| } | |
| # Function to add lines to bashrc idempotently | |
| add_to_bashrc() { | |
| local line="$1" | |
| if ! grep -qxF "$line" ~/.bashrc; then | |
| echo "$line" >>~/.bashrc | |
| fi | |
| } | |
| # Wrapper for non-critical commands - continues on error | |
| run_safe() { | |
| local description="$1" | |
| shift | |
| if "$@" 2>&1 | tee -a "$LOG_FILE"; then | |
| return 0 | |
| else | |
| log_warn "$description failed, but continuing..." | |
| return 0 | |
| fi | |
| } | |
| # ==================================================================== | |
| # 1. SYSTEM PREPARATION | |
| # ==================================================================== | |
| prepare_system() { | |
| log_info "Starting system update..." | |
| sudo dnf update -y --refresh || log_warn "System update encountered errors but continuing..." | |
| log_info "Removing unnecessary packages (Bloatware)..." | |
| sudo dnf remove -y \ | |
| gnome-weather gnome-maps gnome-photos gnome-calendar \ | |
| evolution rhythmbox cheese totem yelp \ | |
| 'libreoffice-*' || true | |
| sudo dnf autoremove -y || true | |
| log_success "System preparation completed." | |
| } | |
| # ==================================================================== | |
| # 2. BASE DEPENDENCIES | |
| # ==================================================================== | |
| install_base_deps() { | |
| log_info "Installing base build dependencies..." | |
| sudo dnf install -y --best --skip-broken \ | |
| git curl wget make gcc gcc-c++ cmake ninja-build \ | |
| openssl-devel pkg-config ca-certificates fontconfig \ | |
| nodejs npm python3-pip unzip zip tar gzip \ | |
| util-linux-user dnf-plugins-core \ | |
| snapd \ | |
| fuse || log_warn "Some base dependencies failed to install" | |
| log_success "Base dependencies installed." | |
| } | |
| # ==================================================================== | |
| # 3. HYPRLAND & GUI | |
| # ==================================================================== | |
| install_hyprland() { | |
| log_info "Enabling Hyprland COPR and installing components..." | |
| sudo dnf copr enable -y solopasha/hyprland || log_warn "Failed to enable solopasha/hyprland copr" | |
| sudo dnf install -y --best --skip-broken \ | |
| hyprland hyprlock hypridle hyprpaper hyprpicker \ | |
| xdg-desktop-portal-hyprland \ | |
| waybar mako dunst \ | |
| wofi rofi-wayland \ | |
| swaybg swayidle swaylock \ | |
| wl-clipboard grim slurp \ | |
| kitty alacritty \ | |
| hyprland-qtutils | |
| log_info "Configuring Hyprland to autostart at boot..." | |
| cat >~/.config/systemd/user/hyprland.service <<'EOF' | |
| [Unit] | |
| Description=Hyprland session | |
| [Service] | |
| ExecStart=/usr/bin/Hyprland | |
| Restart=no | |
| StandardInput=tty | |
| TTYReset=yes | |
| TTYVHangup=yes | |
| [Install] | |
| WantedBy=default.target | |
| EOF | |
| systemctl --user enable hyprland.service | |
| sudo dnf install -y flatpak | |
| flatpak remote-add --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo | |
| flatpak install -y flathub com.ml4w.dotfilesinstaller | |
| echo "PASTE THIS 'https://raw.githubusercontent.com/mylinuxforwork/dotfiles/main/hyprland-dotfiles-stable.dotinst'" | |
| flatpak run com.ml4w.dotfilesinstaller | |
| log_success "Hyprland installation and autostart configured." | |
| } | |
| # ==================================================================== | |
| # 4. SHELL UTILITIES | |
| # ==================================================================== | |
| install_shell_utils() { | |
| log_info "Installing modern shell utilities..." | |
| sudo dnf install -y --skip-broken \ | |
| fzf bat fd-find ripgrep zoxide \ | |
| btop htop ncdu jq yq fastfetch | |
| # Fix for 'fd' command (Fedora names it fdfind) | |
| if ! command -v fd &>/dev/null && command -v fdfind &>/dev/null; then | |
| log_info "Symlinking fdfind to fd..." | |
| sudo ln -sf /usr/bin/fdfind /usr/local/bin/fd | |
| fi | |
| log_success "Shell utilities installed." | |
| ARCH="x64" | |
| echo "Fetching Gitleaks v$GITLEAKS_VERSION for linux ($ARCH)..." | |
| wget -q "https://github.com/gitleaks/gitleaks/releases/download/v${GITLEAKS_VERSION}/gitleaks_${GITLEAKS_VERSION}_linux_${ARCH}.tar.gz" | |
| tar -xf "gitleaks_${GITLEAKS_VERSION}_linux_${ARCH}.tar.gz" | |
| rm "gitleaks_${GITLEAKS_VERSION}_linux_${ARCH}.tar.gz" | |
| } | |
| # ==================================================================== | |
| # 5. STARSHIP PROMPT | |
| # ==================================================================== | |
| install_starship() { | |
| log_info "Installing Starship prompt..." | |
| curl -sS https://starship.rs/install.sh | sh -s -- -y || log_warn "Starship installation failed" | |
| add_to_bashrc 'eval "$(starship init bash)"' || log_warn "Failed to add Starship to bashrc" | |
| mkdir -p ~/.config | |
| cat >~/.config/starship.toml <<'EOF' | |
| format = "$directory$git_branch$git_status $character " | |
| right_format = "$cmd_duration" | |
| [directory] | |
| truncation_length = 3 | |
| truncate_to_repo = true | |
| [git_branch] | |
| format = "[$symbol$branch]($style) " | |
| style = "bold blue" | |
| [git_status] | |
| format = "[\\($all_status$ahead_behind\\)]($style) " | |
| style = "bold red" | |
| [character] | |
| success_symbol = "[❯](bold green)" | |
| error_symbol = "[❯](bold red)" | |
| [cmd_duration] | |
| min_time = 500 | |
| format = "took [$duration]($style)" | |
| style = "bold yellow" | |
| EOF | |
| log_success "Starship installed and configured." | |
| } | |
| # ==================================================================== | |
| # 6. NEOVIM NIGHTLY + LAZYVIM | |
| # ==================================================================== | |
| install_neovim() { | |
| log_info "Installing Neovim Nightly AppImage..." | |
| # Fetch the latest release tag | |
| local nvim_tag | |
| nvim_tag=$(curl -s https://api.github.com/repos/neovim/neovim/releases | grep -oP '"tag_name": "\K[^"]+' | head -n 1) | |
| if [[ -z "$nvim_tag" ]]; then | |
| log_warn "Could not fetch Neovim version tag from GitHub. Skipping." | |
| return | |
| fi | |
| log_info "Detected Neovim version: $nvim_tag" | |
| local download_url="https://github.com/neovim/neovim/releases/download/${nvim_tag}/nvim-linux-x86_64.appimage" | |
| local target_path="/usr/local/bin/nvim" | |
| log_info "Downloading AppImage from $download_url..." | |
| if wget -q --show-progress "$download_url" -O /tmp/nvim.appimage; then | |
| chmod u+x /tmp/nvim.appimage | |
| log_info "Moving AppImage to $target_path..." | |
| sudo mv /tmp/nvim.appimage "$target_path" | |
| if command -v nvim &>/dev/null; then | |
| log_success "Neovim ($nvim_tag) installed successfully." | |
| else | |
| log_error "Neovim binary not found after install." | |
| fi | |
| else | |
| log_warn "Failed to download Neovim AppImage. Check network or URL pattern." | |
| fi | |
| # Install LazyVim | |
| log_info "Installing LazyVim starter..." | |
| mv ~/.config/nvim/*.vim /tmp/ | |
| git clone https://github.com/LazyVim/starter ~/.config/nvim | |
| rm -rf ~/.config/nvim/.git | |
| log_success "LazyVim starter cloned." | |
| } | |
| # ==================================================================== | |
| # 7. VISUAL STUDIO CODE | |
| # ==================================================================== | |
| install_vscode() { | |
| log_info "Installing Visual Studio Code..." | |
| sudo rpm --import https://packages.microsoft.com/keys/microsoft.asc | |
| sudo sh -c 'echo -e "[code]\nname=Visual Studio Code\nbaseurl=https://packages.microsoft.com/yumrepos/vscode\nenabled=1\ngpgcheck=1\ngpgkey=https://packages.microsoft.com/keys/microsoft.asc" > /etc/yum.repos.d/vscode.repo' | |
| sudo dnf check-update | |
| sudo dnf install -y --best code | |
| log_success "Visual Studio Code installed." | |
| } | |
| # ==================================================================== | |
| # 8. ADDITIONAL MISSING PACKAGES | |
| # ==================================================================== | |
| install_missing_packages() { | |
| log_info "Installing additional required packages..." | |
| sudo dnf install -y --skip-broken \ | |
| networkManager-wifi \ | |
| chromium-browser || log_warn "Some additional packages failed to install" | |
| # sudo snap install brave | |
| # echo "brave" > ~/.config/ml4w/settings/browser.sh | |
| log_success "Additional packages installed." | |
| } | |
| # ==================================================================== | |
| # 9. DEVOPS TOOLS | |
| # ==================================================================== | |
| install_devops() { | |
| log_info "Installing DevOps tools..." | |
| # Container Tools | |
| sudo dnf install -y --skip-broken podman podman-docker docker-compose | |
| # Go Lang | |
| if ! command -v go &>/dev/null; then | |
| log_info "Installing Go $GO_VERSION..." | |
| wget -q "https://go.dev/dl/go${GO_VERSION}.linux-amd64.tar.gz" -O /tmp/go.tar.gz | |
| sudo rm -rf /usr/local/go | |
| sudo tar -C /usr/local -xzf /tmp/go.tar.gz | |
| add_to_bashrc 'export PATH=$PATH:/usr/local/go/bin' | |
| rm /tmp/go.tar.gz | |
| log_success "Go $GO_VERSION installed." | |
| else | |
| log_info "Go already installed." | |
| fi | |
| # NOTE: The dev version will be in effect! | |
| go install github.com/derailed/k9s@latest | |
| go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest | |
| # Helm | |
| if ! command -v helm &>/dev/null; then | |
| log_info "Installing Helm $HELM_VERSION..." | |
| wget -q "https://get.helm.sh/helm-v${HELM_VERSION}-linux-amd64.tar.gz" -O /tmp/helm.tar.gz | |
| tar -zxf /tmp/helm.tar.gz -C /tmp | |
| sudo mv /tmp/linux-amd64/helm /usr/local/bin/helm | |
| rm -rf /tmp/helm.tar.gz /tmp/linux-amd64 | |
| log_success "Helm $HELM_VERSION installed." | |
| else | |
| log_info "Helm already installed." | |
| fi | |
| log_success "DevOps tools installation completed." | |
| } | |
| # ==================================================================== | |
| # 10. FONTS (NERD FONTS) | |
| # ==================================================================== | |
| install_fonts() { | |
| log_info "Installing Nerd Fonts (Version: $NERDFONT_VERSION)..." | |
| mkdir -p ~/.local/share/fonts | |
| # Function to download specific font | |
| download_font() { | |
| local font_name="$1" | |
| local zip_name="${font_name}.zip" | |
| local url="https://github.com/ryanoasis/nerd-fonts/releases/download/${NERDFONT_VERSION}/${zip_name}" | |
| if ! fc-list | grep -q "$font_name Nerd Font"; then | |
| log_info "Downloading $font_name..." | |
| if wget -q --show-progress "$url" -O "/tmp/$zip_name"; then | |
| if [ -f "/tmp/$zip_name" ]; then | |
| unzip -o -q "/tmp/$zip_name" -d ~/.local/share/fonts/"$font_name" | |
| rm "/tmp/$zip_name" | |
| log_success "$font_name downloaded and installed." | |
| fi | |
| else | |
| log_warn "Failed to download $font_name from $url" | |
| fi | |
| else | |
| log_info "$font_name already installed." | |
| fi | |
| } | |
| download_font "FiraCode" | |
| download_font "JetBrainsMono" | |
| sudo dnf install -y \ | |
| google-noto-emoji-color-fonts \ | |
| rofimoji | |
| fc-cache -f | |
| log_success "Fonts installation completed." | |
| } | |
| # ==================================================================== | |
| # 11. HYPRLAND CUSTOM KEYBINDINGS | |
| # ==================================================================== | |
| setup_hyprland_keybindings() { | |
| log_info "Configuring custom Hyprland keybindings..." | |
| mkdir -p ~/.config/hypr | |
| # Add keybindings file if it doesn't exist | |
| if [ ! -f ~/.config/hypr/hyprland.conf ]; then | |
| log_warn "Main Hyprland config not found at ~/.config/hypr/hyprland.conf" | |
| log_info "Creating custom keybindings file..." | |
| fi | |
| cat >~/.config/hypr/custom-keybinds.conf <<'EOF' | |
| # ==================================================================== | |
| # CUSTOM KEYBINDINGS - Windows-like behavior | |
| # ==================================================================== | |
| EOF | |
| log_success "Custom Hyprland keybindings created at ~/.config/hypr/custom-keybinds.conf" | |
| log_info "Remember to source this file in your hyprland.conf with: source = ~/.config/hypr/custom-keybinds.conf" | |
| } | |
| # BASHRC | |
| # ==================================================================== | |
| update_bashrc() { | |
| if [ -f /usr/share/bash-completion/bash_completion ]; then | |
| . /usr/share/bash-completion/bash_completion | |
| fi | |
| } | |
| # ==================================================================== | |
| # MAIN EXECUTION | |
| # ==================================================================== | |
| main() { | |
| log_info "==============================================================" | |
| log_info "Fedora 43 Hyprland & DevOps Environment Setup" | |
| log_info "Configuration Version: $CONFIG_VERSION" | |
| log_info "Log file: $LOG_FILE" | |
| log_info "==============================================================" | |
| prepare_system | |
| install_base_deps | |
| install_missing_packages | |
| install_hyprland | |
| install_shell_utils | |
| install_starship | |
| install_neovim | |
| install_vscode | |
| install_devops | |
| install_fonts | |
| setup_hyprland_keybindings | |
| update_bashrc | |
| log_success "==============================================================" | |
| log_success "Setup Completed Successfully!" | |
| log_success "Log file saved to: $LOG_FILE" | |
| log_success "==============================================================" | |
| log_info "Next steps:" | |
| log_info "1. Source your .bashrc: source ~/.bashrc" | |
| log_info "2. Review and source Hyprland keybindings in your hyprland.conf" | |
| log_info "3. Reboot your system to start Hyprland" | |
| log_success "==============================================================" | |
| } | |
| # Run main function | |
| main "$@" |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
✓ set -euo pipefail enabled - Enforces strict error checking for critical operations
✓ Error handling on non-critical DNF installations - Uses || log_warn to continue on package installation failures
✓ --skip-broken flag - Allows DNF to skip missing packages instead of aborting
✓ Helper function run_safe() - Available for wrapping any command that should continue on failure
How it works:
Critical errors still stop the script (e.g., missing git, failed file operations)
Package installation failures are logged as warnings and the script continues
Each function completes and logs its status before moving to the next
The log file captures all warnings for troubleshooting