Modular Fedora Workstation bootstrap for a .NET/Aspire development machine. It installs user-selected applications, configures the development toolchain, and keeps technical dependencies next to the modules that require them.
All programs intended to be changed by the user are listed in the root file:
programs.conf
It contains grouped Bash arrays for:
- modules included in the default unattended run;
- RPM applications and optional RPM applications;
- the Podman toolchain;
- tracked .NET SDK channels and global .NET tools;
- Aspire and global npm tools;
- GNOME Shell extensions;
- Flatpak applications.
For example, removing 11-starship from DEFAULT_MODULES disables Starship
during the full run while keeping ./install.sh starship available. Removing
an application from its package array prevents its installation; associated
third-party repositories for Brave, VS Code, and 1Password are also configured
only when those applications remain selected.
Add or remove entries there instead of editing installation logic. Packages
that exist only to make a module work—such as curl, jq,
shared-mime-info, compiler packages, and driver libraries—stay
inside the relevant module and are not part of the user software selection.
Appearance is intentionally separate:
appearance.conf
Use it to select Nerd Font families, the pinned symbol metadata version, the GNOME monospace font, and the initial developer-icon style and color. All root configuration files are sourced as Bash; keep their existing syntax and run the checks shown in Validation after editing them.
Default-application policy is kept in a third root file:
mime-defaults.conf
It maps missing defaults to Rider or VS Code and contains desktop-ID aliases. The policy repairs only absent or broken defaults; a valid application chosen later in GNOME remains untouched.
- Podman instead of Docker Engine; rootless and daemonless by default.
- Microsoft SDKs managed per user by the official preview of
dotnetup. - The newest LTS and newest stable SDK channels tracked by default.
- Aspire CLI installed as a .NET global tool and configured for Podman.
- Node.js/npm with a user-owned global prefix.
- Zsh, Oh My Zsh, autosuggestions, completion plugins, and Starship.
- Native .NET 10+ Zsh command completion.
- JetBrainsMono, FiraCode, and Meslo Nerd Fonts by default.
- GNOME, Nautilus, Flatpak apps, RPM Fusion codecs, and NVIDIA detection.
- Local development MIME definitions and generated GNOME-style icons.
- No automatic reboot.
chmod +x install.sh modules/*.sh diagnostics/*.sh
./install.shDo not run the installer with sudo. It runs as the current user and requests
sudo once for the modules that make system changes. Modules then run without
pausing for hidden input.
The scripts are designed to be rerunnable. Existing packages, fonts, extensions, repositories, and tools are detected when practical. Components with an update policy are updated by their owning module.
Module numbers express installation order, not stable names. Prefer aliases:
./install.sh podman dotnet aspire
./install.sh zsh nerd-fonts starship
./install.sh mime dev-icons
./install.sh dev-icons-colorList all modules:
./install.sh --listThe color selector is optional and is not part of the unattended full run.
The dotnet module downloads Microsoft's official bootstrap script, which
installs and SHA-512-verifies dotnetup under:
~/.dotnetup
Managed SDKs and runtimes use dotnetup's Linux default root:
~/.local/share/dotnetup/dotnet
The default tracked requirements in programs.conf are:
DOTNET_SDK_CHANNELS=(
lts
latest
)lts always follows the newest supported LTS SDK. latest follows the newest
stable SDK, so it advances to the newest STS when an STS release is current.
If both currently resolve to the same SDK, dotnetup keeps both requirements and
shares the installation.
During the first migration, --migrate-from-system preserves matching SDKs
and runtimes from an existing system-managed installation. Only after dotnetup
and the managed dotnet executable have been verified does the module remove
old dnm launchers/metadata, Fedora .NET packages, and a recognised legacy
LinuxScripts DotnetManager installation.
Useful commands:
dotnetup list
dotnetup update
dotnetup --info
dotnetup env show
dotnetup self updateExact SDK versions in programs.conf, such as 10.0.103, remain pinned during
dotnetup update. Major, minor, feature-band, lts, and latest requirements
continue following their channels.
In Rider, select this CLI executable after running the module:
~/.local/share/dotnetup/dotnet/dotnet
The Zsh module installs its maintained templates from:
config/zsh/zshenv
config/zsh/zshrc
Existing ~/.zshenv and ~/.zshrc files are backed up before replacement.
The new configuration provides:
- command and history completion through Oh My Zsh and Zsh plugins;
- history-based autosuggestions, accepted with
Ctrl+Space; - syntax highlighting;
- the official environment emitted by
dotnetup env script; - native hybrid .NET completion through
dotnet completions script zshwhen the selected SDK supports it; - Starship with adaptive full and compact layouts.
dotnetup itself currently exposes no public shell-completion generator. Zsh
still offers history-based suggestions for its commands through
zsh-autocomplete and zsh-autosuggestions.
Starship source configurations live in:
config/starship/starship.toml
config/starship/starship-compact.toml
config/zsh/starship-adaptive.zsh
The Starship module copies them to ~/.config. It also removes a detected
Powerlevel10k setup after backing up the shell configuration.
Aspire is installed from the package named by ASPIRE_DOTNET_TOOL in
programs.conf (by default Aspire.Cli). The module exports:
export ASPIRE_CONTAINER_RUNTIME=podmanIt refreshes the development certificate without globally overriding
SSL_CERT_DIR, because that variable can break applications with bundled TLS
libraries.
Edit GNOME_EXTENSIONS and FLATPAK_APPS in programs.conf. GNOME extension
download and compatibility handling is isolated in
lib/gnome-extensions.sh; the numbered module remains the orchestration entry
point.
The GNOME module also installs gnome-rounded-blur, required by Blur My Shell
for rounded dynamic-blur corners. It enables the ublue-os/packages COPR only
for that package and leaves the repository disabled globally.
New extensions are discovered by GNOME Shell after logging out and back in.
Edit NERD_FONTS and the GNOME monospace settings in appearance.conf. Fonts
are installed under:
~/.local/share/fonts/NerdFonts
The module refreshes the font cache only when files change and configures JetBrainsMono Nerd Font as GNOME's monospace font when that family is selected.
The mime module installs all XML definitions from config/mime into the
user MIME database. It also handles empty files, which GNOME otherwise reports
as application/x-zerosize, by resolving their intended type from the file
extension.
It also repairs a common source of apparently resetting defaults: application
updates can remove the generated desktop ID still stored in
~/.config/mimeapps.list. The module creates a stable Rider desktop entry,
migrates old Rider and VS Code IDs, removes references to applications that no
longer exist, and fills only missing defaults from mime-defaults.conf.
Broken symlinks and obsolete Rider launchers in the user's applications folder
are moved—not deleted—to timestamped backups under:
~/.config/fedora-setup/backups
The expanded MIME catalog includes .NET/MSBuild user projects, publish profiles, run settings, response and global-config files, NuGet/.NET XML configuration, lock files, Bicep, Thrift, Smithy, Mermaid, Go/Helm templates, Elm, Haxe, Raku, and GLSL/HLSL/WGSL shaders. Matching Nerd Font icons are generated by the developer-icons module.
The dev-icons shell module only orchestrates installation. Its file-based C#
components are split by responsibility, with one class or record per file:
scripts/dev-icons/build_catalog.cs
scripts/dev-icons/CatalogItem.cs
scripts/dev-icons/reconcile.cs
scripts/dev-icons/AppearanceSettings.cs
scripts/dev-icons/IconState.cs
scripts/dev-icons/SvgGlyphExporter.cs
scripts/dev-icons/SvgTranslator.cs
They run directly through dotnet run --file; #:include composes the source
files without a project file. The scripts require .NET SDK 10.0.300 or newer.
Glyph outlines are read through the pinned MIT-licensed OpenFontSharp package.
The resolver downloads a pinned Nerd Fonts Symbols Only asset, maps MIME names and globs to glyphs, and generates icons in the user's active icon theme. It watches MIME default-application changes, not project files.
The initial icon style and base color come from these values in
appearance.conf:
DEV_ICON_DEFAULT_STYLE="monochrome" # monochrome, brand, or custom
DEV_ICON_DEFAULT_COLOR="#5E5E5E"They initialize a new installation without overwriting a style already chosen
through dev-icons-color.
Apply a color style explicitly:
./install.sh dev-icons-color
DEV_ICON_STYLE=brand ./install.sh dev-icons-color
DEV_ICON_STYLE=monochrome ./install.sh dev-icons-color
DEV_ICON_STYLE=custom DEV_ICON_COLOR=#3584E4 ./install.sh dev-icons-colorpodman.socket is intentionally not enabled. Aspire can use Podman directly.
If another tool requires the Docker-compatible API:
systemctl --user enable --now podman.socket
export DOCKER_HOST="unix://$XDG_RUNTIME_DIR/podman/podman.sock"Check source syntax without changing the machine:
bash -n install.sh programs.conf appearance.conf mime-defaults.conf lib/*.sh modules/*.sh diagnostics/*.sh
zsh -n config/zsh/zshenv config/zsh/zshrc
dotnet build scripts/desktop/reconcile.cs
dotnet build scripts/dev-icons/build_catalog.cs
dotnet build scripts/dev-icons/reconcile.cs
./tests/test-desktop-reconcile.sh
git diff --check
./install.sh --listAfter applying the setup:
dotnetup list
dotnet --info
aspire doctor
./diagnostics/check-environment.sh
./diagnostics/check-mime.sh
./diagnostics/check-mime-defaults.shSource checks do not prove that packages were installed or that GNOME loaded new extensions. Run the relevant module for live installation, then log out and back in (or reboot) for shell, GNOME, NVIDIA/kernel, and session-level changes.