This document provides essential information for coding agents working with the Bluefin repository to minimize exploration time and avoid common build failures.
Bluefin is a cloud-native desktop operating system that reimagines the Linux desktop experience. It's an OS built on Fedora Linux using container technologies with atomic updates.
- Type: Container-based Linux distribution build system (75MB total, 74MB system files)
- Base: Fedora Linux with GNOME Desktop + Universal Blue infrastructure
- Languages: Bash scripts, JSON configuration, Python utilities
- Build System: Just (command runner), Podman/Docker containers, GitHub Actions
- Target: desktop OS with two variants (base + developer experience)
Containerfile- Main container build definition (multi-stage: base → dx)Justfile- Build automation recipes (33KB - like Makefile but more readable).pre-commit-config.yaml- Pre-commit hooks for basic validationimage-versions.yml- Image version configurationscosign.pub- Container signing public key
system_files/(74MB) - User-space files, configurations, fonts, themesbuild_files/- Build scripts organized as base/, dx/, shared/base/- Base image build scripts (00-image-info.sh through 19-initramfs.sh)dx/- Developer experience build scriptsshared/- Common build utilities and helper scripts
.github/workflows/- Comprehensive CI/CD pipelinesjust/- Additional Just recipes for apps and system managementbrew/- Homebrew Brewfile definitions for various tool collectionsflatpaks/- Flatpak application lists (system-flatpaks.list, system-flatpaks-dx.list)iso_files/- ISO installation configurations
- Two Build Targets:
base(regular users) anddx(developer experience) - Image Flavors: main, nvidia-open
- Fedora Versions: 42, 43 supported
- Stream Tags:
latest(F42/43),beta(F42/43),stable(F42),gts(F42 Grand Touring Support) - Build Process: Sequential shell scripts in build_files/ directory
- Base Images: Uses
ghcr.io/ublue-os/silverblue-mainas foundation from Universal Blue
ALWAYS install these tools before attempting any builds:
# Install Just command runner (REQUIRED for build commands, may not be available)
# If external access is limited, Just commands will not work
curl --proto '=https' --tlsv1.2 -sSf https://just.systems/install.sh | bash -s -- --to ~/.local/bin
export PATH="$HOME/.local/bin:$PATH"
# Verify container runtime (usually available)
podman --version || docker --version
# Install pre-commit for validation (usually works)
pip install pre-commitNote: In restricted environments, Just command runner may not be installable. Most validation can still be done with pre-commit and manual JSON validation.
Build validation (ALWAYS run before making changes):
# 1. Validate syntax and formatting (2-3 minutes)
# Note: .devcontainer.json will fail JSON check due to comments - this is expected
pre-commit run --all-files
# 2. Check Just syntax (requires Just installation)
just check # Only if Just command runner is available
# 3. Fix formatting issues automatically
just fix # Only if Just command runner is availableBuild commands (use with extreme caution - these take 30+ minutes and require significant resources):
# Build base image (30-60 minutes, requires 20GB+ disk space)
just build bluefin latest main
# Build developer variant (45-90 minutes, requires 25GB+ disk space)
just build bluefin-dx latest main
# Build with specific kernel pin
just build bluefin latest main "" "" "" "6.10.10-200.fc40.x86_64"Utility commands:
# Clean build artifacts (if Just available)
just clean
# List all available recipes (if Just available)
just --list
# Validate image/tag/flavor combinations (if Just available)
just validate bluefin latest mainWorking without Just (when external access is restricted):
# Manual validation instead of 'just check':
find . -name "*.just" -exec echo "Checking {}" \; -exec head -5 {} \;
# Manual cleanup instead of 'just clean':
rm -rf *_build* previous.manifest.json changelog.md output.env
# View Justfile recipes manually:
grep -n "^[a-zA-Z].*:" Justfile | head -20- Container builds require massive resources (20GB+ disk, 8GB+ RAM, 30+ minute runtime)
- Always run
just checkbefore making changes - catches syntax errors early - Pre-commit hooks are mandatory - run
pre-commit run --all-filesto validate changes - Never run full builds in CI unless specifically testing container changes
- Use
just cleanto reset build state if encountering issues
Pre-commit failures:
# Known issue: .devcontainer.json contains comments (invalid for JSON checker)
# This failure is expected and can be ignored:
# ".devcontainer.json: Failed to json decode"
# Fix end-of-file and trailing whitespace automatically
pre-commit run --all-filesJust syntax errors (if Just is available):
# Auto-fix formatting
just fix
# Manual validation
just checkContainer build failures:
- Ensure adequate disk space (25GB+ free)
- Clean previous builds:
just clean(if available) - Check container runtime:
podman system infoordocker system info - Build failures often indicate resource constraints rather than code issues
The repository uses mandatory pre-commit validation:
check-json- Validates JSON syntaxcheck-toml- Validates TOML syntaxcheck-yaml- Validates YAML syntaxend-of-file-fixer- Ensures files end with newlinetrailing-whitespace- Removes trailing whitespace
Always run: pre-commit run --all-files before committing changes.
build-image-latest-main.yml- Builds latest images on main branch changesbuild-image-stable.yml- Builds stable release imagesbuild-image-gts.yml- Builds GTS (Grand Touring Support) imagesbuild-image-beta.yml- Builds beta images for testing F42/F43reusable-build.yml- Core build logic for all image variantsbuild-iso-lts.yml- Builds LTS ISO imagesgenerate-release.yml- Generates release artifacts and changelogsvalidate-brewfiles.yml- Validates Homebrew Brewfile syntaxvalidate-flatpaks.yml- Validates Flatpak list filesclean.yml- Cleanup old images and artifactsmoderator.yml- Repository moderation tasks
Workflow Architecture:
- Stream-specific workflows (gts, stable, latest, beta) call
reusable-build.yml reusable-build.ymlbuilds both base and dx variants for all flavors (main, nvidia-open)- Fedora version is dynamically detected based on stream tag
- Images are signed with cosign and pushed to GHCR
pre-commit run --all-files- Runs validation hooks (2-3 minutes, .devcontainer.json failure is expected)just check- Validates Just syntax (if Just is available, 30 seconds)just fix- Auto-fixes formatting issues (if Just is available, 30 seconds)- Test builds only if making container-related changes (30+ minutes)
Packages are defined directly in build scripts rather than in a central configuration file:
build_files/base/04-packages.sh- Core package installationsFEDORA_PACKAGESarray - Packages from official Fedora repos (installed in bulk)COPR_PACKAGESarray - Packages from COPR repos (installed individually with isolated enablement)- Fedora version-specific package sections using case statements (e.g.,
42),43))
build_files/dx/00-dx.sh- Developer experience package additions
COPR packages use the copr_install_isolated() helper function from build_files/shared/copr-helpers.sh:
# Install packages from COPR with isolated repo enablement
copr_install_isolated "ublue-os/staging" package1 package2
This function:
- Enables the COPR repo
- Immediately disables it
- Installs packages with
--enablerepoflag to prevent repo conflicts
- Edit the appropriate shell script in
build_files/base/orbuild_files/dx/ - Add packages to the appropriate array (
FEDORA_PACKAGESorCOPR_PACKAGES) - For version-specific packages, add them in the Fedora version case statement
- Validate shell script syntax:
bash -n build_files/base/04-packages.sh - Run pre-commit hooks:
pre-commit run --all-files - Test with container build if making critical changes
CRITICAL: Packages are split into separate arrays to prevent COPR repos from injecting malicious versions of Fedora packages:
- Fedora packages are installed first in bulk (safe)
- COPR packages are installed individually with isolated repo enablement
system_files/shared/- System-wide configurationsbuild_files/base/- Base image build scriptsbuild_files/dx/- Developer experience build scriptsbuild_files/shared/- Common build utilities.github/workflows/- CI/CD pipeline definitions
.pre-commit-config.yaml- Pre-commit hook configurationJustfile- Build recipe definitions and validation.github/renovate.json5- Automated dependency updatesContainerfile- Container build instructions
The Justfile is the central build orchestration tool with these key recipes:
Validation Recipes:
just check- Validates Just syntax across all .just filesjust fix- Auto-formats Just filesjust validate <image> <tag> <flavor>- Validates image/tag/flavor combinations
Build Recipes:
just build <image> <tag> <flavor>- Main build command (calls build.sh)just build-ghcr <image> <tag> <flavor>- Build for GHCR (GitHub Container Registry)just rechunk <image> <tag> <flavor>- Rechunk image for optimization
Image/Tag Definitions:
images: bluefin, bluefin-dx
flavors: main, nvidia-open
tags: gts, stable, latest, betaVersion Detection:
just fedora_version <image> <tag> <flavor>- Dynamically detects Fedora version from upstream base images- For
gtsandstable: Checksghcr.io/ublue-os/base-main:<tag> - For
latest/beta: Checks corresponding upstream tags - Returns the Fedora major version (e.g., 42, 43)
The Containerfile uses a multi-stage build process:
- Stage
ctx(FROM scratch): Copies all build context (system_files, build_files, etc.) - Stage
base(FROM silverblue-main): Base Bluefin image- Mounts build context from
ctxstage - Runs
/ctx/build_files/shared/build.shwhich executes all scripts in order
- Mounts build context from
- Stage
dx(optional, in full Containerfile): Developer experience layer
Build Arguments:
BASE_IMAGE_NAME- Upstream base (silverblue/kinoite)FEDORA_MAJOR_VERSION- Dynamically set by Just (42/43)IMAGE_NAME- Target image name (bluefin/bluefin-dx)KERNEL- Pinned kernel version (optional)UBLUE_IMAGE_TAG- Stream tag (gts/stable/latest/beta)
Scripts in build_files/base/ execute in numerical order:
00-image-info.sh- Sets image metadata and os-release info03-install-kernel-akmods.sh- Installs kernel and akmod packages04-packages.sh- Installs Fedora and COPR packages05-override-install.sh- Overrides base image packages08-firmware.sh- Firmware configurations17-cleanup.sh- Cleanup operations18-workarounds.sh- Temporary fixes/workarounds19-initramfs.sh- Regenerates initramfs
just/bluefin-apps.just- User-facing app management recipesjust/bluefin-system.just- System management recipesbrew/*.Brewfile- Homebrew package collections (ai, cli, fonts, k8s)
- ALWAYS validate first:
just check && pre-commit run --all-files - Make minimal modifications - prefer configuration over code changes
- Test formatting:
just fixto auto-format - Avoid full container builds unless specifically testing container changes
- Focus on system_files/ changes for most user-facing modifications
- JSON files: Validate syntax with
pre-commit run check-json - YAML files: Validate syntax with
pre-commit run check-yaml - Justfile: Always run
just checkafter modifications - Shell scripts: Follow existing patterns in build_files/
- Adding packages: Edit
build_files/base/04-packages.sh, add to appropriate array - System configuration: Modify files in
system_files/shared/ - Build logic: Edit scripts in
build_files/base/orbuild_files/dx/ - CI/CD: Modify workflows in
.github/workflows/
The information in this document has been validated against the current repository state. Only search for additional information if:
- Instructions are incomplete for your specific task
- You encounter errors not covered in the workarounds section
- Repository structure has changed significantly
This repository is complex but well-structured. Following these instructions will significantly reduce build failures and exploration time.
- Ensure that conventional commits are used and enforced for every commit and pull request title.
- Always be surgical with the least amount of code, the project strives to be easy to maintain.
- Documentation for this project exists in ublue-os/bluefin-docs
- Bluefin LTS exists in ublue-os/bluefin-lts
AI agents must disclose what tool and model they are using in the "Assisted-by" commit footer:
Assisted-by: [Model Name] via [Tool Name]
Example:
Assisted-by: Claude 3.5 Sonnet via GitHub Copilot