Skip to content

Latest commit

 

History

History
216 lines (176 loc) · 9.15 KB

File metadata and controls

216 lines (176 loc) · 9.15 KB

Project Architecture

Technical deep dive into how the project is structured and how it works.

Quick Overview

What you'll learn:

Best for: Contributors, system administrators, and curious developers who want to understand the internals.

Time to read: 8-10 minutes

Directory Structure

fedora-desktop/
├── ansible.cfg                    # Ansible configuration
├── requirements.yml               # Ansible Galaxy dependencies
├── run.bash                      # Bootstrap installer script
├── vault-pass.secret             # Vault password (gitignored)
├── CLAUDE.md                     # Claude Code instructions
│
├── vars/
│   └── fedora-version.yml        # Target Fedora version
│
├── environment/
│   └── localhost/
│       ├── hosts.yml             # Inventory definition
│       └── host_vars/
│           └── localhost.yml     # User-specific variables
│
├── playbooks/
│   ├── playbook-main.yml         # Main orchestrator
│   └── imports/
│       ├── play-*.yml            # Core playbooks
│       └── optional/
│           ├── common/           # General optional features
│           ├── hardware-specific/# Hardware drivers/configs
│           ├── experimental/     # Bleeding-edge features
│           ├── untested/         # Playbooks not yet verified
│           └── archived/         # Deprecated playbooks
│
├── docs/                         # User-facing documentation
├── CLAUDE/                       # Agent topic docs (style, QA, security, plans)
├── extensions/                   # GNOME Shell extensions source
├── helpers/                      # Stdlib-only Python helpers (TDD'd, CI-tested)
├── tasks/                        # Standalone Ansible task files
├── tests/                        # Test suite
├── fedora-install/               # Fedora installation helpers (ISO/kickstart)
│
├── files/                        # Static configuration files
│   ├── etc/                     # System configs
│   ├── home/                    # User configs
│   ├── opt/                     # Opt-tree payloads
│   ├── usr/                     # /usr payloads
│   └── var/                     # Variable data
│
├── scripts/                      # Utility scripts
├── roles/                        # Ansible roles
│   └── vendor/                  # Third-party roles (from requirements.yml)
│
└── untracked/                    # Runtime data (gitignored)
    └── facts/                    # Ansible fact cache

Execution Flow

1. Bootstrap Phase (run.bash)

The bootstrap script:

  • Validates system requirements
  • Checks Fedora version against vars/fedora-version.yml
  • Installs core dependencies
  • Configures GitHub CLI authentication
  • Generates SSH keys
  • Clones the repository
  • Collects user configuration
  • Initializes Ansible vault
  • Executes main playbook

2. Main Playbook Execution

playbook-main.yml orchestrates these playbooks in order (all run by default — none are optional):

  1. play-AA-preflight-sanity.yml: Version and dependency checks
  2. play-AB-dnf-upgrade.yml: Full system package upgrade
  3. play-basic-configs.yml: System packages and base configuration
  4. play-prevent-ssh-suspend.yml: Prevent SSH session suspend
  5. play-network-wait-tuning.yml: Network startup tuning
  6. play-mask-intel-lpmd.yml: Mask intel_lpmd.service where it only adds boot noise
    • No-op on hosts where the unit is absent (e.g. AMD), so it imports unconditionally.
  7. play-systemd-user-tweaks.yml: Systemd user session tweaks
  8. play-nvm-install.yml: Node Version Manager setup
  9. play-git-configure-and-tools.yml: Git configuration and tools
  10. play-git-hooks-security.yml: Security pre-commit hooks
  11. play-firefox.yml: Firefox browser configuration
  12. play-github-cli-multi.yml: GitHub CLI multi-account support
  13. play-ms-fonts.yml: Microsoft fonts installation
  14. play-rpm-fusion.yml: Third-party repository setup
  15. play-browsers.yml: Additional browser setup
  16. play-toolbox-install.yml: JetBrains Toolbox
  17. play-lxc-install-config.yml: LXC container support
    • Rootful Docker is optional (imports/optional/common/play-docker.yml, podman-first policy). On Docker hosts, run Docker before this play so the DOCKER-USER iptables chain exists when LXC reconciles outbound connectivity; on podman-only hosts the Docker-coexistence block is skipped. See the "Reconcile iptables" block in play-lxc-install-config.yml.
  18. play-podman.yml: Rootless Podman (default container engine)
  19. play-python.yml: Python/pyenv setup
  20. play-claude-yolo.yml: CCY (Claude container wrapper) installation
    • Ordering constraint: CCY must run before play-claude-code.yml because the cc wrapper sources CCY lib files at runtime, and play-claude-code.yml asserts the lib is present before deploying it. See CLAUDE/Plan/00048-cc-token-source-parity.
  21. play-claude-code.yml: Claude Code CLI and cc wrapper
  22. play-comms.yml: Communication applications
  23. play-gnome-shell.yml: GNOME Shell configuration
  24. play-gnome-shell-extensions.yml: GNOME Shell extensions
  25. play-markless.yml: Markless tool setup
  26. play-terminal-emulators.yml: Terminal emulator configuration
  27. play-vscode.yml: Visual Studio Code
  28. play-vpn.yml: VPN configuration
  29. play-gsettings.yml: GNOME settings
  30. play-ZZ-repo-cleanup.yml: Post-run repository cleanup

Desktop or server — the provisioning_profile / scope pair

This repo provisions both a Fedora desktop and a headless Fedora server from the same source tree. That is the defining architectural constraint, and it is what the scope line in every play exists to serve.

Which target is being built is auto-detected with zero flags into provisioning_profile (environment/localhost/group_vars/desktop.yml), from systemctl get-default:

systemctl get-default provisioning_profile
graphical.target desktop
anything else server

The detection is server-biased when uncertain — a box that cannot prove it is a desktop is provisioned as a server, so GUI work is never done on a headless host by accident.

Override for testing or CI (extra-vars have the highest precedence, so the lookup is skipped entirely rather than merely outvoted):

./run.bash -e provisioning_profile=desktop
./run.bash -e provisioning_profile=server

Every play declares a scope in its play-level vars: block — general | gnome | server. A play whose scope does not match the detected profile ends immediately via a two-task guard that is byte-identical everywhere (the QA gate compares the text). general plays run on both.

Full rules: CLAUDE/AnsibleStyle.md §Provisioning Profile Self-Guard. Per-playbook behaviour: playbooks.md.

3. Optional Components

Manually executed based on needs:

  • common/: Development tools, applications
  • hardware-specific/: NVIDIA, DisplayLink, laptop power/thermal management
  • experimental/: LXDE, VirtualBox
  • archived/: Deprecated playbooks (e.g. play-tlp-battery-optimisation.yml moved here)

Configuration Management

Ansible Configuration (ansible.cfg)

Key settings:

  • Inventory: ./environment/localhost
  • Connection: Local transport (not SSH)
  • Privilege Escalation: sudo with -HE flags
  • Vault: Password file at ./vault-pass.secret
  • Fact Caching: JSON files in ./untracked/facts/

Variable Hierarchy

  1. Global Variables: vars/fedora-version.yml
  2. Host Variables: environment/localhost/host_vars/localhost.yml
  3. Playbook Variables: Defined in individual playbooks
  4. Vault-encrypted: API keys and secrets

File Management

Static files are organized by destination:

  • files/etc/: System configuration files
  • files/home/: User configuration files
  • files/var/: Variable data and scripts

Branching Strategy

  • Each Fedora version has its own branch (F42, F43, etc.)
  • Branch name corresponds to Fedora version
  • vars/fedora-version.yml defines target version
  • Default branch updated to current working version

Security Model

  • Vault encryption for sensitive data
  • SSH key generation and management
  • Passwordless sudo configuration
  • GitHub CLI multi-account support
  • Vault password file (plaintext, gitignored) — it holds the key that decrypts the vaulted values, so it is by definition not itself encrypted