Skip to content

Instantly share code, notes, and snippets.

@HackingGate
Last active April 29, 2026 10:43
Show Gist options
  • Select an option

  • Save HackingGate/67f40f1c64c227b2991cc6bc64f9a14c to your computer and use it in GitHub Desktop.

Select an option

Save HackingGate/67f40f1c64c227b2991cc6bc64f9a14c to your computer and use it in GitHub Desktop.
My Fedora Desktop Setup
#!/usr/bin/env bash
set -euo pipefail
echo "Disable GDM auto suspend"
sudo -u gdm dbus-run-session gsettings set org.gnome.settings-daemon.plugins.power sleep-inactive-ac-type 'nothing'
sudo -u gdm dbus-run-session gsettings set org.gnome.settings-daemon.plugins.power sleep-inactive-ac-timeout 0
sudo systemctl restart gdm
echo "Set timezone and RTC policy"
sudo timedatectl set-timezone Asia/Tokyo
sudo timedatectl set-local-rtc 0
timedatectl
echo "Update Fedora and install base packages"
sudo dnf check-update -y
sudo dnf upgrade --refresh -y
sudo dnf install \
emacs-nox \
vim \
neovim \
curl \
wget \
gh \
git \
zsh \
efibootmgr \
jq \
fastfetch \
htop \
seahorse -y
sudo dnf group install development-tools -y
#!/usr/bin/env bash
set -euo pipefail
echo "Install repo-management plugins"
sudo dnf install dnf-plugins-core dnf5-plugins -y
echo "Enable RPM Fusion and Cisco OpenH264"
sudo dnf install \
"https://mirrors.rpmfusion.org/free/fedora/rpmfusion-free-release-$(rpm -E %fedora).noarch.rpm" \
"https://mirrors.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-$(rpm -E %fedora).noarch.rpm" -y
sudo dnf install rpmfusion-free-release-tainted -y
sudo dnf config-manager setopt fedora-cisco-openh264.enabled=1
sudo dnf install rpmfusion-free-appstream-data -y
echo "Replace Fedora ffmpeg build and install multimedia stack"
sudo dnf swap ffmpeg-free ffmpeg --allowerasing -y
sudo dnf group upgrade multimedia --setopt="install_weak_deps=False" --exclude=PackageKit-gstreamer-plugin --allowerasing -y
sudo dnf install \
ffmpegthumbnailer \
gstreamer1-plugin-libav \
gstreamer1-plugin-openh264 \
gstreamer1-plugins-bad-free-extras \
gstreamer1-plugins-bad-freeworld \
gstreamer1-plugins-ugly \
gstreamer1-plugins-ugly-free \
mozilla-openh264 \
openh264 \
mpv \
vlc \
vlc-plugins-freeworld \
libheif-freeworld \
libaacs \
libbdplus -y
#!/usr/bin/env bash
set -euo pipefail
echo "Install AMD and Intel VA/VDPAU freeworld drivers"
sudo dnf swap mesa-va-drivers mesa-va-drivers-freeworld -y
sudo dnf swap mesa-vdpau-drivers mesa-vdpau-drivers-freeworld -y
sudo dnf install libva-intel-media-driver -y
#!/usr/bin/env bash
set -euo pipefail
echo "Install NVIDIA VA-API translation layer"
sudo dnf install libva-nvidia-driver -y
cat <<'EOF'
This only installs the VA-API bridge package.
If the proprietary NVIDIA driver is not installed yet, install that first.
EOF
#!/usr/bin/env bash
set -euo pipefail
append_if_missing() {
local line=$1
local file=$2
mkdir -p "$(dirname "$file")"
touch "$file"
if ! grep -Fqx "$line" "$file"; then
printf '%s\n' "$line" >> "$file"
fi
}
echo "Install Oh My Zsh"
sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
echo "Install Homebrew"
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
append_if_missing 'eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"' "$HOME/.zshrc"
eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"
brew install gcc
echo "Install Starship prompt"
brew install starship
append_if_missing 'eval "$(starship init zsh)"' "$HOME/.zshrc"
#!/usr/bin/env bash
set -euo pipefail
echo "Install Brave repository and package"
sudo dnf install dnf-plugins-core -y
sudo dnf config-manager addrepo --from-repofile=https://brave-browser-rpm-release.s3.brave.com/brave-browser.repo
sudo dnf install brave-browser -y
echo "Apply Brave managed policies"
sudo mkdir -p /etc/brave/policies/managed
sudo chmod 755 /etc/brave/policies/managed
sudo tee /etc/brave/policies/managed/00_debloat.json > /dev/null <<'EOF'
{
"TorDisabled": true,
"BraveRewardsDisabled": true,
"BraveWalletDisabled": true,
"BraveVPNDisabled": true,
"BraveAIChatEnabled": false
}
EOF
echo "Update Flatpaks and install desktop apps"
sudo flatpak update -y
sudo flatpak install flathub org.gnome.Extensions -y
sudo flatpak install flathub org.mozilla.Thunderbird -y
sudo flatpak install page.tesk.Refine -y
echo "Set Firefox as default browser"
xdg-settings set default-web-browser org.mozilla.firefox.desktop
#!/usr/bin/env bash
set -euo pipefail
echo "Install 1Password repository"
sudo rpm --import https://downloads.1password.com/linux/keys/1password.asc
sudo tee /etc/yum.repos.d/1password.repo > /dev/null <<'EOF'
[1password]
name=1Password Stable Channel
baseurl=https://downloads.1password.com/linux/rpm/stable/$basearch
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://downloads.1password.com/linux/keys/1password.asc
EOF
echo "Install 1Password desktop and CLI"
sudo dnf check-update -y
sudo dnf install 1password 1password-cli -y
echo "Configure 1Password autostart"
mkdir -p "$HOME/.config/autostart"
tee "$HOME/.config/autostart/1password.desktop" > /dev/null <<'EOF'
[Desktop Entry]
Name=1Password
Exec=/usr/bin/1password --silent %U
Terminal=false
Type=Application
Icon=1password
StartupWMClass=1Password
Comment=Password manager and secure wallet
MimeType=x-scheme-handler/onepassword;
Categories=Office;
EOF
chmod +x "$HOME/.config/autostart/1password.desktop"
#!/usr/bin/env bash
set -euo pipefail
SSH_ITEM_ID=${OP_SSH_ITEM_ID:-mijcwmynssrwh33ad3mknt77fy}
echo "Sign in to 1Password CLI"
eval "$(op signin)"
echo "Export SSH key material from 1Password item ${SSH_ITEM_ID}"
mkdir -p "$HOME/.ssh"
op item get "$SSH_ITEM_ID" --format json | jq -r '.fields[] | select(.label == "private key") | .value' > "$HOME/.ssh/id_ed25519"
op item get "$SSH_ITEM_ID" --format json | jq -r '.fields[] | select(.label == "public key") | .value' > "$HOME/.ssh/id_ed25519.pub"
chmod 600 "$HOME/.ssh/id_ed25519"
chmod 644 "$HOME/.ssh/id_ed25519.pub"
eval "$(ssh-agent -s)"
ssh-add "$HOME/.ssh/id_ed25519"
echo "Configure global git defaults"
git config --global user.name "HackingGate"
git config --global user.email "i@hackinggate.com"
git config --global core.editor "emacs"
git config --global init.defaultBranch main
git config --global gpg.format ssh
git config --global commit.gpgSign true
git config --global user.signingkey "$HOME/.ssh/id_ed25519.pub"
git config --global submodule.recurse true
#!/usr/bin/env bash
set -euo pipefail
append_block_if_missing() {
local marker=$1
local file=$2
local block=$3
mkdir -p "$(dirname "$file")"
touch "$file"
if ! grep -Fq "$marker" "$file"; then
printf '\n%s\n' "$block" >> "$file"
fi
}
echo "Configure shell defaults"
append_block_if_missing 'export EDITOR="/usr/bin/emacs"' "$HOME/.zshrc" '# Set default editor to Emacs
export EDITOR="/usr/bin/emacs"
export VISUAL="/usr/bin/emacs"'
echo "Install GNOME Tweaks, pipx, and Qt bridge packages"
sudo dnf install gnome-tweaks pipx adwaita-qt5 qgnomeplatform-qt5 adwaita-qt6 qgnomeplatform-qt6 -y
pipx ensurepath
export PATH="$HOME/.local/bin:$PATH"
echo "Install gnome-extensions-cli"
if pipx list | grep -q "package gnome-extensions-cli"; then
pipx reinstall gnome-extensions-cli --python python3
else
pipx install gnome-extensions-cli --system-site-packages --python python3
fi
echo "Apply GNOME preferences"
gsettings set org.gnome.desktop.interface gtk-key-theme "Emacs"
gsettings set org.gnome.desktop.wm.preferences button-layout ':minimize,maximize,close'
gsettings set org.gnome.desktop.interface enable-hot-corners false
gsettings set org.gnome.desktop.peripherals.touchpad tap-to-click false
echo "Configure Caps Lock as Ctrl"
current_options=$(gsettings get org.gnome.desktop.input-sources xkb-options)
if [[ $current_options == "@as []" ]]; then
gsettings set org.gnome.desktop.input-sources xkb-options "['ctrl:nocaps']"
elif [[ $current_options != *"ctrl:nocaps"* ]]; then
current_options=${current_options:1:${#current_options}-2}
gsettings set org.gnome.desktop.input-sources xkb-options "[${current_options}, 'ctrl:nocaps']"
fi
echo "Install GNOME Shell extensions"
extensions=(
caffeine@patapon.info
customreboot@nova1545
kimpanel@kde.org
azwallpaper@azwallpaper.gitlab.com
system-monitor@gnome-shell-extensions.gcampax.github.com
night-light-slider@devoscarm.github.com
monitor-brightness-volume@ailin.nemui
gjsosk@vishram1123.com
screen-rotator@bronzdragon.github.io
)
for ext in "${extensions[@]}"; do
gext install "$ext"
done
#!/usr/bin/env bash
set -euo pipefail
echo "Install fonts"
sudo dnf install \
fira-code-fonts \
google-noto-fonts-all \
google-noto-color-emoji-fonts \
google-noto-sans-cjk-fonts \
adobe-source-han-sans-cn-fonts \
adobe-source-han-sans-tw-fonts \
adobe-source-han-serif-cn-fonts \
adobe-source-han-serif-tw-fonts \
wqy-zenhei-fonts \
wqy-microhei-fonts --allowerasing -y
fc-cache -fv
echo "Install fcitx5 input method stack"
sudo dnf install \
fcitx5 \
fcitx5-chewing \
fcitx5-mozc \
fcitx5-table-extra \
fcitx5-chinese-addons \
fcitx5-autostart -y
#!/usr/bin/env bash
set -euo pipefail
echo "Upgrade system and firmware"
sudo dnf upgrade -y
sudo fwupdmgr refresh
sudo fwupdmgr update
echo "Configure GRUB timeout"
GRUB_TIMEOUT=5
GRUB_DEFAULT_FILE=/etc/default/grub
GRUB_CFG_OUT=/boot/grub2/grub.cfg
if [[ -f $GRUB_DEFAULT_FILE ]]; then
current=$(grep -E '^GRUB_TIMEOUT=' "$GRUB_DEFAULT_FILE" | cut -d= -f2- || true)
if [[ -n $current ]]; then
sudo sed -i "s|^GRUB_TIMEOUT=.*|GRUB_TIMEOUT=$GRUB_TIMEOUT|" "$GRUB_DEFAULT_FILE"
else
echo "GRUB_TIMEOUT=$GRUB_TIMEOUT" | sudo tee -a "$GRUB_DEFAULT_FILE" > /dev/null
fi
sudo grub2-mkconfig -o "$GRUB_CFG_OUT"
else
echo "Warning: $GRUB_DEFAULT_FILE not found" >&2
fi
echo "Enable Emacs user service"
systemctl --user enable --now emacs
#!/usr/bin/env bash
set -euo pipefail
append_if_missing() {
local line=$1
local file=$2
mkdir -p "$(dirname "$file")"
touch "$file"
if ! grep -Fqx "$line" "$file"; then
printf '%s\n' "$line" >> "$file"
fi
}
echo "Install Visual Studio Code"
sudo rpm --import https://packages.microsoft.com/keys/microsoft.asc
sudo tee /etc/yum.repos.d/vscode.repo > /dev/null <<'EOF'
[code]
name=Visual Studio Code
baseurl=https://packages.microsoft.com/yumrepos/vscode
enabled=1
autorefresh=1
type=rpm-md
gpgcheck=1
gpgkey=https://packages.microsoft.com/keys/microsoft.asc
EOF
sudo dnf check-update -y
sudo dnf install code -y
xdg-mime default code.desktop text/plain
echo "Install JetBrains Toolbox"
sudo dnf install jq fuse fuse-libs -y
TOOLBOX_URL=$(curl -s 'https://data.services.jetbrains.com/products/releases?code=TBA&latest=true&type=release' | jq -r '.TBA[0].downloads.linux.link')
mkdir -p "$HOME/.local"
curl -L# "$TOOLBOX_URL" | tar -xzf - -C "$HOME/.local"
TOOLBOX_DIR=$(find "$HOME/.local" -maxdepth 1 -type d -name 'jetbrains-toolbox-*' | head -n 1)
if [[ -n $TOOLBOX_DIR ]]; then
mv "$TOOLBOX_DIR" "$HOME/.local/jetbrains-toolbox"
TOOLBOX_DIR="$HOME/.local/jetbrains-toolbox"
fi
chmod +x "$TOOLBOX_DIR/bin/jetbrains-toolbox"
append_if_missing 'export PATH="$HOME/.local/jetbrains-toolbox/bin:$PATH"' "$HOME/.zshrc"
echo "Install Waydroid and graphics tools"
sudo dnf install waydroid xorg-x11-drv-wacom -y
sudo systemctl enable --now waydroid-container
sudo waydroid init
sudo flatpak install com.github.xournalpp.xournalpp -y
#!/usr/bin/env bash
set -euo pipefail
echo "Install Tailscale"
curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up
echo "Install Docker Engine"
sudo dnf -y install dnf-plugins-core
sudo dnf config-manager addrepo --from-repofile=https://download.docker.com/linux/fedora/docker-ce.repo
sudo dnf install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin -y
sudo systemctl enable --now docker
sudo usermod -aG docker "$USER"
echo "Configure Wake on LAN"
interfaces=($(ip -o link show | grep -v 'lo:' | awk -F': ' '{print $2}'))
for i in "${!interfaces[@]}"; do
mac=$(ip link show "${interfaces[$i]}" | grep -o 'link/ether [^ ]*' | cut -d' ' -f2)
echo "[$i] ${interfaces[$i]} (MAC: $mac)"
done
read -r -p "Select interface number for Wake on LAN configuration: " interface_num
if [[ ! $interface_num =~ ^[0-9]+$ ]] || [[ $interface_num -ge ${#interfaces[@]} ]]; then
echo "Invalid selection. Skipping WoL configuration."
interface_num=
fi
if [[ -n ${interface_num:-} ]]; then
selected_interface="${interfaces[$interface_num]}"
sudo ethtool -s "$selected_interface" wol g
sudo tee /etc/systemd/system/wol@.service > /dev/null <<'EOF'
[Unit]
Description=Wake-on-LAN for %i
Requires=network.target
After=network.target
[Service]
Type=oneshot
ExecStart=/usr/sbin/ethtool -s %i wol g
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
EOF
sudo chmod 644 /etc/systemd/system/wol@.service
sudo systemctl enable "wol@$selected_interface"
sudo systemctl start "wol@$selected_interface"
sudo ethtool "$selected_interface" | grep "Wake-on"
fi
#!/usr/bin/env bash
set -euo pipefail
echo "Resize btrfs filesystem in live environment"
sudo btrfs filesystem resize 100G /run/media/liveuser/fedora
echo "Resize partition and LUKS mapping"
sudo parted /dev/nvme0n1 --script resizepart 3 70%
sudo cryptsetup luksOpen /dev/nvme0n1p3 luksroot
sudo cryptsetup resize luksroot
sudo btrfs filesystem resize max /run/media/liveuser/fedora
cat <<'EOF'
This script assumes:
you are in a live environment
/dev/nvme0n1p3 is the LUKS container
/run/media/liveuser/fedora is the mounted btrfs filesystem
Review it before running.
EOF

Fedora Setup Split

Split from gist: https://gist.github.com/HackingGate/67f40f1c64c227b2991cc6bc64f9a14c

This breaks the original fedora-setup.sh into smaller scripts so risky or hardware-specific parts can be run independently.

Each script is standalone:

  • no shared helper file
  • no cross-script calls
  • no wrapper entrypoint
  • no explicit exit

Run Individually

Run only the scripts you actually need:

./12-gpu-nvidia.sh
./40-1password.sh
./41-git-and-ssh.sh
./80-devtools-apps.sh
./90-network-docker.sh
./91-storage-live-resize.sh

Modules

  • 00-base-system.sh: timezone, RTC policy, Fedora updates, base tools.
  • 10-media-codecs.sh: RPM Fusion, OpenH264, ffmpeg, VLC, media codec packages.
  • 11-gpu-amd-intel.sh: AMD and Intel freeworld VA/VDPAU packages.
  • 12-gpu-nvidia.sh: NVIDIA VA-API bridge package only.
  • 20-shell-tooling.sh: Oh My Zsh, Homebrew, Starship.
  • 30-browser-flatpak.sh: Brave repo and policies, Flatpak apps, default browser.
  • 40-1password.sh: 1Password repo, desktop app, CLI, autostart.
  • 41-git-and-ssh.sh: 1Password-backed SSH key export and git config.
  • 50-gnome-desktop.sh: editor env vars, Tweaks, GNOME settings, shell extensions.
  • 60-fonts-input.sh: fonts and fcitx5 input method packages.
  • 70-boot-editor.sh: firmware refresh, GRUB timeout, Emacs user service.
  • 80-devtools-apps.sh: VS Code, JetBrains Toolbox, Waydroid, Xournal++, Wacom.
  • 90-network-docker.sh: Tailscale, Docker, Wake-on-LAN.
  • 91-storage-live-resize.sh: live-environment partition and filesystem resize.

Notes

  • 41-git-and-ssh.sh expects the 1Password item to contain fields labeled private key and public key.
  • 90-network-docker.sh and 91-storage-live-resize.sh are interactive or high-risk. Review before running.
@HackingGate
Copy link
Copy Markdown
Author

Attempt to fix re-locking issue after unlock.

gsettings set org.gnome.desktop.screensaver lock-delay 5

@HackingGate
Copy link
Copy Markdown
Author

How to Install NVIDIA Drivers on Fedora Linux

https://linuxcapable.com/how-to-install-nvidia-drivers-on-fedora-linux/

@HackingGate
Copy link
Copy Markdown
Author

@HackingGate
Copy link
Copy Markdown
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment