171 Commits

Author SHA1 Message Date
nocode 53ceeabcfb Merge branch 'Main' into Multi-Desktop 2026-07-07 18:48:21 +00:00
nocode 335b59ceca Merge branch 'Multi-Desktop' into Main 2026-07-07 20:46:57 +02:00
nocode ac810f2ee3 docs(trademarks): correct fws version number from 1.0 to 0.6 2026-07-07 13:57:22 +02:00
nocode 5592c57642 docs(readme): update fws version from 1.0 to 0.6 in installation header 2026-07-07 13:57:17 +02:00
nocode 8f6b8e7a95 docs(licensing): update fws version from 1.0 to 0.6 in installation header example 2026-07-07 13:57:12 +02:00
nocode 1826dbfead docs(changelog): update fws version from 1.0 to 0.6 2026-07-07 13:57:08 +02:00
nocode b7bf497cd6 feat(releng): enable systemd-timesyncd ntp synchronization
Add explicit activation of systemd-timesyncd service to ensure proper clock synchronization on installed systems. This prevents clock drift issues that can affect TLS and pacman operations, and meets user expectations for accurate system time.

The service is already present in the image but inherited symlinks from the live environment may be ordinary files that systemd ignores, so explicit enablement ensures correct behavior on all installations.
2026-07-07 13:57:04 +02:00
nocode ae70926ed1 chore(release): bump version to 0.6.0 2026-07-07 13:56:58 +02:00
nocode aac3c8b59e chore(.xinitrc): update anaconda default product version to 0.6 2026-07-07 13:56:54 +02:00
nocode 260547f6b6 chore(releng): convert systemd service files to symlinks
Convert three systemd service configuration files from regular files to symlinks pointing to their respective system libraries. This ensures that the services reference the actual systemd unit files from /usr/lib/systemd/system rather than maintaining duplicate copies.
2026-07-07 13:56:43 +02:00
nocode 730cfd697c chore: bump version to 0.6.0 2026-07-07 02:53:18 +02:00
nocode 292e3071c6 docs(changelog): release version 0.6.0
Update changelog with version 0.6.0 release notes dated 2026-07-07.

Documents major additions including:
- Anaconda installer 45 ported to Arch with Live OS payload
- FWS tooling suite (fws-hello, fws-update, fws-keys, etc.)
- System recovery functionality (fws-recovery-gui and engine)
- zram swap support and firewalld enablement
- Hyprland and i3 desktop parity

Includes changelog entries for changed items (FWS branding, boot entries, compression), fixed issues (splash watchdog, low RAM handling, profile synchronization), and removed items (syslinux config).
2026-07-07 02:53:14 +02:00
nocode 8a90ef4794 docs(environnement): add native arch linux build reference section
Document the native Arch Linux build environment that has been the reference since July 2026. This section explains that build.sh and setup-aur.sh now detect and execute directly on Arch Linux, replacing the previous Windows 11 + WSL setup as the primary reference.

The Windows + WSL path remains functional with automatic fallback from Git Bash but is no longer the reference environment.
2026-07-07 02:48:34 +02:00
nocode 9c7f9b46c5 docs(trademarks): document branding removals and anaconda customization
Add detailed documentation of trademark and branding changes:

- BIOS boot menu: replaced archiso syslinux splash with FWS original artwork
- Login banner: uses FWS PRETTY_NAME without kernel version suffix
- User-facing text: replaced references to Arch Linux/Fedora with generic descriptions
- Anaconda installer: configured to display "FWS 1.0" via environment variables
- Splash screen filtering: removes Fedora mentions from visible logs
- Technical logs: intentionally preserve upstream component identification for diagnostics

All changes maintain nominative fair use and preserve functional upstream tool identifiers.
2026-07-07 02:48:29 +02:00
nocode bf8b29c975 docs(readme): update fws architecture and recovery system documentation
- Add FWS branding details for Anaconda installer (ANACONDA_PRODUCT* exports via .xinitrc)
- Enhance splash screen description with real-time anaconda activity monitoring and auto-diagnostic
- Document memory requirements (4 GB recommended, 2 GB minimum with zram swap)
- Clarify boot menu entries and recovery accessibility from live, GRUB, and installed system
- Add fws-recovery as GTK application with bash engine and console fallback
- Document zram swap configuration for both live and installed system
- Detail recovery system integration: GRUB entry, systemd target, polkit policy, and desktop launcher
- Update syslinux splash and DEFAULT entry documentation
- Expand merge rule warning with syslinux-linux.cfg example and BIOS boot status
- Enhance troubleshooting section with detailed recovery procedures and known issues resolutions
- Add information about splash watchdog, RAM warnings, and diagnostic auto-generation
2026-07-07 02:48:22 +02:00
nocode 9c9891d98e docs(licensing): mark anaconda branding removal as completed and update date
Update the Anaconda branding removal checklist item from incomplete to completed, documenting the implementation details:
- Product name changed to FWS via ANACONDA_PRODUCTNAME and ANACONDA_PRODUCTVERSION variables
- Variables exported by live .xinitrc and read from FWS os-release
- Installation header displays "FWS 1.0 INSTALLATION"
- BIOS boot menu visual replaced with FWS splash screen
- Modified Anaconda version documented in LICENSING.md and TRADEMARKS.md

Also update the compliance date from 2026-06-17 to 2026-07-07.
2026-07-07 02:48:09 +02:00
nocode de05361b28 feat(releng): add polkit policy for fws-recovery privileged operations
Add PolicyKit authorization policy file to allow fws-recovery-gui to execute fws-recovery engine via pkexec with administrative privileges. The policy uses auth_admin_keep to require authentication only once per session.
2026-07-07 02:48:03 +02:00
nocode 9e3a02d96d feat(icons): add fws-recovery scalable application icon
Add a new scalable SVG icon for FWS recovery application featuring a medical cross symbol in FWS brand colors (blues) on a dark background. Icon is placed in the standard hicolor scalable apps directory.
2026-07-07 02:47:59 +02:00
nocode 881f771ed1 feat(releng): add fws-recovery desktop application launcher
Add desktop entry file for FWS Recovery application launcher in the installed OS. Provides bilingual (French/English) interface for system repair operations including GRUB, initramfs, and pacman restoration. The application runs as a regular user with privilege escalation handled via pkexec.
2026-07-07 02:47:54 +02:00
nocode bc08f59e74 feat(releng): add fws-recovery-session script for recovery mode
Add a new script that launches an X session with Openbox and the fws-recovery-gui application. This script is executed by startx during the FWS repair boot entry, providing a minimal graphical environment with Openbox as a fallback if the GUI crashes.
2026-07-07 02:47:48 +02:00
nocode e35b352a2a feat(recovery): add fws-recovery-gui GTK3 application for system repair
Implement a graphical interface for the FWS system recovery tool using GTK3.

Features:
- Scans for FWS installations on disk
- Provides action buttons for common repairs: GRUB reinstall, initramfs
  regeneration, pacman repair, and full system repair
- Displays real-time engine output in a log viewer
- Supports both root session (live mode) and regular user (pkexec elevation)
- Includes terminal access (chroot) for manual diagnostics
- Offers system reboot/poweroff controls

The GUI replaces Arch Linux branding with FWS in output for consistency
while preserving technical identifiers (package names, file paths) for
accurate diagnostics.
2026-07-07 02:47:43 +02:00
nocode 44b476e1d0 feat(zram): add zram-generator configuration for live environment
Enable compressed swap in RAM (zram) for the live environment to prevent memory saturation issues on systems with limited RAM. This configuration provides necessary headroom during Anaconda installation by leveraging zram's ~3:1 compression ratio on Python heaps. The configuration is automatically copied to installed systems via LiveOS payload, maintaining this safety net post-installation on modest hardware.
2026-07-07 02:47:35 +02:00
nocode f3feff4dc2 feat(systemd): add fws-recovery.target unit
Add new systemd target unit for FWS system recovery mode. This target is invoked via GRUB boot menu entry "Reparer FWS" and provides a multi-user environment with network access plus recovery session. The service includes proper dependency management to ensure getty@tty1 is properly handled.
2026-07-07 02:47:30 +02:00
nocode d00bcd4144 feat(releng): add fws-recovery-boot systemd service
Add systemd service unit for FWS system recovery boot mode. This service handles recovery session initialization on tty1 with fallback from GUI (via startx/openbox) to console assistant if graphical startup fails. The service is only activated via fws-recovery.target kernel command line parameter and does not interfere with normal boot processes.
2026-07-07 02:47:24 +02:00
nocode 34bf7909ad chore(releng): add issue file to airootfs
Add /etc/issue file to the releng airootfs configuration. This file provides pre-login banner information displayed to users connecting to the system.
2026-07-07 02:47:19 +02:00
nocode 50773635e8 feat(grub): add fws-recovery boot menu entry script
Add a new GRUB menu entry script that provides system recovery functionality.

The script generates a 'Réparer FWS (récupération du système)' menu entry that boots the system into fws-recovery.target with the fws.recovery=1 marker. This allows the recovery application to launch and perform system repairs via GUI or console fallback.

The script uses the fallback initramfs for maximum hardware compatibility during recovery operations, matching the UUID-based root detection logic of the standard 10_linux script.
2026-07-07 02:47:14 +02:00
nocode a75964e391 chore(releng): optimize syslinux splash image
reduce splash.png file size from 45400 to 14037 bytes through image optimization
2026-07-07 02:47:06 +02:00
nocode 7a44c4c291 chore(releng): change default syslinux boot option from arch to fws 2026-07-07 02:47:01 +02:00
nocode e25935fa75 chore(releng): add file permissions for recovery utilities and grub module
Add file permissions configuration for new recovery-related executables and grub module:
- fws-recovery-session executable
- fws-recovery-gui executable
- grub.d recovery module

All set with standard executable permissions (755) and root ownership.
2026-07-07 02:46:56 +02:00
nocode 40d49cb9e2 feat(releng): add zram-generator to x86_64 packages 2026-07-07 02:46:49 +02:00
nocode 3a437a8bfe docs(anaconda): add comment about fws-recovery boot entry and service
Document the FWS recovery boot entry generated by GRUB configuration and explain how the fws-recovery.target and fws-recovery-boot.service work together. Clarify that no explicit activation is needed as the service has no [Install] section and is pulled by the target through Requires, while the desktop launcher provides an alternative way to invoke recovery.
2026-07-07 02:46:43 +02:00
nocode 8e2fc2ec6a refactor(fws-recovery): restructure recovery script with subcommands and GUI support
Split monolithic script into modular functions and add subcommand interface:

- Add scan subcommand to list FWS installations
- Add repair subcommand with actions: grub, initramfs, pacman, pacman-update, all
- Add shell subcommand for chroot terminal access
- Implement support for operating on running system (no mount/chroot needed)
- Extract detection and mounting logic into reusable functions
- Add in_target() helper to execute commands in target (chroot or direct)
- Improve mkinitcpio warning documentation
- Maintain backward-compatible TUI mode when no args provided
- Enable GUI (fws-recovery-gui) to pilot repairs via subcommands
2026-07-07 02:46:30 +02:00
nocode c7221247f2 fix(fws-about): update distribution description to be more generic
Change the description from "Une distribution Arch Linux" to "Une distribution Linux" to better reflect the project's identity and avoid limiting it to Arch Linux specifically.
2026-07-07 02:46:20 +02:00
nocode 57f86ef5f7 chore(syslinux): remove legacy syslinux linux configuration file
Remove the outdated syslinux-linux.cfg configuration file from the baseline syslinux directory. This file is no longer needed as the project has moved away from syslinux-based boot configurations.
2026-07-07 02:46:11 +02:00
nocode a9ba4be111 chore(baseline): add file permissions for recovery tools and grub config
Add file permission entries for new recovery-related executables and grub configuration:
- /usr/local/bin/fws-recovery-session
- /usr/local/bin/fws-recovery-gui
- /etc/grub.d/42_fws-recovery

All entries set to 0:0:755 (root owner, executable).
2026-07-07 02:46:01 +02:00
nocode 6f5fc95e82 feat(baseline): add zram-generator package 2026-07-07 02:45:52 +02:00
nocode 680ee39e94 fix(baseline): update recovery boot flow to use X with gtk application
Changed recovery mode (fws.recovery=1) to start X server with the GTK recovery application (fws-recovery-session) instead of directly launching the console assistant. This provides a graphical interface when possible, with a fallback to the console assistant if X fails to start.

Also updated comments to clarify the different recovery mechanisms on the live ISO versus the installed system.
2026-07-07 02:45:47 +02:00
nocode ec442193f5 feat(xinitrc): enhance anaconda startup splash with better diagnostics and feedback
Add memory check warning for systems with less than 2GB RAM.

Replace simple pulsing splash with active monitoring that displays:
- Real-time anaconda activity from log files
- Elapsed time and current operation
- Stall detection after 4 minutes of inactivity
- Automatic diagnostic report collection (journal, dmesg, udev status)
- Detection of GUI readiness to auto-hide splash

Add anaconda branding environment variables (ANACONDA_PRODUCTNAME,
ANACONDA_PRODUCTVERSION, ANACONDA_ISFINAL) to show "FWS" instead of
"Fedora" in installer headers and logs.

Improve splash cleanup to handle both feeder process and optional
diagnostic dialogs.
2026-07-07 02:45:32 +02:00
nocode a0fc2c1019 chore(releng): add zenity, xterm, and fws-dnd to installer packages
Add zenity for graphical dialogs in the installer, xterm for terminal debugging and Openbox menu entry, and fws-dnd for D&D 5e management functionality (dice, characters, grimoire, sessions, combat).
2026-07-06 18:40:42 +02:00
nocode 9e62cedff0 feat(anaconda): add desktop installation retry mechanism for network failures
Implement a robust desktop installation retry system that handles transient network issues during the Arch installation process.

Changes:
- Create fws-desktop-retry script in /usr/local/bin for manual recovery after installation
- Add DNS resolution wait loop (up to 10 attempts with 3-second intervals)
- Implement pacman retry logic with up to 3 attempts (15-second delay between retries)
- Generate /var/lib/fws/desktop-failed marker file on installation failure
- Create informative MOTD message guiding users to retry desktop installation
- Preserve FWS-specific MOTD when it contains retry instructions

This allows users to recover from network/mirror failures without reinstalling the entire system.
2026-07-06 18:40:37 +02:00
nocode bfd43ff41a refactor(baseline syslinux)!: restructure syslinux configuration for multi-boot selection
Replace simple serial-based menu with system detection logic using whichsys.c32 to automatically select between PXE and direct system boot. This enables dynamic boot method selection while maintaining support for both boot scenarios.

BREAKING CHANGE: Changes syslinux.cfg structure from single menu-based boot to conditional boot selection. Systems relying on the previous serial menu interface and default 'arch' label will need to adapt to the new whichsys-based selection mechanism.
2026-07-06 18:40:32 +02:00
nocode 6fb48bd3a8 chore(pacman): remove fws-local repository configuration
Remove the custom fws-local repository section from the baseline pacman configuration. This local repository reference is no longer needed in the baseline setup.
2026-07-06 18:40:27 +02:00
nocode 61fa81dd24 feat(baseline): add firewalld to baseline packages
Include firewalld in the baseline x86_64 package list for system firewall management capabilities.
2026-07-06 18:40:23 +02:00
nocode 45ff906097 chore(efiboot): update efifi boot loader entry configuration
Update the UEFI boot loader entry to reflect FWS install medium branding, add sort-key directive for boot order control, align configuration formatting, and increase udev event timeout to 45 seconds for improved hardware compatibility during boot.
2026-07-06 18:40:19 +02:00
nocode 2daac4a455 docs(readme): clarify baseline and releng config merge rules
Expand the ISO branding documentation to include a detailed warning about the build process where baseline configs overwrite releng configs. Add a list of critical files that must be kept in sync between both profiles (profiledef.sh, packages.x86_64, pacman.conf, efiboot/loader/entries/01-archiso-linux.conf, syslinux/syslinux.cfg) and include a verification command to detect file divergences. This prevents silent data loss from config mismatches during the build.
2026-07-06 18:40:10 +02:00
nocode d65f08cfad fix(i3-config): disable picom in virtual machines to prevent rendering artifacts
picom's GPU compositing causes GTK window repaint issues in virtual environments (vmwgfx/llvmpipe), resulting in black content and visual artifacts. Use systemd-detect-virt to skip picom execution on VMs while keeping it enabled on real hardware.

The rounded corners feature is sacrificed in VM environments to maintain stable window rendering.
2026-07-04 14:10:27 +02:00
nocode 7268e7e23d docs(readme): document anaconda integration and fws tooling comprehensive updates
Update README to reflect completed Anaconda 45 integration on Arch Linux, replacing Calamares. Document:

- Desktop choices (GNOME, KDE Plasma, XFCE, Hyprland, i3) with VR compatibility matrix
- Installation flow: Anaconda hub with FWS spokes, LiveOS payload, recap page before write
- fws-* tooling ecosystem: fws-hello, fws-update, fws-keys, fws-powermenu, fws-about, fws-vr-setup, fws-proton-ge, fws-recovery
- Hyprland & i3 visual parity: Catppuccin Mocha theme, waybar/polybar, wofi/rofi, custom SDDM theme
- Boot sequence: menu entries (normal, safe graphics, recovery, speech) → Openbox live → Anaconda → recap → installation
- Build process: incremental AUR + local PKGBUILD compilation (anaconda stack)
- Expanded troubleshooting: VM rendering issues, SteamVR, Bluetooth, recovery mode, BIOS/UEFI boot
- Log locations for live and post-install debugging
- Clarified file locations: kickstart, spokes, configs, tools, branding
2026-07-04 14:10:15 +02:00
nocode d4bef2fe91 chore(releng): add fws-about desktop entry file
Add desktop entry file for the FWS About application with localized names and metadata for system integration.
2026-07-04 13:43:54 +02:00
nocode a1255eb5c6 build(releng): hide xfce4-about application from menus
Add desktop entry file to hide the xfce4-about application from application menus. Since xfce4-about is a dependency of Thunar through libxfce4ui and does not require a full XFCE session, this entry prevents it from appearing in application launchers by leveraging XDG_DATA_DIRS priority where /usr/local/share takes precedence over /usr/share.
2026-07-04 13:43:50 +02:00
nocode cbdb386ba0 feat(powermenu): add fws-powermenu universal power menu utility
Add a Python-based power menu script that works with both Hyprland (Wayland) and i3 (X11) desktop environments. Supports lock, logout, suspend, reboot, and poweroff actions with appropriate display server backends (wofi for Hyprland, rofi for i3).
2026-07-04 13:43:45 +02:00
nocode 4df4b2bff3 feat(fws-about): add fws-about dialog application for system information
Add a new GTK3-based Python application that displays an "About FWS" dialog with two tabs:

- "Le projet FWS" tab: shows project name, description, features, and home URL
- "Système" tab: displays system information including OS, kernel, desktop environment, hardware (CPU, memory, GPUs, disks)

The application detects system information from /proc, lsblk, lspci, and environment variables. It replaces the default Xfce About dialog with FWS branding.
2026-07-04 13:43:39 +02:00
nocode 73cf60e876 chore(releng): add fws-powermenu and fws-about to file permissions 2026-07-04 13:43:32 +02:00
nocode 07ff62af55 chore(anaconda): replace thunar with dolphin and gvfs with udisks2 in desktop environments
Update package lists for Hyprland and i3 desktop environments:
- Replace thunar file manager with dolphin (KDE's file manager)
- Add kio-extras for dolphin functionality
- Replace gvfs with udisks2 for USB mounting
- Update comments to reflect new mount mechanism

This change improves consistency and provides better integration for the respective desktop environments.
2026-07-04 13:43:29 +02:00
nocode 22a95badcf style(waybar): add custom power button styling
Add styling for custom power button with Catppuccin color scheme.

- Default color: #f38ba8 (rouge doux)
- Hover color: #ff6b81 (lighter red)
2026-07-04 13:42:44 +02:00
nocode a1adefe890 feat(waybar): add power menu module to waybar config
Add custom power menu module to waybar configuration with power icon and SUPER+X keyboard shortcut that launches fws-powermenu utility.
2026-07-04 13:42:41 +02:00
nocode 1f465bf647 feat(polybar): add power module to polybar configuration
Add a new power module to the polybar configuration that displays a power icon and triggers the fws-powermenu command on click. The module is styled with red foreground color and integrated into the modules-right bar.
2026-07-04 13:42:37 +02:00
nocode ba2dc4637e chore(i3-config): update file manager and add new keybindings and window rules
- Change default file manager from thunar to dolphin
- Add $mod+x keybinding for fws-powermenu (power menu)
- Add floating window rules for fws-hello and fws-about dialogs
2026-07-04 13:42:32 +02:00
nocode ccdbdf4adf chore(hyprland): update hyprland config with dolphin, powermenu binding, and window rules
Replace thunar file manager with dolphin for consistency.
Add power menu keybinding (Super+X) for shutdown/restart operations.
Add floating window rules for fws-hello and fws-about applications.
2026-07-04 13:42:28 +02:00
nocode 1c74b59459 fix(fws-hello): set window type hint to dialog and prevent resizing
Import Gdk and GLib modules to properly configure window behavior.

Set deterministic WM_CLASS using GLib.set_prgname() so that i3/Hyprland
window rules targeting "fws-hello" floating window behavior work correctly.

Set window type hint to DIALOG and disable resizing to ensure the window
remains floating with its natural size instead of being stretched across
the entire workspace, which would result in unreadable layout.
2026-07-04 13:42:24 +02:00
nocode 1cb48ce4e7 chore(baseline): add file permissions for fws-powermenu and fws-about scripts 2026-07-04 13:42:11 +02:00
nocode 17f9c79983 feat(rofi): add rofi configuration for fws application menu
Add rofi configuration file with FWS styling matching the Hyprland wofi look. Includes dark background, blue borders and selection, icon support, and Catppuccin Mocha color scheme.
2026-07-04 13:15:45 +02:00
nocode 3cdfdcfaeb feat(i3-config): add rofi configuration for i3 desktop environment
Install rofi configuration file (rofi-config.rasi) for i3 desktop to provide an application menu with FWS styling, equivalent to wofi in Hyprland. Configure rofi for both skeleton and existing user home directories with proper ownership settings.
2026-07-04 13:15:33 +02:00
nocode 9e59be79c3 feat(efiboot): add FWS recovery boot entry configuration
Add a new EFI boot loader entry for FWS recovery mode that boots the live system without the installer and launches the recovery assistant console. This enables system repair functionality including GRUB reinstallation, initramfs regeneration, and pacman repair.
2026-07-04 12:57:05 +02:00
nocode 080a77c5e3 feat(releng): add fws-updates-check script for update notifications
Add a new shell script that checks for available package updates using checkupdates from pacman-contrib. The script outputs the number of available updates with an icon for use in waybar/polybar status bars. Silent output when no updates are available allows the bar module to hide.
2026-07-04 12:57:01 +02:00
nocode 7e40a565cc feat(fws-update): add system update utility script
Add fws-update script to provide a one-command system update solution accessible from taskbar, fws-hello menu, or terminal.

The script performs:
- System update via pacman -Syu
- Package cache cleanup (retains 2 latest versions)
- Orphaned package detection and optional removal
- Flatpak updates if available

Requires root privileges and prompts for user confirmation on orphan removal.
2026-07-04 12:56:57 +02:00
nocode 338f6b87ee feat(recovery): add fws-recovery script for system repair from live environment
Add a comprehensive system recovery tool that:
- Detects FWS installations on disks including LVM volumes
- Mounts target root filesystem with /boot and ESP partitions
- Provides interactive menu for common repair operations:
  - GRUB reinstallation (UEFI and BIOS support)
  - Initramfs regeneration via mkinitcpio
  - Pacman database repair and system updates
  - Interactive chroot shell for manual intervention

The script handles automatic LVM activation, filesystem detection via os-release, and proper cleanup on exit.
2026-07-04 12:56:51 +02:00
nocode 4f4afec6b2 feat(releng): add fws-proton-ge script for proton-ge installation
Add a user-friendly bash script that automates downloading and installing
Proton-GE (GloriousEggroll) for Steam. The script fetches the latest release
from GitHub, verifies integrity with SHA512 checksums, and installs it to the
user's Steam compatibility tools directory. Includes error handling and user
guidance for Steam configuration.
2026-07-04 12:56:44 +02:00
nocode 640aa15af8 feat(releng): add fws-hello welcome window script
Add a new GTK3-based welcome window script that displays on first boot after installation. The script provides quick access to system setup tasks including system update, multimedia codecs installation, Proton-GE setup, VR configuration, and keyboard shortcuts (on Hyprland/i3). Users can opt to hide the window on subsequent boots via a checkbox and flag file.
2026-07-04 12:56:39 +02:00
nocode 73f73ff17e feat(releng): add fws-hello desktop autostart entry
Add desktop entry file to automatically launch fws-hello welcome window on first startup. This provides a user-friendly greeting interface when the system boots.
2026-07-04 12:56:33 +02:00
nocode 6c8e7c0f78 feat(syslinux): add fws recovery boot option to syslinux config
Add a new boot menu entry for FWS installation recovery that boots into a guided console assistant without reinstalling. The recovery mode is triggered via the fws.recovery=1 kernel parameter.
2026-07-04 12:56:28 +02:00
nocode 5762f59d95 chore(releng): add new executable file permissions to profiledef
Add permission entries for five new utility scripts:
- fws-hello
- fws-update
- fws-updates-check
- fws-proton-ge
- fws-recovery

All are configured with standard permissions (0:0:755).
2026-07-04 12:56:24 +02:00
nocode affba77349 feat(releng): add firewalld to x86_64 packages 2026-07-04 12:56:17 +02:00
nocode 87977ce8d7 build(releng): add python-gobject, pacman-contrib packages and enable firewalld
- Add python-gobject for fws-hello welcome window (GTK3 comes with Firefox)
- Add pacman-contrib for checkupdates/paccache (update indicator and fws-update)
- Enable firewalld.service by default with public zone (blocks inbound, allows outbound)
- firewalld is already in the base image and can be activated offline
- GUI included in firewall-config package; KDE has additional plasma-firewall
2026-07-04 12:56:13 +02:00
nocode b5f00d8dd2 feat(waybar): add custom updates module to waybar configuration
Add a new custom/updates module to the waybar right-side modules that displays available system updates. The module executes fws-updates-check every 30 minutes (1800 seconds) and allows users to install updates by clicking, which launches a kitty terminal running fws-update. Tooltip text is displayed in French.
2026-07-04 12:56:08 +02:00
nocode 349cc28d7d feat(polybar): add updates module to polybar configuration
Add a new custom script module to check for system updates in the polybar status bar. The module runs fws-updates-check every 30 minutes and allows users to trigger updates with a left click to open the update utility in kitty terminal.
2026-07-04 12:56:03 +02:00
nocode fc1bc218a4 feat(i3-config): add fws-hello welcome window on startup
Add execution of fws-hello with --autostart flag to display a welcome window on first boot only. The window will automatically hide after the initial startup.
2026-07-04 12:55:56 +02:00
nocode d399fc5fa6 feat(hyprland): add fws-hello welcome window on first startup
Add execution of fws-hello with --autostart flag to display a welcome window on first launch. The window will be automatically hidden on subsequent startups.
2026-07-04 12:55:50 +02:00
nocode 4d36e86f51 feat(hardware-setup): add mangohud gaming performance overlay packages
Add mangohud and lib32-mangohud packages to the desktop environment setup for gaming performance monitoring. Mangohud provides an in-game FPS and performance metrics overlay that can be used with Steam games via '%command%' prefix.
2026-07-04 12:55:45 +02:00
nocode a0f269cf90 chore(baseline): add file permissions for new fws utility scripts
Add file permission entries for five new utility scripts in the fws toolkit:
- fws-hello
- fws-update
- fws-updates-check
- fws-proton-ge
- fws-recovery

All scripts are configured with owner:group 0:0 and executable permission 755.
2026-07-04 12:55:38 +02:00
nocode 7831b537d7 feat(baseline): add recovery mode boot option to zprofile
Add support for recovery mode that can be triggered via the fws.recovery=1 kernel parameter. When recovery mode is enabled, the system launches the fws-recovery console assistant directly instead of starting the graphical environment.

This allows users to access repair tools without needing to start X server, improving system recovery capabilities.
2026-07-04 12:55:25 +02:00
nocode 2c5f08330a refactor(fws-keys): make keyboard shortcuts tool universal for hyprland and i3
Rename fws-hypr-keys to fws-keys and extend it to support both Hyprland and i3 desktop environments. The tool now detects the session type and uses appropriate methods:

- Hyprland: queries hyprctl binds for real loaded bindings (wofi dmenu)
- i3: parses ~/.config/i3/config with variable resolution (rofi dmenu)

Update all references in configs and templates. Add VM detection warning in fws-vr-setup to prevent VR attempts in virtual machines where GPU/USB access is unavailable.

Add ttf-liberation font dependency for Steam UI stability on minimal installations and improve error guidance for Steam crashes.
2026-07-04 03:59:09 +02:00
nocode a63021cde7 feat(icons): add fws-vr vr headset icon
Add scalable SVR icon for the fws-vr-setup launcher using FWS/Catppuccin color palette. The icon depicts a VR headset with straps, lenses, and nose notch in blue and dark theme colors.
2026-07-04 03:30:46 +02:00
nocode b408c84a8c feat(releng): add fws-vr-setup desktop application entry
Add desktop application entry for VR setup tool that allows users to install drivers and runtimes for VR headsets including HTC Vive, Valve Index, and Meta Quest devices. The application launches fws-vr-setup command in a kitty terminal.
2026-07-04 03:30:41 +02:00
nocode 2a3824a991 feat(i3): add default i3 window manager configuration
Add FWS default i3 configuration file with X11 session support.

Includes:
- Color scheme based on Catppuccin Mocha palette
- Keyboard bindings for common applications and window management
- VR headset driver setup integration (Super+Shift+V)
- Multi-monitor and workspace navigation support
- Screenshot and multimedia control bindings
- Status bar configuration with i3status
- Autostart for dunst, nm-applet, polkit-gnome, and blueman
2026-07-04 03:30:38 +02:00
nocode 06121343e7 feat(releng): add fws-vr-setup script for VR driver installation
Add interactive shell script for installing VR drivers and runtimes based on headset type. Supports HTC Vive/Valve Index (native SteamVR), Meta Quest/Pico (ALVR streaming), and Monado (OpenXR runtime). Script automatically detects GPU and installs appropriate 32-bit Vulkan libraries required by SteamVR. Includes multilib configuration and user guidance for each VR setup path.
2026-07-04 03:30:28 +02:00
nocode 3c12d9514c chore(releng): add fws-vr-setup executable to file permissions
Register the new fws-vr-setup script with executable permissions (755) in the releng profile configuration.
2026-07-04 03:30:23 +02:00
nocode 5f108c607b feat(releng): add i3 window manager desktop environment configuration
Add i3 window manager as a selectable desktop environment option in the anaconda kickstart configuration. Includes:

- i3-wm with essential packages (i3status, i3lock, rofi, kitty, etc.)
- X11 server requirement for VR compatibility (SteamVR incompatible with Wayland)
- Bluetooth service enablement for i3 sessions
- Icon cache update for VR launcher visibility in rofi
- i3 configuration template installation for skeleton and existing users
- Keyboard layout handling via X11 xorg.conf.d (no keyboard injection needed)

This enables users to install a lightweight X11-based desktop environment with VR support capabilities.
2026-07-04 03:30:18 +02:00
nocode 95eb6c15e0 fix(fws-setup-hardware): add blueman bluetooth manager support for i3 desktop
Include blueman in the base packages for i3 desktop environment, alongside hyprland and xfce, to provide graphical bluetooth management and pairing assistant for i3 users.
2026-07-04 03:30:12 +02:00
nocode 4a598c854a chore(baseline): add fws-vr-setup executable permission 2026-07-04 03:30:07 +02:00
nocode 9f46b9bb1b feat(fws_desktop): add i3 window manager option with VR compatibility note
Add i3 X11 window manager as a desktop environment option with explicit VR compatibility information. Update Hyprland label to clarify it uses Wayland and is not VR compatible. Adjust position indices for subsequent radio button options.
2026-07-04 03:30:02 +02:00
nocode 14d138cae4 feat(fws_recap): add i3 desktop option and update hyprland description
Add i3 desktop environment option with X11 and VR compatibility note.
Update hyprland description to clarify Wayland protocol and VR incompatibility.
Both descriptions now include information about included applications (Firefox, SDDM).
2026-07-04 03:29:56 +02:00
nocode 8e2e74a227 feat(fws_desktop): add i3 desktop option and update hyprland description
Add i3 window manager as a desktop choice with X11 and SteamVR compatibility note. Update Hyprland description to clarify it uses Wayland and is not compatible with VR.
2026-07-04 03:29:44 +02:00
nocode d0e431329d refactor(hyprland): disable splash rendering in hyprland configuration
Add disable_splash_rendering option to misc section to hide the startup splash message at the bottom of the screen.
2026-07-04 03:06:39 +02:00
nocode 75113980f0 refactor(waybar): add format-no-controller for bluetooth module
Configure waybar bluetooth module to use an empty format when no bluetooth controller is detected, improving UI consistency.
2026-07-04 03:06:25 +02:00
nocode 4d123b6f5d fix(hyprland): only launch blueman-applet if bluetooth adapter exists
Prevent blueman-applet from showing connection errors in virtual machines where no Bluetooth adapter is present. The applet now checks for the existence of a Bluetooth adapter in /sys/class/bluetooth before launching.

This change adds a conditional check that gracefully skips the applet initialization when no hardware is available, improving user experience in VM environments.
2026-07-04 03:05:57 +02:00
nocode a09278b63f feat(anaconda): add modified anaconda summary hub glade template
Add anaconda-summary-hub.glade file, a customized copy of anaconda 45.8's summary.glade without the "We won't touch your disks…" disclaimer label at the bottom of the hub.

This file is placed in a neutral path (usr/local/share/fws/) because mkarchiso applies the airootfs before pacstrap. Placing it at the anaconda package path would cause pacman to refuse installation due to filesystem conflicts. The live environment's .xinitrc copies this file to /usr/share/anaconda/ui/hubs/summary.glade during boot.
2026-07-04 02:52:33 +02:00
nocode dd71664b9e chore(baseline): remove anaconda summary glade file overlay
Delete the customized summary.glade file that was overlaying the anaconda package file. This file was previously used to hide the "We won't touch your disks…" message at the bottom of the installation summary hub.
2026-07-04 02:52:24 +02:00
nocode 2aaf1cbfd5 chore(baseline): add anaconda summary hub glade override in xinitrc
Add logic to override the anaconda summary hub glade file at live boot time. The custom glade file is stored in /usr/local/share/fws and copied to /usr/share/anaconda/ui/hubs/summary.glade during X initialization.

This workaround is necessary because mkarchiso applies the airootfs overlay before pacstrap, which prevents pacman from installing anaconda over existing files. The file is therefore delivered to /usr/local/share/fws and overlaid at boot when the live overlay is writable.
2026-07-04 02:52:18 +02:00
nocode e20523470f feat(anaconda): add customized summary glade ui file
Add a customized version of anaconda's summary.glade UI definition file to the baseline airootfs configuration. This file is based on anaconda 45.8 but with the "We won't touch your disks..." label removed from the bottom of the hub, allowing the overlay to mask the original package file without requiring an anaconda rebuild.
2026-07-04 01:07:39 +02:00
nocode c56db3de04 chore(releng): remove fws-dnd package from x86_64 build
Remove the fws-dnd package and its associated comment from the x86_64 package list. This package is no longer needed for the release engineering build.
2026-07-04 01:02:50 +02:00
nocode 81dfac3762 chore(releng): add fws-dnd package to x86_64 configuration
Add fws-dnd (D&D 5e manager for dice, characters, grimoire, sessions, and combat) to the releng packages.x86_64 configuration.
2026-07-04 01:01:27 +02:00
nocode 43ecf7f54f chore(releng): add pipewire and bluetooth packages to desktop environments
Add PipeWire audio stack (pipewire, pipewire-pulse, wireplumber, pavucontrol)
and Bluetooth support (bluez, bluez-utils, blueman) to xfce and hyprland
package lists to ensure they are installed alongside the desktop environment.

Enable bluetooth.service at installation time for hyprland to have Bluetooth
ready at first boot. Update comments to reflect the new guaranteed installation
of audio and Bluetooth components as part of the desktop environment transaction.
2026-07-04 01:01:20 +02:00
nocode 96e5721ad8 chore(hyprland): add blueman applet and remove steam keybinding
Add blueman-applet to the exec-once commands for bluetooth management.
Remove the Steam launcher keybinding (SUPER+KP_Multiply) from the configuration.
2026-07-04 01:01:12 +02:00
nocode cef3b291d1 chore(packages): add fws-dnd package to baseline x86_64 configuration
Add the fws-dnd package (D&D 5e Manager for dice, characters, grimoire, sessions, and combat) to the baseline x86_64 packages list under the FWS section.
2026-07-04 01:01:09 +02:00
nocode 6e59e1d4c4 chore(baseline): update installer preparation message in french
Change the estimated time message from '2 à 4 minutes' to 'Encore une à deux minutes' to provide more accurate timing information to users during the FWS installer preparation phase.
2026-07-04 01:00:53 +02:00
nocode 3a5efffc61 feat(wofi-style): add wofi application menu styling with catppuccin mocha theme
Add a new CSS stylesheet for wofi (application launcher menu triggered with Super+R) that implements the Catppuccin Mocha blue color scheme. The stylesheet includes styling for the window, input field, menu entries, and selection states with rounded corners and appropriate contrast ratios.
2026-07-04 00:26:37 +02:00
nocode 53942aece0 feat(releng): add wofi keyboard shortcuts panel styling
Add CSS stylesheet for the FWS keyboard shortcuts panel (fws-hypr-keys) using monospace font to align key combinations with descriptions. Uses the same color palette as the wofi menu with Catppuccin theme colors.
2026-07-04 00:26:31 +02:00
nocode e98a8320fb feat(wofi): add wofi application menu configuration
Add wofi configuration file for FWS with settings for case-insensitive search, image support, custom dimensions, and application prompt.
2026-07-04 00:26:27 +02:00
nocode 038700e22d feat(hyprland): add desktop portal and notification support to hyprland setup
Add missing packages for hyprland desktop environment:
- mako + libnotify for notifications
- polkit-gnome for GUI authentication
- network-manager-applet for network management in tray
- xdg-desktop-portal-hyprland for screen sharing
- gvfs for USB mounting in thunar
- ttf-nerd-fonts-symbols for waybar icons

Add start-hyprland launcher support for hyprland ≥0.53 to properly prepare systemd session/environment.

Add wofi configuration files (config and style.css) for application menu styling.

Update skeleton directory setup to install wofi configs for new users and fix chown path formatting.
2026-07-04 00:26:23 +02:00
nocode 4857a9fda9 style(waybar): redesign waybar stylesheet with catppuccin mocha theme and pill-style modules
Update waybar-style.css to version 2 with the following changes:

- Switch to Catppuccin Mocha color scheme with blue accents
- Redesign bar as floating rounded container instead of bottom border
- Style modules as pill-shaped boxes with individual backgrounds
- Add Nerd Font symbols support for better icons
- Improve workspace buttons with hover effects and transitions
- Add tooltip styling and proper color coding for each module
- Update clock styling with dedicated background
- Enhance battery, network, and bluetooth status colors
- Refine spacing, padding, and border-radius throughout for modern appearance
2026-07-04 00:26:16 +02:00
nocode 289a70c10c style(waybar): enhance waybar configuration with improved styling and additional modules
Update waybar configuration with:
- Adjusted height (34 to 36) and spacing (4 to 2)
- Added margins (top: 6, left: 10, right: 10)
- Added workspace navigation with scroll (e-1/e+1)
- Added backlight, bluetooth, and battery modules
- Enhanced clock format with calendar styling
- Improved audio controls with pavucontrol integration
- Added network bandwidth display
- Updated all module icons to use modern emoji/nerd font glyphs
- Improved tooltips with more detailed information
- Adjusted max window name length from 55 to 45 characters
2026-07-04 00:26:09 +02:00
nocode 8224a24d02 chore(hyprland): add startup services and brightness/blueman window rules
- Add mako notification daemon to startup services
- Add nm-applet for network tray icon
- Add polkit-gnome authentication agent for privilege escalation dialogs
- Add brightness control keybinds for XF86MonBrightnessUp/Down
- Add float window rule for blueman-manager
- Update startup comment to describe all session initialization tasks
2026-07-04 00:26:02 +02:00
nocode 0ab90857e5 feat(fws-setup-hardware): add brightnessctl and blueman to base stack
Add brightnessctl for brightness control without root via logind,
consumed by XF86MonBrightness* keys and waybar backlight module.

Add blueman as graphical Bluetooth manager for desktop environments
that don't provide their own (KDE and GNOME have built-in managers).
Blueman provides system tray integration and pairing assistant.

Update comments to clarify the purpose of these new packages.
2026-07-04 00:25:57 +02:00
nocode d6212deaa9 feat(fws-hypr-keys): add optional style support and adjust wofi dimensions
- Import os module to check for style file existence
- Add _STYLE constant pointing to wofi-keys.css stylesheet
- Increase wofi window dimensions from 780x560 to 820x600
- Conditionally apply custom style if the stylesheet exists
- Refactor wofi command construction for better readability
2026-07-04 00:25:45 +02:00
nocode 754b6e8802 fix(syslinux): add udev event timeout to all boot options
Add udev.event_timeout=45 parameter to all APPEND kernel boot options in the syslinux configuration to prevent udev event timeout issues during boot on systems with slow device initialization.
2026-07-04 00:13:13 +02:00
nocode 053998d1c0 fix(releng): add udev event timeout to speech boot entry
Add udev.event_timeout=45 parameter to the accessibility boot entry to prevent timeout issues during device initialization on systems with slower hardware or many devices.
2026-07-04 00:13:09 +02:00
nocode 218b0707a4 fix(efiboot): add udev event timeout to nomodeset boot entry
Add udev.event_timeout=45 parameter to the safe graphics boot option to prevent timeout issues during device initialization on systems with slower hardware or complex device trees.
2026-07-04 00:13:04 +02:00
nocode 7c11f53520 fix(releng): add udev event timeout to archiso linux boot entry
Add udev.event_timeout=45 kernel parameter to the UEFI boot entry for the archiso linux image. This timeout helps prevent boot delays caused by udev waiting for device events to complete.
2026-07-04 00:12:53 +02:00
nocode be0844b50b feat(releng): add uefi boot entry with nomodeset graphics option
Add a new UEFI boot loader entry for Arch Linux installation medium with the nomodeset kernel parameter. This provides a fallback boot option for systems with GPU or hypervisor drivers that have issues with KMS (kernel mode setting), allowing the system to fall back to VESA/EFI framebuffer graphics mode which is slower but more reliable.
2026-07-04 00:00:11 +02:00
nocode 24370461ea feat(sddm): add fws login theme for kde xfce and hyprland
Introduce a new SDDM theme "fws" designed for FWS with support for KDE, XFCE, and Hyprland desktop environments.

The theme is built using pure QtQuick and QtQuick.Controls (Basic style) with no additional dependencies beyond what SDDM already requires. It includes:

- Main.qml: Custom login screen with clock, date, user/password fields, session selector, and power controls
- metadata.desktop: Theme metadata and configuration
- theme.conf: Default configuration with customizable accent color and gradient colors

The design uses a dark theme with accent colors and supports capslock detection and login error handling.
2026-07-04 00:00:05 +02:00
nocode 5d6d1c6db8 feat(waybar): add waybar style configuration for fws theme
Add CSS stylesheet for Waybar that matches the FWS theme, SDDM appearance, and Hyprland borders. Includes styling for workspaces, clock, custom key help button, and system status modules with Catppuccin blue accent color (#89b4fa).
2026-07-03 23:59:58 +02:00
nocode 23df7656e5 feat(waybar): add waybar configuration for hyprland desktop environment
Add waybar panel configuration with modules for workspaces, window title, clock, volume, network, CPU, and memory monitoring. Configured for top panel layout with French localization support.
2026-07-03 23:59:53 +02:00
nocode a28a64310a feat(releng): add fws-hypr-keys script to display hyprland keyboard shortcuts
Add a new Python utility script that displays actual Hyprland keyboard shortcuts from hyprctl binds output. The script:

- Queries hyprctl binds to get loaded key bindings from the compositor
- Formats keybinds with human-readable modifiers and key labels (French localization)
- Displays descriptions from bindd config entries or falls back to dispatcher actions
- Opens results in wofi dmenu for incremental search and filtering
- Handles special keys like mouse buttons, arrow keys, and common special keys
- Deduplicates repeated bindings (e.g., from resize actions)

No additional dependencies required beyond python3 and wofi (already in FWS + Hyprland packages).
2026-07-03 23:59:49 +02:00
nocode 7aa1276e2c feat(anaconda): add fws recap glade ui definition
Add new Glade UI definition file for the FWS recap (summary before installation) spoke. This defines the AnacondaStandaloneWindow layout with a scrollable text view to display installation summary information.
2026-07-03 23:59:44 +02:00
nocode 9df1f444bc feat(fws): add recap spoke for pre-installation summary
Add FWSRecapSpoke, a standalone spoke that displays a comprehensive summary of user configuration choices and detected hardware before installation begins. The spoke intercepts the installation flow between the SummaryHub and ProgressSpoke, allowing users to review and modify their choices before any disk writes occur.

Features:
- Displays user-selected configuration (language, keyboard, timezone, users, partitioning, desktop, hostname)
- Shows detected hardware (virtualization, GPUs, disks, network status)
- Provides installation flow overview and warnings about automatic partitioning
- Implements back navigation to return to the hub for modifications
- Never marks as completed to ensure proper flow control in anaconda's action queue
2026-07-03 23:59:39 +02:00
nocode 7fe54d0791 fix(setup-aur.sh)!: use explicit package list instead of glob for install and publish
Change publish_to_repo() to accept explicit file list via variadic arguments
instead of a directory glob. This prevents re-publishing stale .pkg files
from previous builds that may still exist in BUILD_DIR.

Update build_or_skip() to get the actual list of packages produced by the
current makepkg invocation using --packagelist, filter for .pkg.tar.* files,
verify they exist on disk, and pass only those to pacman -U and publish_to_repo().

This fixes issues where:
- After pkgrel bumps, old .pkg files would cause pacman to receive duplicate
  package names ("repeated target" error)
- Stale packages would be republished over the purge in local-repo
- Optional debug packages would cause errors when not produced

BREAKING CHANGE: publish_to_repo() function signature changed from publish_to_repo(name, directory) to publish_to_repo(name, file1, file2, ...) - callers must pass explicit file paths instead of a directory path
2026-07-03 23:59:32 +02:00
nocode 4249282052 fix(python-meh): fix python 3.11 compatibility by replacing removed gettext.ldgettext
Replace gettext.ldgettext with gettext.dgettext in Anaconda exception handler
since ldgettext was removed in Python 3.11. Without this fix, the exception
handler crashes with AttributeError when trying to display errors, resulting
in raw tracebacks instead of the meh dialog in both GUI and TUI modes.

Also clean up stale __pycache__ directories from previous extractions and
add validation to ensure ldgettext is completely removed.
2026-07-03 23:59:25 +02:00
nocode 5e66f99816 feat(syslinux): add safe graphics boot option with nomodeset kernel parameter
Add a new boot menu entry for FWS without kernel mode setting (KMS) to provide a fallback option for systems where KMS causes issues. This entry uses the nomodeset kernel parameter to force the framebuffer to VESA/EFI mode, which is slower but more reliable for problematic GPU drivers and hypervisors like VMware.
2026-07-03 23:59:20 +02:00
nocode 35f77ba33d chore(releng): add file permissions for fws-hypr-keys script 2026-07-03 23:59:13 +02:00
nocode d8e67fe861 refactor(anaconda): clarify payload mechanism and enhance desktop environment configurations
Update interactive-defaults.ks kickstart file with:

- Clarified documentation on LiveOS payload detection and mounting via /run/rootfsbase bind-mount instead of direct liveimg directive
- Added comprehensive comments explaining why liveimg directive is intentionally omitted and how anaconda --liveinst handles payload creation
- Enhanced XFCE and Hyprland package sets with noto-fonts for proper TTF rendering and additional tools (thunar, hyprlock, grim, slurp, wl-clipboard, playerctl)
- Implemented SDDM theme configuration with FWS theme support and accent colors per desktop environment (teal for XFCE, Catppuccin blue for Hyprland, Breeze blue for KDE)
- Added GDM (GNOME) configuration via dconf with welcome banner, clock enhancements, and numlock settings
- Expanded Waybar configuration installation for Hyprland with config and style files
- Added comprehensive documentation for greeter customization and Hyprland VM compatibility
- Included details about FWS recap spoke (standalone GUI summary screen) replacing zenity-based pre-install approach
2026-07-03 23:59:09 +02:00
nocode 68850f0ed2 feat(hyprland): expand hyprland config with keybindings, animations, and window rules
Add comprehensive keybinding descriptions using bindd/binde for keyboard shortcut display, implement Catppuccin Mocha color scheme with blue gradient borders, enable animations with custom bezier curve, configure touchpad settings, add blur/shadow configuration for VM compatibility, implement scratchpad support, add screenshot and multimedia key bindings with PipeWire/playerctl integration, and define window floating rules.

Keybindings now match i3/sway FWS configuration with French descriptions that automatically appear in fws-hypr-keys shortcut viewer. Configuration includes multi-screen support, workspace navigation (1-10), window resizing, and various utility bindings.
2026-07-03 23:59:00 +02:00
nocode aa9cb13648 chore(baseline): add file permissions for selinux and hardware setup scripts
Add executable permissions for load_policy, setstatus, fws-setup-hardware, and fws-hypr-keys scripts in the baseline profile configuration.
2026-07-03 23:58:53 +02:00
nocode 8b7af60239 chore: remove pycache file 2026-07-03 23:58:48 +02:00
nocode ee0082baa1 feat(xinitrc): add anaconda installer improvements and splash screen
Add several improvements to the liveinst installer workflow:

- Expose archiso squashfs at /run/rootfsbase where Anaconda expects to find
  the Live OS image, fixing SourceSetupError crashes
- Display immediate splash screen with zenity during Anaconda startup (2-4 min
  wait time) to provide user feedback and prevent perceived hangs
- Wrap liveinst with dbus-run-session to provide D-Bus session bus, fixing
  GLib.GError crashes from missing ScreenSaver service
- Add hardware summary log output to debug information collection

These changes address three crash scenarios identified during testing and
improve user experience during installer initialization.
2026-07-03 23:58:28 +02:00
nocode 0b0fcd8ce4 feat(releng): add hardware detection and driver setup script
Add fws-setup-hardware script that automatically detects and installs:
- GPU drivers (NVIDIA, AMD, Intel) based on lspci output
- Hypervisor guest tools (VMware, VirtualBox, QEMU, Hyper-V)
- Audio/mic/headset stack (PipeWire), Bluetooth (BlueZ), containers (Podman)
- Optional desktop stack when non-CLI desktop is selected: Steam, Wine, VR support (Monado/OpenXR), and winboat-bin

The script is integrated into the Anaconda kickstart post-installation phase and is non-blocking to prevent installation failures from missing packages or network issues.

Also update profiledef.sh to set correct permissions (755) for the new script.
2026-06-24 23:32:37 +02:00
nocode 99006b9ede feat(hyprland): add hyprland configuration with keyboard layout injection and vm compatibility
Add Hyprland desktop environment support with:

- New hyprland.conf template with keyboard layout placeholders (__KB_LAYOUT__ and __KB_VARIANT__) that get injected during installation
- Hyprland wrapper script (/usr/local/bin/fws-hyprland) that detects virtual machines and forces software rendering to prevent compositor crashes on virtual GPUs (VMware vmwgfx, VirtualBox)
- Automatic configuration deployment to /etc/skel and existing user home directories
- Refactored keyboard layout detection logic (moved to section 3bis) to support both X11/SDDM and Hyprland configurations
- Added locale generation during installation to ensure proper language support

Keyboard layout is now derived from either kickstart configuration or system locale using langtable, providing consistent keyboard behavior across all desktop environments.
2026-06-24 23:06:20 +02:00
nocode ff98a1e186 fix(anaconda): improve desktop environment setup and system configuration
- Fix XFCE display manager: replace lightdm-gtk-greeter with sddm for consistency
- Add SDDM numlock initialization for KDE, XFCE, and Hyprland
- Configure X11 keyboard layout from kickstart or locale via langtable to ensure correct SDDM login keyboard
- Enable wheel group sudo access and add all human users to wheel group
- Apply FWS branding to os-release, lsb-release, and GRUB configuration
- Remove inappropriate live system motd file
- Fix DNS resolution: configure systemd-resolved stub resolver with NetworkManager integration to prevent "Limited Connectivity" on first boot
- Reformat case statement for better readability
2026-06-24 19:02:31 +02:00
nocode 7daca57714 feat(anaconda): add desktop environment selection spoke for FWS
Implement a new Anaconda spoke that allows users to select their preferred desktop environment (CLI, GNOME, KDE Plasma, Hyprland, or XFCE) during installation.

The spoke:
- Displays radio buttons for five desktop choices with CLI as the default
- Persists the selection to /tmp/fws-desktop for the kickstart %post script
- Supports revisiting the spoke and resuming previous selections
- Includes a GTK UI definition file (glade) with translatable labels
- Integrates as a SoftwareCategory spoke in the Anaconda installer

The implementation leverages Anaconda's runtime spoke discovery mechanism via the airootfs overlay, avoiding the need to rebuild the anaconda package.
2026-06-24 17:58:52 +02:00
nocode d409406fde feat(build-offi): add build date to iso filename and prompt for version/variant on host
Refactor version and variant handling to prompt for metadata on the host before entering container, enabling proper terminal display. Pass FWS_ISO_VERSION and FWS_ISO_TAG via environment variables to container.

Add build date (AAAA.MM.JJ format) to the final ISO filename: fws-<version>-<variant>-<AAAA.MM.JJ>.iso

Implement ask_iso_meta_host() function to validate and collect version (major.minor.build) and variant name inputs before containerization. Use sudo -E to preserve environment variables across privilege escalation.

Update ISO metadata prompt logic to skip if already provided, supporting both container execution and native Arch/WSL environments.
2026-06-23 12:50:45 +02:00
nocode 0de970239f feat(build): refactor build script with interactive version and variant selection
Replace automatic version reading from VERSION file with interactive prompts for version (major.minor.build) and ISO variant name (e.g., cli, gnome, kde).

Changes:
- Remove automatic VERSION file reading; now serves as default with prompt
- Add interactive prompts for version and variant name with validation
- Simplify ISO naming from FWS-v{major}-{minor}-{build}-{date}-x86_64.iso to fws-{version}-{variant}.iso
- Update hostname from 'archiso' to 'fws'
- Add custom FWS logo for fastfetch with color configuration
- Improve error messages and user feedback

This enables flexible build variants and streamlines the build process.
2026-06-23 11:02:41 +02:00
nocode 7d6bba42b2 feat(anaconda): add hostname field to user spoke and fix keyboard layout by territory
Replace keyboard correction logic in kickstart with anaconda package patches:

- Add "Nom de machine" (hostname) field to the User spoke in anaconda GUI
- user.py writes the hostname value to /tmp/fws-hostname for the kickstart %post
- Simplify kickstart to read from /tmp/fws-hostname instead of live hostname
- Fix keyboard layout selection to use full locale (e.g. fr_CH) instead of just language (fr)
  to correctly derive territory-specific keymaps (ch(fr) for Switzerland, not fr for France)
- Remove outdated fix_keyboard() function from kickstart

Also add --network=host flag to podman run in setup-aur.sh to ensure DNS and internet
connectivity through the host stack instead of the bridge (fixes timeout issues on
certain networks with firewalld/NAT).

Bump anaconda pkgrel from 2 to 4.
2026-06-23 10:48:32 +02:00
nocode 1184ba17d9 fix(releng): correct hostname and keyboard mapping in anaconda post-installation
Fix two bugs in the anaconda post-installation script:

1. Hostname handling: Anaconda writes an empty /etc/hostname to the target system. Now we preserve the hostname set during installation from the live environment, falling back to 'fws' if using default values.

2. Keyboard mapping: Anaconda derives keyboard layout from language only, ignoring territory. For locales with territory variants (e.g., fr_CH for Switzerland), we now apply territory-specific keyboard maps to both console (vconsole.conf) and X11 (xorg.conf.d) using langtable for proper mapping.
2026-06-23 08:40:42 +02:00
nocode d25ab9b4da fix(build): add --network=host to podman run commands for dns connectivity
Add --network=host flag to podman run commands in both build.sh and build-offi.sh to fix DNS resolution issues.

The podman bridge network was unable to route to external hosts on certain wifi networks due to firewalld/NAT misconfiguration after network changes, resulting in "core.db: Resolving timed out" errors. By sharing the host's network stack, the container inherits the same network connectivity including DNS resolution via 127.0.0.53/systemd-resolved that is available on the host.
2026-06-23 08:06:53 +02:00
nocode 2c9e4e6260 feat(anaconda): improve installation process and post-install handling
- Add kernel copy step in %pre to ensure vmlinuz-linux is available for mkinitcpio
- Refactor xinitrc post-install log detection to use /tmp/fws-post-chroot.log copied by kickstart
- Add success detection based on mkinitcpio and grub-install log markers
- Display success screen and poweroff on successful installation, show debug logs on failure
- Add load_policy and setstatus stub scripts to suppress SELinux-related Anaconda warnings
- Force MBR partition table (--disklabel=msdos) for BIOS boot compatibility
- Create standard mkinitcpio preset to replace archiso-specific configuration
- Automatically inject lvm2 hook when root is on LVM
- Fix GRUB installation to properly extract disk path from lsblk output
- Downgrade version to 0.5.3 (development/testing release)
2026-06-22 15:04:41 +02:00
nocode 9e3cca8efc fix(installer): improve bootloader installation and debug logging
- Add fallback GRUB installation for UEFI systems using --removable flag to ensure boot without NVRAM entries
- Fix BIOS disk detection for LVM root partitions by using lsblk with proper filtering instead of pkname
- Enhance debug logging to include %post chroot phase logs (fws-post.log) which indicate bootloader success
- Automatically mount and retrieve installation logs from the installed disk to verify bootloader installation
- Add detailed comments explaining UEFI/BIOS fallback strategies and LVM-aware disk detection

These changes ensure the system can boot even when NVRAM entries are missing or forgotten by firmware, and provide better visibility into bootloader installation success during the debug phase.
2026-06-19 15:44:18 +02:00
nocode fd3c2c998c chore(releng): add disk cleanup commands to anaconda kickstart
Add zerombr and clearpart commands to ensure clean disk state before installation.

This prevents issues when reinstalling on previously partitioned disks by:
- Reinitializing invalid partition tables (zerombr)
- Removing all partitions from all disks (clearpart --all)
- Writing a fresh disk label (--initlabel)

This makes reinstallation reliable even on disks with previous installations,
while allowing users to override defaults via the GUI if needed.
2026-06-18 18:41:38 +02:00
nocode e76db05206 feat(baseline): add grub2 symlinks for compatibility
Add symbolic links for grub2 commands that point to their grub equivalents. This provides compatibility for systems expecting grub2 command names.

Symlinks created:
- grub2-editenv -> grub-editenv
- grub2-install -> grub-install
- grub2-mkconfig -> grub-mkconfig
- grub2-mkpasswd-pbkdf2 -> grub-mkpasswd-pbkdf2
- grub2-set-default -> grub-set-default
2026-06-17 23:42:19 +02:00
nocode ee7a5fdaab feat(baseline): add locale generation and rootfs mounting infrastructure
Add locale configuration, systemd service for rootfs mounting, and customization script:

- Add locale.gen to generate en_US.UTF-8 locale required by Anaconda
- Add fws-rootfsbase.service to expose squashfs as /run/rootfsbase for Anaconda LiveOS payload detection
- Add customize_airootfs.sh to run locale-gen during image build
- Add python-iso639 0.1.4 PKGBUILD (local package with correct find() API)
- Add python-langtable 0.0.71 PKGBUILD (local package with list_common_languages())
- Remove python-iso639 and python-langtable from AUR packages due to version/API incompatibilities
- Update LOCAL_BUILD_ORDER to include new local packages
2026-06-17 23:32:46 +02:00
nocode a4e46a4309 feat(anaconda): add python-crypt_r and ostree dependencies for python 3.13+ compatibility
Add python-crypt_r PKGBUILD to provide the crypt module removed in Python 3.13 (PEP 594), required by pyanaconda/core/users.py for password hashing.

Add python-legacy-cgi for the cgi module also removed in Python 3.13, required by python-requests-ftp imported by pyanaconda/core/util.py.

Add ostree to provide the OSTree-1.0 GI namespace required by pyanaconda/rescue.py for the rpm_ostree payload.

Add libblockdev LVM CLI mode configuration to avoid DBus dependency issues with lvmdbusd unavailable in Arch.

Update setup-aur.sh to include python-crypt_r in the local build order before python-meh.
2026-06-17 18:35:12 +02:00
nocode 92bae9e4a6 feat(anaconda): integrate anaconda installer with openbox and add licensing documentation
Add Anaconda installer integration to FWS live environment:

- Implement Anaconda launcher in .xinitrc with comprehensive error logging and debugging support
- Add anaconda and anaconda-widgets packages to baseline and releng ISO configs
- Fix anaconda-widgets PKGBUILD: replace gladeui with glib2-devel, disable Glade module
- Update anaconda PKGBUILD with improved dependencies and build configuration
- Add python-blivet PKGBUILD with detailed dependency documentation

Enhance documentation and branding:

- Expand AUTHORS.rst to clarify FWS vs archiso authorship and licensing
- Update CONTRIBUTING.rst with inbound=outbound licensing policy and DCO requirements
- Extend README.md with comprehensive legal basis table and licensing checklist
- Remove Arch Linux references from MOTD and update to FWS GitHub project page
- Fix fastfetch.sh to avoid read-only variable conflict in zsh
- Add xterm to packages for installer debugging

All changes maintain GPL-3.0-or-later compliance and improve GPL offer transparency.
2026-06-17 15:45:15 +02:00
nocode 43c1053bd7 docs: add licensing and compliance documentation
Add comprehensive FOSS compliance documentation including:
- COPYRIGHT.md: copyright holders and code ownership
- LICENSING.md: GPL-3.0-or-later policy and source offer
- NOTICE: attribution requirements for permissive licenses
- THIRD-PARTY-LICENSES.md: third-party software inventory
- TRADEMARKS.md: trademark notices and non-affiliation
- os-release hook and files: identify FWS as separate from Arch Linux

These documents establish legal compliance baseline for GPL/AGPL/Apache/MIT/BSD obligations before public distribution.
2026-06-17 15:18:39 +02:00
nocode 3f83316fa8 fix(setup-aur): fix variable expansion order in build_or_skip function
Fixed a bash variable expansion bug where $name was being referenced before assignment in a multi-variable local declaration. Changed d assignment to use $1 directly instead of $name to ensure the correct directory path is set. This prevents PKGBUILD lookup failures when processing dependent packages in AUR chains.
2026-06-17 13:42:08 +02:00
nocode fc62c7e9c2 refactor(setup-aur): implement incremental build system for AUR and local packages
Replace the full rebuild approach with an incremental system that skips packages already present in local-repo at the same version. This provides significant performance improvement when iterating on individual packages.

Key changes:
- Add helper functions: pkgbuild_fullver(), repo_has(), publish_to_repo(), and build_or_skip()
- Use shallow git clones (--depth=1) for AUR packages to reduce download time
- Skip package builds if already present in local-repo with matching version
- Always install packages to resolve inter-package dependencies (AUR→AUR chains, anaconda, etc.)
- Consolidate local PKGBUILD building with the new incremental system
- Regenerate only the repo database instead of copying all packages each run
- Update step 4 to regenerate repo database from existing packages in local-repo
2026-06-17 13:21:52 +02:00
nocode 4473f0eee7 feat(pkgbuild): add anaconda and anaconda-widgets packages with dependency ordering
Add PKGBUILD files for anaconda (45.8) and anaconda-widgets (45.8) to support Fedora's Anaconda installer ported to Arch for FWS with liveimg payload.

anaconda-widgets:
- GTK3 UI widgets with GObject introspection
- Extracted from anaconda source as autonomous autotools project
- Versioned on anaconda release

anaconda:
- Main installer with comprehensive dependency set
- Includes note that further iteration needed on real Arch for buildtime deps and Fedora-specific paths
- Removes widgets files (provided by anaconda-widgets package)

Update setup-aur.sh to build local packages in proper dependency order:
- Define LOCAL_BUILD_ORDER array to ensure leaf packages build first
- anaconda builds last (depends on all other local packages)
- Extract build logic into build_local_pkg function
- Fallback to alphabetical scan for future unlisted packages
- This prevents makepkg -s failures when deps are not yet installed
2026-06-17 11:24:10 +02:00
nocode c6f066b0d9 feat(pkgbuilds): add anaconda dependencies packaging
Add PKGBUILD files for four Anaconda installer dependencies:
- pykickstart: Kickstart language parser (>= 3.73)
- python-blivet: Storage management abstraction layer
- python-productmd: OS product metadata parsers
- python-requests-file: file:// URL transport adapter for requests

These packages are required by rhinstaller but absent from Arch repos and AUR.
All use manual module installation to avoid unnecessary build dependencies.

Also fix .gitignore by removing pkgbuilds/ exclusion to allow tracking these new packages.
2026-06-17 11:15:53 +02:00
nocode 2420bf2404 feat(build): add podman container support for non-arch linux distributions
Add automatic detection and relaunching of build scripts in an Arch Linux container via podman when running on non-Arch distributions (Fedora, Ubuntu, Debian, etc.).

Key changes:
- Implement host_is_arch() function to detect if running on Arch Linux by checking both pacman availability and /etc/os-release
- When non-Arch host is detected, scripts automatically pull docker.io/library/archlinux:latest and relaunch themselves in rootful podman container with --privileged
- Mount repository at same absolute path inside container so WORK_DIR and out/ directories work transparently
- Set up persistent pacman cache volume (fws-pacman-cache) between runs
- Auto-chown output files back to host user after build completes
- Update pacman config to disable landlock sandbox in containers (similar to WSL workaround)
- Run full pacman -Syu upgrade in container before installing archiso to avoid partial upgrade issues
- Add comprehensive documentation in README about Fedora/non-Arch setup
- Update .gitignore to exclude pkgbuilds/ directory
- Add environnement.md documentation file
2026-06-17 11:05:59 +02:00
nocode de9647a00d chore: migrate from calamares to anaconda installer
Remove Calamares compilation and configuration, replace with Anaconda installer setup.

Changes:
- Remove Calamares-related entries from .gitignore
- Update README with migration status from Calamares to Anaconda
- Rename setup-calamares.sh references to setup-aur.sh
- Remove Calamares packages from package lists
- Add anaconda and liveimg payload packages
- Add Anaconda kickstart configuration (interactive-defaults.ks)
- Update boot sequence documentation: remove Calamares desktop selection, simplify to Openbox live environment
- Remove Calamares-specific troubleshooting entries
- Clean up .xinitrc and .zlogin to remove Calamares launcher
- Update build scripts to reference local repo generically instead of Calamares-specific
2026-06-17 10:33:28 +02:00
nocode c412cd5d33 feat(Anaconda): Local Repo 2026-06-13 02:06:34 +02:00
nocode 05ae9c36c3 refactor(Anaconda)! : Changing the installator to Anaconda
'cause Calamares is a way to difficult for what we want and we want to try something else
2026-06-12 23:31:35 +02:00
nocode 98d47d497c fix(Calamares): Installater will ask the desktop env before the calamares install
- The installer is still W.I.P
2026-06-04 23:30:33 +02:00
nocode a7a5055ee8 fix(Multi-Desktop Hyperland): Fix some bugs of hyperland 2026-05-28 22:42:57 +02:00
nocode 1fa2c72ef7 refactor(INSTALLATION MD): Explain the installation precisly 2026-05-28 22:41:32 +02:00
nocode 0d26227169 docs(ENV): Explain the environnement needed to build the .ISO 2026-05-28 22:40:24 +02:00
nocode 241bd5c219 fix(Installer ─ Multi-Desktop): Fix Multi Desktop 2026-05-28 18:00:25 +02:00
nocode 40fd289a9f docs(ReadMe): Refactor of the ReadMe.MD 2026-05-28 01:03:30 +02:00
nocode d1198b9d04 chore(Installer-MultiDesktop): Save to be able to work somewhere else 2026-05-28 00:41:11 +02:00
nocode c629e0f196 fix(Installer-MultiDesktop): Fix the Multi Desktop Env you can now choose and use a desktop environnement 2026-05-27 23:21:53 +02:00
nocode f6ee07429b feat(Installer): Add Multi Desktop environnement in the installer to allow the user to choose wich desktop env 2026-05-27 19:22:42 +02:00
BlackAngelTV a9d4b9ac91 feat: multi environnemnt desktop
[180][WIP]
2026-05-27 16:02:05 +02:00
BlackAngelTV d5e0069889 feat: install and Xfce
[50][DONE]
2026-05-27 10:21:41 +02:00
nocode 0fb4c1bf5c fix(Installer): fix the whole installer now its finishing the installation 2026-05-26 23:48:54 +02:00
354 changed files with 31499 additions and 1413 deletions
-4
View File
@@ -2,7 +2,3 @@ out/
local-repo/
configs/baseline/airootfs/etc/systemd/system/multi-user.target.wants/
configs/releng/airootfs/etc/systemd/system/multi-user.target.wants/
configs/baseline/airootfs/usr/lib/
configs/baseline/airootfs/usr/bin/
configs/baseline/airootfs/usr/include/
configs/baseline/airootfs/usr/share/calamares/branding/default/
+16 -1
View File
@@ -1,7 +1,22 @@
===============
=======
Authors
=======
FWS
===
FWS is a fork of archiso. The FWS-specific work (build chain, installer
integration, package recipes under ``pkgbuilds/``) is © the FWS contributors,
distributed under ``GPL-3.0-or-later`` (see ``COPYRIGHT.md``).
* FWS contributors <suzuku295@gmail.com>
Archiso Authors
===============
The build system (``mkarchiso``, profiles, man pages) derives from archiso and
retains the authorship of its original contributors:
* 2hexed <2hexed@protonmail.com>
* Aaron Griffin <aaron@archlinux.org>
* Adam Purkrt <adam@purkrt.net>
+31 -2
View File
@@ -2,15 +2,35 @@
Changelog
#########
[XX] - YYYY-MM-DD
=================
[0.6.0] - 2026-07-07
====================
Added
-----
- **Installateur Anaconda 45 porté sur Arch** (payload LiveOS) : page « Récapitulatif avant installation » avec bouton
Précédent, choix du bureau intégré (GNOME, KDE, XFCE, Hyprland, i3, CLI) avec compatibilité VR affichée, splash de
préparation alimenté en direct par les logs (diagnostic automatique en cas de blocage), garde-fou RAM (< 2 Go),
mécanisme de retry réseau pour l'installation du bureau (``fws-desktop-retry``).
- **Outillage FWS** : ``fws-hello`` (accueil 1er démarrage), ``fws-update`` + indicateur de mises à jour,
``fws-keys`` (raccourcis réels), ``fws-powermenu``, ``fws-about``, ``fws-vr-setup`` (SteamVR/ALVR/Monado),
``fws-proton-ge``, ``fws-setup-hardware`` (drivers GPU/VM/audio/Bluetooth), ``fws-dnd``.
- **Récupération système** (« point de restauration ») : application GTK ``fws-recovery-gui`` + moteur ``fws-recovery``
(GRUB, initramfs, pacman, chroot), accessible depuis le live (entrée de boot), le menu GRUB du système installé
(``fws-recovery.target``) et son menu d'applications (élévation polkit).
- **Swap zram** sur le live et le système installé (``zram-generator``).
- **firewalld** activé par défaut sur le système installé.
- Bureaux Hyprland et i3 à parité visuelle (waybar/polybar, wofi/rofi, Catppuccin Mocha), thème SDDM « fws »,
bannière GDM.
Changed
-------
- **Branding FWS complet** : l'installateur s'annonce « FWS 0.6 » (variables ``ANACONDA_PRODUCT*``), splash FWS au menu
de boot BIOS (l'image Arch d'archiso est remplacée), ``/etc/issue`` sans version de noyau, filtres d'affichage
Fedora/Arch sur le splash et le journal de récupération.
- Toutes les entrées de boot plafonnent les workers udev bloqués (``udev.event_timeout=45``) ; le menu BIOS démarre
explicitement l'entrée FWS (``DEFAULT fws``).
- Use xz compression for the baseline profile's bootstrap tarball so that it has more differences when compared to the
releng profile.
- Match network interfaces by their type, instead of name, in systemd-networkd configuration.
@@ -21,12 +41,21 @@ Deprecated
Fixed
-----
- Watchdog du splash qui affichait son diagnostic PAR-DESSUS l'installateur (il se désarme désormais dès que la GUI
d'anaconda est à l'écran, et mesure l'inactivité en itérations — insensible aux sauts d'horloge des VM).
- Gel de l'installateur sur machines à faible RAM (1 Go) : zram + avertissement préalable.
- Profils ``baseline``/``releng`` synchronisés (la fusion baseline-écrase-releng avait fait perdre ``firewalld``,
le cap udev et les entrées de boot FWS d'ISO précédentes).
- DNS du système installé (NetworkManager + systemd-resolved), hook ``lvm2`` dans l'initramfs, GRUB de secours
``--removable`` en UEFI.
- Use ``systemd-run`` to invoke ``curl`` with a transient service that depends on ``network-online.target`` since no
services are currently pulling in ``network_online.target``.
Removed
-------
- ``configs/baseline/syslinux/syslinux-linux.cfg`` (label ``arch`` stock, orphelin et sans cap udev).
[87] - 2025-10-29
=================
+23 -2
View File
@@ -2,8 +2,29 @@
Contributing
============
These are the contribution guidelines for archiso.
All contributions fall under the terms of the GPL-3.0-or-later (see `LICENSE <LICENSE>`_).
These are the contribution guidelines for **FWS**. FWS is a fork of `archiso
<https://gitlab.archlinux.org/archlinux/archiso>`_; the build-system parts
derived from archiso retain their original history and authorship (see
`AUTHORS.rst <AUTHORS.rst>`_).
Licensing of contributions (inbound = outbound)
===============================================
All contributions are accepted under the **same license as the project**,
``GPL-3.0-or-later`` (see `LICENSE <LICENSE>`_). By submitting a contribution you
agree that it is licensed under ``GPL-3.0-or-later`` and that you have the right
to submit it under that license.
Sign off every commit to certify the `Developer Certificate of Origin 1.1
<https://developercertificate.org/>`_:
.. code:: bash
git commit --signoff # adds a "Signed-off-by: Name <email>" trailer
For the full licensing, third-party and trademark picture, see `LICENSING.md
<LICENSING.md>`_, `THIRD-PARTY-LICENSES.md <THIRD-PARTY-LICENSES.md>`_ and
`TRADEMARKS.md <TRADEMARKS.md>`_.
Editorconfig
============
+59
View File
@@ -0,0 +1,59 @@
# Droits d'auteur — FWS
`SPDX-License-Identifier: GPL-3.0-or-later`
FWS est une distribution Linux live/installable dérivée d'**Arch Linux**, dont le
système de construction est un fork d'**archiso**. Ce fichier identifie les
titulaires de droits sur le code **du dépôt** ; les logiciels **embarqués**
(Anaconda, paquets Python, paquets Arch de l'ISO…) restent la propriété de leurs
auteurs respectifs — voir [THIRD-PARTY-LICENSES.md](THIRD-PARTY-LICENSES.md).
## Code du dépôt (système de build FWS)
```
Copyright (C) 2026 Contributeurs FWS (« FWS contributors »)
Copyright (C) Arch Linux / Archiso Authors — voir AUTHORS.rst
```
Sont couverts par les droits FWS, sous **GPL-3.0-or-later** :
- les scripts de construction (`build.sh`, `build-offi.sh`, `setup-aur.sh`,
`scripts/`) ;
- les profils et overlays `configs/baseline/` et `configs/releng/` modifiés
par FWS ;
- les recettes de paquets `pkgbuilds/*/PKGBUILD` rédigées ou adaptées par FWS ;
- la documentation FWS (`README.md`, `environnement.md`, `docs/`).
Sont des œuvres d'**archiso** (Arch Linux), conservées sous **GPL-3.0-or-later** :
- `fws/mkarchiso`, `Makefile`, `man/`, `CHANGELOG.rst` et la structure de
profil héritée. Les auteurs originaux sont listés dans [AUTHORS.rst](AUTHORS.rst).
## Titulaire / entité
Le titulaire collectif est désigné ici par « Contributeurs FWS ». Si le projet
adopte une personne morale (association, société) ou un mainteneur nommé comme
titulaire de référence, remplacer « Contributeurs FWS » par cette entité dans
ce fichier et dans les en-têtes SPDX.
## Marques
Les noms et logos cités (Arch Linux, Red Hat, Fedora, Anaconda, Windows…) sont
des marques de leurs détenteurs respectifs. Voir [TRADEMARKS.md](TRADEMARKS.md).
## Résumé des licences
| Élément | Licence |
|---|---|
| Code du dépôt FWS (build, configs, PKGBUILDs, docs) | `GPL-3.0-or-later` |
| Texte de licence intégral | [LICENSE](LICENSE) |
| Logiciels tiers embarqués | licences propres — [THIRD-PARTY-LICENSES.md](THIRD-PARTY-LICENSES.md) |
| Attributions Apache/MIT/BSD | [NOTICE](NOTICE) |
| Politique de licences & obtention des sources | [LICENSING.md](LICENSING.md) |
| Marques & non-affiliation | [TRADEMARKS.md](TRADEMARKS.md) |
> **Avertissement.** Ces documents constituent une base de conformité FOSS
> sérieuse et de bonne foi, mais ne sont pas un avis juridique. Avant toute
> diffusion publique large ou commerciale, faites-les valider par un conseil
> spécialisé en propriété intellectuelle / open source — en particulier les
> points signalés ⚠ dans [THIRD-PARTY-LICENSES.md](THIRD-PARTY-LICENSES.md).
+103
View File
@@ -0,0 +1,103 @@
# Politique de licences & obtention des sources — FWS
`SPDX-License-Identifier: GPL-3.0-or-later`
## 1. Licence du projet
Le code du dépôt FWS (système de build, profils, overlays, PKGBUILD et docs
rédigés par FWS) est distribué sous **GNU General Public License v3.0 ou
ultérieure** (`GPL-3.0-or-later`). Cette licence est **héritée d'archiso**, dont
FWS est un fork : une œuvre dérivée d'archiso (GPL-3.0-or-later) ne peut être
redistribuée que sous GPL-3.0-or-later.
Texte intégral : [LICENSE](LICENSE).
Périmètre exact (couvert / hérité) : voir [COPYRIGHT.md](COPYRIGHT.md).
Logiciels embarqués (licences distinctes) : voir
[THIRD-PARTY-LICENSES.md](THIRD-PARTY-LICENSES.md).
## 2. En-têtes SPDX (recommandation)
Pour une traçabilité « béton », ajouter en tête de chaque fichier source rédigé
par FWS :
```sh
# SPDX-License-Identifier: GPL-3.0-or-later
# SPDX-FileCopyrightText: 2026 Contributeurs FWS
```
(Les fichiers hérités d'archiso conservent leurs en-têtes d'origine.)
## 3. Obligation de fourniture des sources (GPL/LGPL)
FWS distribue des **binaires** couverts par la GPL/LGPL/AGPL : l'ISO
(`out/FWS-*.iso`) et les paquets (`local-repo/*.pkg.tar.zst`). La GPL impose de
fournir la **source correspondante** de ces binaires.
Pour FWS, la source correspondante est :
1. **le présent dépôt** (système de build, profils, recettes `pkgbuilds/`), et
2. **les tarballs amont** référencés par `source=()` dans chaque PKGBUILD
(téléchargés à l'identique depuis les URL listées dans
[THIRD-PARTY-LICENSES.md](THIRD-PARTY-LICENSES.md)), et
3. pour les paquets Arch agrégés dans l'ISO, **les sources publiées par Arch
Linux** pour chaque paquet (`pkgctl`/dépôts amont Arch).
### Offre écrite (GPLv3 §6 / GPLv2 §3b)
> Pour tout binaire couvert par la GPL/LGPL distribué dans une image ou un paquet
> FWS, le projet FWS s'engage à fournir, sur demande et pour une durée d'au moins
> trois (3) ans, la source correspondante complète sous une forme lisible par
> machine, soit via le dépôt public du projet, soit sur un support physique au
> coût de distribution.
>
> - **Dépôt public (source) :** https://github.com/You-re-like-Windows-a-bitch/fws
> - **Contact :** suzuku295@gmail.com
>
> *« FWS offers, for any GPL/LGPL-covered binary it distributes, to provide the
> complete corresponding source code, for at least three years, via the project
> repository (https://github.com/You-re-like-Windows-a-bitch/fws) or on physical
> media at cost. Contact: suzuku295@gmail.com. »*
> **Condition d'effectivité :** l'offre n'est réellement opposable que si le dépôt
> ci-dessus est **publiquement accessible** et contient `pkgbuilds/` (recettes +
> URL `source=()`). Tant que le dépôt reste privé, publier au minimum les sources
> correspondantes des binaires diffusés.
## 4. Reproductibilité
Le build honore `SOURCE_DATE_EPOCH` (cf. `profiledef.sh`, horodatages d'ISO et
de label) pour des reconstructions déterministes — utile pour prouver la
correspondance source/binaire.
## 5. Contributions
Les contributions entrantes sont acceptées sous la **même** licence que le
projet (« inbound = outbound », `GPL-3.0-or-later`), avec attestation d'origine
**DCO**. Voir [CONTRIBUTING.rst](CONTRIBUTING.rst).
## 6. Liste de contrôle conformité (avant release publique)
- [x] `LICENSE` (GPL-3.0-or-later) présent à la racine
- [x] `COPYRIGHT.md`, `NOTICE`, `THIRD-PARTY-LICENSES.md`, `TRADEMARKS.md` rédigés
- [x] Offre écrite §3 complétée avec URL (dépôt) + contact e-mail
- [x] `os-release` FWS livré — hook `zz-fws-os-release.hook` (le live ne s'annonce
plus « Arch Linux ») ; `motd` ne renvoie plus vers `archlinux.org`
- [ ] **Dépôt rendu publiquement accessible** (sinon l'offre écrite n'est pas
opposable) — action hors-code
- [x] Branding Red Hat/Fedora retiré de l'UI Anaconda : nom de produit **FWS**
via les variables `ANACONDA_PRODUCTNAME`/`ANACONDA_PRODUCTVERSION`
(exportées par le `.xinitrc` du live, lues depuis l'os-release FWS —
l'en-tête affiche « FWS 0.6 INSTALLATION ») ; visuel **Arch** du menu de
boot BIOS remplacé par un splash FWS ; le caractère « version modifiée
d'Anaconda » reste documenté ici et dans TRADEMARKS.md
- [ ] Décision tranchée sur `python-iso639` (AGPL-3.0-only) : garder ou remplacer
- [ ] Revue par un conseil FOSS (recommandé avant diffusion commerciale)
> Les étiquettes `license=` des PKGBUILD **présents dans `pkgbuilds/`** sont déjà
> en SPDX exact. Les libellés imprécis relevés (`satyr` → `GPL`, `python-pid` →
> `Apache`…) concernent des paquets de `local-repo/` **sans PKGBUILD dans ce
> dépôt** (construits depuis l'AUR) : à corriger à la source AUR, pas ici.
> **Ceci n'est pas un avis juridique.** Base de conformité de bonne foi au
> 2026-07-07.
+58
View File
@@ -0,0 +1,58 @@
FWS — Avis d'attribution / Attribution NOTICE
=============================================
FWS (« FWS contributors »), 2026.
Distribution Linux dérivée d'Arch Linux ; système de build dérivé d'archiso.
Ce fichier regroupe les attributions exigées par les licences permissives
(Apache-2.0, MIT, BSD) des composants redistribués par FWS. Il complète :
- LICENSE — GPL-3.0-or-later (projet)
- COPYRIGHT.md — droits d'auteur du dépôt
- THIRD-PARTY-LICENSES.md — inventaire complet & compatibilité
- TRADEMARKS.md — marques & non-affiliation
L'absence d'un composant ici ne vaut pas absence d'obligation : voir
THIRD-PARTY-LICENSES.md pour l'inventaire exhaustif et les avis GPL/LGPL/AGPL
(préservés dans /usr/share/licenses/<paquet>/ sur le système).
-----------------------------------------------------------------------
Base du dépôt
-----------------------------------------------------------------------
archiso — Copyright (C) Arch Linux / Archiso Authors (voir AUTHORS.rst)
GPL-3.0-or-later — https://gitlab.archlinux.org/archlinux/archiso
-----------------------------------------------------------------------
Composants sous Apache-2.0
(Apache-2.0 §4 : conservation des avis de droit d'auteur et de licence ;
ce NOTICE accompagne les œuvres redistribuées.)
-----------------------------------------------------------------------
requests-file (python-requests-file) — Copyright (C) David Shea
https://github.com/dashea/requests-file
requests-ftp (python-requests-ftp) — Copyright (C) Cory Benfield
https://github.com/Lukasa/requests-ftp
pid (python-pid) — Copyright (C) trbs and contributors
https://github.com/trbs/pid
-----------------------------------------------------------------------
Composants sous MIT
-----------------------------------------------------------------------
python-xkbregistry — Copyright (C) Stephen Early
https://github.com/sde1000/python-xkbregistry
WinBoat (winboat-bin) — Copyright (C) WinBoat authors (TibixDev)
https://www.winboat.app
langtable (python-langtable, partie MIT) — Copyright (C) Mike FABIAN
https://github.com/mike-fabian/langtable
-----------------------------------------------------------------------
Composants sous licence permissive de type BSD / custom
-----------------------------------------------------------------------
xmlrpc-c (libxmlrpc) — Copyright (C) les auteurs de xmlrpc-c
Licence permissive de type BSD (« custom ») — voir le source amont
https://xmlrpc-c.sourceforge.net/
-----------------------------------------------------------------------
Marques
-----------------------------------------------------------------------
Arch Linux, Red Hat, Fedora, Anaconda, Windows, Microsoft, GNOME, KDE,
Plasma, Xfce, Hyprland, GTK, Linux et WinBoat sont des marques de leurs
détenteurs respectifs. FWS n'est affilié à aucun d'eux. Voir TRADEMARKS.md.
+309 -48
View File
@@ -1,85 +1,331 @@
# FWS
**FWS** est une distribution Linux live/installable basée sur **Arch Linux**, livrée sous forme d'ISO bootable BIOS/UEFI avec l'installeur graphique **Calamares** lancé automatiquement au démarrage.
**FWS** est une distribution Linux live/installable basée sur **Arch Linux**, pensée pour **remplacer Windows** : bureau prêt à l'emploi, jeux (Steam/Proton-GE), réalité virtuelle (SteamVR), compatibilité applicative (winboat/Wine) et outillage de maintenance intégré. L'installateur graphique est **Anaconda** (celui de Fedora/RHEL), **porté sur Arch** : payload LiveOS (copie du live sur le disque), spokes FWS (choix du bureau, récapitulatif avant installation), finalisation pacman/GRUB/mkinitcpio en `%post`.
Le projet est construit avec une chaîne `mkarchiso` adaptée pour fonctionner **depuis Windows via WSL** (Git Bash → WSL Arch), sans nécessiter de machine Linux dédiée.
Le projet est conçu pour être **construit depuis Windows via WSL** (les scripts détectent Git Bash et basculent automatiquement dans WSL), mais fonctionne aussi directement depuis une **Arch Linux native** ou depuis **toute distribution non-Arch (Fedora, Ubuntu…) via une bascule automatique dans un conteneur Arch podman**.
---
## Aperçu
- **Base** : Arch Linux (rolling release)
- **Installeur** : Calamares (compilé depuis l'AUR, servi via un repo local pacman)
- **Affichage live** : Xorg + Openbox, lancement automatique de Calamares
- **Boot** : BIOS (syslinux) + UEFI (systemd-boot)
- **Installateur** : **Anaconda 45 porté sur Arch** — payload LiveOS (installe FWS, pas Fedora), page « Récapitulatif avant installation » avec bouton Précédent, choix du bureau intégré, **brandé FWS** (en-tête « FWS 0.6 INSTALLATION », via les variables `ANACONDA_PRODUCT*` exportées par le `.xinitrc`)
- **Affichage live** : Xorg + Openbox + splash de préparation qui montre l'activité réelle d'anaconda (dernier log actif + chrono ; si rien ne bouge avant l'apparition de l'installateur, il le dit puis affiche un diagnostic complet — le watchdog se désarme dès que la GUI est à l'écran)
- **Mémoire** : **4 Go recommandés** pour installer (2 Go minimum — swap **zram** intégré au live ET au système installé ; sous 2 Go le live avertit, à 1 Go sans zram l'installateur graphique gèle)
- **Bureaux installables** : GNOME, KDE Plasma, XFCE, **Hyprland** (Wayland — non compatible VR), **i3** (X11 — compatible VR/SteamVR), ou ligne de commande seule
- **Boot** : UEFI (systemd-boot) + BIOS (syslinux, splash **FWS**, `DEFAULT fws`) — entrées *normale*, *safe graphics (nomodeset)*, *Réparer FWS (recovery)* et *speech*
- **Récupération** : accessible depuis le live (entrée de boot), depuis le **menu GRUB du système installé** (« Réparer FWS ») et depuis son **menu d'applications** (« Récupération FWS », élévation polkit)
- **Compression** : squashfs (xz)
- **Build** : Windows + WSL (Arch) ou directement depuis Arch
## Prérequis
---
### Côté Windows
- Windows 10/11
- WSL 2 avec une distribution **Arch Linux** installée (`Arch`, `ArchLinux`, `ArchWSL`…)
- Git Bash (pour exécuter les scripts depuis Windows)
## Ce qu'il y a dans FWS
### Côté Arch (WSL ou natif)
Les scripts installent automatiquement les paquets nécessaires (`archiso`, `base-devel`, `git`, `reflector`, `dos2unix`).
### À l'installation
- **Choix du bureau** dans Anaconda, avec compatibilité VR affichée (i3 = SteamVR ✔ ; Hyprland = ✘)
- **Page récapitulative** avant toute écriture disque : config choisie (langue, clavier, fuseau, comptes, partitionnement, bureau, nom de machine) + matériel détecté (GPU, disques, virtualisation, réseau)
- **Automatique en fin d'install** : drivers GPU (NVIDIA/AMD/Intel), outils invité VM (VMware/VirtualBox/QEMU/Hyper-V), PipeWire + pavucontrol, Bluetooth (BlueZ + blueman), luminosité (brightnessctl), **pare-feu firewalld activé**, Steam + Wine + Monado + MangoHud + gamemode, clavier/locale, hostname, sudo pour l'utilisateur créé, branding FWS
## Démarrage rapide
### Sur le système installé (outillage `fws-*`)
| Commande | Rôle | Accès |
|---|---|---|
| `fws-hello` | Bienvenue au 1er démarrage (mise à jour, codecs, Proton-GE, VR, raccourcis) | auto au 1er login |
| `fws-update` | Mise à jour complète (pacman + cache + orphelins + flatpak) | bouton 󰚰 de la barre |
| `fws-keys` | Panneau des **raccourcis clavier réels** (lit la config Hyprland/i3) | `Super+K`, bouton ⌨ |
| `fws-powermenu` | Verrouiller / déconnexion / suspendre / redémarrer / éteindre | `Super+X`, bouton 󰐥 |
| `fws-about` | « À propos » : le projet FWS + infos système | menu d'applications |
| `fws-vr-setup` | Drivers/runtimes VR (Vive/Index → SteamVR natif ; Quest → ALVR ; Monado) | `Super+Shift+V` (i3), menu |
| `fws-proton-ge` | Installe/actualise Proton-GE pour Steam (vérif sha512) | fws-hello, terminal |
| `fws-recovery` | **Application GTK de réparation** : GRUB, initramfs, pacman, terminal chroot (moteur bash + repli console) | menu « Récupération FWS » de l'OS installé, entrée GRUB « Réparer FWS », entrée de boot du live |
### Hyprland & i3 : parité visuelle
Même identité Catppuccin Mocha (nuances de bleu) sur les deux : barre flottante arrondie (**waybar** / **polybar**) avec date+heure, indicateur de mises à jour, volume/réseau/CPU/RAM/luminosité/Bluetooth cliquables ; menus assortis (**wofi** / **rofi**) ; mêmes raccourcis (déclarés avec descriptions → `Super+K`) ; **Dolphin** en gestionnaire de fichiers ; thème **SDDM « fws »** maison (pur QtQuick, accent adapté au bureau ; GNOME garde GDM avec bannière FWS).
---
## Environnement requis — INSTALLATION ULTRA PRÉCISE
### Côté Windows (machine hôte)
| Composant | Version / état requis | Commande de vérif |
|---|---|---|
| Windows | 10 (22H2+) ou 11 | `winver` |
| WSL | **WSL 2** (pas WSL 1) | `wsl --status` |
| Virtualisation CPU | Activée dans le BIOS (VT-x / AMD-V) | Gestionnaire des tâches → Performance → CPU → "Virtualisation : Activé" |
| Git for Windows | ≥ 2.40 (fournit Git Bash) | `git --version` |
| Espace disque libre | ≥ 25 GB sur la partition WSL | — |
| RAM | ≥ 8 GB (16 GB recommandés) | — |
#### 1. Activer WSL 2
Dans **PowerShell administrateur** :
```powershell
wsl --install --no-distribution
wsl --set-default-version 2
wsl --update
```
Puis **redémarrer Windows**.
#### 2. Installer Arch Linux dans WSL
Arch n'est pas dans le store Microsoft. Installer **ArchWSL** :
```powershell
# Télécharger la dernière release
Invoke-WebRequest -Uri "https://github.com/yuk7/ArchWSL/releases/latest/download/Arch.zip" -OutFile "$env:TEMP\Arch.zip"
Expand-Archive "$env:TEMP\Arch.zip" -DestinationPath "$env:LOCALAPPDATA\ArchWSL"
& "$env:LOCALAPPDATA\ArchWSL\Arch.exe"
```
Au premier lancement, la distribution s'enregistre sous le nom **`Arch`** (ce nom est attendu par les scripts — il est paramétrable via `ARCH_WSL_DISTRO` si besoin).
Vérifier :
```powershell
wsl -l -v
# Doit afficher :
# NAME STATE VERSION
# * Arch Stopped 2
```
#### 3. Installer Git for Windows
Télécharger depuis https://git-scm.com/download/win et installer avec les options par défaut. **Git Bash** est inclus.
---
### Côté WSL Arch (préparation système)
Le **premier lancement** de la WSL ouvre une session root. Effectuer une seule fois :
```bash
# 1. Préparation : compile Calamares depuis l'AUR, crée le repo local,
# patche pacman.conf et configure les services systemd (Xorg + autostart).
./setup-calamares.sh
# 1. Initialiser le keyring (sinon pacman refuse tout install signé)
pacman-key --init
pacman-key --populate archlinux
# 2. Build de l'ISO via mkarchiso (fusionne configs/releng + configs/baseline)
# 2. Mettre à jour le keyring AVANT toute autre opération
# (les WSL fraîches ont un keyring périmé)
pacman -Sy --noconfirm archlinux-keyring
# 3. Mise à jour complète du système
pacman -Syu --noconfirm
# 4. Vérifier que /tmp est bien un tmpfs (sinon mkarchiso lent)
mount | grep '/tmp'
```
> **Note** : le script `setup-aur.sh` désactive automatiquement le sandbox landlock de pacman ≥ 7 (incompatible avec le kernel WSL) en ajoutant `DisableSandbox` dans `/etc/pacman.conf`. Tu n'as rien à faire.
---
### Côté Arch Linux native (alternative)
Si tu build depuis une vraie Arch (pas WSL) :
```bash
sudo pacman -Syu
sudo pacman -S --needed base-devel git archiso reflector dos2unix
```
Les scripts détectent l'absence de WSL et s'exécutent en local. Il faut être **root** ou avoir `sudo` configuré.
---
### Côté Fedora / Linux non-Arch (conteneur podman)
Sur une distribution **qui n'est pas Arch** (Fedora, Ubuntu, Debian…), les scripts
détectent l'hôte non-Arch et **se relancent automatiquement dans un conteneur Arch**
via podman. Tu n'as qu'à installer podman, puis lancer les scripts normalement.
```bash
# Fedora
sudo dnf install -y podman
# Debian / Ubuntu
sudo apt install -y podman
# Puis, à la racine du repo, exactement comme sur Arch :
./setup-aur.sh
./build.sh
```
L'ISO finale est générée dans `./out/`.
Détails utiles :
Les deux scripts détectent automatiquement s'ils sont lancés depuis **Git Bash** (et basculent dans WSL en root) ou directement depuis **WSL/Arch**.
- **podman rootful obligatoire** : les scripts préfixent `sudo podman` (rootless ne
gère pas les mounts/chroot de `mkarchiso`). `sudo` peut demander ton mot de passe.
- L'image utilisée est `docker.io/library/archlinux:latest`, pull explicite à chaque
run (le tag `latest` n'est pas re-résolu sinon).
- Le dépôt est monté **au même chemin absolu** dans le conteneur : l'ISO (`out/`) et
`local-repo/` reviennent directement sur l'hôte (re-`chown` automatique vers toi).
- Le cache pacman est conservé entre les runs dans le volume `fws-pacman-cache`.
- SELinux enforcing (Fedora) est géré par `--privileged` — rien à configurer.
## Structure du projet
> Pour forcer l'exécution **locale** (si tu es déjà sur Arch et que pacman est là),
> la bascule ne se déclenche pas : la détection exige `pacman` **et** un
> `ID`/`ID_LIKE` « arch » dans `/etc/os-release`.
| Chemin | Rôle |
|--------|------|
| `setup-calamares.sh` | Préparation one-shot : build Calamares (AUR), repo local, services systemd, autostart Xorg + Calamares |
| `build.sh` | Build de l'ISO via `mkarchiso` (utilisable depuis Git Bash ou WSL) |
| `configs/releng/` | Profil principal (base ArchISO releng) |
| `configs/baseline/` | Overlay FWS appliqué par-dessus `releng` (prioritaire) |
| `local-repo/` | Repo pacman local généré (Calamares + dépendances AUR) |
| `out/` | ISOs générées |
| `fws/mkarchiso` | Binaire `mkarchiso` embarqué (fork) |
---
## Séquence de boot de l'ISO
## Démarrage rapide
1. Démarrage de l'ISO FWS (BIOS ou UEFI)
2. `systemd` → autologin root sur `tty1`
3. `xorg-start.service``Xorg :0`
4. `calamares.service``DISPLAY=:0 calamares`
5. **Fallback** : si les services échouent, `.zprofile` relance Xorg + Openbox + Calamares manuellement
Depuis **Git Bash sur Windows** (à la racine du repo) :
```bash
# Étape 1 : compilation des paquets AUR (winboat) + PKGBUILD locaux
# (anaconda porté sur Arch + ses dépendances python)
# → crée local-repo/ avec les .pkg.tar.zst
./setup-aur.sh
# Étape 2 : build de l'ISO via mkarchiso
# → fusionne configs/releng + configs/baseline
# → injecte le repo local dans pacman.conf
# → sort l'ISO dans ./out/
./build.sh
```
L'ISO finale est générée dans `./out/FWS-YYYY.MM.DD-x86_64.iso`.
---
## Ce que fait `setup-aur.sh` (étape par étape)
1. **Détection environnement** : si lancé depuis Git Bash, bascule dans `wsl.exe -d Arch -u root`.
2. **Patch pacman** : désactive landlock sur WSL (`DisableSandbox`).
3. **Refresh keyring** : `pacman-key --init && --populate archlinux`, mise à jour `archlinux-keyring`.
4. **`pacman -Syu`** complet (obligatoire — sinon `makepkg` plante sur les "conflicting files" lors des splits de paquets type `gcc-libs`).
5. **Install des outils de build** : `base-devel git`.
6. **Création d'un utilisateur `fwsbuild`** non-root avec `sudo` NOPASSWD (makepkg refuse de tourner en root).
7. **Clone + build AUR** : `winboat-bin` via `makepkg -s --noconfirm`, plus les PKGBUILD locaux de `pkgbuilds/` (anaconda, anaconda-widgets, pykickstart, blivet, python-meh patché…). Le build est **incrémental** : un paquet déjà présent dans `local-repo/` à la bonne version est sauté.
8. **Création du repo local** : `repo-add local-repo/fws-local.db.tar.gz`.
9. **Cleanup** : suppression de l'utilisateur `fwsbuild`.
**Durée** : quelques minutes en incrémental ; le premier build complet (anaconda + deps) est plus long.
---
## Ce que fait `build.sh` (étape par étape)
1. **Détection environnement** : Git Bash → bascule dans WSL ; sinon exécution locale.
2. **Update miroirs** : `reflector --latest 10 --sort rate`.
3. **Install `archiso`**.
4. **Fusion configs** : `cp -ar configs/releng/* /tmp/fws-build/releng/` puis overlay `configs/baseline/*` par-dessus (baseline prioritaire).
5. **Activation NetworkManager** sur le live (symlink réel `multi-user.target.wants/`).
6. **Injection du repo local** : ajoute `[fws-local]` (`SigLevel = Optional TrustAll`) en tête de `pacman.conf`.
7. **`dos2unix`** sur l'arborescence (au cas où tu as édité depuis Windows).
8. **`mkarchiso -v -w /tmp/fws-build/work -o out/ /tmp/fws-build/releng`**.
9. **Cleanup** du workdir.
**Durée** : 515 minutes selon la machine et le cache pacman.
---
## Test rapide en QEMU
```bash
./scripts/run_archiso.sh -i out/fws-*.iso # BIOS
./scripts/run_archiso.sh -u -i out/fws-*.iso # UEFI
./scripts/run_archiso.sh -i out/FWS-*.iso # BIOS
./scripts/run_archiso.sh -u -i out/FWS-*.iso # UEFI
```
---
## Structure du projet
| Chemin | Rôle |
|---|---|
| `setup-aur.sh` | Build des paquets AUR (winboat) + PKGBUILD locaux, crée `local-repo/` |
| `build.sh` | Build de l'ISO via `mkarchiso` |
| `configs/releng/` | Profil principal (base ArchISO releng) |
| `configs/baseline/` | Overlay FWS (surcharge le profil releng) — **prioritaire** sur releng |
| `local-repo/` | Repo pacman local (généré par `setup-aur.sh`) |
| `out/` | ISOs générées |
| `fws/mkarchiso` | Binaire `mkarchiso` embarqué (fork) |
| `scripts/run_archiso.sh` | Lanceur QEMU |
---
## Séquence de boot de l'ISO
1. Menu de boot : **installation** (défaut), **safe graphics** (`nomodeset`), **Réparer FWS** (`fws.recovery=1` → app GTK `fws-recovery-gui` via openbox, repli console `fws-recovery`), **speech**. Toutes les entrées plafonnent les workers udev bloqués (`udev.event_timeout=45`)
2. `systemd` → autologin root sur `tty1`
3. `.zprofile` → mode recovery si demandé, sinon `startx`
4. `.xinitrc` → Openbox + **garde-fou RAM** (avertissement sous 2 Go) + **splash « Préparation de l'installateur »** (label alimenté en direct par les logs anaconda ; à 4 min sans activité → diagnostic auto `/tmp/fws-stall.txt` ; le tout se désarme dès que la GUI d'anaconda apparaît), bind mount `/run/rootfsbase` (source du payload LiveOS), patch du hub Anaconda, **exports `ANACONDA_PRODUCT*`** (branding FWS), puis `dbus-run-session liveinst`
5. **Anaconda** : accueil → hub (langue, clavier, disque, utilisateur, **bureau FWS**) → « Commencer l'installation » → **page Récapitulatif** (bouton Précédent / Lancer l'installation) → installation → écran de réussite → extinction
6. En cas d'échec : écran de debug avec tous les logs (liveinst, %post chrooté, anaconda)
---
## Personnalisation
- **Paquets** : éditer `configs/releng/packages.x86_64`
- **Overlay rootfs** : déposer les fichiers dans `configs/releng/airootfs/` ou `configs/baseline/airootfs/`
- **Modules / séquence Calamares** : `configs/baseline/airootfs/etc/calamares/`
- **Branding ISO** : `configs/releng/profiledef.sh` (`iso_name`, `iso_label`, `iso_publisher`)
- **Paquets du live** : `configs/releng/packages.x86_64`
- **Paquets baseline** : `configs/baseline/packages.x86_64`
- **Overlay rootfs** : `configs/releng/airootfs/` ou `configs/baseline/airootfs/`
- **Kickstart de l'installateur** : `configs/releng/airootfs/usr/share/anaconda/interactive-defaults.ks` (payload LiveOS via `--liveinst` + tout le `%post` : bureaux, drivers, pare-feu, branding)
- **Spokes Anaconda FWS** : `configs/baseline/airootfs/usr/lib/python3.14/site-packages/pyanaconda/ui/gui/spokes/` (`fws_desktop.py`, `fws_recap.py`) + glades dans `usr/share/anaconda/ui/spokes/`
- **Configs bureaux & thèmes** : `configs/releng/airootfs/usr/local/share/fws/` (hyprland, i3, waybar, polybar, wofi, rofi, picom) et `usr/share/sddm/themes/fws/`
- **Outils fws-\*** : `configs/releng/airootfs/usr/local/bin/`
- **Récupération sur l'OS installé** : entrée GRUB générée par `configs/releng/airootfs/etc/grub.d/42_fws-recovery``fws-recovery.target` + `fws-recovery-boot.service` (`etc/systemd/system/`) ; lanceur `usr/local/share/applications/fws-recovery.desktop` + politique polkit `usr/share/polkit-1/actions/org.fws.recovery.policy`
- **Swap zram** (live + installé) : `configs/releng/airootfs/etc/systemd/zram-generator.conf` (paquet `zram-generator`)
- **Branding ISO** : `configs/releng/profiledef.sh` (`iso_name`, `iso_label`, `iso_publisher`) ; **visuel du menu BIOS** : `configs/releng/syslinux/splash.png` (PNG 8-bit) ; **nom/version affichés par l'installateur** : exports `ANACONDA_PRODUCTNAME`/`ANACONDA_PRODUCTVERSION` dans le `.xinitrc` (lus depuis l'os-release du live)
> ⚠ **Règle d'or de la fusion** : au build, `configs/baseline/*` est copié **par-dessus** `configs/releng/*` — tout fichier homonyme de baseline **écrase** celui de releng. Ça concerne notamment `profiledef.sh`, `packages.x86_64`, `pacman.conf`, `efiboot/loader/entries/01-archiso-linux.conf` et `syslinux/syslinux.cfg` : **toute modification d'un de ces fichiers doit être reportée dans les deux profils** (des divergences ont déjà fait perdre silencieusement `firewalld` et le cap `udev.event_timeout` d'une ISO ; un `syslinux-linux.cfg` stock orphelin côté baseline définissait aussi un label `arch` sans le cap — supprimé, et le menu BIOS pointe désormais explicitement sur `DEFAULT fws`). Vérifier avec :
> ```bash
> comm -12 <(cd configs/baseline && find . -type f | sort) <(cd configs/releng && find . -type f | sort)
> ```
---
## Dépannage
- **`pacman.conf introuvable`** : vérifier que `configs/releng/pacman.conf` existe.
- **Calamares ne démarre pas dans l'ISO** : se logger en tty (autologin root) et lancer `journalctl -u xorg-start -u calamares`.
- **Erreurs de retours à la ligne** : `build.sh` lance `dos2unix` sur l'arborescence ; si vous éditez des fichiers depuis Windows, ce n'est pas un problème.
- **`mkarchiso` échoue sur un paquet AUR** : relancer `./setup-calamares.sh` pour reconstruire le repo local.
| Symptôme | Cause / fix |
|---|---|
| `Aucune distribution WSL Arch joignable` | Aucune distro Arch n'est installée/joignable. Les scripts auto-détectent désormais toute distro dont le nom contient « arch » (via `wsl -l -q`) ; installe ArchWSL (nom `Arch`) ou `wsl --install -d archlinux`, ou force `ARCH_WSL_DISTRO=NomDeMaDistro`. |
| `WSL introuvable` | WSL n'est pas installé. PowerShell admin : `wsl --install`, puis installe une distro Arch. |
| `pacman: signature unknown trust` | Keyring périmé → `pacman -Sy --noconfirm archlinux-keyring` puis relancer. |
| `makepkg: conflicting files` | `pacman -Syu` incomplet avant le build. Relancer `setup-aur.sh`. |
| `mkarchiso` plante sur `[fws-local]` | Le repo local n'a pas été généré. Relancer `setup-aur.sh`. |
| Écran bleu 1-2 min au boot du live | Normal en VM : un worker udev traîne (plafonné à 45 s) — le splash « Préparation de l'installateur » l'indique. Attendre. |
| L'installateur semble figé / fenêtre blanche | Rendu logiciel en VM : la fenêtre Anaconda se peint lentement. Patienter quelques secondes. |
| Session Hyprland/i3 : fenêtres au contenu noir en VM | Compositing sur GPU virtuel — picom est auto-désactivé en VM (config FWS) ; si tu l'as réactivé, `pkill picom`. |
| Hyprland crash au lancement en VM | Géré : le wrapper `fws-hyprland` force le rendu logiciel (`kms_swrast`/llvmpipe) sous hyperviseur. Sur vrai GPU, rendu matériel normal. |
| Steam plante à l'install de SteamVR | En VM : `steam -cef-disable-gpu -cef-disable-gpu-compositing` (et la VR ne peut PAS marcher en VM — GPU/USB inaccessibles). |
| Icône Bluetooth absente / blueman en erreur | Pas d'adaptateur Bluetooth (cas VM) : le module de barre se cache et l'applet ne se lance pas — comportement voulu. |
| Le système installé ne boote plus | Menu GRUB → « **Réparer FWS (récupération du système)** » (boote l'initramfs fallback + l'app de réparation). Si GRUB lui-même est mort : booter l'ISO → entrée « **Réparer FWS (recovery)** ». |
| Réparer depuis le système installé (il boote encore) | Menu d'applications → « **Récupération FWS** » (mot de passe admin demandé une fois — polkit). |
| Réinstallation par-dessus une install existante | Le kickstart nettoie tout (`zerombr` + `clearpart --all`), mais en cas de comportement étrange au 2ᵉ passage, effacer/recréer le disque virtuel. |
| Boot BIOS | Fonctionne (résolu) : syslinux est sous `/boot/syslinux` de l'ISO (pas `/syslinux`), El-Torito BIOS + UEFI présents ; install BIOS complète validée en VM. Le menu BIOS démarre l'entrée FWS par défaut (`DEFAULT fws`). |
| Splash « Préparation de l'installateur » figé | **RAM insuffisante** (reproduit : gel à 1 Go, OK à 2 Go, aucun swap sur le live avant zram). En VM : allouer **4 Go** (le wizard VMware « Other 64-bit » n'en met que 1 !). Le live avertit désormais sous 2 Go, embarque un swap zram, et le splash affiche l'activité réelle d'anaconda (+ diagnostic auto si les logs ne bougent plus). |
| Dialogue « préparation bloquée : diagnostic » PAR-DESSUS l'installateur | Bug corrigé (ISO ≤ 2026-07-07 01:04) : le watchdog du splash se déclenchait alors qu'anaconda était à l'écran (logs silencieux = normal quand il attend l'utilisateur). Il se désarme désormais dès l'apparition de la GUI ; ferme le dialogue et continue, ou rebuild. |
| « Possibly missing firmware for module … » pendant une réparation Recovery | Avertissements `mkinitcpio` **normaux** : firmware de matériel exotique (SCSI/fibre channel…) absent de `linux-firmware`. Sans effet, sauf si tu possèdes ce matériel précis. Le journal Recovery l'explique désormais. |
| Recovery : « tout est grisé » | Corrigé : seul le sélecteur était désactivé (une seule installation détectée) mais toute l'app semblait morte ; il reste actif désormais. Les boutons d'action, eux, ont toujours été fonctionnels. |
| Retours à la ligne CRLF | `build.sh` lance `dos2unix` automatiquement, mais si tu modifies pendant le build, relancer. |
### Logs utiles
```bash
# Pendant le build
tail -f /tmp/fws-build/work/iso/arch/pkglist.x86_64.txt
# Dans le LIVE (Ctrl+Alt+F2, login root) — pendant/après l'installation
journalctl -b # système
cat /tmp/fws-liveinst.log # sortie complète de liveinst/anaconda
cat /tmp/anaconda.log # log principal anaconda
cat /tmp/fws-post-chroot.log # %post chrooté = grub-install/mkinitcpio
# En cas d'échec, l'écran de debug du live affiche déjà tout ça (zenity).
# Sur le système installé
cat /var/log/fws-post.log # trace complète du %post d'installation
journalctl -b # premier démarrage
```
---
## Variables d'environnement supportées
| Variable | Effet | Défaut |
|---|---|---|
| `ARCH_WSL_DISTRO` | Nom de la distro WSL Arch | `Arch` |
| `MSYS_NO_PATHCONV` | Désactive la conversion auto des chemins Git Bash | `1` (forcé dans les scripts) |
---
@@ -87,6 +333,21 @@ Les deux scripts détectent automatiquement s'ils sont lancés depuis **Git Bash
FWS est un fork de **[archiso](https://gitlab.archlinux.org/archlinux/archiso)** (Arch Linux), redistribué sous les termes de la **GPL-3.0-or-later**.
Voir [LICENSE](LICENSE) pour le texte complet, et [AUTHORS.rst](AUTHORS.rst) pour la liste des auteurs originaux d'archiso.
Les modifications spécifiques à FWS (scripts `build.sh`, `setup-aur.sh`, overlay `configs/baseline/`, intégration de l'installateur + Xorg autostart, chaîne de build WSL) sont également distribuées sous GPL-3.0-or-later.
Les modifications spécifiques à FWS (scripts `build.sh`, `setup-calamares.sh`, overlay `configs/baseline/`, intégration Calamares + Xorg autostart, chaîne de build WSL) sont également distribuées sous GPL-3.0-or-later.
### Base légale complète
| Document | Objet |
|---|---|
| [LICENSE](LICENSE) | Texte intégral GPL-3.0-or-later |
| [COPYRIGHT.md](COPYRIGHT.md) | Droits d'auteur du dépôt & périmètre |
| [LICENSING.md](LICENSING.md) | Politique de licences, **offre écrite GPL (sources)**, checklist release |
| [THIRD-PARTY-LICENSES.md](THIRD-PARTY-LICENSES.md) | Inventaire des logiciels tiers (Anaconda, deps…) & **analyse de compatibilité** |
| [TRADEMARKS.md](TRADEMARKS.md) | Marques & **non-affiliation** (Arch, Red Hat, Fedora, Anaconda, Windows…) |
| [NOTICE](NOTICE) | Attributions Apache/MIT/BSD |
| [AUTHORS.rst](AUTHORS.rst) | Auteurs FWS + auteurs originaux d'archiso |
| [CONTRIBUTING.rst](CONTRIBUTING.rst) | Contribuer (inbound = outbound, DCO) |
> ✅ **Déjà réglé** : offre écrite GPL (URL dépôt + contact), `os-release` FWS (le live ne s'annonce plus « Arch Linux », via hook pacman) et `motd` (plus de lien `archlinux.org`).
>
> ⚠️ **Reste avant diffusion publique** (détail dans [LICENSING.md](LICENSING.md) §6) : **rendre le dépôt public** (sinon l'offre GPL n'est pas opposable), retirer le branding Red Hat/Fedora de l'UI Anaconda lors de la migration, et **trancher sur `python-iso639`** (AGPL-3.0-only). **Ces documents ne sont pas un avis juridique.**
+147
View File
@@ -0,0 +1,147 @@
# Logiciels tiers & licences — FWS
Ce document est l'**inventaire de conformité** (« bill of materials ») des
logiciels tiers que FWS reconditionne, embarque ou redistribue. Il sert à
satisfaire les obligations d'**attribution** et de **préservation des avis de
licence** des licences GPL, LGPL, AGPL, Apache, MIT et BSD.
Trois familles de tiers :
1. **La base du dépôt** : FWS est un fork d'**archiso**.
2. **Les paquets construits/redistribués par FWS** (`pkgbuilds/` + `local-repo/`),
notamment l'installateur **Anaconda** et ses dépendances Python.
3. **L'ensemble des paquets Arch Linux** agrégés dans l'ISO live (chacun sous sa
propre licence ; l'avis de licence de chaque paquet est présent dans
`/usr/share/licenses/<paquet>/` sur le système installé/live).
---
## 1. Base du dépôt
| Composant | Rôle | SPDX | Détenteur | Source amont |
|---|---|---|---|---|
| **archiso** | système de build (mkarchiso, profils, man, Makefile) | `GPL-3.0-or-later` | Arch Linux / Archiso Authors | https://gitlab.archlinux.org/archlinux/archiso |
Auteurs originaux : voir [AUTHORS.rst](AUTHORS.rst).
---
## 2. Paquets construits / redistribués par FWS
Sources des recettes : `pkgbuilds/*/PKGBUILD`. Binaires : `local-repo/*.pkg.tar.zst`.
La **source correspondante** (au sens GPL/LGPL) de chacun est le tarball amont
référencé par `source=()` dans le PKGBUILD, plus le PKGBUILD lui-même.
| Paquet | Version | SPDX | Détenteur principal | Source amont |
|---|---|---|---|---|
| anaconda | 45.8 | `GPL-2.0-or-later` | Red Hat, Inc. & contributeurs Anaconda | https://github.com/rhinstaller/anaconda |
| anaconda-widgets | 45.8 | `GPL-2.0-or-later` | Red Hat, Inc. | https://github.com/rhinstaller/anaconda |
| pykickstart | 3.74 | `GPL-2.0-or-later` | Red Hat, Inc. | https://github.com/pykickstart/pykickstart |
| python-blivet | 3.13.2 | `LGPL-2.1-only` | Red Hat, Inc. | https://github.com/storaged-project/blivet |
| python-meh | 0.43 | `GPL-2.0-or-later` | Red Hat, Inc. | https://github.com/rhinstaller/python-meh |
| python-productmd | 1.50 | `LGPL-2.1-or-later` | Red Hat, Inc. / release-engineering | https://github.com/release-engineering/productmd |
| python-simpleline | 1.8 | `LGPL-3.0-or-later` | Red Hat, Inc. | https://github.com/rhinstaller/python-simpleline |
| python-requests-file | 2.1.0 | `Apache-2.0` | David Shea | https://github.com/dashea/requests-file |
| python-requests-ftp | 0.3.1 | `Apache-2.0` | Cory Benfield | https://github.com/Lukasa/requests-ftp |
| python-pid | 3.0.4 | `Apache-2.0` | trbs | https://github.com/trbs/pid |
| python-iso639 | 0.4.5 | **`AGPL-3.0-only`** ⚠ | Mikael Karlsson (noumar) | https://github.com/noumar/iso639 |
| python-langtable | 0.0.51 | `GPL-3.0-or-later AND MIT` | Mike FABIAN | https://github.com/mike-fabian/langtable |
| python-xkbregistry | 1.5 | `MIT` | Stephen Early | https://github.com/sde1000/python-xkbregistry |
| libreport | 2.17.15 | **`GPL-2.0-only`** ⚠ | Red Hat, Inc. (projet ABRT) | https://github.com/abrt/libreport |
| satyr | 0.43 | `GPL-2.0-or-later` | Red Hat, Inc. (projet ABRT) | https://github.com/abrt/satyr |
| libxmlrpc (xmlrpc-c) | 1.64.03 | `custom` (BSD-style permissive) | Auteurs xmlrpc-c | https://xmlrpc-c.sourceforge.net/ |
| winboat-bin | 0.9.0 | `MIT` | Auteurs WinBoat (TibixDev) | https://www.winboat.app |
> Les versions et identifiants SPDX ci-dessus proviennent des champs `license=`
> des PKGBUILD et des `.PKGINFO` des paquets de `local-repo/`. Quand le `.PKGINFO`
> portait une étiquette ancienne et imprécise (`GPL`, `Apache`), l'identifiant
> SPDX retenu est celui du dépôt amont (p. ex. `satyr` → `GPL-2.0-or-later`).
> **À corriger dans les PKGBUILD** pour des étiquettes SPDX exactes.
---
## 3. Paquets Arch Linux de l'ISO
L'ISO live agrège tout l'ensemble de paquets listé dans
`configs/releng/packages.x86_64` et `configs/baseline/packages.x86_64` (noyau
Linux, Xorg, Openbox, environnements de bureau, utilitaires…). Chaque paquet
conserve sa licence d'origine ; l'avis correspondant est fourni dans
`/usr/share/licenses/<paquet>/` sur le système. FWS ne revendique aucun droit
sur ces paquets.
---
## 4. Analyse de compatibilité des licences
**Licence effective du dépôt FWS : `GPL-3.0-or-later`** (imposée par la dérivation
d'archiso, lui-même GPL-3.0-or-later).
### 4.1 Principe d'agrégation (le cas général)
L'ISO et le dépôt de paquets sont des **agrégations** de programmes indépendants
(« mere aggregation », GPLv3 §5 / GPLv2 §2). Chaque paquet est distribué comme
une unité séparée (binaire `.pkg.tar.zst` distinct, processus distinct,
bibliothèque partagée distincte) et **conserve sa propre licence**. C'est
exactement le modèle juridique sous lequel Arch Linux, Debian et Fedora
distribuent des milliers de paquets de licences hétérogènes sur un même média.
À ce niveau, la compatibilité copyleft **n'est pas requise** : il n'y a pas
d'« œuvre combinée » unique.
### 4.2 Compatibilité au sein du runtime Anaconda
Anaconda charge plusieurs modules dans **un même processus Python** au moment de
l'exécution. Les licences en présence et leur compatibilité montante vers GPLv3 :
| Licence du composant | Compatible GPLv3 ? | Note |
|---|---|---|
| `GPL-2.0-or-later` (anaconda, meh, pykickstart, satyr…) | ✅ | la clause « or later » autorise l'usage en GPLv3 |
| `LGPL-2.1-only` (blivet) | ✅ | LGPL-2.1 §3 autorise la relicence en GPL ; usage dynamique |
| `LGPL-2.1-or-later` (productmd) | ✅ | montée vers (L)GPLv3 |
| `LGPL-3.0-or-later` (simpleline) | ✅ | sous-ensemble de GPLv3 |
| `Apache-2.0` (requests-file, requests-ftp, pid) | ✅ | compatible GPLv3 (sens unique) ; voir [NOTICE](NOTICE) |
| `MIT` (xkbregistry, winboat) | ✅ | permissive |
| `MIT`/`BSD-style` (langtable, libxmlrpc) | ✅ | permissive |
### 4.3 ⚠ Deux points à surveiller (signalés en bonne foi)
1. **`python-iso639` est `AGPL-3.0-only`.** L'AGPL est compatible avec GPLv3 via
la clause de compatibilité réciproque (GPLv3 §13 / AGPLv3 §13) : on peut
combiner du code AGPLv3 et GPLv3. La **clause réseau** de l'AGPL (mise à
disposition de la source aux utilisateurs distants d'un service réseau) est
en pratique **inerte** pour un installateur hors-ligne. **Cependant**, l'AGPL
est la licence la plus contaminante et beaucoup d'organisations l'interdisent
par politique interne. **Recommandation béton :** si l'AGPL n'est pas
souhaitée, remplacer `noumar/iso639` par une bibliothèque ISO-639 non-AGPL
(p. ex. `pycountry` — BSD, ou les données `iso-codes`), ce qui élimine le
sujet.
2. **`libreport` est `GPL-2.0-only`** (sans « or later »). GPL-2.0-**only** n'est
**pas** compatible en montée avec GPLv3/AGPLv3. Tant que `libreport` reste un
paquet **séparé** (bibliothèque partagée distincte, appelée via `python-meh`
qui importe `report`), on demeure dans le régime d'agrégation §4.1 — et c'est
la configuration que **Fedora elle-même distribue**. Le risque n'apparaîtrait
que si l'on **liait statiquement** `libreport` (GPLv2-only) avec un composant
AGPLv3-only/GPLv3-only dans un **seul binaire** : à éviter. En l'état (paquets
séparés), pas de conflit.
### 4.4 Verdict
En l'état (paquets séparés, agrégation sur ISO, modules Python chargés au
runtime), **la configuration est cohérente et alignée sur la pratique des
distributions majeures**. Les deux points ⚠ ci-dessus méritent une décision
explicite (garder / remplacer l'AGPL) et une revue par un juriste FOSS avant
diffusion commerciale.
> **Ceci n'est pas un avis juridique.** Analyse de bonne foi fondée sur les
> métadonnées de licence du dépôt à la date du 2026-06-17.
---
## 5. Préservation des avis
- Les textes de licence amont présents dans les sources sont conservés lors du
`package()` (pacman installe `LICENSE`/`COPYING` dans
`/usr/share/licenses/<paquet>/`).
- Les attributions requises par Apache-2.0 / MIT / BSD figurent dans [NOTICE](NOTICE).
- Aucun avis de droit d'auteur amont ne doit être retiré des sources ou binaires
redistribués.
+155
View File
@@ -0,0 +1,155 @@
# Marques & non-affiliation — FWS
FWS redistribue et modifie des logiciels portant des **marques** de tiers. Les
licences libres (GPL, LGPL, Apache…) accordent des droits sur le **code**, mais
**jamais** sur les **marques, noms et logos**. Ce document liste les marques
concernées et les déclarations de non-affiliation. Il vaut engagement du projet
à les respecter.
## Marque du projet
- **FWS** est le nom (marque non déposée) du présent projet, utilisé par les
Contributeurs FWS. Toute reprise du nom/logo FWS pour désigner une version
modifiée non officielle doit éviter de laisser croire à un aval du projet FWS.
---
## Arch Linux
> **Arch Linux™** est une marque du projet Arch Linux. FWS est une distribution
> **dérivée indépendante**, *basée sur* Arch Linux. FWS **n'est ni affilié, ni
> sponsorisé, ni approuvé** par le projet Arch Linux. *« Arch Linux is a
> trademark of the Arch Linux project. FWS is an independent derivative and is
> not affiliated with, sponsored by, or endorsed by Arch Linux. »*
Engagements FWS :
- ne pas présenter FWS **comme étant** Arch Linux ;
- ne pas utiliser le **logo Arch Linux** comme logo de FWS ;
- usage **nominatif** uniquement (« basé sur Arch Linux », « compatible
paquets Arch ») ;
- respecter les recommandations Arch pour les dérivés
(https://wiki.archlinux.org/title/DeveloperWiki:TrademarkPolicy).
### ✅ Remédiation appliquée (le live ne s'annonce plus comme « Arch Linux »)
Le système live héritait de l'`os-release` du paquet `filesystem` d'Arch et
**s'annonçait comme « Arch Linux »** ; le `motd` renvoyait vers
`wiki.archlinux.org`. Corrigé :
- **`os-release` FWS** : fourni dans
`configs/releng/airootfs/usr/local/share/fws/os-release` et appliqué sur
`/usr/lib/os-release` par un **hook pacman PostTransaction**
(`configs/releng/airootfs/etc/pacman.d/hooks/zz-fws-os-release.hook`). On ne
peut pas poser le fichier directement dans l'overlay : `filesystem` possède ce
chemin et `mkarchiso` copie l'overlay **avant** pacstrap → conflit pacman
« exists in filesystem ». Le hook s'exécute après l'installation des paquets,
donc sans conflit, et est retiré du système final par
`zzzz99-remove-custom-hooks-from-airootfs.hook`.
- **`motd`** : ne référence plus `archlinux.org` ; pointe vers le dépôt FWS.
- **Menu de boot BIOS (2026-07-07)** : l'image de fond `syslinux/splash.png`
héritée d'archiso affichait le **logo Arch Linux plein écran** — remplacée
par un visuel FWS original (générique, sans logo tiers).
- **Bannière de login (`/etc/issue`)** : `\S (\l)` — affiche le `PRETTY_NAME`
FWS, sans la version du noyau (dont le suffixe `-archN`).
- **Textes utilisateur** : `fws-about` dit « distribution Linux » ; le splash
de préparation et le journal de l'app Récupération remplacent à l'affichage
les mentions « Arch Linux »/« Fedora » issues des logs d'outils tiers (les
identifiants techniques réels — `archlinux-keyring`, miroirs — restent
intacts : usage nominatif fonctionnel).
> Note technique : `ID=fws` + `ID_LIKE=arch` préserve la détection « famille
> Arch » des outils tiers (et satisfait les checks `^ID(_LIKE)?=.*arch` de
> `build.sh`/`setup-aur.sh`, qui portent de toute façon sur l'hôte de build).
> Si la migration Anaconda révèle un composant testant `ID=arch` en dur, basculer
> transitoirement le hook sur `ID=arch` tout en gardant `NAME`/`PRETTY_NAME` FWS.
> Le suffixe `-archN` de `uname -r` vient du binaire du noyau Arch : usage
> nominatif inévitable sans recompiler le kernel.
---
## Red Hat & Fedora
> **Red Hat®** et **Fedora®** sont des marques déposées de **Red Hat, Inc.**
> L'installateur **Anaconda** est développé par Red Hat. FWS distribue une
> **version MODIFIÉE** d'Anaconda (portée sur Arch, payload LiveOS), **non
> officielle**, **non fournie ni approuvée** par Red Hat ou le projet Fedora.
> *« This product includes a modified version of Anaconda. Red Hat and Fedora
> are trademarks of Red Hat, Inc. This is an unofficial build, not provided or
> endorsed by Red Hat or the Fedora Project. »*
Engagements FWS :
- ne pas utiliser les marques Red Hat / Fedora pour suggérer un aval ;
- **marquer clairement Anaconda comme modifié** (la GPL exige d'identifier les
versions modifiées ; la politique de marque Red Hat exige de ne pas faire
passer une version modifiée pour officielle) ;
- **recommandation béton :** retirer tout **logo / nom de produit Red Hat ou
Fedora** de l'interface de l'installateur si présent, et y afficher
« Installateur FWS (basé sur Anaconda) ».
### ✅ Remédiation appliquée (2026-07-07 — l'installateur s'annonce « FWS »)
Sans `/.buildstamp`, Anaconda s'annonçait « ANACONDA BLUESKY INSTALLATION » et
ses logs parlent de Fedora. `pyanaconda/core/product.py` donne priorité aux
variables d'environnement : le `.xinitrc` du live exporte
`ANACONDA_PRODUCTNAME`/`ANACONDA_PRODUCTVERSION` (depuis l'os-release FWS) et
`ANACONDA_ISFINAL=true` → l'en-tête et l'accueil affichent **« FWS 0.6 »**. Le
splash de préparation filtre en outre les mentions Fedora des lignes de log
affichées. Les mentions profondes dans les **logs techniques** (fichiers
`/tmp/*.log`, écrans de debug) sont conservées volontairement : identification
loyale du composant amont (version modifiée d'Anaconda), utile au diagnostic.
---
## Anaconda — désambiguïsation
> Le nom **« Anaconda »** désigne ici **l'installateur de Red Hat/Fedora**
> (https://github.com/rhinstaller/anaconda). Il **n'a aucun rapport** avec
> **Anaconda®**, marque déposée d'**Anaconda, Inc.** (la distribution Python /
> data-science). FWS n'utilise ni ne distribue le produit d'Anaconda, Inc.
À mentionner dans la doc utilisateur pour éviter toute confusion.
---
## Windows & Microsoft
> **Windows®** et **Microsoft®** sont des marques de **Microsoft Corporation**.
> FWS embarque **WinBoat** (MIT), qui permet d'exécuter des applications Windows
> sous Linux. FWS et WinBoat **ne sont ni affiliés, ni approuvés** par Microsoft.
> Exécuter des applications Windows requiert vos **propres licences Windows
> valides** ; FWS ne fournit aucun logiciel ni licence Microsoft.
Le nom du projet et son slogan font un usage **parodique / nominatif** du terme
« Windows » et n'impliquent aucun lien avec Microsoft.
---
## Autres marques (usage nominatif)
Les noms suivants désignent des projets/options proposés à l'installation ou
utilisés comme composants, et sont des marques de leurs détenteurs, employées
de façon **purement descriptive** :
- **GNOME®** — The GNOME Foundation
- **KDE®**, **Plasma** — KDE e.V.
- **Xfce** — projet Xfce
- **Hyprland** — projet Hyprland
- **GTK** — The GNOME Foundation
- **Linux®** — marque déposée de Linus Torvalds
- **WinBoat** — projet WinBoat
---
## Principe général
L'emploi de ces marques dans FWS relève de l'**usage nominatif loyal** (décrire
l'origine, la compatibilité ou les composants), **sans** suggérer parrainage ou
affiliation. Aucune licence sur ces marques n'est accordée ni reçue. Pour toute
utilisation commerciale du nom/logo d'un tiers au-delà de l'usage nominatif,
obtenir l'autorisation du détenteur.
> **Ceci n'est pas un avis juridique.** Faites valider la stratégie de marque
> (notamment le nom du projet et le rebranding d'Anaconda) par un conseil avant
> diffusion publique large.
+1
View File
@@ -0,0 +1 @@
0.6.0
Executable
+383
View File
@@ -0,0 +1,383 @@
#!/bin/bash
# ============================================================
# FWS — Build OFFICIEL versionné de l'ISO (archiso)
#
# IDENTIQUE à build.sh (même bascule conteneur/WSL, --network=host, fusion
# baseline, MÊME injection local-repo → donc même paquet anaconda avec le champ
# Hostname), avec EN PLUS uniquement le RENOMMAGE :
# - demande la version (major.minor.build) + le nom de variante, le fichier
# VERSION servant de défaut,
# - nomme l'ISO fws-<version>-<nom>.iso (ex. fws-1.5.0-cli.iso),
# - range l'ISO dans out/vMAJOR/vMAJOR.MINOR/.
#
# Fonctionne sur :
# - Windows 10 / 11 (Git Bash → bascule auto dans WSL Arch)
# - Arch Linux natif (exécution directe)
# - WSL Arch lancé directement (exécution directe)
#
# Nom de la distro WSL : "Arch" par défaut, ou $ARCH_WSL_DISTRO,
# ou auto-détecté parmi les noms courants.
# ============================================================
set -e
trap 'rc=$?; echo -e "\e[31mÉchec (build-offi.sh) ligne $LINENO, code $rc.\e[0m" >&2; exit $rc' ERR
DISTRO_NAME="${ARCH_WSL_DISTRO:-Arch}"
# ============================================================
# Bascule Git Bash (Windows 10/11) → WSL si besoin
# ============================================================
if [[ "$OSTYPE" == "msys" || "$OSTYPE" == "cygwin" || -n "$WINDIR" ]]; then
echo -e "\e[36mGit Bash détecté — bascule dans WSL ($DISTRO_NAME)...\e[0m"
export MSYS_NO_PATHCONV=1
export MSYS2_ARG_CONV_EXCL="*"
# WSL doit être présent (sinon message clair plutôt que command not found).
command -v wsl.exe >/dev/null 2>&1 || {
echo -e "\e[31mWSL introuvable. Installe WSL2 puis une distro Arch :\e[0m" >&2
echo " 1) PowerShell admin : wsl --install" >&2
echo " 2) Installe Arch (ArchWSL, ou 'wsl --install -d archlinux') puis relance." >&2
exit 1
}
# Choix de la distro Arch : override $ARCH_WSL_DISTRO, sinon nom exact,
# sinon 1re distro « arch » réellement joignable. On énumère via
# `wsl -l -q` (sortie UTF-16LE → on retire NUL/CR) au lieu d'une liste
# figée, mais on garde la sonde « echo ok » (une distro listée peut
# être en cours d'install / cassée).
pick_arch_distro() {
wsl.exe -d "$DISTRO_NAME" -u root -- echo ok >/dev/null 2>&1 && return 0
local d distros=()
mapfile -t distros < <(wsl.exe -l -q 2>/dev/null | tr -d '\0\r' | sed 's/[[:space:]]*$//;/^$/d')
for d in "${distros[@]}"; do
[[ "$d" == "$DISTRO_NAME" ]] || continue
wsl.exe -d "$d" -u root -- echo ok >/dev/null 2>&1 && { DISTRO_NAME="$d"; return 0; }
done
for d in "${distros[@]}"; do
[[ "$d" =~ [Aa][Rr][Cc][Hh] ]] || continue
wsl.exe -d "$d" -u root -- echo ok >/dev/null 2>&1 && { DISTRO_NAME="$d"; return 0; }
done
return 1
}
if ! pick_arch_distro; then
echo -e "\e[31mAucune distribution WSL Arch joignable.\e[0m" >&2
echo "Distros WSL installées :" >&2
wsl.exe -l -v 2>/dev/null | tr -d '\0' >&2 || true
echo "" >&2
echo "Installe Arch dans WSL puis relance :" >&2
echo " - ArchWSL (yuk7) — s'enregistre sous 'Arch' : https://github.com/yuk7/ArchWSL/releases/latest" >&2
echo " - ou image officielle : wsl --install -d archlinux (nom 'archlinux')" >&2
echo "Distro sous un autre nom ? export ARCH_WSL_DISTRO=<nom> (cf. 'wsl -l -v' ci-dessus)." >&2
exit 1
fi
echo -e "\e[36m==> Distro WSL : $DISTRO_NAME\e[0m"
# Traduit le dossier du script en chemin WSL.
SCRIPT_DIR_WIN="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -W)"
SCRIPT_PATH_WSL=$(MSYS_NO_PATHCONV=1 wsl.exe -d "$DISTRO_NAME" -u root -- \
wslpath "$(echo "$SCRIPT_DIR_WIN" | sed 's|/|\\\\|g')/build-offi.sh" \
2>/dev/null | tr -d '\r\n')
[ -n "$SCRIPT_PATH_WSL" ] || {
echo -e "\e[31mTraduction du chemin vers WSL échouée (wslpath). Vérifie ARCH_WSL_DISTRO ($DISTRO_NAME).\e[0m" >&2
exit 1
}
wsl.exe -d "$DISTRO_NAME" -u root -- test -f "$SCRIPT_PATH_WSL" || {
echo -e "\e[31mScript introuvable dans WSL : $SCRIPT_PATH_WSL\e[0m" >&2
exit 1
}
# Relance ce même script dans WSL, en root, depuis son vrai chemin
# (BASH_SOURCE → WORK_DIR correct). Les fins de ligne sont garanties LF
# par .gitattributes (*.sh text eol=lf) ; le profil copié est en plus
# passé à dos2unix plus loin.
echo "==> Script à exécuter dans WSL : $SCRIPT_PATH_WSL"
MSYS_NO_PATHCONV=1 wsl.exe -d "$DISTRO_NAME" -u root -- bash "$SCRIPT_PATH_WSL"
exit 0
fi
# ============================================================
# Bascule conteneur : hôte non-Arch (Fedora, Ubuntu, …) →
# build dans un conteneur Arch via podman.
#
# mkarchiso exige pacman + des mounts/chroot/loop privilégiés que
# seul un environnement Arch fournit. Sur un hôte non-Arch on relance
# CE script à l'identique dans docker.io/library/archlinux:latest, le
# dépôt monté au MÊME chemin absolu (→ WORK_DIR et out/ inchangés).
# podman ROOTFUL + --privileged obligatoire : rootless ne gère pas les
# mounts/chroot de mkarchiso (et --privileged relâche aussi SELinux,
# enforcing sur Fedora, sur le bind-mount sans avoir besoin de :Z).
# ============================================================
host_is_arch() {
# Fedora empaquette aussi « pacman » → sa seule présence ne suffit pas ;
# on exige en plus un ID/ID_LIKE « arch » dans /etc/os-release.
command -v pacman >/dev/null 2>&1 \
&& grep -qiE '^ID(_LIKE)?=.*arch' /etc/os-release 2>/dev/null
}
if [ -z "$FWS_IN_CONTAINER" ] && ! host_is_arch; then
echo -e "\e[36mHôte non-Arch détecté — build officiel dans un conteneur Arch (podman)...\e[0m"
command -v podman >/dev/null 2>&1 || {
echo -e "\e[31mpodman introuvable.\e[0m" >&2
echo " Fedora : sudo dnf install -y podman" >&2
echo " Debian/Ubuntu : sudo apt install -y podman" >&2
exit 1
}
# La version + le nom sont DEMANDÉS sur l'hôte (avant le conteneur) et passés
# via -e, pour que le prompt s'affiche au bon endroit (terminal de l'hôte).
# (Définis FWS_ISO_VERSION / FWS_ISO_TAG ; lus plus bas, prompt sauté si déjà
# fournis — c.-à-d. dans le conteneur.)
ask_iso_meta_host() {
[ -n "$FWS_ISO_VERSION" ] && [ -n "$FWS_ISO_TAG" ] && return 0
local def=""
if [ -f "$(dirname "${BASH_SOURCE[0]}")/VERSION" ]; then
def="$(tr -d ' \t\r\n' < "$(dirname "${BASH_SOURCE[0]}")/VERSION")"
[[ "$def" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]] || def=""
fi
while :; do
if [ -n "$def" ]; then
read -rp "==> Version (major.minor.build) [Entrée = $def] : " FWS_ISO_VERSION || exit 1
[ -n "$FWS_ISO_VERSION" ] || FWS_ISO_VERSION="$def"
else
read -rp "==> Version (major.minor.build, ex. 1.5.0) : " FWS_ISO_VERSION || exit 1
fi
[[ "$FWS_ISO_VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]] && break
echo -e "\e[31m Format attendu : major.minor.build (ex. 1.5.0)\e[0m" >&2
done
while :; do
read -rp "==> Nom de la variante (ex. cli, gnome, kde) : " FWS_ISO_TAG || exit 1
FWS_ISO_TAG="$(printf '%s' "$FWS_ISO_TAG" | tr '[:upper:]' '[:lower:]' | tr -cd 'a-z0-9-')"
[ -n "$FWS_ISO_TAG" ] && break
echo -e "\e[31m Nom requis (lettres, chiffres, tirets)\e[0m" >&2
done
export FWS_ISO_VERSION FWS_ISO_TAG
}
ask_iso_meta_host
# Rootful : préfixe sudo si on n'est pas déjà root.
SUDO=(); [ "$EUID" -eq 0 ] || SUDO=(sudo)
# -it seulement si on est dans un terminal (sinon podman casse en CI).
TTY=(); [ -t 0 ] && TTY=(-it)
REPO_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
SELF="$(basename "${BASH_SOURCE[0]}")"
IMAGE="docker.io/library/archlinux:latest"
# pull explicite : « run » ne re-résout jamais le tag « latest » une fois
# l'image en cache → sans ça on build indéfiniment sur une image qui
# vieillit (puis partial upgrades pacman). Le -Syu côté conteneur (plus
# bas) complète la parade.
echo "==> Pull de l'image $IMAGE..."
"${SUDO[@]}" podman pull "$IMAGE"
echo "==> Relance dans le conteneur ($SELF)..."
# --network=host : le réseau bridge de podman ne route plus vers l'extérieur
# sur ce wifi (firewalld/NAT cassé après changement de réseau → « core.db :
# Resolving timed out », même avec --dns). En partageant la pile réseau de
# l'hôte (qui, lui, a internet + DNS via 127.0.0.53/systemd-resolved joignable
# dans son propre netns), le conteneur récupère une connectivité identique.
"${SUDO[@]}" podman run --rm "${TTY[@]}" --network=host --privileged \
-e FWS_IN_CONTAINER=1 \
-e FWS_ISO_VERSION -e FWS_ISO_TAG \
-v "$REPO_DIR":"$REPO_DIR" \
-v fws-pacman-cache:/var/cache/pacman/pkg \
-w "$REPO_DIR" \
"$IMAGE" \
bash "$REPO_DIR/$SELF"
# podman rootful → les fichiers produits (out/) appartiennent à root.
# On les rend au propriétaire du dépôt pour confort côté hôte.
OWNER="$(stat -c '%u:%g' "$REPO_DIR" 2>/dev/null || true)"
if [ -n "$OWNER" ]; then
for d in out local-repo; do
[ -e "$REPO_DIR/$d" ] && "${SUDO[@]}" chown -R "$OWNER" "$REPO_DIR/$d" 2>/dev/null || true
done
fi
exit 0
fi
# ============================================================
# Exécution native (Arch Linux bare-metal, WSL, OU conteneur Arch)
# ============================================================
command -v pacman >/dev/null \
|| { echo -e "\e[31mpacman introuvable — lance ce script depuis Arch / WSL.\e[0m"; exit 1; }
# mkarchiso exige root. Sur Arch natif on s'élève (sudo de préférence,
# sinon su) ; depuis la bascule Git Bash on est déjà root (-u root).
# $0 est cité pour gérer les chemins à espaces (ex. "1. FWS").
if [ "$EUID" -ne 0 ]; then
if command -v sudo >/dev/null 2>&1; then
# -E : conserve FWS_ISO_VERSION / FWS_ISO_TAG (demandés avant) à travers sudo.
exec sudo -E bash "$0" "$@"
else
exec su -c "bash \"$0\"" root
fi
fi
if grep -qi 'microsoft\|wsl' /proc/version 2>/dev/null; then
echo -e "\e[36mBuild officiel dans WSL ($DISTRO_NAME) en tant que root...\e[0m"
IS_WSL=1
else
echo -e "\e[36mBuild officiel sur Arch Linux natif en tant que root...\e[0m"
IS_WSL=0
fi
# Le dossier de travail = dossier qui contient ce script (gère les
# espaces du chemin, ex. "1. FWS").
WORK_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
echo "==> Dossier de travail : $WORK_DIR"
# ============================================================
# Version (major.minor.build) + nom de la variante.
# Déjà demandés sur l'hôte (FWS_ISO_VERSION/FWS_ISO_TAG passés via -e) ; sinon
# (exécution native Arch / WSL directe) on les demande ici. Le fichier VERSION
# sert de défaut (Entrée = le reprendre). Produit fws-<version>-<nom>.iso.
# ============================================================
VERSION="$FWS_ISO_VERSION"
ISO_TAG="$FWS_ISO_TAG"
VERSION_DEFAULT=""
if [ -f "$WORK_DIR/VERSION" ]; then
VERSION_DEFAULT="$(tr -d ' \t\r\n' < "$WORK_DIR/VERSION")"
[[ "$VERSION_DEFAULT" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]] || VERSION_DEFAULT=""
fi
while [[ ! "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; do
if [ -n "$VERSION_DEFAULT" ]; then
read -rp "==> Version (major.minor.build) [Entrée = $VERSION_DEFAULT] : " VERSION \
|| { echo -e "\e[31mEntrée requise — lance le script en interactif.\e[0m" >&2; exit 1; }
[ -n "$VERSION" ] || VERSION="$VERSION_DEFAULT"
else
read -rp "==> Version (major.minor.build, ex. 1.5.0) : " VERSION \
|| { echo -e "\e[31mEntrée requise — lance le script en interactif.\e[0m" >&2; exit 1; }
fi
[[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]] \
|| echo -e "\e[31m Format attendu : major.minor.build (ex. 1.5.0)\e[0m" >&2
done
while [ -z "$ISO_TAG" ]; do
read -rp "==> Nom de la variante (ex. cli, gnome, kde) : " ISO_TAG \
|| { echo -e "\e[31mEntrée requise — lance le script en interactif.\e[0m" >&2; exit 1; }
ISO_TAG="$(printf '%s' "$ISO_TAG" | tr '[:upper:]' '[:lower:]' | tr -cd 'a-z0-9-')"
[ -n "$ISO_TAG" ] || echo -e "\e[31m Nom requis (lettres, chiffres, tirets)\e[0m" >&2
done
IFS='.' read -r MAJOR MINOR BUILD <<< "$VERSION"
BUILD_DATE="$(date +%Y.%m.%d)"
# iso_version interne (passé à mkarchiso) ; l'ISO finale est renommée plus bas.
ISO_VERSION="${VERSION}-${ISO_TAG}"
OUT_DIR="$WORK_DIR/out/v${MAJOR}/v${MAJOR}.${MINOR}"
# Date ajoutée À LA FIN du nom, avant .iso → fws-<version>-<nom>-<AAAA.MM.JJ>.iso
ISO_FILE="$OUT_DIR/fws-${VERSION}-${ISO_TAG}-${BUILD_DATE}.iso"
echo "==> Version : ${VERSION} · variante : ${ISO_TAG} · date : ${BUILD_DATE}"
echo "==> ISO finale : fws-${VERSION}-${ISO_TAG}-${BUILD_DATE}.iso"
echo "==> Dossier : $OUT_DIR"
# pacman ≥ 7 sandboxe les ops FS via landlock, non supporté par le kernel
# WSL ni (selon le noyau) par le conteneur → désactivation. Idempotent,
# sans effet sur Arch natif.
if { [ "$IS_WSL" -eq 1 ] || [ -n "$FWS_IN_CONTAINER" ]; } \
&& ! grep -qE '^[[:space:]]*DisableSandbox' /etc/pacman.conf; then
sed -i '/^\[options\]/a DisableSandbox' /etc/pacman.conf
echo "==> WSL/conteneur détecté → DisableSandbox ajouté à /etc/pacman.conf"
fi
echo "==> Mise à jour des miroirs et installation de archiso..."
pacman -Sy --noconfirm reflector || true
reflector --verbose --latest 10 --sort rate --save /etc/pacman.d/mirrorlist || true
if [ -n "$FWS_IN_CONTAINER" ]; then
# Image de base qui vieillit → upgrade complet AVANT d'ajouter archiso,
# sinon partial upgrade (archiso tire des deps plus récentes que la base).
pacman -Syu --noconfirm archiso
else
pacman -Sy --noconfirm archiso
fi
echo "==> Préparation de l'environnement de build..."
rm -rf /tmp/fws-build
mkdir -p /tmp/fws-build/releng
# Copie configs/releng/ en base
if [ -d "$WORK_DIR/configs/releng" ]; then
cp -ar "$WORK_DIR/configs/releng/"* /tmp/fws-build/releng/
echo "==> configs/releng/ copié"
fi
# Fusionne configs/baseline/ par dessus (priorité aux fichiers baseline)
if [ -d "$WORK_DIR/configs/baseline" ]; then
cp -ar "$WORK_DIR/configs/baseline/"* /tmp/fws-build/releng/
echo "==> configs/baseline/ fusionné (prioritaire)"
fi
# ── Injection de la version dans profiledef.sh (copie temporaire) ──
# mkarchiso nomme l'ISO ${iso_name}-${iso_version}-${arch}.iso ; on force
# iso_version pour obtenir le nom voulu (l'ISO est renommée fws-… plus bas).
if [ -f /tmp/fws-build/releng/profiledef.sh ]; then
sed -i "s|^iso_version=.*|iso_version=\"${ISO_VERSION}\"|" \
/tmp/fws-build/releng/profiledef.sh
echo "==> iso_version forcé à '${ISO_VERSION}' dans profiledef.sh"
else
echo -e "\e[31mprofiledef.sh introuvable dans le profil de build.\e[0m"
exit 1
fi
echo "==> Activation de NetworkManager.service sur le live (symlink réel)..."
mkdir -p /tmp/fws-build/releng/airootfs/etc/systemd/system/multi-user.target.wants
ln -sf /usr/lib/systemd/system/NetworkManager.service \
/tmp/fws-build/releng/airootfs/etc/systemd/system/multi-user.target.wants/NetworkManager.service
echo "==> Vérification des services systemd..."
ls /tmp/fws-build/releng/airootfs/etc/systemd/system/ 2>/dev/null || echo " (aucun service)"
ls /tmp/fws-build/releng/airootfs/etc/systemd/system/multi-user.target.wants/ 2>/dev/null || echo " (aucun symlink)"
# Copie le repo local (winboat-bin + deps Anaconda packagées)
if ls "$WORK_DIR/local-repo/"*.pkg.tar.zst &>/dev/null 2>&1; then
echo "==> Copie du repo local fws-local..."
mkdir -p /tmp/fws-build/local-repo
cp -a "$WORK_DIR/local-repo/"* /tmp/fws-build/local-repo/
echo "==> Injection [fws-local] dans pacman.conf..."
sed -i '/^\[fws-local\]/,/^$/d' /tmp/fws-build/releng/pacman.conf
PACMAN_TMP=$(mktemp)
printf '[fws-local]\nSigLevel = Optional TrustAll\nServer = file:///tmp/fws-build/local-repo\n\n' \
> "$PACMAN_TMP"
cat /tmp/fws-build/releng/pacman.conf >> "$PACMAN_TMP"
mv "$PACMAN_TMP" /tmp/fws-build/releng/pacman.conf
echo "==> Vérification pacman.conf :"
head -5 /tmp/fws-build/releng/pacman.conf
else
echo "==> Aucun repo local détecté."
fi
echo "==> Correction des retours à la ligne Windows (dos2unix)..."
pacman -S --needed --noconfirm dos2unix
find /tmp/fws-build/releng -type f -exec dos2unix {} + 2>/dev/null
echo "==> Lancement de mkarchiso..."
mkdir -p "$OUT_DIR"
# mkarchiso fait un « rm » interne de l'ISO cible avant de la (ré)écrire ; si
# une ISO du même nom est VERROUILLÉE par Windows (VM encore ouverte dessus,
# ISO montée, antivirus), ce rm échoue et tout le build casse à la toute fin.
# Parade : mkarchiso écrit dans un dossier de staging neuf, puis on déplace
# l'ISO. Si la cible (cette même version) est verrouillée, on bascule sur un
# nom horodaté → on ne touche jamais aux ISO des autres versions.
STAGE="$OUT_DIR/.staging-$$"
rm -rf "$STAGE"; mkdir -p "$STAGE"
mkarchiso -v -w /tmp/fws-build/work -o "$STAGE" /tmp/fws-build/releng
NEW_ISO="$(ls -1 "$STAGE/"*.iso 2>/dev/null | head -1)"
[ -n "$NEW_ISO" ] || { echo -e "\e[31mAucune ISO produite par mkarchiso.\e[0m" >&2; exit 1; }
if { chmod -f 666 "$ISO_FILE" 2>/dev/null; rm -f "$ISO_FILE" 2>/dev/null; } && mv -f "$NEW_ISO" "$ISO_FILE" 2>/dev/null; then
FINAL="$ISO_FILE"
else
FINAL="${ISO_FILE%.iso}-$(date +%H%M%S).iso"
echo -e "\e[33m[!] '$ISO_FILE' est verrouillée (une VM l'utilise ?). Écriture sous un nom unique.\e[0m" >&2
mv -f "$NEW_ISO" "$FINAL"
fi
rm -rf "$STAGE" 2>/dev/null || true
echo "==> Nettoyage..."
rm -rf /tmp/fws-build/work
echo "==> Build officiel terminé ! ISO : $FINAL"
echo -e "\e[32mScript de build officiel (fws-${VERSION}-${ISO_TAG}-${BUILD_DATE}) terminé avec succès.\e[0m"
Regular → Executable
+236 -129
View File
@@ -1,54 +1,229 @@
#!/bin/bash
export MSYS_NO_PATHCONV=1
# ============================================================
# FWS — Build de l'ISO via mkarchiso (archiso)
#
# Fonctionne sur :
# - Windows 10 / 11 (Git Bash → bascule auto dans WSL Arch)
# - Arch Linux natif (exécution directe)
# - WSL Arch lancé directement (exécution directe)
#
# Nom de la distro WSL : "Arch" par défaut, ou $ARCH_WSL_DISTRO,
# ou auto-détecté parmi les noms courants.
# ============================================================
set -e
trap 'echo -e "\e[31mErreur lors de l execution (build.sh).\e[0m"; exit 1' ERR
trap 'rc=$?; echo -e "\e[31mÉchec (build.sh) ligne $LINENO, code $rc.\e[0m" >&2; exit $rc' ERR
DISTRO_NAME="Arch"
DISTRO_NAME="${ARCH_WSL_DISTRO:-Arch}"
if [ -n "$WSL_DISTRO_NAME" ]; then
echo -e "\e[36mBuild exécuté depuis WSL ($WSL_DISTRO_NAME) en tant que root...\e[0m"
IN_WSL=1
else
echo -e "\e[36mLancement du processus de build dans WSL ($DISTRO_NAME) en tant que root...\e[0m"
# ============================================================
# Bascule Git Bash (Windows 10/11) → WSL si besoin
# ============================================================
if [[ "$OSTYPE" == "msys" || "$OSTYPE" == "cygwin" || -n "$WINDIR" ]]; then
echo -e "\e[36mGit Bash détecté — bascule dans WSL ($DISTRO_NAME)...\e[0m"
export MSYS_NO_PATHCONV=1
export MSYS2_ARG_CONV_EXCL="*"
# WSL doit être présent (sinon message clair plutôt que command not found).
command -v wsl.exe >/dev/null 2>&1 || {
echo -e "\e[31mWSL introuvable. Installe WSL2 puis une distro Arch :\e[0m" >&2
echo " 1) PowerShell admin : wsl --install" >&2
echo " 2) Installe Arch (ArchWSL, ou 'wsl --install -d archlinux') puis relance." >&2
exit 1
}
# Choix de la distro Arch : override $ARCH_WSL_DISTRO, sinon nom exact,
# sinon 1re distro « arch » réellement joignable. On énumère via
# `wsl -l -q` (sortie UTF-16LE → on retire NUL/CR) au lieu d'une liste
# figée, mais on garde la sonde « echo ok » (une distro listée peut
# être en cours d'install / cassée).
pick_arch_distro() {
wsl.exe -d "$DISTRO_NAME" -u root -- echo ok >/dev/null 2>&1 && return 0
local d distros=()
mapfile -t distros < <(wsl.exe -l -q 2>/dev/null | tr -d '\0\r' | sed 's/[[:space:]]*$//;/^$/d')
for d in "${distros[@]}"; do
[[ "$d" == "$DISTRO_NAME" ]] || continue
wsl.exe -d "$d" -u root -- echo ok >/dev/null 2>&1 && { DISTRO_NAME="$d"; return 0; }
done
for d in "${distros[@]}"; do
[[ "$d" =~ [Aa][Rr][Cc][Hh] ]] || continue
wsl.exe -d "$d" -u root -- echo ok >/dev/null 2>&1 && { DISTRO_NAME="$d"; return 0; }
done
return 1
}
if ! pick_arch_distro; then
echo -e "\e[31mAucune distribution WSL Arch joignable.\e[0m" >&2
echo "Distros WSL installées :" >&2
wsl.exe -l -v 2>/dev/null | tr -d '\0' >&2 || true
echo "" >&2
echo "Installe Arch dans WSL puis relance :" >&2
echo " - ArchWSL (yuk7) — s'enregistre sous 'Arch' : https://github.com/yuk7/ArchWSL/releases/latest" >&2
echo " - ou image officielle : wsl --install -d archlinux (nom 'archlinux')" >&2
echo "Distro sous un autre nom ? export ARCH_WSL_DISTRO=<nom> (cf. 'wsl -l -v' ci-dessus)." >&2
exit 1
fi
echo -e "\e[36m==> Distro WSL : $DISTRO_NAME\e[0m"
# Traduit le dossier du script en chemin WSL.
SCRIPT_DIR_WIN="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -W)"
SCRIPT_PATH_WSL=$(MSYS_NO_PATHCONV=1 wsl.exe -d "$DISTRO_NAME" -u root -- \
wslpath "$(echo "$SCRIPT_DIR_WIN" | sed 's|/|\\\\|g')/build.sh" \
2>/dev/null | tr -d '\r\n')
[ -n "$SCRIPT_PATH_WSL" ] || {
echo -e "\e[31mTraduction du chemin vers WSL échouée (wslpath). Vérifie ARCH_WSL_DISTRO ($DISTRO_NAME).\e[0m" >&2
exit 1
}
wsl.exe -d "$DISTRO_NAME" -u root -- test -f "$SCRIPT_PATH_WSL" || {
echo -e "\e[31mScript introuvable dans WSL : $SCRIPT_PATH_WSL\e[0m" >&2
exit 1
}
# Relance ce même script dans WSL, en root, depuis son vrai chemin
# (BASH_SOURCE → WORK_DIR correct). Les fins de ligne sont garanties LF
# par .gitattributes (*.sh text eol=lf) ; le profil copié est en plus
# passé à dos2unix plus loin.
echo "==> Script à exécuter dans WSL : $SCRIPT_PATH_WSL"
MSYS_NO_PATHCONV=1 wsl.exe -d "$DISTRO_NAME" -u root -- bash "$SCRIPT_PATH_WSL"
exit 0
fi
if [ -z "$IN_WSL" ]; then
# ── Depuis Git Bash ──────────────────────────────────────
SCRIPT_DIR_WIN="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -W)"
WORK_DIR_WSL=$(MSYS_NO_PATHCONV=1 wsl.exe -d "$DISTRO_NAME" -u root -- \
wslpath "$(echo "$SCRIPT_DIR_WIN" | sed 's|/|\\\\|g')" 2>/dev/null | tr -d '\r\n')
# ============================================================
# Bascule conteneur : hôte non-Arch (Fedora, Ubuntu, …) →
# build dans un conteneur Arch via podman.
#
# mkarchiso exige pacman + des mounts/chroot/loop privilégiés que
# seul un environnement Arch fournit. Sur un hôte non-Arch on relance
# CE script à l'identique dans docker.io/library/archlinux:latest, le
# dépôt monté au MÊME chemin absolu (→ WORK_DIR et out/ inchangés).
# podman ROOTFUL + --privileged obligatoire : rootless ne gère pas les
# mounts/chroot de mkarchiso (et --privileged relâche aussi SELinux,
# enforcing sur Fedora, sur le bind-mount sans avoir besoin de :Z).
# ============================================================
host_is_arch() {
# Fedora empaquette aussi « pacman » → sa seule présence ne suffit pas ;
# on exige en plus un ID/ID_LIKE « arch » dans /etc/os-release.
command -v pacman >/dev/null 2>&1 \
&& grep -qiE '^ID(_LIKE)?=.*arch' /etc/os-release 2>/dev/null
}
echo "==> Dossier de travail WSL : $WORK_DIR_WSL"
if [ -z "$FWS_IN_CONTAINER" ] && ! host_is_arch; then
echo -e "\e[36mHôte non-Arch détecté — build dans un conteneur Arch (podman)...\e[0m"
MSYS_NO_PATHCONV=1 wsl.exe -d "$DISTRO_NAME" -u root -- bash << EOF
set -e
WORK_DIR="${WORK_DIR_WSL}"
echo "==> Dossier de travail : \$WORK_DIR"
command -v podman >/dev/null 2>&1 || {
echo -e "\e[31mpodman introuvable.\e[0m" >&2
echo " Fedora : sudo dnf install -y podman" >&2
echo " Debian/Ubuntu : sudo apt install -y podman" >&2
exit 1
}
# Rootful : préfixe sudo si on n'est pas déjà root.
SUDO=(); [ "$EUID" -eq 0 ] || SUDO=(sudo)
# -it seulement si on est dans un terminal (sinon podman casse en CI).
TTY=(); [ -t 0 ] && TTY=(-it)
REPO_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
SELF="$(basename "${BASH_SOURCE[0]}")"
IMAGE="docker.io/library/archlinux:latest"
# pull explicite : « run » ne re-résout jamais le tag « latest » une fois
# l'image en cache → sans ça on build indéfiniment sur une image qui
# vieillit (puis partial upgrades pacman). Le -Syu côté conteneur (plus
# bas) complète la parade.
echo "==> Pull de l'image $IMAGE..."
"${SUDO[@]}" podman pull "$IMAGE"
echo "==> Relance dans le conteneur ($SELF)..."
# --network=host : le réseau bridge de podman ne route plus vers l'extérieur
# sur ce wifi (firewalld/NAT cassé après changement de réseau → « core.db :
# Resolving timed out », même avec --dns). En partageant la pile réseau de
# l'hôte (qui, lui, a internet + DNS via 127.0.0.53/systemd-resolved joignable
# dans son propre netns), le conteneur récupère une connectivité identique.
"${SUDO[@]}" podman run --rm "${TTY[@]}" --network=host --privileged \
-e FWS_IN_CONTAINER=1 \
-v "$REPO_DIR":"$REPO_DIR" \
-v fws-pacman-cache:/var/cache/pacman/pkg \
-w "$REPO_DIR" \
"$IMAGE" \
bash "$REPO_DIR/$SELF"
# podman rootful → les fichiers produits (out/) appartiennent à root.
# On les rend au propriétaire du dépôt pour confort côté hôte.
OWNER="$(stat -c '%u:%g' "$REPO_DIR" 2>/dev/null || true)"
if [ -n "$OWNER" ]; then
for d in out local-repo; do
[ -e "$REPO_DIR/$d" ] && "${SUDO[@]}" chown -R "$OWNER" "$REPO_DIR/$d" 2>/dev/null || true
done
fi
exit 0
fi
# ============================================================
# Exécution native (Arch Linux bare-metal, WSL, OU conteneur Arch)
# ============================================================
command -v pacman >/dev/null \
|| { echo -e "\e[31mpacman introuvable — lance ce script depuis Arch / WSL.\e[0m"; exit 1; }
# mkarchiso exige root. Sur Arch natif on s'élève (sudo de préférence,
# sinon su) ; depuis la bascule Git Bash on est déjà root (-u root).
# $0 est cité pour gérer les chemins à espaces (ex. "1. FWS").
if [ "$EUID" -ne 0 ]; then
if command -v sudo >/dev/null 2>&1; then
exec sudo bash "$0" "$@"
else
exec su -c "bash \"$0\"" root
fi
fi
if grep -qi 'microsoft\|wsl' /proc/version 2>/dev/null; then
echo -e "\e[36mBuild exécuté dans WSL ($DISTRO_NAME) en tant que root...\e[0m"
IS_WSL=1
else
echo -e "\e[36mBuild exécuté sur Arch Linux natif en tant que root...\e[0m"
IS_WSL=0
fi
# Le dossier de travail = dossier qui contient ce script (gère les
# espaces du chemin, ex. "1. FWS").
WORK_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
echo "==> Dossier de travail : $WORK_DIR"
# pacman ≥ 7 sandboxe les ops FS via landlock, non supporté par le kernel
# WSL ni (selon le noyau) par le conteneur → désactivation. Idempotent,
# sans effet sur Arch natif.
if { [ "$IS_WSL" -eq 1 ] || [ -n "$FWS_IN_CONTAINER" ]; } \
&& ! grep -qE '^[[:space:]]*DisableSandbox' /etc/pacman.conf; then
sed -i '/^\[options\]/a DisableSandbox' /etc/pacman.conf
echo "==> WSL/conteneur détecté → DisableSandbox ajouté à /etc/pacman.conf"
fi
echo "==> Mise à jour des miroirs et installation de archiso..."
pacman -Sy --noconfirm reflector || true
reflector --verbose --latest 10 --sort rate --save /etc/pacman.d/mirrorlist || true
pacman -Sy --noconfirm archiso
if [ -n "$FWS_IN_CONTAINER" ]; then
# Image de base qui vieillit → upgrade complet AVANT d'ajouter archiso,
# sinon partial upgrade (archiso tire des deps plus récentes que la base).
pacman -Syu --noconfirm archiso
else
pacman -Sy --noconfirm archiso
fi
echo "==> Préparation de l'environnement de build..."
rm -rf /tmp/fws-build
mkdir -p /tmp/fws-build/releng
# Copie configs/releng/ en base
if [ -d "\$WORK_DIR/configs/releng" ]; then
cp -ar "\$WORK_DIR/configs/releng/"* /tmp/fws-build/releng/
if [ -d "$WORK_DIR/configs/releng" ]; then
cp -ar "$WORK_DIR/configs/releng/"* /tmp/fws-build/releng/
echo "==> configs/releng/ copié"
fi
# Fusionne configs/baseline/ par dessus (priorité aux fichiers baseline)
if [ -d "\$WORK_DIR/configs/baseline" ]; then
cp -ar "\$WORK_DIR/configs/baseline/"* /tmp/fws-build/releng/
if [ -d "$WORK_DIR/configs/baseline" ]; then
cp -ar "$WORK_DIR/configs/baseline/"* /tmp/fws-build/releng/
echo "==> configs/baseline/ fusionné (prioritaire)"
fi
echo "==> Activation de NetworkManager.service sur le live (symlink réel WSL)..."
echo "==> Activation de NetworkManager.service sur le live (symlink réel)..."
mkdir -p /tmp/fws-build/releng/airootfs/etc/systemd/system/multi-user.target.wants
ln -sf /usr/lib/systemd/system/NetworkManager.service \
/tmp/fws-build/releng/airootfs/etc/systemd/system/multi-user.target.wants/NetworkManager.service
@@ -57,85 +232,9 @@ echo "==> Vérification des services systemd..."
ls /tmp/fws-build/releng/airootfs/etc/systemd/system/ 2>/dev/null || echo " (aucun service)"
ls /tmp/fws-build/releng/airootfs/etc/systemd/system/multi-user.target.wants/ 2>/dev/null || echo " (aucun symlink)"
# Copie le repo local (calamares + winboat-bin)
if ls "\$WORK_DIR/local-repo/"*.pkg.tar.zst &>/dev/null 2>&1; then
echo "==> Copie du repo local Calamares..."
mkdir -p /tmp/fws-build/local-repo
cp -a "\$WORK_DIR/local-repo/"* /tmp/fws-build/local-repo/
echo "==> Injection [fws-local] dans pacman.conf..."
sed -i '/^\[fws-local\]/,/^$/d' /tmp/fws-build/releng/pacman.conf
PACMAN_TMP=\$(mktemp)
printf '[fws-local]\nSigLevel = Optional TrustAll\nServer = file:///tmp/fws-build/local-repo\n\n' \
> "\$PACMAN_TMP"
cat /tmp/fws-build/releng/pacman.conf >> "\$PACMAN_TMP"
mv "\$PACMAN_TMP" /tmp/fws-build/releng/pacman.conf
echo "==> Vérification pacman.conf :"
head -5 /tmp/fws-build/releng/pacman.conf
else
echo "==> Aucun repo local détecté."
fi
echo "==> Correction des retours à la ligne Windows (dos2unix)..."
pacman -S --needed --noconfirm dos2unix
find /tmp/fws-build/releng -type f -exec dos2unix {} + 2>/dev/null
echo "==> Lancement de mkarchiso..."
# Simulation Try/Catch en Bash pour l'écriture du fichier ISO
TARGET_OUT="\$WORK_DIR/out"
mkdir -p "\$TARGET_OUT" 2>/dev/null || true
if [ -w "\$TARGET_OUT" ]; then
mkarchiso -v -w /tmp/fws-build/work -o "\$TARGET_OUT" /tmp/fws-build/releng
echo "==> Build terminé ! ISO dans \$TARGET_OUT"
else
echo -e "\e[33m[Attention] Impossible d'écrire dans \$TARGET_OUT. Utilisation d'un dossier temporaire de secours...\e[0m"
BACKUP_OUT="/tmp/fws-out-backup"
mkdir -p "\$BACKUP_OUT"
mkarchiso -v -w /tmp/fws-build/work -o "\$BACKUP_OUT" /tmp/fws-build/releng
echo -e "\e[32m==> Build terminé ! ISO sauvegardée en sécurité dans : \$BACKUP_OUT\e[0m"
fi
echo "==> Nettoyage..."
rm -rf /tmp/fws-build/work
EOF
else
# ── Déjà dans WSL ────────────────────────────────────────
WORK_DIR="$PWD"
echo "==> Dossier de travail : $WORK_DIR"
echo "==> Mise à jour et installation de archiso..."
pacman -Sy --noconfirm reflector || true
reflector --verbose --latest 10 --sort rate --save /etc/pacman.d/mirrorlist || true
pacman -Sy --noconfirm archiso
echo "==> Préparation de l'environnement de build..."
rm -rf /tmp/fws-build
mkdir -p /tmp/fws-build/releng
if [ -d "$WORK_DIR/configs/releng" ]; then
cp -ar "$WORK_DIR/configs/releng/"* /tmp/fws-build/releng/
echo "==> configs/releng/ copié"
fi
if [ -d "$WORK_DIR/configs/baseline" ]; then
cp -ar "$WORK_DIR/configs/baseline/"* /tmp/fws-build/releng/
echo "==> configs/baseline/ fusionné (prioritaire)"
fi
echo "==> Activation de NetworkManager.service sur le live (symlink réel)..."
mkdir -p /tmp/fws-build/releng/airootfs/etc/systemd/system/multi-user.target.wants
ln -sf /usr/lib/systemd/system/NetworkManager.service \
/tmp/fws-build/releng/airootfs/etc/systemd/system/multi-user.target.wants/NetworkManager.service
echo "==> Vérification des services systemd..."
ls /tmp/fws-build/releng/airootfs/etc/systemd/system/ 2>/dev/null || echo " (aucun service)"
ls /tmp/fws-build/releng/airootfs/etc/systemd/system/multi-user.target.wants/ 2>/dev/null || echo " (aucun symlink)"
if ls "$WORK_DIR/local-repo/"*.pkg.tar.zst &>/dev/null 2>&1; then
echo "==> Copie du repo local Calamares..."
# Copie le repo local (winboat-bin + deps Anaconda packagées)
if ls "$WORK_DIR/local-repo/"*.pkg.tar.zst &>/dev/null 2>&1; then
echo "==> Copie du repo local fws-local..."
mkdir -p /tmp/fws-build/local-repo
cp -a "$WORK_DIR/local-repo/"* /tmp/fws-build/local-repo/
@@ -149,32 +248,40 @@ else
echo "==> Vérification pacman.conf :"
head -5 /tmp/fws-build/releng/pacman.conf
else
else
echo "==> Aucun repo local détecté."
fi
echo "==> Correction des retours à la ligne Windows (dos2unix)..."
pacman -S --needed --noconfirm dos2unix
find /tmp/fws-build/releng -type f -exec dos2unix {} + 2>/dev/null
echo "==> Lancement de mkarchiso..."
# Simulation Try/Catch en Bash pour l'écriture du fichier ISO
TARGET_OUT="$WORK_DIR/out"
mkdir -p "$TARGET_OUT" 2>/dev/null || true
if [ -w "$TARGET_OUT" ]; then
mkarchiso -v -w /tmp/fws-build/work -o "$TARGET_OUT" /tmp/fws-build/releng
echo "==> Build terminé ! ISO dans $TARGET_OUT"
else
echo -e "\e[33m[Attention] Impossible d'écrire dans $TARGET_OUT. Utilisation d'un dossier temporaire de secours...\e[0m"
BACKUP_OUT="/tmp/fws-out-backup"
mkdir -p "$BACKUP_OUT"
mkarchiso -v -w /tmp/fws-build/work -o "$BACKUP_OUT" /tmp/fws-build/releng
echo -e "\e[32m==> Build terminé ! ISO sauvegardée en sécurité dans : $BACKUP_OUT\e[0m"
fi
echo "==> Nettoyage..."
rm -rf /tmp/fws-build/work
fi
echo "==> Correction des retours à la ligne Windows (dos2unix)..."
pacman -S --needed --noconfirm dos2unix
find /tmp/fws-build/releng -type f -exec dos2unix {} + 2>/dev/null
echo "==> Lancement de mkarchiso..."
mkdir -p "$WORK_DIR/out"
# mkarchiso fait un « rm » interne de l'ISO cible avant de la (ré)écrire ; si
# une ISO du même nom est VERROUILLÉE par Windows (VM encore ouverte dessus,
# ISO montée, antivirus), ce rm échoue et tout le build casse à la toute fin.
# Parade : mkarchiso écrit dans un dossier de staging neuf, puis on déplace
# l'ISO. Si la cible est verrouillée, on bascule sur un nom horodaté → le
# build réussit quand même au lieu de tout perdre.
STAGE="$WORK_DIR/out/.staging-$$"
rm -rf "$STAGE"; mkdir -p "$STAGE"
mkarchiso -v -w /tmp/fws-build/work -o "$STAGE" /tmp/fws-build/releng
NEW_ISO="$(ls -1 "$STAGE/"*.iso 2>/dev/null | head -1)"
[ -n "$NEW_ISO" ] || { echo -e "\e[31mAucune ISO produite par mkarchiso.\e[0m" >&2; exit 1; }
DEST="$WORK_DIR/out/$(basename "$NEW_ISO")"
if { chmod -f 666 "$DEST" 2>/dev/null; rm -f "$DEST" 2>/dev/null; } && mv -f "$NEW_ISO" "$DEST" 2>/dev/null; then
FINAL="$DEST"
else
FINAL="$WORK_DIR/out/$(basename "${NEW_ISO%.iso}")-$(date +%H%M%S).iso"
echo -e "\e[33m[!] '$DEST' est verrouillée (une VM l'utilise ?). Écriture sous un nom unique.\e[0m" >&2
mv -f "$NEW_ISO" "$FINAL"
fi
rm -rf "$STAGE" 2>/dev/null || true
echo "==> Nettoyage..."
rm -rf /tmp/fws-build/work
echo "==> Build terminé ! ISO : $FINAL"
echo -e "\e[32mScript de build terminé avec succès.\e[0m"
@@ -1,40 +0,0 @@
# ============================================================
# FWS Linux — branding.desc
# ============================================================
componentName: fws
strings:
productName: "FWS"
shortProductName: "FWS"
version: "1.0"
shortVersion: "1.0"
versionedName: "FWS 1.0"
shortVersionedName: "FWS 1.0"
bootloaderEntryName: "FWS"
productUrl: ""
supportUrl: ""
releaseNotesUrl: ""
donateUrl: ""
images:
productLogo: "logo.png"
productIcon: "logo.png"
productWelcome: "logo.png"
slideshow: "slideshow.qml"
slideshowAPI: 2
style:
# Couleurs de la sidebar
sidebarBackground: "#1a1a2e"
sidebarText: "#e0e0e0"
sidebarTextHighlight: "#00d4ff"
sidebarSelect: "#16213e"
# Couleurs générales
backgroundColor: "#0f3460"
highlightedTextColor: "#ffffff"
genericTextColor: "#e0e0e0"
errorTextColor: "#ff6b6b"
warningTextColor: "#ffa500"
Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

@@ -1,138 +0,0 @@
/* ============================================================
FWS Linux — slideshow.qml
Affiché pendant l'installation
============================================================ */
import QtQuick 2.0
import calamares.slideshow 1.0
Presentation {
id: presentation
function nextSlide() {
if (presentation.currentSlide < slides.count - 1)
presentation.currentSlide++
else
presentation.currentSlide = 0
}
Timer {
id: timer
interval: 4000
repeat: true
running: true
onTriggered: nextSlide()
}
Slide {
anchors.fill: parent
Rectangle {
anchors.fill: parent
color: "#1a1a2e"
Column {
anchors.centerIn: parent
spacing: 20
Text {
text: "🚀 Bienvenue sur FWS Linux"
color: "#00d4ff"
font.pixelSize: 32
font.bold: true
anchors.horizontalCenter: parent.horizontalCenter
}
Text {
text: "Un système rapide, léger et puissant."
color: "#e0e0e0"
font.pixelSize: 18
anchors.horizontalCenter: parent.horizontalCenter
}
}
}
}
Slide {
anchors.fill: parent
Rectangle {
anchors.fill: parent
color: "#16213e"
Column {
anchors.centerIn: parent
spacing: 20
Text {
text: "⚡ Basé sur Arch Linux"
color: "#00d4ff"
font.pixelSize: 32
font.bold: true
anchors.horizontalCenter: parent.horizontalCenter
}
Text {
text: "Accès à l'AUR et aux derniers paquets."
color: "#e0e0e0"
font.pixelSize: 18
anchors.horizontalCenter: parent.horizontalCenter
}
}
}
}
Slide {
anchors.fill: parent
Rectangle {
anchors.fill: parent
color: "#0f3460"
Column {
anchors.centerIn: parent
spacing: 20
Text {
text: "🛡️ Sécurité & Stabilité"
color: "#00d4ff"
font.pixelSize: 32
font.bold: true
anchors.horizontalCenter: parent.horizontalCenter
}
Text {
text: "FWS est conçu pour être robuste et fiable."
color: "#e0e0e0"
font.pixelSize: 18
anchors.horizontalCenter: parent.horizontalCenter
}
}
}
}
Slide {
anchors.fill: parent
Rectangle {
anchors.fill: parent
color: "#1a1a2e"
Column {
anchors.centerIn: parent
spacing: 20
Text {
text: "✅ Installation en cours..."
color: "#00d4ff"
font.pixelSize: 32
font.bold: true
anchors.horizontalCenter: parent.horizontalCenter
}
Text {
text: "Merci de patienter, FWS s'installe sur votre machine."
color: "#e0e0e0"
font.pixelSize: 18
anchors.horizontalCenter: parent.horizontalCenter
}
}
}
}
}
@@ -1,18 +0,0 @@
---
efiBootLoader: "grub"
kernel: "/vmlinuz-linux"
img: "/initramfs-linux.img"
fallback: "/initramfs-linux-fallback.img"
timeout: "5"
grubInstall: "grub-install"
grubMkconfig: "grub-mkconfig"
grubCfg: "/boot/grub/grub.cfg"
grubProbe: "grub-probe"
efiBootMgr: "efibootmgr"
efiDirectory: "/boot/efi"
efiBootloaderId: "FWS"
installEFIFallback: true
@@ -1,6 +0,0 @@
---
restartNowEnabled: true
restartNowChecked: false
restartNowCommand: "systemctl -i reboot"
notifyOnFinished: true
@@ -1,13 +0,0 @@
---
mountOptions:
default: defaults,noatime
btrfs: defaults,noatime,compress=zstd,space_cache=v2
ssdExtraMountOptions:
ext4: discard
jfs: discard
xfs: discard
swap: discard
btrfs: discard=async
crypttabOptions: luks,keyscript=/bin/cat
@@ -1,13 +0,0 @@
---
overwrite: true
kernel_params:
- "quiet"
defaults:
GRUB_TIMEOUT: 5
GRUB_DEFAULT: "saved"
GRUB_DISABLE_SUBMENU: true
GRUB_TERMINAL_OUTPUT: "console"
GRUB_DISABLE_RECOVERY: true
GRUB_DISTRIBUTOR: "FWS"
@@ -1,6 +0,0 @@
---
location: EtcFile
writeHostsFile: true
setSystemdHostname: EtcFile
template: "fws-${first}"
@@ -1 +0,0 @@
---
@@ -1,19 +0,0 @@
---
# Hooks par défaut Arch + support clavier/LUKS avant block/filesystems.
modules: []
binaries: []
files: []
hooks:
- base
- udev
- autodetect
- microcode
- modconf
- kms
- keyboard
- keymap
- consolefont
- block
- filesystems
- fsck
@@ -1,6 +0,0 @@
---
xOrgConfFileName: "00-keyboard.conf"
convertedKeymapPath: "/usr/share/X11/xkb/symbols/pc"
keyboardLayout: "fr"
keyboardVariant: ""
keyboardModel: "pc105"
@@ -1,6 +0,0 @@
---
region: "Europe"
zone: "Paris"
localeGenPath: "/etc/locale.gen"
geoipStyle: "json"
geoipUrl: "https://geoip.kde.org/v1/calamares"
@@ -1 +0,0 @@
---
@@ -1,4 +0,0 @@
---
systemd: true
dbus: true
dbus-symlink: true
@@ -1,25 +0,0 @@
---
extraMounts:
- device: proc
fs: proc
mountPoint: /proc
- device: sys
fs: sysfs
mountPoint: /sys
- device: /dev
mountPoint: /dev
options: [bind]
- device: /dev/pts
fs: devpts
mountPoint: /dev/pts
- device: tmpfs
fs: tmpfs
mountPoint: /run
- device: /run/udev
mountPoint: /run/udev
options: [bind]
extraMountsEfi:
- device: efivarfs
fs: efivarfs
mountPoint: /sys/firmware/efi/efivars
@@ -1,2 +0,0 @@
---
# Copie /etc/NetworkManager du live vers le système cible (NM gérera le réseau).
@@ -1,16 +0,0 @@
---
# Étape post-unpackfs : on retire les paquets qui ne servent que dans
# l'ISO live (installeur + outils archiso). Les paquets utiles sont déjà
# présents sur le système cible parce qu'unpackfs a copié tout le live.
backend: pacman
update_db: false
update_system: false
operations:
- remove:
- calamares
- kpmcore
- archinstall
- livecd-sounds
- mkinitcpio-archiso
@@ -1,22 +0,0 @@
---
efiSystemPartition: "/boot/efi"
efiSystemPartitionSize: 300M
efiSystemPartitionName: EFI
userSwapChoices:
- none
- small
- suspend
- file
drawNestedPartitions: true
alwaysShowPartitionLabels: true
initialPartitioningChoice: replace
initialSwapChoice: small
defaultFileSystemType: "ext4"
availableFileSystemTypes: ["ext4", "btrfs", "xfs", "f2fs"]
enableLuksAutomatedPartitioning: true
allowManualPartitioning: true
@@ -1,15 +0,0 @@
---
services:
- name: NetworkManager
mandatory: true
- name: systemd-resolved
mandatory: true
- name: systemd-timesyncd
mandatory: true
- name: sshd
mandatory: false
targets: []
@@ -1,9 +0,0 @@
---
# Copie le squashfs du live vers le disque cible.
# Le chemin /run/archiso/bootmnt/<install_dir>/<arch>/airootfs.sfs
# doit correspondre à `install_dir` dans configs/releng/profiledef.sh ("fws").
unpack:
- source: "/run/archiso/bootmnt/fws/x86_64/airootfs.sfs"
sourcefs: "squashfs"
destination: ""
@@ -1,24 +0,0 @@
---
defaultGroups:
- wheel
- audio
- video
- network
- storage
- power
- lp
- scanner
autologinGroup: autologin
sudoersGroup: wheel
setRootPassword: true
doAutologin: false
userShell: /bin/bash
passwordRequirements:
minLength: 6
maxLength: -1
nonempty: true
allowWeakPasswords: false
allowWeakPasswordsDefault: false
@@ -1,20 +0,0 @@
---
showSupportUrl: true
showKnownIssuesUrl: true
showReleaseNotesUrl: false
showDonateUrl: false
requirements:
requiredStorage: 8.0
requiredRam: 1.5
internetCheckUrl: "https://archlinux.org"
check:
- storage
- ram
- power
- root
- screen
required:
- storage
- ram
- root
@@ -1,45 +0,0 @@
---
# ============================================================
# FWS — Calamares settings
# ============================================================
modules-search: [ local, /usr/lib/calamares/modules ]
sequence:
- show:
- welcome
- locale
- keyboard
- partition
- users
- summary
- exec:
- partition
- mount
- unpackfs
- machineid
- fstab
- locale
- keyboard
- localecfg
- users
- hostname
- hwclock
- networkcfg
- initcpiocfg
- initcpio
- grubcfg
- bootloader
- packages
- services-systemd
- umount
- show:
- finished
branding: fws
prompt-install: true
dont-chroot: false
oem-setup: false
disable-cancel: false
disable-cancel-during-exec: false
@@ -0,0 +1,16 @@
# FWS — force le plugin LVM de libblockdev en mode CLI (libbd_lvm.so) au lieu
# du mode DBus (libbd_lvm-dbus.so).
#
# POURQUOI : libblockdev 3.x sur Arch charge par défaut la variante LVM qui
# pilote le démon « lvmdbusd » (service DBus com.redhat.lvmdbus1). Or Arch ne
# package PAS lvmdbusd (lvm2 ne livre ni le binaire ni le .service DBus). Quand
# Anaconda/blivet peuple l'arbre des périphériques, blivet appelle
# blockdev.lvm.lvs() → la variante DBus tente d'activer com.redhat.lvmdbus1 →
# GDBus.Error:org.freedesktop.DBus.Error.ServiceUnknown: name is not activatable
# ce qui FAIT PLANTER Anaconda au démarrage.
#
# La variante CLI (libbd_lvm.so) parle directement aux binaires LVM (lvs, vgs…)
# sans démon → fonctionne sans lvmdbusd. Ce fichier conf.d (numéro élevé → lu
# après 00-default.cfg) force ce choix de façon fiable.
[lvm]
sonames=libbd_lvm.so.3
+10
View File
@@ -0,0 +1,10 @@
# FWS — locales à générer dans l'ISO (par locale-gen, via le hook pacman
# etc/pacman.d/hooks/zzz-fws-locale-gen.hook au moment du pacstrap).
#
# en_US.UTF-8 est REQUIS par Anaconda : ses modules DBus font
# locale.setlocale(LC_ALL, "en_US.UTF-8") (DEFAULT_LANG)
# au démarrage → sans cette locale générée : « locale.Error: unsupported
# locale setting » et le module Boss sort en status 1 (installateur planté).
# C.UTF-8 (la locale par défaut du live, cf. locale.conf) est intégrée à la
# glibc et n'a pas besoin d'être générée.
en_US.UTF-8 UTF-8
@@ -0,0 +1,28 @@
# FWS — expose la base squashfs du live à /run/rootfsbase.
#
# POURQUOI : avec --liveinst, Anaconda utilise le payload « LiveOS » qui RECOPIE
# le système live en cours sur le disque. Sa tâche DetectLiveOSImageTask cherche
# l'image de base à /dev/mapper/live-base, /dev/mapper/live-osimg-min ou
# /run/rootfsbase (conventions dracut-live de Fedora). archiso n'en crée AUCUNE
# → « SourceSetupError: No Live OS image found! » et l'installateur plante.
#
# archiso a pourtant la squashfs (montée en lecture seule sur /run/archiso/
# airootfs). On la remonte ici en loop sur /run/rootfsbase pour qu'Anaconda la
# détecte : findmnt -o SOURCE /run/rootfsbase → /dev/loopN, qu'Anaconda monte
# puis recopie sur la cible (= installe FWS). Le %post du kickstart fait ensuite
# mkinitcpio + grub-install (bootloader --disabled côté Anaconda).
[Unit]
Description=FWS — base squashfs sur /run/rootfsbase (payload LiveOS Anaconda)
DefaultDependencies=no
After=local-fs.target
ConditionPathExists=/run/archiso/bootmnt/fws/x86_64/airootfs.sfs
ConditionPathIsMountPoint=!/run/rootfsbase
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/bin/mkdir -p /run/rootfsbase
ExecStart=/usr/bin/mount -o loop,ro /run/archiso/bootmnt/fws/x86_64/airootfs.sfs /run/rootfsbase
[Install]
WantedBy=multi-user.target
+239 -3
View File
@@ -1,6 +1,242 @@
#!/bin/sh
# Lancé par startx (cf. /root/.zprofile)
# Lancé par startx (cf. /root/.zprofile), uniquement dans le live FWS.
if [ ! -d /run/archiso ]; then
exit 0
fi
xsetroot -solid "#1a1a2e"
# Openbox en arrière-plan : gestionnaire de fenêtres pour l'installateur.
openbox &
sleep 1
exec calamares
_OB_PID=$!
# Chantier C : lance l'installateur Anaconda en mode live s'il est présent.
# « liveinst » re-exécute anaconda (ici on est déjà root → pas de pkexec/polkit).
#
# DEBUG (premier run réel) : on CAPTURE stdout+stderr — un plantage d'import
# précoce de Python n'apparaît QUE là, pas dans /tmp/anaconda.log — et, si
# liveinst quitte en erreur, on regroupe tous les logs Anaconda et on les AFFICHE
# (zenity) au lieu de laisser startx rendre la main → .zprofile relancerait X en
# boucle (symptôme « fond bleu qui clignote/reboote »). On NE rend jamais la main
# à startx : on reste sur Openbox pour lire les logs / rebooter proprement.
if command -v liveinst >/dev/null 2>&1; then
# Payload LiveOS : avec --liveinst (passé par liveinst), Anaconda IGNORE le
# payload du kickstart (anaconda.py teste opts.liveinst AVANT le type du
# payload DBus — un « liveimg » dans le ks serait du code mort) et détecte
# l'image live sur des chemins Fedora/dracut : /dev/mapper/live-base,
# /dev/mapper/live-osimg-min ou /run/rootfsbase — tous ABSENTS d'archiso →
# « SourceSetupError: No Live OS image found! » = crash au démarrage
# (reproduit hors VM dans un chroot de l'airootfs). On expose donc le
# squashfs archiso (monté ro sur /run/archiso/airootfs) là où Anaconda le
# cherche : findmnt y résout le loop device → montage → rsync vers la cible.
if [ -d /run/archiso/airootfs ] && [ ! -e /run/rootfsbase ]; then
mkdir -p /run/rootfsbase
mount --bind /run/archiso/airootfs /run/rootfsbase || rmdir /run/rootfsbase
fi
# GARDE-FOU RAM : le live n'a que le zram comme marge — en dessous de
# ~2 Go, Anaconda (GUI Python + squashfs) peut geler la machine en plein
# « Préparation de l'installateur ». On prévient AVANT plutôt que de
# laisser l'utilisateur croire à un bug.
_MEMKB=$(awk '/^MemTotal:/{print $2}' /proc/meminfo 2>/dev/null)
if [ -n "$_MEMKB" ] && [ "$_MEMKB" -lt 2000000 ] && command -v zenity >/dev/null 2>&1; then
zenity --warning --width=460 --title="FWS — mémoire insuffisante ?" \
--text="<b>Cette machine n'a que $(( _MEMKB / 1024 )) Mo de RAM.</b>\n\nL'installateur graphique peut geler en dessous de 2 Go.\nEn VM : augmente la mémoire (4 Go recommandés) puis redémarre.\n\nOK pour tenter quand même." 2>/dev/null
fi
# ÉCRAN D'ATTENTE immédiat : le démarrage d'anaconda peut prendre 2 à
# 4 minutes (observé en VM VMware : un worker udev se bloque au boot et
# n'est tué par udevd qu'après 45 s — udev.event_timeout). Sans feedback,
# l'utilisateur croit à une panne alors que TOUT va bien. Le splash montre
# EN DIRECT ce que fait anaconda : un nourrisseur écrit sur stdin de
# zenity --progress (« # texte » = mise à jour du libellé) le log anaconda
# le plus récemment modifié + son dernier message + un chrono. Si les logs
# ne bougent plus (vrai blocage), le libellé le DIT (au lieu d'une barre
# qui pulse pour rien) et, au-delà de 4 min d'inactivité, on collecte
# journal+dmesg dans /tmp/fws-stall.txt et on l'affiche : l'écran devient
# lui-même le rapport de bug. Le nourrisseur meurt par SIGPIPE quand le
# splash est tué à la sortie de liveinst.
_SPLASH_PID=""
if command -v zenity >/dev/null 2>&1; then
(
_el=0; _quiet=0; _prevstamp=""
while :; do
sleep 3
# GUI d'anaconda à l'écran (marqueur ui.gui) → le splash n'a
# plus de raison d'être et le watchdog DOIT se désarmer : des
# logs silencieux pendant que l'utilisateur remplit les écrans
# sont NORMAUX (bug vécu : le rapport « préparation bloquée »
# s'affichait PAR-DESSUS l'installateur au bout de 4 min).
if grep -q 'ui\.gui' /tmp/anaconda.log 2>/dev/null; then
pkill -f 'zenity --progress' 2>/dev/null
exit 0
fi
# Compteurs en itérations (pas d'heure murale : l'horloge du
# guest SAUTE en VM — resynchro RTC — et gonflerait les âges,
# vu en vrai : « 242 s d'inactivité » 90 s après le boot).
_el=$(( _el + 3 ))
_last=$(ls -t /tmp/storage.log /tmp/anaconda.log /tmp/program.log /tmp/dbus.log 2>/dev/null | head -n1)
if [ -z "$_last" ]; then
printf '# Démarrage d'"'"'Anaconda… (%d min %02d s)\n' $(( _el / 60 )) $(( _el % 60 )) || exit 0
continue
fi
_stamp=$(stat -c %Y "$_last" 2>/dev/null)
if [ "$_stamp" = "$_prevstamp" ]; then
_quiet=$(( _quiet + 3 ))
else
_quiet=0; _prevstamp="$_stamp"
fi
# Rebranding d'affichage : anaconda (installateur Fedora) parle
# de Fedora/Arch dans ses logs — on ne montre pas ça à l'écran.
_msg=$(tail -n1 "$_last" 2>/dev/null | tr -d '\r' \
| sed -E 's/Fedora( Linux)?/FWS/g; s/Arch Linux/FWS/g; s/\<Arch\>/FWS/g' \
| cut -c1-90)
if [ "$_quiet" -ge 240 ] && [ ! -f /tmp/fws-stall.txt ]; then
{
echo "=== FWS : préparation bloquée (aucune activité log depuis ${_quiet}s) ==="
echo "--- dernier log actif : $_last"; tail -n 25 "$_last" 2>/dev/null
echo "--- udev (workers bloqués ?)"; udevadm settle --timeout=0 2>&1
echo "--- journal (fin)"; journalctl -b --no-pager 2>/dev/null | tail -n 60
echo "--- dmesg (fin)"; dmesg 2>/dev/null | tail -n 40
} > /tmp/fws-stall.txt 2>&1
zenity --text-info --title="FWS — préparation bloquée : diagnostic" \
--filename=/tmp/fws-stall.txt --width=1000 --height=650 2>/dev/null &
fi
if [ "$_quiet" -ge 60 ]; then
printf '# ⚠ Aucune activité depuis %d s (%s) — dernier message : %s\n' "$_quiet" "$(basename "$_last")" "$_msg" || exit 0
else
printf '# Préparation (%d min %02d s) — %s : %s\n' $(( _el / 60 )) $(( _el % 60 )) "$(basename "$_last")" "$_msg" || exit 0
fi
done
) | zenity --progress --pulsate --no-cancel \
--title="FWS" \
--text="<b>Préparation de l'installateur FWS…</b>\n\nAnalyse du matériel et des disques en cours.\nEncore une à deux minutes, c'est normal." \
--width=560 2>/dev/null &
_SPLASH_PID=$!
fi
# Hub Résumé SANS le libellé « We won't touch your disks… » : notre glade
# modifié NE PEUT PAS être livré directement à son chemin final —
# mkarchiso pose l'overlay airootfs AVANT pacstrap, et pacman refuse
# alors d'installer anaconda par-dessus (« exists in filesystem »). On le
# livre donc sous /usr/local/share/fws et on ÉCRASE ici, au boot du live
# (l'overlay du live est inscriptible), le fichier du paquet.
if [ -f /usr/local/share/fws/anaconda-summary-hub.glade ]; then
cp -f /usr/local/share/fws/anaconda-summary-hub.glade \
/usr/share/anaconda/ui/hubs/summary.glade 2>/dev/null || true
fi
# BRANDING : sans /.buildstamp, anaconda s'appelle « anaconda bluesky »
# (défauts de pyanaconda/core/product.py) et ses logs parlent de Fedora.
# Les variables d'environnement ANACONDA_* ont priorité → l'en-tête
# devient « FWS 1.0 INSTALLATION » et le log « anaconda … for FWS started ».
# (Les mentions Fedora PROFONDES dans les logs — GeoIP, profils — restent :
# ce sont des chaînes internes de l'installateur, sans effet sur l'install.)
export ANACONDA_PRODUCTNAME="$(. /etc/os-release 2>/dev/null; echo "${NAME:-FWS}")"
export ANACONDA_PRODUCTVERSION="$(. /etc/os-release 2>/dev/null; echo "${VERSION_ID:-0.6}")"
export ANACONDA_ISFINAL=true
LIVEINST_LOG=/tmp/fws-liveinst.log
# Bus D-Bus de SESSION : au démarrage (--liveinst), inhibit_screensaver()
# de pyanaconda se connecte au bus de session. S'il n'y en a AUCUN (notre
# startx root minimal n'en garantit pas), Gio lève une GLib.GError que
# pyanaconda n'attrape PAS (il n'attrape que DBusError) → crash immédiat
# (2e crash reproduit hors VM). dbus-run-session fournit un bus de session
# pour toute la durée de l'installateur ; avec un bus présent, l'absence du
# service ScreenSaver est attrapée (simple warning dans anaconda.log).
if command -v dbus-run-session >/dev/null 2>&1 && [ -z "${DBUS_SESSION_BUS_ADDRESS:-}" ]; then
dbus-run-session -- liveinst >"$LIVEINST_LOG" 2>&1
else
liveinst >"$LIVEINST_LOG" 2>&1
fi
rc=$?
# liveinst terminé (install finie ou échec) : le splash n'a plus de raison
# d'être — kill de zenity ; le nourrisseur meurt de SIGPIPE à son
# prochain printf. Idem pour un éventuel dialogue de diagnostic de stall.
if [ -n "$_SPLASH_PID" ]; then
pkill -P "$_SPLASH_PID" 2>/dev/null
kill "$_SPLASH_PID" 2>/dev/null
fi
pkill -f "fws-stall.txt" 2>/dev/null
# ATTENTION : liveinst NE propage PAS le code de sortie d'anaconda — il
# enchaîne son propre nettoyage et sort souvent 0 même quand anaconda a
# planté. On ne se fie donc PAS à $rc : en phase debug on regroupe TOUS les
# logs et on les affiche systématiquement (zenity). Le traceback Python d'un
# crash d'import précoce n'est QUE dans $LIVEINST_LOG (stderr capturé).
# Log du %post chrooté (grub-install / mkinitcpio) = CE qui rend le disque
# bootable. Le kickstart en copie une version dans le LIVE
# (/tmp/fws-post-chroot.log, via un %post --nochroot final, cible encore
# montée → fiable). SECOURS si absent : on réactive le LVM (pvscan/vgscan
# rescannent les PV qu'Anaconda a désactivés) et on remonte le disque pour
# le lire.
if [ ! -s /tmp/fws-post-chroot.log ]; then
pvscan --cache >/dev/null 2>&1 || true
vgscan --mknodes >/dev/null 2>&1 || true
vgchange -ay >/dev/null 2>&1 || true
udevadm settle --timeout=10 >/dev/null 2>&1 || true
mkdir -p /run/fws-installed
for _dev in /dev/mapper/*-root /dev/mapper/* /dev/sd*[0-9] /dev/vd*[0-9] /dev/nvme*n*p*; do
[ -b "$_dev" ] || continue
mount -o ro "$_dev" /run/fws-installed 2>/dev/null || continue
if [ -f /run/fws-installed/var/log/fws-post.log ]; then
cp -f /run/fws-installed/var/log/fws-post.log /tmp/fws-post-chroot.log 2>/dev/null
umount /run/fws-installed 2>/dev/null || true
break
fi
umount /run/fws-installed 2>/dev/null || true
done
fi
DBG=/tmp/fws-debug.txt
{
echo "===== liveinst sorti (code $rc) — logs Anaconda ====="
echo
echo "########## sortie liveinst (stdout+stderr) ##########"
cat "$LIVEINST_LOG" 2>/dev/null
echo
echo "########## %post chrooté = grub-install / mkinitcpio ##########"
echo "########## >>> C'EST CE BLOC QUI DIT SI LE DISQUE VA BOOTER <<< ##########"
cat /tmp/fws-post-chroot.log 2>/dev/null || echo "(log introuvable)"
echo
echo "########## %post --nochroot (/tmp/fws-post-nochroot.log) ##########"
cat /tmp/fws-post-nochroot.log 2>/dev/null || echo "(absent)"
echo
echo "########## Récapitulatif (page GUI fws_recap, avant install) ##########"
cat /tmp/fws-hw-summary.txt 2>/dev/null || echo "(absent — page récap pas atteinte)"
for f in /tmp/anaconda.log /tmp/syslog /tmp/program.log \
/tmp/storage.log /tmp/dbus.log /tmp/packaging.log /tmp/X.log; do
echo
echo "########## $f ##########"
tail -n 200 "$f" 2>/dev/null || echo "(absent)"
done
} >"$DBG" 2>&1
# Succès d'install = les DEUX étapes qui rendent le disque bootable ont
# réussi dans le %post : mkinitcpio (« Initcpio image generation successful »)
# ET grub-install (« Installation finished. No error reported. »). Si oui →
# on montre un écran de RÉUSSITE et on éteint (l'utilisateur retire l'ISO puis
# rallume sur FWS). Sinon → on affiche tous les logs de debug (comportement
# debug). Les lignes cosmétiques (load_policy, warnings GTK…) n'influent PAS
# sur cette détection : on ne regarde que le log du %post.
if grep -q 'Initcpio image generation successful' /tmp/fws-post-chroot.log 2>/dev/null \
&& grep -q 'Installation finished. No error reported.' /tmp/fws-post-chroot.log 2>/dev/null; then
if command -v zenity >/dev/null 2>&1; then
zenity --info --width=480 --title="FWS — installation réussie ✅" \
--text="<b>FWS est installé sur le disque.</b>\n\n1. Clique OK pour <b>éteindre</b> la machine.\n2. <b>Retire l'ISO</b> (lecteur CD/DVD).\n3. Rallume → FWS démarre." \
2>/dev/null
fi
systemctl poweroff
else
# Échec (ou install non terminée) : on montre les logs pour diagnostiquer.
if command -v zenity >/dev/null 2>&1; then
zenity --text-info --title="FWS — logs Anaconda (sortie $rc)" \
--filename="$DBG" --width=1100 --height=720 2>/dev/null &
fi
wait "$_OB_PID"
fi
else
echo "[FWS] Anaconda absent de l'ISO — à builder (setup-aur.sh) + ajouter à packages.x86_64." >&2
exec openbox
fi
+11
View File
@@ -0,0 +1,11 @@
# fix for screen readers
if grep -Fqa 'accessibility=' /proc/cmdline &> /dev/null; then
setopt SINGLE_LINE_ZLE
fi
# Provisionnement automatique archiso (param noyau script=) : LIVE uniquement.
# Sur le système installé /run/archiso n'existe pas, donc ce bloc ne s'exécute
# jamais hors du live — c'est la barrière qui empêche l'auto-script sur la cible.
if [[ -d /run/archiso ]]; then
~/.automated_script.sh
fi
+16 -3
View File
@@ -1,5 +1,18 @@
# Démarrage automatique de Xorg + Calamares sur tty1 (autologin root).
# La session X exécute /root/.xinitrc qui lance Openbox + Calamares.
if [[ "$(tty)" == "/dev/tty1" && -z "$DISPLAY" ]]; then
# Démarrage automatique dans le live FWS uniquement.
# Sur le système installé, /run/archiso n'existe pas, donc rien ne se lance.
# Mode RÉPARATION (entrée de boot « Réparer FWS », paramètre fws.recovery=1) :
# on démarre X + l'application GTK (fws-recovery-session lance openbox puis
# fws-recovery-gui, qui pilote le moteur fws-recovery). Si X échoue à
# démarrer, startx rend la main → repli sur l'assistant console fws-recovery.
# (Sur le SYSTÈME INSTALLÉ, l'équivalent est fws-recovery-boot.service via
# l'entrée GRUB « Réparer FWS » — pas ce fichier.)
if [[ -d /run/archiso && "$(tty)" == "/dev/tty1" ]] \
&& grep -qw 'fws.recovery=1' /proc/cmdline 2>/dev/null; then
startx /usr/local/bin/fws-recovery-session -- vt1
exec fws-recovery
fi
if [[ -d /run/archiso && "$(tty)" == "/dev/tty1" && -z "$DISPLAY" ]]; then
exec startx -- vt1
fi
@@ -0,0 +1,15 @@
#!/usr/bin/env bash
# ============================================================================
# FWS — script de customisation de l'airootfs.
# Exécuté par mkarchiso DANS le chroot airootfs, APRÈS le pacstrap
# (cf. fws/mkarchiso _make_customize_airootfs), puis supprimé : il n'apparaît
# donc PAS dans l'ISO finale. C'est le seul endroit fiable pour lancer des
# commandes dans l'image (les hooks pacman ne tournent pas sous pacstrap).
# ============================================================================
set -euo pipefail
# Génère les locales déclarées dans /etc/locale.gen. en_US.UTF-8 est REQUIS par
# Anaconda (ses modules DBus font setlocale(LC_ALL, "en_US.UTF-8") au démarrage,
# sinon « locale.Error: unsupported locale setting » → le module Boss plante).
# ~3 Mo générés, vs 222 Mo pour le paquet glibc-locales complet.
locale-gen
+1
View File
@@ -0,0 +1 @@
grub-editenv
+1
View File
@@ -0,0 +1 @@
grub-install
+1
View File
@@ -0,0 +1 @@
grub-mkconfig
@@ -0,0 +1 @@
grub-mkpasswd-pbkdf2
+1
View File
@@ -0,0 +1 @@
grub-set-default
+11
View File
@@ -0,0 +1,11 @@
#!/bin/sh
# FWS — stub no-op de load_policy.
#
# À sa fermeture, le module Runtime d'Anaconda appelle /usr/sbin/load_policy
# pour recharger la politique SELinux. Arch N'EST PAS SELinux → le vrai binaire
# n'existe pas → « AnacondaError: ... '/usr/sbin/load_policy' » dans un atexit
# callback (« Exception ignored »). C'est cosmétique (exit 0 quand même), mais
# ça affiche un traceback rouge. Ce stub renvoie 0 → plus aucune erreur.
# (/usr/sbin est un lien vers /usr/bin sur Arch usr-merge → ce fichier répond
# aussi pour /usr/sbin/load_policy.)
exit 0
+8
View File
@@ -0,0 +1,8 @@
#!/bin/sh
# FWS — stub no-op de setstatus.
#
# Le script Fedora « liveinst » appelle « setstatus » (ligne ~154) pour publier
# un statut SELinux/systemd. Cet outil n'existe pas sur Arch →
# « /usr/bin/liveinst: line 154: setstatus: command not found » (cosmétique,
# liveinst continue). Ce stub renvoie 0 → l'avertissement disparaît.
exit 0
@@ -0,0 +1,106 @@
# FWS — Spoke « Desktop Environment » : nouvel onglet de choix du bureau.
#
# POURQUOI ICI (airootfs, pas dans le paquet anaconda) : Anaconda découvre les
# spokes au RUNTIME via collect()/collect_spokes (os.listdir du dossier des
# spokes puis import de chaque .py). Déposer ce fichier dans le dossier des
# spokes via l'overlay airootfs suffit donc à le faire apparaître — SANS rebuild
# du paquet anaconda (juste ./build.sh). Le glade associé est dans
# /usr/share/anaconda/ui/spokes/fws_desktop.glade (aussi via l'airootfs).
#
# ⚠ Le chemin /usr/lib/python3.14/... est couplé à la version de Python d'Arch
# (3.14 au moment du build d'anaconda). À mettre à jour si Python change de
# version majeure (en même temps que le rebuild d'anaconda de toute façon).
#
# FONCTION : afficher 5 choix (CLI/GNOME/KDE/Hyprland/XFCE) et écrire la clé
# choisie dans /tmp/fws-desktop. Le %post du kickstart lit ce fichier, fait
# « pacman -S » du bureau + d'un navigateur (Firefox), et active le display
# manager. « cli » (défaut) = aucun bureau, rien à installer.
from pyanaconda.core.i18n import CN_, _
from pyanaconda.ui.categories.software import SoftwareCategory
from pyanaconda.ui.gui.spokes import NormalSpoke
__all__ = ["FWSDesktopSpoke"]
# clé interne (écrite dans /tmp/fws-desktop) → libellé affiché dans le statut.
_CHOICES = [
("cli", _("Command line only (no desktop)")),
("gnome", "GNOME"),
("kde", "KDE Plasma"),
("hyprland", "Hyprland — Wayland (non compatible VR)"),
("i3", "i3 — X11 (compatible VR : SteamVR)"),
("xfce", "XFCE"),
]
_DESKTOP_FILE = "/tmp/fws-desktop"
class FWSDesktopSpoke(NormalSpoke):
"""Choix de l'environnement de bureau FWS (écrit /tmp/fws-desktop)."""
builderObjects = ["fwsDesktopWindow"]
mainWidgetName = "fwsDesktopWindow"
uiFile = "spokes/fws_desktop.glade"
category = SoftwareCategory
icon = "preferences-desktop-display-symbolic"
title = CN_("GUI|Spoke", "_Desktop Environment")
@staticmethod
def get_screen_id():
"""Identifiant unique de cet écran."""
return "fws-desktop-selection"
def __init__(self, *args):
NormalSpoke.__init__(self, *args)
self._choice = "cli"
self._radios = {}
def initialize(self):
NormalSpoke.initialize(self)
for key, _label in _CHOICES:
self._radios[key] = self.builder.get_object("radio_" + key)
# Reprend un éventuel choix déjà écrit (revisite du spoke).
try:
with open(_DESKTOP_FILE) as fh:
val = fh.read().strip()
if val in self._radios:
self._choice = val
except OSError:
pass
def refresh(self):
# Coche le bouton correspondant au choix courant.
rb = self._radios.get(self._choice) or self._radios.get("cli")
if rb is not None:
rb.set_active(True)
def apply(self):
# Relit le bouton actif et persiste le choix pour le %post du kickstart.
for key, rb in self._radios.items():
if rb is not None and rb.get_active():
self._choice = key
break
try:
with open(_DESKTOP_FILE, "w") as fh:
fh.write(self._choice)
except OSError:
pass
@property
def status(self):
for key, label in _CHOICES:
if key == self._choice:
return label
return _("Command line only (no desktop)")
@property
def completed(self):
# « cli » est un défaut valide → le spoke n'est jamais bloquant.
return True
@property
def mandatory(self):
return False
@property
def ready(self):
return True
@@ -0,0 +1,348 @@
# FWS — Page « Récapitulatif » : écran À PART ENTIÈRE avant l'installation.
#
# POURQUOI ICI (airootfs, pas dans le paquet anaconda) : même mécanisme que la
# spoke « Desktop Environment » (fws_desktop.py) — Anaconda découvre les spokes
# au RUNTIME (collect) dans ce dossier → l'overlay airootfs suffit, AUCUN
# rebuild du paquet anaconda. Le glade associé est dans
# /usr/share/anaconda/ui/spokes/fws_recap.glade (aussi via l'airootfs).
#
# PLACEMENT DANS LE FLUX : standalone spoke « postForHub = SummaryHub » avec
# priority = -10. L'ordre des écrans est pre(SummaryHub) → SummaryHub →
# post(SummaryHub) trié par priority croissante (UserInterface.
# _orderActionClasses). ProgressSpoke — l'écran qui DÉMARRE l'installation
# dans son refresh() — est aussi post(SummaryHub), priority 0 par défaut →
# cette page s'intercale ENTRE les deux : l'utilisateur clique « Commencer
# l'installation » sur le hub, voit CE récapitulatif (le disque n'a encore
# subi AUCUNE écriture), et l'installation ne démarre qu'à son clic
# « Lancer l'installation ». Le bouton « Précédent » ramène au hub pour
# modifier les choix (cf. _on_back_clicked : la file d'actions du GUI est
# consommée à chaque écran, on y réinsère le hub).
#
# CONTENU : configuration choisie par l'utilisateur (via les modules D-Bus
# d'Anaconda : langue, clavier, fuseau, comptes, partitionnement + les
# fichiers /tmp des spokes FWS : bureau, hostname) ET matériel détecté
# (virtualisation, GPU, disques, réseau) — mêmes sources que ce que le
# %post du kickstart et fws-setup-hardware appliqueront.
#
# ⚠ « completed » doit rester False : _instantiateAction SAUTE les standalone
# spokes complétées (mécanisme prévu pour les installs kickstart).
# ⚠ Chemin couplé à la version Python d'Arch (3.14) — comme fws_desktop.py —
# et le bouton « Précédent » s'appuie sur les internes du GUI d'anaconda
# 45.8 (_actions/_currentAction) : à re-vérifier à chaque bump d'anaconda.
import inspect
import gi
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk
from pyanaconda.anaconda_loggers import get_module_logger
from pyanaconda.core import util
from pyanaconda.modules.common.constants.objects import DISK_SELECTION
from pyanaconda.modules.common.constants.services import (
LOCALIZATION,
STORAGE,
TIMEZONE,
USERS,
)
from pyanaconda.modules.common.structures.user import UserData
from pyanaconda.ui.gui import GraphicalUserInterface
from pyanaconda.ui.gui.hubs.summary import SummaryHub
from pyanaconda.ui.gui.spokes import StandaloneSpoke
log = get_module_logger(__name__)
__all__ = ["FWSRecapSpoke"]
# Doit rester aligné sur le %post du kickstart (étape « Bureau choisi ») et
# sur les libellés de la spoke fws_desktop.
_DESKTOP_LABELS = {
"cli": "ligne de commande uniquement (aucun bureau)",
"gnome": "GNOME (+ Firefox, GDM)",
"kde": "KDE Plasma (+ Firefox, SDDM)",
"hyprland": "Hyprland — Wayland, non compatible VR (+ Firefox, SDDM)",
"i3": "i3 — X11, compatible VR/SteamVR (+ Firefox, SDDM)",
"xfce": "XFCE (+ Firefox, SDDM)",
}
_PARTITIONING_LABELS = {
"AUTOMATIC": "automatique (recommandé)",
"INTERACTIVE": "personnalisé (assistant)",
"CUSTOM": "personnalisé",
"BLIVET": "avancé (blivet-gui)",
"MANUAL": "points de montage manuels",
}
def _safe(getter, default):
"""Valeur d'un getter D-Bus/système, ou défaut : le récap ne doit JAMAIS
faire tomber l'installateur, quel que soit le module indisponible (d'
le except large : dasbus lève des types variés selon la panne)."""
try:
return getter()
except Exception: # pylint: disable=broad-except
return default
def _capture(*argv):
"""stdout d'une commande, chaîne vide si absente ou en échec."""
try:
return util.execWithCapture(argv[0], list(argv[1:])) or ""
except (OSError, RuntimeError):
return ""
def _read_flag(path):
try:
with open(path) as fh:
return fh.read().strip()
except OSError:
return ""
def _config_lines():
"""Section « configuration choisie » : interroge les modules D-Bus
d'Anaconda (remplis par les spokes) + les fichiers /tmp des spokes FWS."""
lines = []
lang = _safe(lambda: LOCALIZATION.get_proxy().Language, "")
if lang:
lines.append(f" • Langue : {lang}")
layouts = _safe(lambda: list(LOCALIZATION.get_proxy().XLayouts), [])
if layouts:
lines.append(f" • Clavier (X11) : {', '.join(layouts)}")
tz = _safe(lambda: TIMEZONE.get_proxy().Timezone, "")
if tz:
ntp = _safe(lambda: TIMEZONE.get_proxy().NTPEnabled, None)
suffix = {True: " — synchronisation NTP activée",
False: " — synchronisation NTP désactivée"}.get(ntp, "")
lines.append(f" • Fuseau horaire : {tz}{suffix}")
users = _safe(
lambda: UserData.from_structure_list(USERS.get_proxy().Users), [])
if users:
names = ", ".join(u.name for u in users if u.name)
lines.append(f" • Utilisateur(s) : {names} (sudo via wheel)")
else:
lines.append(" • Utilisateur(s) : AUCUN — pensez-y avant de lancer !")
root_locked = _safe(lambda: USERS.get_proxy().IsRootAccountLocked, None)
root_pw = _safe(lambda: USERS.get_proxy().IsRootPasswordSet, None)
if root_locked:
root_txt = "verrouillé (recommandé)"
elif root_pw:
root_txt = "actif, mot de passe défini"
elif root_pw is not None:
# Même règle que l'étape « Sécurité » du %post : un root resté sans
# mot de passe sera verrouillé en fin d'installation.
root_txt = "sans mot de passe → sera VERROUILLÉ en fin d'install"
else:
root_txt = ""
if root_txt:
lines.append(f" • Compte root : {root_txt}")
# Hostname : écrit par le spoke Utilisateur (patch user.py du paquet
# anaconda). Même nettoyage / même défaut que le %post --nochroot.
hn = "".join(c for c in _read_flag("/tmp/fws-hostname")
if c.isalnum() or c in "._-") or "fws"
lines.append(f" • Nom de machine : {hn}")
# Bureau : écrit par fws_desktop.apply() (sortie de la spoke). Absent =
# spoke jamais visitée = « cli », exactement le défaut du %post.
desk = _read_flag("/tmp/fws-desktop") or "cli"
lines.append(f" • Bureau : {_DESKTOP_LABELS.get(desk, desk)}")
method = _safe(
lambda: STORAGE.get_proxy(
STORAGE.get_proxy().AppliedPartitioning).PartitioningMethod, "")
if method:
lines.append(" • Partitionnement : "
f"{_PARTITIONING_LABELS.get(method, method)}")
return lines, desk, method
def _build_summary():
config_lines, desk, method = _config_lines()
config_text = "\n".join(config_lines) \
or " (configuration non disponible)"
# Disques ciblés par l'installation (spoke « Destination »).
selected = set(_safe(
lambda: list(STORAGE.get_proxy(DISK_SELECTION).SelectedDisks), []))
disks = []
for line in _capture("lsblk", "-dno", "NAME,SIZE,MODEL,TYPE").splitlines():
fields = line.split()
if fields and fields[-1] == "disk":
mark = " ← CIBLE de l'installation" if fields[0] in selected else ""
disks.append("" + " ".join(fields[:-1]) + mark)
disk_text = "\n".join(disks) or " (aucun disque détecté)"
if method == "AUTOMATIC":
disk_warn = (
" ⚠ Rien n'a encore été écrit. Le partitionnement automatique\n"
" EFFACERA ENTIÈREMENT le(s) disque(s) cible(s) au lancement.")
else:
disk_warn = (
" ⚠ Rien n'a encore été écrit. Au lancement, ce sont vos choix\n"
" de partitionnement faits dans l'installateur qui s'appliqueront.")
virt = (_capture("systemd-detect-virt").strip().splitlines() or ["none"])[0]
if virt in ("", "none"):
virt = "aucune (machine physique)"
gpus = []
for line in _capture("lspci").splitlines():
low = line.lower()
if ("vga" in low or "3d" in low or "display" in low) and ":" in line:
gpus.append("" + line.split(":", 2)[-1].strip())
gpu_text = "\n".join(gpus) or " (aucune carte graphique détectée)"
try:
net_ok = util.execWithRedirect("ip", ["route", "get", "1.1.1.1"]) == 0
except (OSError, RuntimeError):
net_ok = False
if net_ok:
net = "disponible ✔"
else:
net = ("INDISPONIBLE ✖ — bureau, drivers et stack FWS ne\n"
" s'installeront PAS (rattrapable au 1er boot)")
extras = ("Steam, Wine, VR (Monado/OpenXR), winboat-bin"
if desk != "cli" else "rien de plus (choix CLI)")
return f"""\
══════════════════════════════════════════════════════════
FWS — RÉCAPITULATIF AVANT INSTALLATION
══════════════════════════════════════════════════════════
CONFIGURATION CHOISIE
{config_text}
DISQUES
{disk_warn}
{disk_text}
MATÉRIEL DÉTECTÉ
• Virtualisation : {virt}
• Réseau : {net}
Cartes graphiques (drivers installés automatiquement en fin d'install) :
{gpu_text}
DÉROULEMENT DE L'INSTALLATION
1. Partitionnement, puis copie du système live FWS (payload LiveOS)
2. Noyau + initramfs régénérés (mkinitcpio), GRUB installé
3. Bureau choisi + navigateur installés (réseau requis)
4. Matériel : drivers GPU, outils VM, son, Bluetooth, Podman
+ si bureau choisi : {extras}
« Précédent » pour revenir modifier vos choix —
« Lancer l'installation » pour démarrer réellement l'installation.
"""
class FWSRecapSpoke(StandaloneSpoke):
"""Récapitulatif des choix, affiché entre le hub et l'installation."""
builderObjects = ["fwsRecapWindow"]
mainWidgetName = "fwsRecapWindow"
uiFile = "spokes/fws_recap.glade"
postForHub = SummaryHub
priority = -10
@staticmethod
def get_screen_id():
"""Identifiant unique de cet écran."""
return "fws-recap"
@property
def completed(self):
# False, sinon _instantiateAction saute l'écran (cf. en-tête).
return False
def apply(self):
# Rien à persister : cette page ne fait que montrer l'état.
pass
def initialize(self):
StandaloneSpoke.initialize(self)
# Le bouton « continuer » de CETTE page est le vrai déclencheur :
# l'écran suivant (ProgressSpoke) démarre la file d'installation.
self.window.get_continue_button().set_label("_Lancer l'installation")
# Capture pour « Précédent » : initialize() est appelé DEPUIS
# GraphicalUserInterface._on_continue_clicked (clic « Commencer
# l'installation » du hub), AVANT la bascule de _currentAction → à
# cet instant ui._currentAction est ENCORE l'instance du hub Résumé,
# et le « self » de l'appelant est l'UI. Aucune API publique ne les
# expose ; on remonte la pile d'appels (déterministe — pas de scan
# mémoire, pas de variable globale).
self._gui = None
self._hub = None
frame = inspect.currentframe()
try:
frame = frame.f_back
while frame is not None:
candidate = frame.f_locals.get("self")
if isinstance(candidate, GraphicalUserInterface):
self._gui = candidate
current = getattr(candidate, "_currentAction", None)
if isinstance(current, SummaryHub):
self._hub = current
break
frame = frame.f_back
finally:
del frame
# Bouton « Précédent », placé avec les boutons de navigation
# (à côté de « Quitter » — leur parent est la GtkButtonBox du bas).
quit_button = self.window.get_quit_button()
button_box = quit_button.get_parent()
self._back_button = Gtk.Button.new_with_mnemonic("_Précédent")
self._back_button.connect("clicked", self._on_back_clicked)
button_box.add(self._back_button)
button_box.reorder_child(self._back_button, 0)
if self._gui is None or self._hub is None:
# Références introuvables (flux inattendu) : bouton grisé plutôt
# qu'une navigation cassée — l'install reste possible.
log.warning("FWS recap: hub/UI introuvables, « Précédent » désactivé.")
self._back_button.set_sensitive(False)
self._back_button.show()
def _on_back_clicked(self, _button):
ui = self._gui
hub = self._hub
if ui is None or hub is None:
return
log.info("FWS recap: retour au hub Résumé pour modification.")
# La file d'actions du GUI est CONSOMMÉE (pop(0)) à chaque écran :
# ici _actions = [FWSRecapSpoke, ProgressSpoke] et le hub en est déjà
# sorti. On le réinsère en tête pour que le prochain « Commencer
# l'installation » ré-enchaîne hub → NOUVELLE page récap (résumé
# recalculé avec les choix modifiés) → installation.
if not ui._actions or ui._actions[0] is not SummaryHub:
ui._actions.insert(0, SummaryHub)
# _on_continue_clicked a désactivé le « continuer » du hub en le
# quittant : on le réarme, sinon « Commencer l'installation » est mort.
hub.window.set_may_continue(True)
# Même séquence que la transition officielle (_on_continue_clicked).
self.exited.emit(self)
hub.refresh()
ui.mainWindow.setCurrentAction(hub)
hub.entered.emit(hub)
ui._currentAction = hub
def refresh(self):
StandaloneSpoke.refresh(self)
text = _build_summary()
self.builder.get_object("recapView").get_buffer().set_text(text)
# Copie pour le harnais de debug du .xinitrc (fws-debug.txt).
try:
with open("/tmp/fws-hw-summary.txt", "w") as fh:
fh.write(text)
except OSError:
pass
@@ -0,0 +1,136 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.18.3 -->
<interface>
<!-- FWS : copie de summary.glade d'anaconda 45.8 SANS le libellé
« We won't touch your disks… » du bas du hub. Livré ICI (chemin neutre)
car mkarchiso pose l'airootfs AVANT pacstrap : au chemin du paquet,
pacman refuserait d'installer anaconda (« exists in filesystem »).
C'est le .xinitrc du live qui le copie sur
/usr/share/anaconda/ui/hubs/summary.glade au boot. -->
<requires lib="gtk+" version="3.0"/>
<requires lib="AnacondaWidgets" version="3.0"/>
<object class="AnacondaHubWindow" id="summaryWindow">
<property name="can_focus">False</property>
<property name="window_name" translatable="yes">INSTALLATION SUMMARY</property>
<property name="quit_button">quitButton</property>
<property name="continue_button">continueButton</property>
<child internal-child="main_box">
<object class="GtkBox" id="AnacondaHubWindow-main_box1">
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child internal-child="nav_box">
<object class="GtkEventBox" id="AnacondaHubWindow-nav_box1">
<property name="can_focus">False</property>
<child internal-child="nav_area">
<object class="GtkGrid" id="AnacondaHubWindow-nav_area1">
<property name="can_focus">False</property>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child internal-child="alignment">
<object class="GtkAlignment" id="AnacondaHubWindow-alignment1">
<property name="can_focus">False</property>
<property name="yalign">0</property>
<property name="left_padding">12</property>
<property name="right_padding">6</property>
<child internal-child="action_area">
<object class="GtkBox" id="summaryWindow-actionArea">
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<property name="spacing">6</property>
<child internal-child="scrolled_window">
<object class="GtkScrolledWindow" id="summaryWindow-scroll">
<property name="can_focus">True</property>
<property name="is_focus">True</property>
<property name="hscrollbar_policy">never</property>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkButtonBox" id="buttonbox1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_left">6</property>
<property name="margin_right">6</property>
<property name="spacing">12</property>
<property name="layout_style">end</property>
<child>
<object class="GtkButton" id="quitButton">
<property name="label" translatable="yes" context="GUI|Summary">_Quit</property>
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="hexpand">True</property>
<property name="use_underline">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="continueButton">
<property name="label" translatable="yes" context="GUI|Summary">_Begin Installation</property>
<property name="use_action_appearance">False</property>
<property name="visible">True</property>
<property name="sensitive">False</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_underline">True</property>
<style>
<class name="suggested-action"/>
</style>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="pack_type">end</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
</object>
</child>
<child internal-child="accessible">
<object class="AtkObject" id="summaryWindow-atkobject">
<property name="AtkObject::accessible-name" translatable="yes">INSTALLATION SUMMARY</property>
</object>
</child>
</object>
</interface>
@@ -0,0 +1,168 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- FWS — onglet « Desktop Environment » (choix du bureau à installer). -->
<interface>
<requires lib="gtk+" version="3.6"/>
<requires lib="AnacondaWidgets" version="1.0"/>
<object class="AnacondaSpokeWindow" id="fwsDesktopWindow">
<property name="can-focus">False</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<property name="window-name" translatable="yes">DESKTOP ENVIRONMENT</property>
<signal name="button-clicked" handler="on_back_clicked" swapped="no"/>
<child internal-child="main_box">
<object class="GtkBox" id="AnacondaSpokeWindow-main_box1">
<property name="can-focus">False</property>
<property name="orientation">vertical</property>
<property name="spacing">6</property>
<child internal-child="nav_box">
<object class="GtkEventBox" id="AnacondaSpokeWindow-nav_box1">
<property name="can-focus">False</property>
<child internal-child="nav_area">
<object class="GtkGrid" id="AnacondaSpokeWindow-nav_area1">
<property name="can-focus">False</property>
<property name="margin-left">6</property>
<property name="margin-right">6</property>
<property name="margin-top">6</property>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child internal-child="alignment">
<object class="GtkAlignment" id="AnacondaSpokeWindow-alignment1">
<property name="can-focus">False</property>
<property name="margin-top">12</property>
<property name="yalign">0</property>
<property name="xscale">0</property>
<property name="yscale">0</property>
<property name="bottom-padding">48</property>
<property name="left-padding">24</property>
<property name="right-padding">24</property>
<child internal-child="action_area">
<object class="GtkBox" id="AnacondaSpokeWindow-action_area1">
<property name="can-focus">False</property>
<property name="orientation">vertical</property>
<property name="spacing">8</property>
<child>
<object class="GtkLabel" id="fws_desktop_desc">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="xalign">0</property>
<property name="margin-bottom">12</property>
<property name="wrap">True</property>
<property name="max-width-chars">60</property>
<property name="label" translatable="yes">Choose the desktop environment to install. A web browser (Firefox) is installed automatically with any desktop.</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="radio_cli">
<property name="label" translatable="yes">Command line only (no desktop)</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">False</property>
<property name="active">True</property>
<property name="draw-indicator">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="radio_gnome">
<property name="label" translatable="yes">GNOME</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">False</property>
<property name="draw-indicator">True</property>
<property name="group">radio_cli</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="radio_kde">
<property name="label" translatable="yes">KDE Plasma</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">False</property>
<property name="draw-indicator">True</property>
<property name="group">radio_cli</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">3</property>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="radio_hyprland">
<property name="label" translatable="yes">Hyprland — Wayland (NOT VR compatible)</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">False</property>
<property name="draw-indicator">True</property>
<property name="group">radio_cli</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">4</property>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="radio_i3">
<property name="label" translatable="yes">i3 — X11 (VR compatible: SteamVR, HTC Vive, Valve Index…)</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">False</property>
<property name="draw-indicator">True</property>
<property name="group">radio_cli</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">5</property>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="radio_xfce">
<property name="label" translatable="yes">XFCE</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">False</property>
<property name="draw-indicator">True</property>
<property name="group">radio_cli</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">6</property>
</packing>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
<child internal-child="accessible">
<object class="AtkObject" id="fwsDesktopWindow-atkobject">
<property name="AtkObject::accessible-name" translatable="yes">DESKTOP ENVIRONMENT</property>
</object>
</child>
</object>
</interface>
@@ -0,0 +1,85 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- FWS — page « Récapitulatif avant installation » (cf. fws_recap.py).
Squelette calqué sur installation_progress.glade : AnacondaStandaloneWindow
avec ses enfants internes (nav_box/nav_area, alignment/action_area). -->
<interface>
<requires lib="gtk+" version="3.0"/>
<requires lib="AnacondaWidgets" version="3.0"/>
<object class="AnacondaStandaloneWindow" id="fwsRecapWindow">
<property name="can_focus">False</property>
<property name="window_name" translatable="yes">RÉCAPITULATIF AVANT INSTALLATION</property>
<child internal-child="main_box">
<object class="GtkBox" id="AnacondaStandaloneWindow-main_box1">
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child internal-child="nav_box">
<object class="GtkEventBox" id="AnacondaStandaloneWindow-nav_box1">
<property name="can_focus">False</property>
<child internal-child="nav_area">
<object class="GtkGrid" id="AnacondaStandaloneWindow-nav_area1">
<property name="can_focus">False</property>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child internal-child="alignment">
<object class="GtkAlignment" id="AnacondaStandaloneWindow-alignment1">
<property name="can_focus">False</property>
<property name="yalign">0</property>
<property name="left_padding">12</property>
<property name="right_padding">6</property>
<child internal-child="action_area">
<object class="GtkBox" id="fwsRecapWindow-actionArea">
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
<object class="GtkScrolledWindow" id="recapScroll">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="shadow_type">in</property>
<child>
<object class="GtkTextView" id="recapView">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="editable">False</property>
<property name="cursor_visible">False</property>
<property name="monospace">True</property>
<property name="left_margin">12</property>
<property name="right_margin">12</property>
<property name="top_margin">12</property>
<property name="bottom_margin">12</property>
<property name="wrap_mode">word-char</property>
</object>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
</object>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
</object>
</interface>
@@ -1,4 +1,5 @@
title Arch Linux (%ARCH%, UEFI)
title FWS install medium (%ARCH%, UEFI)
sort-key 01
linux /%INSTALL_DIR%/boot/%ARCH%/vmlinuz-linux
initrd /%INSTALL_DIR%/boot/%ARCH%/initramfs-linux.img
options archisobasedir=%INSTALL_DIR% archisosearchuuid=%ARCHISO_UUID%
options archisobasedir=%INSTALL_DIR% archisosearchuuid=%ARCHISO_UUID% udev.event_timeout=45
+25 -11
View File
@@ -1,7 +1,7 @@
# ============================================================
# FWS — paquets de l'ISO live
# Objectif : système live bootable + installeur Calamares
# fonctionnel + jeu minimal d'outils de rescue.
# Objectif : système live bootable + installateur Anaconda
# (migration depuis Calamares) + jeu minimal d'outils de rescue.
# ============================================================
# --- Base système ---
@@ -26,6 +26,7 @@ memtest86+
memtest86+-efi
# --- Filesystems ---
squashfs-tools
btrfs-progs
e2fsprogs
exfatprogs
@@ -60,6 +61,8 @@ wget
zsh
grml-zsh-config
bash
zenity
zram-generator
nano
vim
less
@@ -77,6 +80,7 @@ pacman-contrib
dmidecode
usbutils
pciutils
firewalld
fastfetch
htop
@@ -84,21 +88,15 @@ htop
alsa-utils
sof-firmware
# --- Xorg + Openbox (pour Calamares) ---
# --- Xorg + Openbox (session graphique de l'installateur) ---
xorg-server
xorg-xinit
xorg-xrandr
xorg-xsetroot
openbox
ttf-dejavu
# --- Calamares (fournis par fws-local) ---
calamares
kpmcore
qt5-base
qt5-svg
qt5-webengine
qt6-base
# Terminal X : debug de l'installateur + entrée « Terminals » du menu Openbox.
xterm
# --- Agents VM (pratique pour tester l'ISO) ---
qemu-guest-agent
@@ -107,3 +105,19 @@ open-vm-tools
# --- FWS (fws-local) ---
winboat-bin
# Gestionnaire D&D 5e (dés, personnages, grimoire, sessions, combat).
fws-dnd
# --- Installateur Anaconda (fws-local) ---
# 'anaconda' tire automatiquement anaconda-widgets + toutes ses dépendances
# (python-blivet, pykickstart, libreport, gtk3, NetworkManager…).
anaconda
# Module 'cgi' (retiré de Python 3.13, PEP 594) requis par python-requests-ftp
# que pyanaconda/core/util.py importe en dur. python-legacy-cgi le réintroduit.
python-legacy-cgi
# Module 'crypt'/'crypt_r' (retiré de Python 3.13, PEP 594) requis par
# pyanaconda/core/users.py (hash des mots de passe). Paquet maison (fws-local).
python-crypt_r
# Namespace GI 'OSTree-1.0' : pyanaconda/rescue.py importe le payload rpm_ostree
# (inconditionnellement, même si FWS utilise liveimg) → fourni par 'ostree'.
ostree
-5
View File
@@ -1,8 +1,3 @@
[fws-local]
SigLevel = Optional TrustAll
Server = file:///mnt/c/Users/Murasaki/Documents/FWS/fws/local-repo
#
# /etc/pacman.conf
#
+25
View File
@@ -14,6 +14,31 @@ pacman_conf="pacman.conf"
airootfs_image_type="squashfs"
airootfs_image_tool_options=('-comp' 'xz' '-Xbcj' 'x86' '-b' '1M' '-Xdict-size' '1M')
bootstrap_tarball_compression=(xz -9e)
# NB : ce profiledef.sh ÉCRASE celui de configs/releng/ lors de la fusion du
# build (baseline prioritaire). Il doit donc être un SUR-ENSEMBLE des
# permissions de releng, sinon les helpers live perdent leur bit exécutable
# (ils sont versionnés en 0644) et /root/.gnupg perd son 0700 (gpg refuse).
file_permissions=(
["/etc/shadow"]="0:0:400"
["/root"]="0:0:750"
["/root/.automated_script.sh"]="0:0:755"
["/root/.gnupg"]="0:0:700"
["/usr/local/bin/choose-mirror"]="0:0:755"
["/usr/local/bin/Installation_guide"]="0:0:755"
["/usr/local/bin/livecd-sound"]="0:0:755"
["/usr/bin/load_policy"]="0:0:755"
["/usr/bin/setstatus"]="0:0:755"
["/usr/local/bin/fws-setup-hardware"]="0:0:755"
["/usr/local/bin/fws-keys"]="0:0:755"
["/usr/local/bin/fws-vr-setup"]="0:0:755"
["/usr/local/bin/fws-hello"]="0:0:755"
["/usr/local/bin/fws-update"]="0:0:755"
["/usr/local/bin/fws-updates-check"]="0:0:755"
["/usr/local/bin/fws-proton-ge"]="0:0:755"
["/usr/local/bin/fws-recovery"]="0:0:755"
["/usr/local/bin/fws-recovery-session"]="0:0:755"
["/usr/local/bin/fws-recovery-gui"]="0:0:755"
["/usr/local/bin/fws-powermenu"]="0:0:755"
["/usr/local/bin/fws-about"]="0:0:755"
["/etc/grub.d/42_fws-recovery"]="0:0:755"
)
@@ -1,5 +0,0 @@
LABEL arch
MENU LABEL Arch Linux (%ARCH%, BIOS)
LINUX /%INSTALL_DIR%/boot/%ARCH%/vmlinuz-linux
INITRD /%INSTALL_DIR%/boot/%ARCH%/initramfs-linux.img
APPEND archisobasedir=%INSTALL_DIR% archisosearchuuid=%ARCHISO_UUID%
+9 -7
View File
@@ -1,9 +1,11 @@
SERIAL 0 115200
UI menu.c32
MENU TITLE Arch Linux
MENU CLEAR
DEFAULT select
DEFAULT arch
TIMEOUT 30
LABEL select
COM32 whichsys.c32
APPEND -pxe- pxe -sys- sys -iso- sys
INCLUDE syslinux-linux.cfg
LABEL pxe
CONFIG archiso_pxe.cfg
LABEL sys
CONFIG archiso_sys.cfg
@@ -1,40 +0,0 @@
# ============================================================
# FWS Linux — branding.desc
# ============================================================
componentName: fws
strings:
productName: "FWS Linux"
shortProductName: "FWS"
version: "1.0"
shortVersion: "1.0"
versionedName: "FWS Linux 1.0"
shortVersionedName: "FWS 1.0"
bootloaderEntryName: "FWS Linux"
productUrl: "https://fws-linux.org"
supportUrl: "https://fws-linux.org/support"
releaseNotesUrl: "https://fws-linux.org/release-notes"
donateUrl: "https://fws-linux.org/donate"
images:
productLogo: "logo.png"
productIcon: "logo.png"
productWelcome: "logo.png"
slideshow: "slideshow.qml"
slideshowAPI: 2
style:
# Couleurs de la sidebar
sidebarBackground: "#1a1a2e"
sidebarText: "#e0e0e0"
sidebarTextHighlight: "#00d4ff"
sidebarSelect: "#16213e"
# Couleurs générales
backgroundColor: "#0f3460"
highlightedTextColor: "#ffffff"
genericTextColor: "#e0e0e0"
errorTextColor: "#ff6b6b"
warningTextColor: "#ffa500"
Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

@@ -1,138 +0,0 @@
/* ============================================================
FWS Linux — slideshow.qml
Affiché pendant l'installation
============================================================ */
import QtQuick 2.0
import calamares.slideshow 1.0
Presentation {
id: presentation
function nextSlide() {
if (presentation.currentSlide < slides.count - 1)
presentation.currentSlide++
else
presentation.currentSlide = 0
}
Timer {
id: timer
interval: 4000
repeat: true
running: true
onTriggered: nextSlide()
}
Slide {
anchors.fill: parent
Rectangle {
anchors.fill: parent
color: "#1a1a2e"
Column {
anchors.centerIn: parent
spacing: 20
Text {
text: "🚀 Bienvenue sur FWS Linux"
color: "#00d4ff"
font.pixelSize: 32
font.bold: true
anchors.horizontalCenter: parent.horizontalCenter
}
Text {
text: "Un système rapide, léger et puissant."
color: "#e0e0e0"
font.pixelSize: 18
anchors.horizontalCenter: parent.horizontalCenter
}
}
}
}
Slide {
anchors.fill: parent
Rectangle {
anchors.fill: parent
color: "#16213e"
Column {
anchors.centerIn: parent
spacing: 20
Text {
text: "⚡ Basé sur Arch Linux"
color: "#00d4ff"
font.pixelSize: 32
font.bold: true
anchors.horizontalCenter: parent.horizontalCenter
}
Text {
text: "Accès à l'AUR et aux derniers paquets."
color: "#e0e0e0"
font.pixelSize: 18
anchors.horizontalCenter: parent.horizontalCenter
}
}
}
}
Slide {
anchors.fill: parent
Rectangle {
anchors.fill: parent
color: "#0f3460"
Column {
anchors.centerIn: parent
spacing: 20
Text {
text: "🛡️ Sécurité & Stabilité"
color: "#00d4ff"
font.pixelSize: 32
font.bold: true
anchors.horizontalCenter: parent.horizontalCenter
}
Text {
text: "FWS est conçu pour être robuste et fiable."
color: "#e0e0e0"
font.pixelSize: 18
anchors.horizontalCenter: parent.horizontalCenter
}
}
}
}
Slide {
anchors.fill: parent
Rectangle {
anchors.fill: parent
color: "#1a1a2e"
Column {
anchors.centerIn: parent
spacing: 20
Text {
text: "✅ Installation en cours..."
color: "#00d4ff"
font.pixelSize: 32
font.bold: true
anchors.horizontalCenter: parent.horizontalCenter
}
Text {
text: "Merci de patienter, FWS s'installe sur votre machine."
color: "#e0e0e0"
font.pixelSize: 18
anchors.horizontalCenter: parent.horizontalCenter
}
}
}
}
}
@@ -1,22 +0,0 @@
# ============================================================
# FWS Linux — modules/bootloader.conf
# ============================================================
# Bootloader à utiliser
# Options: grub, systemd-boot, refind
efiBootLoader: "grub"
# Paramètres GRUB
grubInstall: "grub-install"
grubMkconfig: "grub-mkconfig"
grubCfg: "/boot/grub/grub.cfg"
# Chemin EFI
efiDirectory: "/boot/efi"
# ID pour l'entrée EFI
efiBootEntryName: "FWS Linux"
# Menu GRUB
grubTimeout: 5
grubQuiet: false
@@ -1,11 +0,0 @@
# ============================================================
# FWS Linux — modules/finished.conf
# ============================================================
# Redémarrer automatiquement après l'installation
restartNowEnabled: true
restartNowChecked: false
restartNowCommand: "systemctl reboot"
# Message de fin affiché à l'utilisateur
notifyOnFinished: true
@@ -1,28 +0,0 @@
# ============================================================
# FWS Linux — modules/grubcfg.conf
# Paramètres passés à grub-mkconfig
# ============================================================
# Nom de l'entrée dans le menu GRUB
defaultEntry: "FWS Linux"
defaults:
GRUB_ENABLE_CRYPTODISK: true
# Paramètres kernel supplémentaires
kernel_params: ""
# Désactiver l'écran splash (mettre false pour debug)
splash: true
# Thème GRUB (laisse vide pour le thème par défaut)
theme: ""
# Timeout du menu GRUB (en secondes)
timeout: 5
# Activer les entrées des autres OS détectés (os-prober)
enable_osprober: true
# Écrire /etc/default/grub
writeEtcDefaultGrub: true
@@ -1,24 +0,0 @@
# ============================================================
# FWS Linux — modules/initcpiocfg.conf
# Configure /etc/mkinitcpio.conf sur le système cible
# ============================================================
# Modules à inclure dans le initramfs
modules: []
# Binaires supplémentaires
binaries: []
# Fichiers supplémentaires
files: []
# Hooks — ordre important !
hooks:
- base
- udev
- autodetect
- modconf
- block
- filesystems
- keyboard
- fsck
@@ -1,17 +0,0 @@
# ============================================================
# FWS Linux — modules/keyboard.conf
# ============================================================
# Disposition clavier par défaut
xorgConfigFileName: "/etc/X11/xorg.conf.d/00-keyboard.conf"
# Clavier par défaut
keyboardLayout: "fr"
keyboardVariant: ""
keyboardModel: "pc105"
# Permettre à l'utilisateur de choisir son clavier
guiTimezone: true
# Conversions vc (console virtuelle) → X11
convertedKeymapPath: "/lib/kbd/keymaps/xkb"
@@ -1,18 +0,0 @@
# ============================================================
# FWS Linux — modules/locale.conf
# ============================================================
# Région/timezone par défaut
region: "Europe"
zone: "Paris"
# Langue par défaut
locale: "fr_FR.UTF-8"
# Format des nombres, dates, monnaie
# Laisse vide pour utiliser la même valeur que locale
localeGenPath: "/etc/locale.gen"
# Timezone GeoIP (détection auto basée sur l'IP)
geoipStyle: "json"
geoipUrl: "https://geoip.kde.org/v1/calamares"
@@ -1,54 +0,0 @@
# ============================================================
# FWS Linux — modules/packages.conf
# Paquets installés via pacman pendant l'installation
# ============================================================
# Gestionnaire de paquets
backend: pacman
# Ne pas mettre à jour la base de données pacman (déjà dans le live)
update_db: false
operations:
- install:
# Base système
- base
- base-devel
- linux
- linux-headers
- linux-firmware
# Bootloader
- grub
- efibootmgr
- os-prober
- mkinitcpio-openswap
# Réseau
- networkmanager
- network-manager-applet
- wpa_supplicant
- dhcpcd
# Outils essentiels
- sudo
- nano
- vim
- git
- curl
- wget
- htop
- bash-completion
# Locale & timezone
- tzdata
# Optionnel — retire ce qui ne correspond pas à FWS
- pipewire
- pipewire-pulse
- wireplumber
# Paquets à retirer du système live (pas nécessaires après install)
- remove:
- calamares
- calamares-config
@@ -1,34 +0,0 @@
# ============================================================
# FWS Linux — modules/partition.conf
# ============================================================
# Backend de partitionnement
backend: kpmcore
# Autoriser le partitionnement manuel
allowManualPartitioning: true
# Schéma de partition par défaut (pour install automatique)
# Options: mbr, gpt
defaultPartitionTableType: gpt
# Swap
# Options: none, small, suspend, file
defaultSwapType: small
# Taille minimale des partitions en MiB
defaultFileSystemType: "ext4"
# Partitions EFI (pour UEFI)
efiSystemPartition: "/boot/efi"
efiSystemPartitionSize: 300
# Point de montage racine
requiredStorage: 20.0
# Systèmes de fichiers proposés à l'utilisateur
availableFileSystemTypes: ["ext4", "btrfs", "xfs", "f2fs"]
# Chiffrement
# Activer le chiffrement LUKS
allowZfs: true
@@ -1,23 +0,0 @@
# ============================================================
# FWS Linux — modules/services-systemd.conf
# Services systemd activés sur le système installé
# ============================================================
services:
# Réseau
- name: NetworkManager
mandatory: true
# DHCP
- name: dhcpcd
mandatory: false
# Heure synchronisée
- name: systemd-timesyncd
mandatory: true
# Ajoute ici tes services FWS supplémentaires
# - name: mon-service-fws
# mandatory: false
targets: []
@@ -1,16 +0,0 @@
# ============================================================
# FWS Linux — modules/unpackfs.conf
# Copie le système live vers le disque cible
# ============================================================
unpack:
# Source : le squashfs de l'ISO FWS
# Adapte "FWS" selon la valeur de iso_name dans profiledef.sh
- source: /run/archiso/bootmnt/FWS/x86_64/airootfs.sfs
sourcefs: squashfs
destination: ""
# Alternative si tu utilises erofs au lieu de squashfs :
# - source: /run/archiso/bootmnt/FWS/x86_64/airootfs.erofs
# sourcefs: erofs
# destination: ""
@@ -1,39 +0,0 @@
# ============================================================
# FWS Linux — modules/users.conf
# ============================================================
# Nom d'hôte par défaut
defaultGroups:
- users
- lp
- video
- network
- storage
- wheel
- audio
- optical
- scanner
- power
# Autoriser le login automatique
autologinGroup: autologin
# Sudoers — donne les droits sudo au groupe wheel
sudoersGroup: wheel
# Shell par défaut pour les nouveaux utilisateurs
userShell: /bin/bash
# Hostname par défaut
hostname:
location: EtcFile
template: "fws-${first}"
# Règles pour les mots de passe
passwordRequirements:
minLength: 6
maxLength: -1
nonempty: true
# Permet de définir le même mot de passe pour root et user
allowWeakPasswords: false
@@ -1,29 +0,0 @@
# ============================================================
# FWS Linux — modules/welcome.conf
# ============================================================
# Afficher les conditions requises avant l'installation
showSupportUrl: true
showKnownIssuesUrl: true
showReleaseNotesUrl: false
showDonateUrl: false
# Vérifications système requises
requirements:
# Espace disque minimum en MiB
requiredStorage: 20.0
# RAM minimum en MiB
requiredRam: 2.0
# Vérifier la connexion internet (optionnel)
checkInternet: false
# Vérifier si on tourne en live (pas déjà installé)
checkForRoot: true
# Vérifier l'alimentation (AC power)
checkPower: true
# Ne bloque pas l'install si pas connecté
internetCheckUrl: "https://cloudflare.com"
@@ -1,51 +0,0 @@
# ============================================================
# FWS Linux — Calamares settings.conf
# ============================================================
modules-search: [ local, /usr/lib/calamares/modules ]
sequence:
- show:
- welcome
- locale
- keyboard
- partition
- users
- summary
- exec:
- partition
- mount
- luksbootkeyfile
- luksopenswaphookcfg
- unpackfs
- machineid
- fstab
- locale
- keyboard
- localecfg
- users
- networkcfg
- hwclock
- services-systemd
- packages
- initcpiocfg
- initcpio
- grubcfg
- bootloader
- umount
- show:
- finished
branding: fws
# Demande confirmation avant d'installer
prompt-install: true
# Ne pas chroot (laisser à false pour une install normale)
dont-chroot: false
# Désactive les vérifications réseau au démarrage
disable-cancel: false
disable-cancel-during-exec: true
+40
View File
@@ -0,0 +1,40 @@
#!/bin/sh
# ============================================================================
# FWS — entrée « Réparer FWS » dans le menu GRUB du SYSTÈME INSTALLÉ
# (l'équivalent de l'environnement de récupération de Windows).
#
# Ce script est exécuté par grub-mkconfig (à l'installation via le %post du
# kickstart, puis à chaque fws-recovery « Réinstaller GRUB »). Il démarre le
# MÊME système sur fws-recovery.target (+ marqueur fws.recovery=1) :
# fws-recovery-boot.service prend alors tty1 et lance l'application de
# réparation (GUI via startx, repli console).
#
# Sur le live, ce fichier est inerte (grub-mkconfig n'y tourne jamais).
# ============================================================================
set -e
. /usr/share/grub/grub-mkconfig_lib
kernel=/boot/vmlinuz-linux
# L'initramfs FALLBACK (sans autodetect) : c'est l'entrée de secours, elle
# doit démarrer même si le matériel a changé depuis le dernier mkinitcpio.
initrd=/boot/initramfs-linux-fallback.img
[ -f "$initrd" ] || initrd=/boot/initramfs-linux.img
[ -f "$kernel" ] && [ -f "$initrd" ] || exit 0
# Même logique racine que 10_linux : UUID sauf refus explicite.
if [ -n "${GRUB_DEVICE_UUID:-}" ] && [ "x${GRUB_DISABLE_LINUX_UUID:-}" != xtrue ]; then
rootarg="root=UUID=$GRUB_DEVICE_UUID"
else
rootarg="root=$GRUB_DEVICE"
fi
rel_kernel="$(make_system_path_relative_to_its_root "$kernel")"
rel_initrd="$(make_system_path_relative_to_its_root "$initrd")"
cat <<EOF
menuentry 'Réparer FWS (récupération du système)' --class recovery {
$(prepare_grub_to_access_device "${GRUB_DEVICE_BOOT}" | grub_add_tab)
linux $rel_kernel $rootarg rw ${GRUB_CMDLINE_LINUX:-} systemd.unit=fws-recovery.target fws.recovery=1
initrd $rel_initrd
}
EOF
+1 -1
View File
@@ -1 +1 @@
archiso
fws
+2
View File
@@ -0,0 +1,2 @@
\S (\l)
+4 -7
View File
@@ -1,11 +1,8 @@
To install FWS follow the installation guide:
https://wiki.archlinux.org/title/Installation_guide
Welcome to FWS live media.
To install FWS, see the project page:
https://github.com/You-re-like-Windows-a-bitch/fws
For Wi-Fi, authenticate to the wireless network using the iwctl utility.
For mobile broadband (WWAN) modems, connect with the mmcli utility.
Ethernet, WLAN and WWAN interfaces using DHCP should work automatically.
After connecting to the internet, the installation guide can be accessed
via the convenience script Installation_guide.
                                          
@@ -0,0 +1,20 @@
# remove from airootfs!
# Branding FWS : le paquet « filesystem » d'Arch installe /usr/lib/os-release
# avec NAME="Arch Linux". On le remplace par la version FWS APRÈS l'installation
# des paquets (PostTransaction), donc sans conflit pacman « exists in filesystem »
# (poser le fichier dans l'overlay déclencherait ce conflit, cf. ordre overlay→
# pacstrap dans mkarchiso). /etc/os-release reste un lien vers ce fichier.
# Ce hook ne sert qu'au build : zzzz99-remove-custom-hooks le retire du système.
[Trigger]
Operation = Install
Operation = Upgrade
Type = Package
Target = filesystem
[Action]
Description = Applying FWS branding to /usr/lib/os-release...
When = PostTransaction
Depends = filesystem
Depends = coreutils
Exec = /usr/bin/install -Dm0644 /usr/local/share/fws/os-release /usr/lib/os-release
@@ -1,5 +1,18 @@
#!/usr/bin/env bash
status=$?
if [ "${status}" -eq 0 ]; then
fastfetch
# NB : ce fichier est SOURCÉ par le shell de login (zsh sur le live), pas exécuté
# → le shebang est ignoré. En zsh « status » est une variable spéciale EN LECTURE
# SEULE (alias de $?) : s'y affecter casse (« read-only variable: status »).
# On utilise donc un autre nom.
_fastfetch_rc=$?
if [ "${_fastfetch_rc}" -eq 0 ]; then
# Logo FWS maison (4 carrés + Tux) au lieu du logo Arch détecté par défaut.
fastfetch \
--logo-type file \
--logo /usr/local/share/fws/logo.txt \
--logo-color-1 '38;2;30;160;100' \
--logo-color-2 '38;2;45;125;210' \
--logo-color-3 '38;2;240;180;40' \
--logo-color-4 '38;2;25;85;145' \
--logo-color-5 '38;2;28;28;34' \
--logo-color-6 '38;2;245;165;35'
fi
@@ -1,12 +0,0 @@
[Unit]
Description=Calamares Installer
After=display-manager.service
Requires=display-manager.service
[Service]
Type=simple
ExecStart=/usr/bin/calamares
Restart=on-failure
[Install]
WantedBy=graphical.target
@@ -1 +0,0 @@
/usr/lib/systemd/system/systemd-timesyncd.service
@@ -0,0 +1 @@
/usr/lib/systemd/system/systemd-timesyncd.service
@@ -0,0 +1,24 @@
[Unit]
Description=FWS - Reparation du systeme (session de secours sur tty1)
# Demarre UNIQUEMENT via fws-recovery.target (entree GRUB « Reparer FWS » du
# systeme installe : systemd.unit=fws-recovery.target). PAS de [Install] :
# enrole dans aucun boot normal, donc son Conflicts=getty@tty1 ne peut jamais
# casser le login tty1 d'un boot ordinaire.
# Sur le live, c'est /root/.zprofile (autologin tty1) qui gere la reparation.
ConditionKernelCommandLine=fws.recovery=1
ConditionPathExists=!/run/archiso
Conflicts=getty@tty1.service display-manager.service
After=systemd-user-sessions.service getty@tty1.service display-manager.service
[Service]
Type=idle
# GUI via startx (openbox + fws-recovery-gui) ; si X ne demarre pas (pilote
# video casse — un cas de reparation typique), repli sur l'assistant CONSOLE.
ExecStart=/bin/sh -c '/usr/bin/startx /usr/local/bin/fws-recovery-session -- vt1 || exec /usr/local/bin/fws-recovery'
StandardInput=tty
StandardOutput=tty
StandardError=tty
TTYPath=/dev/tty1
TTYReset=yes
TTYVHangup=yes
Restart=no
@@ -0,0 +1,10 @@
[Unit]
Description=FWS - Cible de reparation du systeme
# Demandee par l'entree GRUB « Reparer FWS » du systeme installe
# (kernel : systemd.unit=fws-recovery.target fws.recovery=1).
# Un multi-user complet (reseau pour pacman -Syu) + la session de reparation ;
# le Conflicts du service libere tty1 (son start est REQUIS ici, il gagne
# contre le Wants de getty@tty1).
Requires=multi-user.target fws-recovery-boot.service
After=multi-user.target fws-recovery-boot.service
AllowIsolate=yes
@@ -1 +0,0 @@
/usr/lib/systemd/system/systemd-time-wait-sync.service
@@ -0,0 +1 @@
/usr/lib/systemd/system/systemd-time-wait-sync.service
@@ -1 +0,0 @@
/usr/lib/systemd/system/systemd-timesyncd.service
@@ -0,0 +1 @@
/usr/lib/systemd/system/systemd-timesyncd.service
@@ -0,0 +1,12 @@
# FWS — swap compressé en RAM (zram), activé automatiquement par
# zram-generator (paquet dans packages.x86_64, aucun service à activer).
#
# Le LIVE n'a AUCUN swap : sur une machine/VM à 2 Go, Anaconda + le rootfs
# squashfs saturent la mémoire → livelock, écran figé pendant « Préparation
# de l'installateur ». Le zram (compression ~3:1 sur les tas Python) donne
# la marge nécessaire. Copié tel quel sur le SYSTÈME INSTALLÉ par le payload
# LiveOS → FWS garde ce filet de sécurité après installation (esprit
# « remplaçant de Windows » sur des machines modestes).
[zram0]
zram-size = min(ram, 4096)
compression-algorithm = zstd
@@ -0,0 +1,9 @@
[Desktop Entry]
Type=Application
Name=Bienvenue sur FWS
Comment=Fenêtre de bienvenue au premier démarrage
Exec=fws-hello --autostart
Icon=help-about
Terminal=false
Categories=System;
X-GNOME-Autostart-enabled=true
@@ -1,31 +0,0 @@
#!/bin/bash
# ============================================================
# FWS Linux — fws-installer
# Script de lancement de Calamares
# ============================================================
# Vérifie que Calamares est installé
if ! command -v calamares &>/dev/null; then
echo "ERREUR : calamares n'est pas installé."
exit 1
fi
# Vérifie qu'on tourne bien en live
if [ ! -d /run/archiso ]; then
echo "ATTENTION : Ce script doit être lancé depuis le live FWS."
fi
# Lance Calamares avec les droits root
# -D6 active les logs de debug (retirer en production)
if [ "$EUID" -ne 0 ]; then
if command -v sudo >/dev/null 2>&1; then
exec sudo -E calamares "$@"
elif command -v pkexec >/dev/null 2>&1; then
exec pkexec calamares "$@"
else
echo "ERREUR : Impossible de lancer Calamares en tant que root (sudo/pkexec non trouvés)."
exit 1
fi
else
exec calamares "$@"
fi
View File
View File
+185
View File
@@ -0,0 +1,185 @@
#!/usr/bin/env python3
# FWS — fenêtre « À propos » : deux onglets, « Le projet FWS » (ce qu'est FWS,
# version, liens) et « Système » (matériel + logiciel détectés). Remplace le
# « About Xfce » de libxfce4ui par une page de marque FWS. GTK3 (python-gobject
# installé avec le bureau).
import os
import re
import subprocess
import gi
gi.require_version("Gtk", "3.0")
gi.require_version("Gdk", "3.0") # sinon gi charge Gdk 4.0 (conflit avec Gtk3)
from gi.repository import Gdk, GLib, Gtk # noqa: E402
GLib.set_prgname("fws-about")
def _osrelease():
data = {}
for path in ("/etc/os-release", "/usr/lib/os-release"):
try:
with open(path) as fh:
for line in fh:
m = re.match(r'^([A-Z_]+)=(.*)$', line.strip())
if m:
data[m.group(1)] = m.group(2).strip('"')
break
except OSError:
continue
return data
def _cmd(*argv):
try:
return subprocess.check_output(argv, text=True,
stderr=subprocess.DEVNULL).strip()
except (OSError, subprocess.CalledProcessError):
return ""
def _cpu():
try:
with open("/proc/cpuinfo") as fh:
for line in fh:
if line.startswith("model name"):
return line.split(":", 1)[1].strip()
except OSError:
pass
return "inconnu"
def _mem():
try:
with open("/proc/meminfo") as fh:
for line in fh:
if line.startswith("MemTotal"):
kib = int(line.split()[1])
return f"{kib / 1048576:.1f} Gio"
except OSError:
pass
return "inconnu"
def _gpus():
out = []
for line in _cmd("lspci").splitlines():
low = line.lower()
if "vga" in low or "3d" in low or "display" in low:
out.append(line.split(":", 2)[-1].strip())
return out or ["inconnu"]
def _desktop():
if os.environ.get("HYPRLAND_INSTANCE_SIGNATURE"):
return "Hyprland"
env = os.environ.get("XDG_CURRENT_DESKTOP") \
or os.environ.get("DESKTOP_SESSION") or ""
return env or "inconnu"
def _session_type():
t = os.environ.get("XDG_SESSION_TYPE", "")
return {"wayland": "Wayland", "x11": "X11"}.get(t, t or "inconnu")
def _disks():
out = []
for line in _cmd("lsblk", "-dno", "NAME,SIZE,MODEL,TYPE").splitlines():
f = line.split()
if f and f[-1] == "disk":
out.append(" ".join(f[:-1]))
return out or ["inconnu"]
def _grid(rows):
grid = Gtk.Grid(column_spacing=18, row_spacing=8, margin=18)
for i, (key, val) in enumerate(rows):
k = Gtk.Label(xalign=1)
k.set_markup(f"<b>{GLib.markup_escape_text(key)}</b>")
k.get_style_context().add_class("dim-label")
v = Gtk.Label(label=val, xalign=0, selectable=True)
v.set_line_wrap(True)
grid.attach(k, 0, i, 1, 1)
grid.attach(v, 1, i, 1, 1)
return grid
def _project_tab(osr):
box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=10, margin=20)
title = Gtk.Label()
name = osr.get("PRETTY_NAME") or osr.get("NAME") or "FWS Linux"
title.set_markup(f"<span size='xx-large' weight='bold'>{name}</span>")
box.pack_start(title, False, False, 0)
tag = Gtk.Label(label="Une distribution Linux pensée pour remplacer "
"Windows : bureau prêt à l'emploi, jeux, VR et "
"compatibilité applicative.")
tag.set_line_wrap(True)
tag.set_max_width_chars(52)
box.pack_start(tag, False, False, 0)
feats = Gtk.Label()
feats.set_markup(
"<b>Inclus :</b> installateur graphique · plusieurs bureaux "
"(GNOME, KDE, Hyprland, i3, XFCE) · Steam &amp; Proton-GE · "
"réalité virtuelle (SteamVR) · winboat (applications Windows) · "
"pare-feu · réparation système intégrée.")
feats.set_line_wrap(True)
feats.set_max_width_chars(52)
feats.set_xalign(0)
box.pack_start(feats, False, False, 6)
home = osr.get("HOME_URL") or "https://github.com/You-re-like-Windows-a-bitch/fws"
link = Gtk.LinkButton.new_with_label(home, "Site du projet")
box.pack_start(link, False, False, 0)
return box
def _system_tab(osr):
rows = [
("Système", osr.get("PRETTY_NAME", "FWS Linux")),
("Build", osr.get("BUILD_ID", "rolling")),
("Noyau", _cmd("uname", "-r") or "inconnu"),
("Bureau", _desktop()),
("Affichage", _session_type()),
("Nom de machine", _cmd("hostname") or os.uname().nodename),
("Processeur", _cpu()),
("Mémoire", _mem()),
("Carte(s) graphique(s)", "\n".join(_gpus())),
("Disque(s)", "\n".join(_disks())),
]
scroll = Gtk.ScrolledWindow()
scroll.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC)
scroll.add(_grid(rows))
return scroll
class AboutWindow(Gtk.Window):
def __init__(self):
super().__init__(title="À propos de FWS")
self.set_default_size(520, 460)
self.set_position(Gtk.WindowPosition.CENTER)
self.set_type_hint(Gdk.WindowTypeHint.DIALOG)
osr = _osrelease()
notebook = Gtk.Notebook()
notebook.append_page(_project_tab(osr), Gtk.Label(label="Le projet FWS"))
notebook.append_page(_system_tab(osr), Gtk.Label(label="Système"))
self.add(notebook)
self.connect("destroy", Gtk.main_quit)
def main():
if not Gtk.init_check()[0]:
return 1
win = AboutWindow()
win.show_all()
Gtk.main()
return 0
if __name__ == "__main__":
raise SystemExit(main())
+158
View File
@@ -0,0 +1,158 @@
#!/usr/bin/env python3
# FWS — fenêtre de bienvenue au premier démarrage (pendant post-install de la
# page récap de l'installateur). Boutons : mise à jour, codecs, VR, raccourcis,
# Proton-GE. GTK3 : présent sur TOUS les bureaux FWS (Firefox le tire) ;
# python-gobject est installé avec le bureau par le kickstart.
#
# Lancement : /etc/xdg/autostart (KDE/GNOME/XFCE) et exec des configs
# Hyprland/i3, toujours avec --autostart : on se retire sans bruit si
# l'utilisateur a coché « ne plus afficher » (~/.config/fws/hello-done).
import os
import shutil
import subprocess
import sys
import gi
gi.require_version("Gtk", "3.0")
gi.require_version("Gdk", "3.0") # sinon gi charge Gdk 4.0 (conflit avec Gtk3)
from gi.repository import Gdk, GLib, Gtk # noqa: E402
# WM_CLASS déterministe : les règles i3/Hyprland « fenêtre flottante »
# ciblent cette classe.
GLib.set_prgname("fws-hello")
_FLAG = os.path.expanduser("~/.config/fws/hello-done")
_CODECS = ("gst-plugins-base gst-plugins-good gst-plugins-bad "
"gst-plugins-ugly gst-libav ffmpeg mpv")
# (libellé, description, commande, en_terminal)
_ACTIONS = [
("Mettre à jour le système",
"pacman -Syu + nettoyage du cache",
"fws-update", True),
("Installer les codecs multimédia",
"lecture vidéo/audio (GStreamer, ffmpeg, mpv)",
f"sudo pacman -S --needed {_CODECS}", True),
("Proton-GE pour Steam",
"meilleure compatibilité des jeux Windows",
"fws-proton-ge", True),
("Configurer la VR",
"drivers casque : HTC Vive, Index, Quest…",
"fws-vr-setup", True),
]
_TERMINALS = ["kitty", "konsole", "gnome-terminal", "xfce4-terminal", "xterm"]
def _terminal():
for term in _TERMINALS:
if shutil.which(term):
return term
return None
def _run(command, in_terminal):
if in_terminal:
term = _terminal()
if term is None:
return
if term == "gnome-terminal":
argv = [term, "--", "sh", "-c", command]
else:
argv = [term, "-e", "sh", "-c", command]
else:
argv = ["sh", "-c", command]
subprocess.Popen(argv) # noqa: S603 — commandes internes FWS
class HelloWindow(Gtk.Window):
def __init__(self):
super().__init__(title="Bienvenue sur FWS")
self.set_default_size(460, -1)
self.set_position(Gtk.WindowPosition.CENTER)
self.set_border_width(18)
# DIALOGUE : les tuileurs (i3/Hyprland) laissent les dialogues en
# flottant → la fenêtre garde sa taille naturelle au lieu d'être
# étirée sur tout l'espace de travail (layout illisible sinon).
self.set_type_hint(Gdk.WindowTypeHint.DIALOG)
self.set_resizable(False)
box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=12)
self.add(box)
title = Gtk.Label()
title.set_markup("<span size='x-large' weight='bold'>Bienvenue sur FWS !</span>")
box.pack_start(title, False, False, 0)
subtitle = Gtk.Label(
label="Ton système est prêt. Quelques réglages utiles pour bien démarrer :")
subtitle.set_line_wrap(True)
subtitle.set_xalign(0)
box.pack_start(subtitle, False, False, 0)
actions = list(_ACTIONS)
# Raccourcis clavier : uniquement sur les sessions qui ont fws-keys
# (Hyprland/i3) — les autres bureaux ont leurs propres réglages.
session = os.environ.get("XDG_CURRENT_DESKTOP", "").lower()
if os.environ.get("HYPRLAND_INSTANCE_SIGNATURE") or "i3" in session:
actions.append(("Voir les raccourcis clavier",
"aussi disponible à tout moment : Super+K",
"fws-keys", False))
for label, desc, command, in_term in actions:
button = Gtk.Button()
inner = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=2)
lab = Gtk.Label()
lab.set_markup(f"<b>{label}</b>")
lab.set_xalign(0)
sub = Gtk.Label(label=desc)
sub.set_xalign(0)
sub.get_style_context().add_class("dim-label")
inner.pack_start(lab, False, False, 0)
inner.pack_start(sub, False, False, 0)
button.add(inner)
button.connect("clicked",
lambda _b, c=command, t=in_term: _run(c, t))
box.pack_start(button, False, False, 0)
self._again = Gtk.CheckButton(label="Afficher cette fenêtre au prochain démarrage")
self._again.set_active(False)
box.pack_start(self._again, False, False, 6)
close = Gtk.Button(label="Fermer")
close.connect("clicked", lambda _b: self.close())
box.pack_start(close, False, False, 0)
self.connect("destroy", self._on_destroy)
def _on_destroy(self, _win):
if not self._again.get_active():
os.makedirs(os.path.dirname(_FLAG), exist_ok=True)
with open(_FLAG, "w") as fh:
fh.write("ok\n")
else:
try:
os.unlink(_FLAG)
except OSError:
pass
Gtk.main_quit()
def main():
if "--autostart" in sys.argv and os.path.exists(_FLAG):
return 0
# Pas d'affichage joignable (lancement hors session graphique) : on se
# retire sans traceback plutôt que de crasher.
if not Gtk.init_check()[0]:
return 1
win = HelloWindow()
win.show_all()
Gtk.main()
return 0
if __name__ == "__main__":
sys.exit(main())
+129
View File
@@ -0,0 +1,129 @@
#!/usr/bin/env python3
# FWS — affiche les raccourcis clavier RÉELS de la session (bouton ⌨ de la
# barre ou Super+K). Universel :
# • Hyprland : « hyprctl binds -j » = les binds effectivement chargés
# (descriptions des bindd) — affichage wofi (Wayland).
# • i3 : parse ~/.config/i3/config (bindsym, variables résolues)
# — affichage rofi (X11).
# Aucune dépendance hors python3 + wofi/rofi (déjà installés avec le bureau).
import json
import os
import re
import subprocess
import sys
_WOFI_STYLE = "/usr/local/share/fws/wofi-keys.css"
# Bits de modmask Hyprland (masques X11) dans l'ordre d'affichage voulu.
_MODS = [(64, "SUPER"), (4, "CTRL"), (8, "ALT"), (1, "SHIFT")]
_KEY_LABELS = {
"mouse:272": "clic gauche",
"mouse:273": "clic droit",
"mouse:274": "clic molette",
"mouse_down": "molette bas",
"mouse_up": "molette haut",
"button4": "molette haut",
"button5": "molette bas",
"return": "Entrée",
"space": "Espace",
"escape": "Échap",
"tab": "Tab",
"left": "←",
"right": "→",
"up": "↑",
"down": "↓",
"print": "Impr écran",
}
def _label(key):
return _KEY_LABELS.get(key.lower(), key)
# --- Hyprland : binds réels via hyprctl ------------------------------------
def hyprland_lines():
raw = subprocess.check_output(["hyprctl", "binds", "-j"], text=True)
lines, seen = [], set()
for bind in json.loads(raw):
parts = [name for bit, name in _MODS if bind.get("modmask", 0) & bit]
key = bind.get("key") or (f"code {bind['keycode']}" if bind.get("keycode") else "")
parts.append(_label(key))
combo = " + ".join(p for p in parts if p)
if not combo or combo in seen:
continue
seen.add(combo)
desc = (bind.get("description") or "").strip() \
or f"{bind.get('dispatcher', '?')} {(bind.get('arg') or '').strip()}".strip()
lines.append(f"{combo:<24} {desc}")
return lines
# --- i3 : parse de la config (variables résolues) ----------------------------
def i3_lines():
path = os.path.expanduser("~/.config/i3/config")
variables = {}
lines, seen = [], set()
with open(path, encoding="utf-8", errors="replace") as fh:
content = fh.readlines()
for line in content:
m = re.match(r"\s*set\s+(\$\S+)\s+(.+)$", line)
if m:
variables[m.group(1)] = m.group(2).strip()
def resolve(text):
# $var les plus longs d'abord ($filemanager avant $file…).
for var in sorted(variables, key=len, reverse=True):
text = text.replace(var, variables[var])
return text
for line in content:
m = re.match(r"\s*bindsym\s+(?:--\S+\s+)*(\S+)\s+(.+)$", line)
if not m:
continue
combo_raw, action = m.groups()
combo_raw = resolve(combo_raw).replace("Mod4", "Super").replace("Mod1", "Alt")
combo = " + ".join(_label(k) for k in combo_raw.split("+"))
if combo in seen:
continue
seen.add(combo)
action = resolve(action)
action = re.sub(r"^exec\s+(--no-startup-id\s+)?", "", action).strip().strip('"')
lines.append(f"{combo:<24} {action}")
return lines
def show(lines):
if not lines:
lines = ["(aucun raccourci trouvé)"]
text = "\n".join(lines)
if os.environ.get("HYPRLAND_INSTANCE_SIGNATURE"):
cmd = ["wofi", "--dmenu", "--prompt", "Raccourcis clavier — taper pour filtrer",
"--width", "820", "--height", "600", "--insensitive",
"--cache-file", "/dev/null"]
if os.path.exists(_WOFI_STYLE):
cmd += ["--style", _WOFI_STYLE]
else:
# X11/i3 : rofi en dmenu, style assorti (mono pour l'alignement).
cmd = ["rofi", "-dmenu", "-i", "-p", "Raccourcis clavier",
"-no-custom",
"-theme-str", 'window { width: 880px; } listview { lines: 18; }',
"-theme-str", '* { font: "Noto Sans Mono 11"; }']
subprocess.run(cmd, input=text, text=True, check=False)
def main():
try:
if os.environ.get("HYPRLAND_INSTANCE_SIGNATURE"):
lines = hyprland_lines()
else:
lines = i3_lines()
except Exception as exc: # noqa: BLE001 — best effort, jamais de crash muet
subprocess.run(["notify-send", "Raccourcis FWS", f"Erreur : {exc}"],
check=False)
return 1
show(lines)
return 0
if __name__ == "__main__":
sys.exit(main())

Some files were not shown because too many files have changed in this diff Show More