commit 9a4a970f764bb0e5fe1a0dc4ab88ad280aa10498 Author: Damien Coles Date: Sat Jan 24 20:47:35 2026 -0500 public-ready-init diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..85e7c1d --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/.idea/ diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..14fac91 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..15e46a1 --- /dev/null +++ b/README.md @@ -0,0 +1,159 @@ +# Gentoo Legion + +Complete Gentoo Linux installation with Hyprland, greetd, and hybrid GPU support for Lenovo Legion laptops and similar AMD + NVIDIA setups. + +## About + +This represents my third attempt at getting Gentoo running properly on this laptop with my preferred Hyprland setup. The hybrid GPU setup was the main challenge - particularly understanding how the USB-C ports route through the NVIDIA GPU while the laptop panel connects to the AMD iGPU. Once that clicked, everything fell into place. + +The result is a lean system that idles under 2GB of RAM while still providing a full Hyprland desktop. I opted for the distribution kernel (`gentoo-kernel`) rather than a custom compile - it works out of the box with the hardware and saves hours of configuration. + +Your mileage may vary - I tried to isolate as many of the use flags as I could + +## Features + +- **Full disk encryption** - LUKS2 with Btrfs subvolumes +- **Hybrid GPU support** - AMD iGPU + NVIDIA dGPU working together +- **Hyprland desktop** - Modern Wayland compositor with greetd + regreet login +- **OpenRC init** - Traditional init system, no systemd +- **Automated installation** - Scripts for disk setup, chroot, and service configuration + +## Hardware Tested + +**Lenovo Legion S7 15ACH6** +- AMD Ryzen 9 5900HX (Zen 3, 16 threads) +- AMD Radeon Vega (Cezanne) - integrated GPU +- NVIDIA GeForce RTX 3050 Ti Mobile - discrete GPU +- 24GB DDR4 RAM (THIS IS AN UPGRADE FROM STANDARD! 8GB ON THIS MODEL IS SOLDERED) +- NVMe SSD with LUKS2 encryption + +This configuration should work with other Legion models and similar AMD + NVIDIA hybrid laptops with minor adjustments. + +## Quick Start + +1. Boot Gentoo minimal install ISO +2. Clone this repository: + ```bash + git clone https://github.com//gentoo-legion + cd gentoo-legion + ``` +3. Follow the [Installation Guide](docs/installation.md) + +## Directory Structure + +``` +gentoo-legion/ +├── docs/ # Documentation +│ ├── installation.md # Full installation guide +│ ├── hybrid-gpu.md # AMD+NVIDIA GPU configuration +│ ├── greetd-setup.md # Display manager setup +│ └── troubleshooting.md # Common issues and fixes +├── install/ # Installation scripts +│ ├── init.sh # Stage 1: Disk partitioning, LUKS, Btrfs +│ ├── chroot.sh # Chroot helper script +│ └── services.sh # Stage 3: Service configuration +├── portage/ # Portage configuration → /etc/portage/ +│ ├── make.conf # Compiler flags, USE flags +│ ├── package.use/ # Package-specific USE flags +│ ├── package.accept_keywords/ # ~amd64 keywords +│ ├── package.license/ # License acceptance +│ └── sets/ # Package sets (@hyprland) +├── system/ # System configuration +│ ├── ccache.conf # Compiler cache config +│ ├── dracut.conf.d/ # Initramfs configuration +│ └── conf.d/ # OpenRC service configs +├── greetd/ # Display manager configuration +│ ├── config.toml # greetd main config +│ ├── regreet.toml # GTK greeter theming +│ ├── hyprland.conf # Greeter Hyprland session +│ ├── greetd.pam # PAM configuration +│ └── start-hyprland-dbus # User session launcher +├── firewall/ # iptables rules +│ ├── iptables.rules.example # IPv4 rules (customize) +│ └── ip6tables.rules # IPv6 rules +├── hypr/ # Hyprland configuration +│ ├── ENVariables.conf # GPU environment variables +│ ├── monitors.conf.example # Monitor layout (customize) +│ └── wlogout-layout # Power menu for OpenRC +└── shell/ # Shell configuration + ├── zshrc.example # Zsh config (customize) + └── starship.toml # Starship prompt theme +``` + +## Configuration Categories + +### Copy As-Is +These files can be copied directly to your system: + +| Source | Destination | +|--------|-------------| +| `portage/*` | `/etc/portage/` | +| `system/ccache.conf` | `/etc/ccache.conf` | +| `system/dracut.conf.d/*` | `/etc/dracut.conf.d/` | +| `system/conf.d/{iptables,ip6tables,snapper}` | `/etc/conf.d/` | +| `greetd/*` | `/etc/greetd/` (and `/etc/pam.d/greetd`) | +| `firewall/ip6tables.rules` | `/etc/iptables/` | +| `shell/starship.toml` | `~/.config/starship.toml` | + +### Customize Before Use +These files need editing for your system: + +| File | What to customize | +|------|-------------------| +| `system/conf.d/dmcrypt.example` | Set your swap partition device | +| `firewall/iptables.rules.example` | Add your trusted networks | +| `hypr/monitors.conf.example` | Configure your display layout | +| `shell/zshrc.example` | Add your aliases, paths, etc. | + +## Key Technologies + +- **Compositor**: [Hyprland](https://hyprland.org/) with [KooL's dotfiles](https://github.com/JaKooLit/Hyprland-Dots) +- **Display Manager**: [greetd](https://sr.ht/~kennylevinsen/greetd/) + [regreet](https://github.com/rharish101/ReGreet) +- **Init System**: OpenRC +- **Filesystem**: Btrfs with zstd compression +- **Encryption**: LUKS2 (dm-crypt) +- **Snapshots**: Snapper for system rollback +- **Shell**: Zsh with Starship prompt + +## Documentation + +- [Installation Guide](docs/installation.md) - Complete step-by-step installation +- [Hybrid GPU Guide](docs/hybrid-gpu.md) - AMD + NVIDIA configuration +- [greetd Setup](docs/greetd-setup.md) - Display manager configuration +- [Troubleshooting](docs/troubleshooting.md) - Common issues and fixes + +## Btrfs Subvolume Layout + +| Subvolume | Mount Point | Purpose | +|-----------|-------------|---------| +| @ | / | Root filesystem | +| @home | /home | User data | +| @var | /var | Variable data | +| @log | /var/log | System logs | +| @snapshots | /.snapshots | Snapper backups | + +## OpenRC Services + +**Boot runlevel:** dbus, elogind, dmcrypt + +**Default runlevel:** sysklogd, sshd, NetworkManager, chronyd, cronie, power-profiles-daemon, display-manager, bluetooth, iptables, ip6tables + +## Contributing + +Contributions are welcome! Please: + +1. Fork the repository +2. Create a feature branch +3. Test your changes on actual hardware if possible +4. Submit a pull request + +## License + +MIT License - See [LICENSE](LICENSE) + +## Acknowledgments + +- [JaKooLit](https://github.com/JaKooLit) for Hyprland dotfiles +- [Gentoo Wiki](https://wiki.gentoo.org/) for comprehensive documentation +- [Hyprland](https://hyprland.org/) for the compositor +- The Gentoo and Hyprland communities diff --git a/docs/greetd-setup.md b/docs/greetd-setup.md new file mode 100644 index 0000000..416cf94 --- /dev/null +++ b/docs/greetd-setup.md @@ -0,0 +1,205 @@ +# greetd Display Manager Setup + +Guide for configuring greetd with regreet (GTK greeter) on Gentoo with Hyprland. + +## Overview + +greetd is a minimal display manager that launches regreet inside a temporary Hyprland session. This provides a graphical login screen that works well with Wayland compositors. + +**Architecture:** +``` +greetd (daemon) → Hyprland (minimal) → regreet (GTK greeter) → User session +``` + +## Installation + +### Required Packages +```bash +emerge gui-libs/greetd gui-apps/regreet gui-libs/display-manager-init +``` + +### Enable Service +```bash +# Set greetd as display manager +echo 'DISPLAYMANAGER="greetd"' > /etc/conf.d/display-manager + +# Add to default runlevel +rc-update add display-manager default +``` + +## Configuration Files + +### /etc/greetd/config.toml +Main greetd configuration: +```toml +[terminal] +vt = 7 + +[default_session] +command = "start-hyprland -- --config /etc/greetd/hyprland.conf > /var/log/hyprland-greeter.log 2>&1" +user = "greetd" +``` + +### /etc/greetd/regreet.toml +GTK greeter theming: +```toml +[background] +path = "/usr/share/backgrounds/default.png" +fit = "Cover" + +[GTK] +application_prefer_dark_theme = true + +[commands] +reboot = ["loginctl", "reboot"] +poweroff = ["loginctl", "poweroff"] +``` + +**Note:** Uses `loginctl` for power commands (OpenRC-compatible, not systemd). + +### /etc/greetd/hyprland.conf +Minimal Hyprland config for the greeter session: +```bash +exec-once = regreet; hyprctl dispatch exit + +env = XCURSOR_THEME,Bibata-Modern-Ice +env = XCURSOR_SIZE,24 + +# Force greeter to laptop display only +monitor=eDP-2, 1920x1080@60, 0x0, 1 +monitor=DP-1, disable +monitor=DP-2, disable + +cursor { + default_monitor = eDP-2 +} + +input { + touchpad { + disable_while_typing = true + natural_scroll = true + tap-to-click = true + } +} + +misc { + disable_hyprland_logo = true + disable_splash_rendering = true + disable_autoreload = true +} + +debug { + disable_logs = true +} +``` + +### /etc/pam.d/greetd +Custom PAM configuration to prevent `user.greetd` errors: +``` +# greetd PAM configuration +# Omits pam_openrc.so to prevent user.greetd service errors + +auth include system-local-login +account include system-local-login +password include system-local-login +session optional pam_loginuid.so +session required pam_env.so envfile=/etc/profile.env +session include system-auth +session optional pam_motd.so motd=/etc/motd +session optional pam_lastlog.so never showfailed +session optional pam_mail.so +-session optional pam_elogind.so +``` + +**Why custom PAM?** The default PAM chain includes `pam_openrc.so` which tries to start a user session service (`user.greetd`). Since greetd is a system service, not a user login, this fails and generates errors at boot. + +## User Session Launcher + +### /usr/local/bin/start-hyprland-dbus +Wrapper script for user Hyprland sessions with logging: +```bash +#!/bin/bash +exec dbus-run-session /usr/bin/start-hyprland > ~/.local/log/hyprland.log 2>&1 +``` + +### Update Desktop Entry +Modify `/usr/share/wayland-sessions/hyprland.desktop`: +```ini +Exec=/usr/local/bin/start-hyprland-dbus +``` + +### Create Log Directory +```bash +mkdir -p ~/.local/log +``` + +## Log Files + +| Log | Location | Purpose | +|-----|----------|---------| +| Greeter | `/var/log/hyprland-greeter.log` | Greeter Hyprland session | +| User | `~/.local/log/hyprland.log` | User Hyprland session | + +The greeter log file needs correct ownership: +```bash +sudo touch /var/log/hyprland-greeter.log +sudo chown greetd:greetd /var/log/hyprland-greeter.log +``` + +## Customization + +### Change Background +Edit `/etc/greetd/regreet.toml`: +```toml +[background] +path = "/path/to/your/wallpaper.png" +``` + +### Change Cursor Theme +Edit `/etc/greetd/hyprland.conf`: +```bash +env = XCURSOR_THEME, +env = XCURSOR_SIZE,24 +``` + +### Enable External Monitors at Login +Remove or modify the `disable` lines in `/etc/greetd/hyprland.conf`: +```bash +# Enable external monitors +monitor=DP-1, 1920x1080@60, 0x0, 1 +monitor=eDP-2, 1920x1080@60, 1920x0, 1 +``` + +## Troubleshooting + +### "failed to start user.greetd" at boot +Ensure you're using the custom `/etc/pam.d/greetd` that omits `pam_openrc.so`. + +### Black screen at login +1. Check `/var/log/hyprland-greeter.log` for errors +2. Verify monitor configuration in `/etc/greetd/hyprland.conf` +3. Ensure greetd user has access to DRI devices + +### regreet not appearing +1. Verify regreet is installed: `which regreet` +2. Check the exec-once line in hyprland.conf +3. Review greeter logs + +### Keyboard not working +Ensure elogind is running and in boot runlevel: +```bash +rc-update add elogind boot +rc-service elogind start +``` + +### Service management +```bash +# Check status +rc-service display-manager status + +# Restart +rc-service display-manager restart + +# View logs +cat /var/log/hyprland-greeter.log +``` diff --git a/docs/hybrid-gpu.md b/docs/hybrid-gpu.md new file mode 100644 index 0000000..7ad8100 --- /dev/null +++ b/docs/hybrid-gpu.md @@ -0,0 +1,169 @@ +# Hybrid GPU Configuration + +Guide for configuring AMD + NVIDIA hybrid graphics on Legion laptops with Hyprland. + +## Hardware Topology + +On Legion laptops with hybrid graphics: +- **AMD iGPU (card1)**: Drives the laptop display (eDP-2) +- **NVIDIA dGPU (card0)**: Drives external displays (DP-1, DP-2 via USB-C) + +This is hardware-wired and cannot be changed via software. + +## BIOS Configuration + +**Critical:** Set GPU mode to **Hybrid/Dynamic** (not Discrete). + +Discrete mode may cause: +- Lower resolution options on laptop display +- Display detection issues +- Power management problems + +## NVIDIA Driver Setup + +### Install Drivers +```bash +emerge x11-drivers/nvidia-drivers +``` + +### Blacklist Nouveau +```bash +echo "blacklist nouveau" > /etc/modprobe.d/blacklist-nouveau.conf +echo "options nouveau modeset=0" >> /etc/modprobe.d/blacklist-nouveau.conf +``` + +### Enable DRM +```bash +echo "options nvidia_drm modeset=1 fbdev=1" > /etc/modprobe.d/nvidia.conf +``` + +### GRUB Configuration +Add to `/etc/default/grub`: +```bash +GRUB_CMDLINE_LINUX_DEFAULT="nvidia_drm.modeset=1 acpi_backlight=native" +``` + +Regenerate: +```bash +grub-mkconfig -o /boot/grub/grub.cfg +``` + +### Dracut Configuration +Create `/etc/dracut.conf.d/nvidia.conf`: +```bash +add_drivers+=" nvidia nvidia_modeset nvidia_uvm nvidia_drm " +force_drivers+=" nvidia nvidia_modeset nvidia_uvm nvidia_drm " +``` + +Rebuild initramfs: +```bash +emerge --config sys-kernel/gentoo-kernel +``` + +## Hyprland Configuration + +### GPU Auto-Detection + +Hyprland should auto-detect GPUs. **Do NOT** set these variables in your config: +```bash +# Leave these commented out for auto-detection +# env = AQ_DRM_DEVICES,/dev/dri/card0:/dev/dri/card1 +# env = AQ_MGPU_NO_EXPLICIT,1 +``` + +If auto-detection fails, try explicit order as fallback: +```bash +env = AQ_DRM_DEVICES,/dev/dri/card1:/dev/dri/card0 +env = AQ_MGPU_NO_EXPLICIT,1 +``` + +### Monitor Configuration + +Example triple-monitor layout: +```bash +# Left external | Center laptop | Right external +monitor=DP-1, 1920x1080@60, 0x0, 1 +monitor=eDP-2, 1920x1080@60, 1920x0, 1 +monitor=DP-2, 1920x1080@60, 3840x0, 1 +``` + +Use `hyprctl monitors` to get your monitor names. + +### Cursor Fix (Multi-GPU) + +Disable hardware cursors to prevent duplicate/missing cursor issues: + +In `~/.config/hypr/configs/SystemSettings.conf`: +``` +cursor { + no_hardware_cursors = 2 + default_monitor = eDP-2 +} +``` + +### Workspace Assignment + +Assign workspaces to specific monitors: +```bash +workspace = 1, monitor:eDP-2, default:true +workspace = 2, monitor:DP-1, default:true +workspace = 3, monitor:DP-2, default:true +``` + +## Gaming + +Games automatically use the NVIDIA GPU in hybrid mode. No `prime-run` needed for most cases. + +If a game isn't using the NVIDIA GPU: +```bash +prime-run +``` + +Or set environment variables: +```bash +__NV_PRIME_RENDER_OFFLOAD=1 __GLX_VENDOR_LIBRARY_NAME=nvidia +``` + +## Backlight Control + +The laptop backlight is controlled by the AMD iGPU. If brightness controls don't work: + +1. Check available backlight devices: + ```bash + ls /sys/class/backlight/ + ``` + +2. Use the correct device in brightness scripts (usually `amdgpu_bl1` for Legion). + +3. GRUB setting helps: + ```bash + GRUB_CMDLINE_LINUX_DEFAULT="... acpi_backlight=native" + ``` + +## Troubleshooting + +### Pink/Artifacts on External Monitors + +1. Ensure BIOS is set to Hybrid/Dynamic mode +2. Try letting Hyprland auto-detect GPUs (comment out AQ_* variables) +3. If auto-detect fails, try explicit GPU order + +### External Monitors Not Detected + +1. Check connections (USB-C to DisplayPort) +2. Verify NVIDIA driver is loaded: `lsmod | grep nvidia` +3. Check Xorg/Wayland logs for errors + +### Performance Issues + +1. Verify NVIDIA persistence daemon is running +2. Check power profile: `powerprofilesctl get` +3. Monitor GPU usage: `nvidia-smi` + +### Screen Tearing + +Ensure NVIDIA DRM is enabled: +```bash +cat /sys/module/nvidia_drm/parameters/modeset +# Should return: Y +``` diff --git a/docs/installation.md b/docs/installation.md new file mode 100644 index 0000000..d218018 --- /dev/null +++ b/docs/installation.md @@ -0,0 +1,351 @@ +# Gentoo Installation Guide - Legion Laptop + +Complete installation guide for Gentoo Linux with Hyprland, greetd, and hybrid GPU support. + +## Hardware Requirements + +- **CPU**: AMD Ryzen (tested with 5900HX) +- **iGPU**: AMD Radeon integrated +- **dGPU**: NVIDIA GeForce (tested with RTX 3050 Ti Mobile) +- **RAM**: 16GB+ recommended +- **Storage**: NVMe or SSD recommended + +## Pre-Installation + +### 1. Prepare LUKS Passphrase + +Generate a strong passphrase for disk encryption: +```bash +openssl rand -base64 64 | tr -dc 'A-Za-z0-9' | head -c 56 +``` + +**Important:** +- Store this passphrase securely (password manager, hardware key, or offline backup) +- You'll need to enter it at every boot + +### 2. Boot Live Environment + +**HiDPI Fix (4K display):** At the GRUB menu, press `e` to edit the boot entry, find the `linux` line, add `video=1920x1080` at the end, then `Ctrl+X` to boot. + +```bash +# Configure network +net-setup +``` + +### 3. Verify DNS Resolution +```bash +cat /etc/resolv.conf +# Should have valid nameservers (1.1.1.1, 8.8.8.8, etc.) +``` + +--- + +## Stage 1: Disk Setup & Stage3 + +### 4. Run init.sh + +Clone this repository and run the initialization script: +```bash +git clone https://github.com//gentoo-legion +cd gentoo-legion +./install/init.sh +``` + +This handles: +- Disk partitioning (EFI 512MB, Swap 16GB, LUKS root) +- LUKS2 encryption setup +- Btrfs subvolume creation (@, @home, @var, @log, @snapshots) +- Stage3 download and extraction +- Copying Portage configs + +**You'll be prompted for the LUKS passphrase twice** (format + open). + +### 5. Enter Chroot +```bash +./install/chroot.sh +``` + +--- + +## Stage 2: Base System Configuration + +### 6. Verify Network +```bash +ping -c 2 gentoo.org +``` +If no network, check `/etc/resolv.conf` has valid nameservers. + +### 7. Sync Portage & Select Profile +```bash +emerge --sync +eselect profile list +# Select: default/linux/amd64/23.0/desktop +eselect profile set +``` + +### 8. Enable GURU Overlay +Required for Hyprland ecosystem packages: +```bash +emerge app-eselect/eselect-repository +eselect repository enable guru +emerge --sync +``` + +### 9. Configure ccache +```bash +emerge dev-util/ccache +mkdir -p /var/cache/ccache +# ccache.conf was already copied by init.sh +``` + +### 10. Install Firmware & Compile @world +```bash +emerge sys-kernel/linux-firmware --autounmask-write +dispatch-conf # Choose 'u' to update +emerge sys-kernel/linux-firmware +emerge --update --deep --newuse @world +# This will take a while +``` + +### 11. Re-enable Harfbuzz +After @world completes, restore harfbuzz support: +```bash +# Remove the -harfbuzz line from circular-dependencies +nano /etc/portage/package.use/circular-dependencies + +# Rebuild with full support +emerge -1 media-libs/freetype media-libs/harfbuzz +``` + +### 12. Set Timezone & Locale +```bash +echo "America/New_York" > /etc/timezone # Adjust for your timezone +emerge --config sys-libs/timezone-data + +nano /etc/locale.gen +# Uncomment: en_US.UTF-8 UTF-8 + +locale-gen + +eselect locale list +eselect locale set # en_US.utf8 + +echo "LANG=en_US.UTF-8" > /etc/locale.conf + +env-update && source /etc/profile +``` + +### 13. Set Hostname +```bash +echo "" > /etc/hostname +``` + +--- + +## Stage 3: Services & Kernel + +### 14. Run services.sh +```bash +cd /path/to/gentoo-legion +./install/services.sh +# Installs and configures OpenRC services +``` + +### 15. Verify Dracut Configuration +```bash +ls -la /etc/dracut.conf.d/ +# Should show: crypt.conf, nvidia.conf +``` + +If missing, create manually: +```bash +mkdir -p /etc/dracut.conf.d +echo 'add_dracutmodules+=" crypt "' > /etc/dracut.conf.d/crypt.conf +echo 'add_drivers+=" nvidia nvidia_modeset nvidia_uvm nvidia_drm "' > /etc/dracut.conf.d/nvidia.conf +echo 'force_drivers+=" nvidia nvidia_modeset nvidia_uvm nvidia_drm "' >> /etc/dracut.conf.d/nvidia.conf +``` + +### 16. Compile Kernel +```bash +emerge sys-kernel/gentoo-kernel +# This will also take a while +# Dracut automatically includes NVIDIA modules in initramfs +``` + +### 17. Verify fstab and crypttab +```bash +cat /etc/crypttab +# Should show: cryptroot UUID= none luks + +cat /etc/fstab +# Should show EFI, encrypted swap, and Btrfs mounts +``` + +--- + +## Stage 4: User Configuration + +### 18. Set Root Password +```bash +passwd +``` + +### 19. Install Shell & Tools +```bash +emerge app-shells/zsh app-shells/gentoo-zsh-completions \ + app-portage/gentoolkit app-portage/portage-utils app-portage/eix + +# Copy shell configs +cp shell/zshrc.example /root/.zshrc +mkdir -p /root/.config +cp shell/starship.toml /root/.config/starship.toml +chsh -s /bin/zsh +``` + +### 20. Configure sudo & Create User +```bash +emerge app-admin/sudo +visudo +# Uncomment: %wheel ALL=(ALL:ALL) ALL + +useradd -m -G users,wheel,audio,video,input,lp,cdrom,portage,usb,render,network,power -s /bin/zsh +passwd + +# Copy shell configs for user +cp shell/zshrc.example /home//.zshrc +mkdir -p /home//.config +cp shell/starship.toml /home//.config/starship.toml +chown -R : /home/ +``` + +--- + +## Stage 5: Graphics & Bootloader + +### 21. Configure NVIDIA +```bash +emerge x11-drivers/nvidia-drivers + +# Blacklist nouveau +echo "blacklist nouveau" > /etc/modprobe.d/blacklist-nouveau.conf +echo "options nouveau modeset=0" >> /etc/modprobe.d/blacklist-nouveau.conf + +# Enable NVIDIA DRM +echo "options nvidia_drm modeset=1 fbdev=1" > /etc/modprobe.d/nvidia.conf +``` + +### 22. Install & Configure GRUB +```bash +emerge sys-boot/grub +grub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id=Gentoo + +nano /etc/default/grub +``` + +Required GRUB settings for LUKS + NVIDIA: +```bash +GRUB_CMDLINE_LINUX_DEFAULT="nvidia_drm.modeset=1 acpi_backlight=native" +GRUB_ENABLE_CRYPTODISK=y +``` + +Generate config: +```bash +grub-mkconfig -o /boot/grub/grub.cfg +``` + +### 23. Verify Initramfs Setup +```bash +# Check LUKS/crypt modules +lsinitrd /boot/initramfs-*.img | grep -E "(crypt|luks)" + +# Check NVIDIA modules +lsinitrd /boot/initramfs-*.img | grep nvidia +``` + +### 24. Verify Boot Services +```bash +rc-update show boot | grep -E "(dbus|elogind)" + +# If missing: +rc-update add dbus boot +rc-update add elogind boot +``` + +### 25. Exit & Reboot +```bash +exit +umount -lR /mnt/gentoo +cryptsetup close cryptroot +reboot +# Remove installation media +``` + +**First Boot:** +1. GRUB loads, system prompts for LUKS passphrase +2. Enter your passphrase +3. System boots to greetd/regreet login screen + +--- + +## Stage 6: Desktop Environment + +### 26. Install Hyprland Desktop Set +```bash +# Login as your user +emerge @hyprland +``` + +### 27. Install KooL's Dotfiles + +This configuration is designed to work with KooL's Hyprland dotfiles. Install them: + +```bash +# Clone the dotfiles installer +git clone --depth=1 https://github.com/JaKooLit/Hyprland-Dots +cd Hyprland-Dots + +# Run the installer (select options as needed) +chmod +x copy.sh +./copy.sh +``` + +**Notes:** +- The installer will prompt for various options (fonts, themes, etc.) +- Skip package installation if you've already emerged @hyprland +- After installation, copy configs from this repo's `hypr/` directory to customize for your setup + +See: https://github.com/JaKooLit/Hyprland-Dots + +### 28. Configure User Session Logging +```bash +mkdir -p ~/.local/log +``` + +--- + +## Post-Installation + +See the following guides for additional configuration: +- [Hybrid GPU Guide](hybrid-gpu.md) - AMD + NVIDIA configuration +- [greetd Setup](greetd-setup.md) - Display manager configuration +- [Troubleshooting](troubleshooting.md) - Common issues and fixes + +### Quick Reference + +**Update system:** +```bash +emerge --sync +emerge -avuDN @world +``` + +**Create snapshot before risky operation:** +```bash +sudo snapper create -d "before " +``` + +**Service management (OpenRC):** +```bash +rc-service start|stop|restart|status +rc-update add|del +loginctl reboot|poweroff|suspend # NOT systemctl +``` diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md new file mode 100644 index 0000000..35ea611 --- /dev/null +++ b/docs/troubleshooting.md @@ -0,0 +1,256 @@ +# Troubleshooting Guide + +Common issues and solutions for Gentoo + Hyprland on Legion laptops. + +## Display Issues + +### Pink/Artifacts on External Monitors + +1. **Check BIOS setting** - Must be set to Hybrid/Dynamic (not Discrete) + +2. **Let Hyprland auto-detect GPUs** - Comment out AQ_* variables in ENVariables.conf: + ```bash + # env = AQ_DRM_DEVICES,... + # env = AQ_MGPU_NO_EXPLICIT,... + ``` + +3. **Try explicit GPU order** as fallback: + ```bash + env = AQ_DRM_DEVICES,/dev/dri/card1:/dev/dri/card0 + env = AQ_MGPU_NO_EXPLICIT,1 + ``` + +### Duplicate Mouse Cursors (Multi-GPU) + +In `~/.config/hypr/configs/SystemSettings.conf`: +``` +cursor { + no_hardware_cursors = 2 +} +``` + +### External Monitors Not Detected + +1. Check physical connections +2. Verify NVIDIA driver: `lsmod | grep nvidia` +3. Check monitor names: `hyprctl monitors` +4. Verify DRM is enabled: `cat /sys/module/nvidia_drm/parameters/modeset` + +### Screen Tearing + +Ensure NVIDIA DRM modeset is enabled in: +- `/etc/modprobe.d/nvidia.conf`: `options nvidia_drm modeset=1` +- GRUB: `GRUB_CMDLINE_LINUX_DEFAULT="nvidia_drm.modeset=1 ..."` + +## Boot Issues + +### Swap Not Activating + +Gentoo uses `/etc/conf.d/dmcrypt`, not `/etc/crypttab` for encrypted swap. + +1. Check dmcrypt config: + ```bash + cat /etc/conf.d/dmcrypt + ``` + +2. Ensure dmcrypt is in boot runlevel: + ```bash + rc-update add dmcrypt boot + ``` + +3. Verify swap partition path is correct + +### LUKS Prompt Not Appearing + +1. Verify dracut includes crypt module: + ```bash + lsinitrd /boot/initramfs-*.img | grep crypt + ``` + +2. Check `/etc/dracut.conf.d/crypt.conf` exists + +3. Rebuild initramfs: + ```bash + emerge --config sys-kernel/gentoo-kernel + ``` + +### "failed to start user.greetd" Error + +Use custom PAM config for greetd that omits `pam_openrc.so`. See [greetd Setup](greetd-setup.md). + +## Shell Issues + +### Zsh Plugins Not Loading + +Gentoo paths differ from other distros: +```bash +# Correct Gentoo paths +/usr/share/zsh/site-functions/zsh-autosuggestions.zsh +/usr/share/zsh/site-functions/zsh-syntax-highlighting.zsh + +# NOT +/usr/share/zsh/plugins/... +``` + +### Starship Colors Overridden by Wallust + +Use hex codes instead of color names in `starship.toml`: +```toml +# Good +format = "[](#89b4fa)..." + +# Bad (wallust overrides) +format = "[](blue)..." +``` + +## Service Issues + +### Service Won't Start + +1. Check for error messages: + ```bash + rc-service status + ``` + +2. Check dependencies: + ```bash + rc-service start --verbose + ``` + +3. Review logs: + ```bash + cat /var/log/messages | grep + ``` + +### OpenRC vs systemd Commands + +| Task | OpenRC | systemd | +|------|--------|---------| +| Start service | `rc-service start` | `systemctl start ` | +| Stop service | `rc-service stop` | `systemctl stop ` | +| Enable at boot | `rc-update add default` | `systemctl enable ` | +| Check status | `rc-service status` | `systemctl status ` | +| Reboot | `loginctl reboot` | `systemctl reboot` | +| Poweroff | `loginctl poweroff` | `systemctl poweroff` | +| Suspend | `loginctl suspend` | `systemctl suspend` | + +## Network Issues + +### NetworkManager Not Working + +1. Ensure it's in default runlevel: + ```bash + rc-update add NetworkManager default + ``` + +2. Check status: + ```bash + rc-service NetworkManager status + ``` + +3. Use nmcli for configuration: + ```bash + nmcli device wifi list + nmcli device wifi connect "SSID" password "password" + ``` + +### DNS Resolution Failing + +Check `/etc/resolv.conf`: +```bash +cat /etc/resolv.conf +``` + +If empty or wrong, NetworkManager may need configuration: +```bash +# /etc/NetworkManager/conf.d/dns.conf +[main] +dns=default +``` + +## Performance Issues + +### System Running Hot + +1. Check power profile: + ```bash + powerprofilesctl get + powerprofilesctl set balanced # or power-saver + ``` + +### Slow Compilation + +1. Verify ccache is working: + ```bash + ccache -s + ``` + +2. Check make.conf MAKEOPTS: + ```bash + # Should match CPU threads + MAKEOPTS="-j16" + ``` + +## Portage Issues + +### WebKit-GTK Out of Memory + +`net-libs/webkit-gtk` is extremely memory-hungry during compilation. If your build gets OOM-killed: + +1. Resume the emerge, skipping the failed package: + ```bash + emerge --resume --skipfirst + ``` + +2. Create a package-specific environment to limit parallelism: + ```bash + mkdir -p /etc/portage/env /etc/portage/package.env + echo 'MAKEOPTS="-j4"' > /etc/portage/env/webkit-gtk.conf + echo 'NINJAOPTS="-j4"' >> /etc/portage/env/webkit-gtk.conf + echo 'net-libs/webkit-gtk webkit-gtk.conf' >> /etc/portage/package.env/webkit-gtk + ``` + +3. Build webkit-gtk with reduced parallelism: + ```bash + emerge net-libs/webkit-gtk + ``` + +Adjust `-j4` based on your available RAM (roughly 2-3GB per job). With 24GB RAM, `-j6` to `-j8` is usually safe. + +### Circular Dependency (freetype/harfbuzz) + +During initial install, use `-harfbuzz` flag temporarily: +```bash +# /etc/portage/package.use/circular-dependencies +media-libs/freetype -harfbuzz +``` + +After @world compiles, remove and rebuild: +```bash +# Remove the line, then: +emerge -1 media-libs/freetype media-libs/harfbuzz +``` + +### Package Masked + +For ~amd64 packages, add to accept_keywords: +```bash +# /etc/portage/package.accept_keywords/ + ~amd64 +``` + +### USE Flag Conflicts + +Check required USE flags: +```bash +emerge -pv +``` + +Add missing flags to `/etc/portage/package.use/`. + +## Getting Help + +1. Check Gentoo Wiki: https://wiki.gentoo.org/ +2. Check Hyprland Wiki: https://wiki.hyprland.org/ +3. Review system logs: `/var/log/messages` +4. Check application-specific logs in `~/.local/log/` or `/var/log/` diff --git a/firewall/ip6tables.rules b/firewall/ip6tables.rules new file mode 100644 index 0000000..364168e --- /dev/null +++ b/firewall/ip6tables.rules @@ -0,0 +1,42 @@ +*filter +:INPUT DROP [0:0] +:FORWARD DROP [0:0] +:OUTPUT ACCEPT [0:0] + +# ============================================================ +# Stateful connection tracking +# ============================================================ + +# Allow established and related connections +-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT + +# ============================================================ +# Loopback interface - always allow +# ============================================================ + +-A INPUT -i lo -j ACCEPT + +# ============================================================ +# ICMPv6 - required for IPv6 neighbor discovery +# ============================================================ + +-A INPUT -p icmpv6 --icmpv6-type router-solicitation -j ACCEPT +-A INPUT -p icmpv6 --icmpv6-type router-advertisement -j ACCEPT +-A INPUT -p icmpv6 --icmpv6-type neighbor-solicitation -j ACCEPT +-A INPUT -p icmpv6 --icmpv6-type neighbor-advertisement -j ACCEPT +-A INPUT -p icmpv6 --icmpv6-type echo-request -j ACCEPT +-A INPUT -p icmpv6 --icmpv6-type echo-reply -j ACCEPT + +# ============================================================ +# Link-local addresses only +# ============================================================ + +-A INPUT -s fe80::/10 -j ACCEPT + +# ============================================================ +# Default deny - drop everything not explicitly allowed +# ============================================================ + +-A INPUT -j DROP + +COMMIT diff --git a/firewall/iptables.rules.example b/firewall/iptables.rules.example new file mode 100644 index 0000000..8a1e063 --- /dev/null +++ b/firewall/iptables.rules.example @@ -0,0 +1,42 @@ +*filter +:INPUT DROP [0:0] +:FORWARD DROP [0:0] +:OUTPUT ACCEPT [0:0] + +# ============================================================ +# Stateful connection tracking +# ============================================================ + +# Allow established and related connections (return traffic) +-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT + +# ============================================================ +# Loopback interface - always allow +# ============================================================ + +-A INPUT -i lo -j ACCEPT + +# ============================================================ +# Trusted networks - full access +# ============================================================ + +# VPN/overlay network interface (uncomment and customize) +# -A INPUT -i -j ACCEPT + +# Trusted local network (uncomment and customize to your network) +# -A INPUT -s /24 -j ACCEPT + +# ============================================================ +# ICMP - allow ping for diagnostics +# ============================================================ + +-A INPUT -p icmp --icmp-type echo-request -j ACCEPT +-A INPUT -p icmp --icmp-type echo-reply -j ACCEPT + +# ============================================================ +# Default deny - drop everything not explicitly allowed +# ============================================================ + +-A INPUT -j DROP + +COMMIT diff --git a/greetd/config.toml b/greetd/config.toml new file mode 100644 index 0000000..cb51231 --- /dev/null +++ b/greetd/config.toml @@ -0,0 +1,6 @@ +[terminal] +vt = 7 + +[default_session] +command = "start-hyprland -- --config /etc/greetd/hyprland.conf > /var/log/hyprland-greeter.log 2>&1" +user = "greetd" diff --git a/greetd/greetd.pam b/greetd/greetd.pam new file mode 100644 index 0000000..f74fd38 --- /dev/null +++ b/greetd/greetd.pam @@ -0,0 +1,13 @@ +# greetd PAM configuration +# custom config to avoid pam_openrc.so trying to start user.greetd service + +auth include system-local-login +account include system-local-login +password include system-local-login +session optional pam_loginuid.so +session required pam_env.so envfile=/etc/profile.env +session include system-auth +session optional pam_motd.so motd=/etc/motd +session optional pam_lastlog.so never showfailed +session optional pam_mail.so +-session optional pam_elogind.so diff --git a/greetd/hyprland.conf b/greetd/hyprland.conf new file mode 100644 index 0000000..1964dae --- /dev/null +++ b/greetd/hyprland.conf @@ -0,0 +1,36 @@ +exec-once = regreet; hyprctl dispatch exit + +env = XCURSOR_THEME,Bibata-Modern-Ice +env = XCURSOR_SIZE,24 + +# Force greeter to laptop display only +monitor=eDP-2, 1920x1080@60, 0x0, 1 +monitor=DP-1, disable +monitor=DP-2, disable + +cursor { + default_monitor = eDP-2 +} + +input { + touchpad { + disable_while_typing = true + natural_scroll = true + tap-to-click = true + } +} + +misc { + disable_hyprland_logo = true + disable_splash_rendering = true + disable_autoreload = true +} + +ecosystem { + no_update_news = true + no_donation_nag = true +} + +debug { + disable_logs = true +} diff --git a/greetd/regreet.toml b/greetd/regreet.toml new file mode 100644 index 0000000..a1d31bb --- /dev/null +++ b/greetd/regreet.toml @@ -0,0 +1,10 @@ +[background] +path = "/usr/share/backgrounds/default.png" +fit = "Cover" + +[GTK] +application_prefer_dark_theme = true + +[commands] +reboot = ["loginctl", "reboot"] +poweroff = ["loginctl", "poweroff"] diff --git a/greetd/start-hyprland-dbus b/greetd/start-hyprland-dbus new file mode 100755 index 0000000..1f2806a --- /dev/null +++ b/greetd/start-hyprland-dbus @@ -0,0 +1,2 @@ +#!/bin/bash +exec dbus-run-session /usr/bin/start-hyprland > ~/.local/log/hyprland.log 2>&1 diff --git a/hypr/ENVariables.conf b/hypr/ENVariables.conf new file mode 100644 index 0000000..d460a06 --- /dev/null +++ b/hypr/ENVariables.conf @@ -0,0 +1,55 @@ +# /* ---- 💫 https://github.com/JaKooLit 💫 ---- */ # +# Environment variables. See https://wiki.hyprland.org/Configuring/Environment-variables/ + +# Set your defaults editor through ENV in ~/.config/hypr/UserConfigs/01-UserDefaults.conf + +### QT Variables ### +# env = QT_AUTO_SCREEN_SCALE_FACTOR,1 +# env = QT_WAYLAND_DISABLE_WINDOWDECORATION,1 +# env = QT_QPA_PLATFORMTHEME,qt5ct +# env = QT_QPA_PLATFORMTHEME,qt6ct + +### xwayland apps scale fix (useful if you are use monitor scaling). ### +# Set same value if you use scaling in Monitors.conf +# 1 is 100% 1.5 is 150% +# see https://wiki.hyprland.org/Configuring/XWayland/ +# env = GDK_SCALE,1 +# env = QT_SCALE_FACTOR,1 + +### NVIDIA ### +# This is from Hyprland Wiki. Below will be activated nvidia gpu detected +# See hyprland wiki https://wiki.hyprland.org/Nvidia/#environment-variables + +#env = LIBVA_DRIVER_NAME,nvidia +#env = __GLX_VENDOR_LIBRARY_NAME,nvidia +#env = NVD_BACKEND,direct +#env = GSK_RENDERER,ngl + +### additional ENV's for nvidia. Caution, activate with care ### +#env = GBM_BACKEND,nvidia-drm +#env = __GL_GSYNC_ALLOWED,1 #adaptive Vsync +#env = __NV_PRIME_RENDER_OFFLOAD,1 +#env = __VK_LAYER_NV_optimus,NVIDIA_only +#env = WLR_DRM_NO_ATOMIC,1 + +### FOR VM and POSSIBLY NVIDIA ### +# LIBGL_ALWAYS_SOFTWARE software mesa rendering +#env = LIBGL_ALWAYS_SOFTWARE,1 # Warning. May cause hyprland to crash +#env = WLR_RENDERER_ALLOW_SOFTWARE,1 + +### nvidia firefox ### +# check this post https://github.com/elFarto/nvidia-vaapi-driver#configuration +#env = MOZ_DISABLE_RDD_SANDBOX,1 +#env = EGL_PLATFORM,wayland + +### Aquamarine Environment Variables (Hyprland > 0.45) ### +# https://wiki.hyprland.org/Configuring/Environment-variables/#aquamarine-environment-variables +# env = AQ_TRACE,1 # Enables more verbose logging. +env = AQ_DRM_DEVICES,/dev/dri/card1:/dev/dri/card0 # AMD primary, NVIDIA for external displays +env = AQ_MGPU_NO_EXPLICIT,1 # Disables explicit syncing on mgpu buffers (fixes pink screen) +# env = AQ_NO_MODIFIERS,1 # Disables modifiers for DRM buffers + +### Cursor ### +env = XCURSOR_THEME,Bibata-Modern-Ice +env = XCURSOR_SIZE,24 + diff --git a/hypr/monitors.conf.example b/hypr/monitors.conf.example new file mode 100644 index 0000000..59daa3a --- /dev/null +++ b/hypr/monitors.conf.example @@ -0,0 +1,27 @@ +# Hyprland Monitor Configuration +# https://wiki.hyprland.org/Configuring/Monitors/ +# +# Use `hyprctl monitors` to get your monitor names and supported resolutions +# +# CUSTOMIZE: Adjust for your display setup + +# Example: Triple monitor layout +# DP-1 (left) | eDP-2 (center/laptop) | DP-2 (right) +# monitor=DP-1, 1920x1080@60, 0x0, 1 +# monitor=eDP-2, 1920x1080@60, 1920x0, 1 +# monitor=DP-2, 1920x1080@60, 3840x0, 1 + +# Example: Laptop only +# monitor=eDP-1, preferred, auto, 1 + +# Example: Single external monitor +# monitor=HDMI-A-1, 1920x1080@60, 0x0, 1 + +# Example: Disable a monitor +# monitor=, disable + +# Example: Mirror displays +# monitor=HDMI-A-1, 1920x1080@60, 0x0, 1, mirror, eDP-1 + +# Your configuration: +monitor=eDP-1, preferred, auto, 1 diff --git a/hypr/wlogout-layout b/hypr/wlogout-layout new file mode 100644 index 0000000..ac3097e --- /dev/null +++ b/hypr/wlogout-layout @@ -0,0 +1,30 @@ +{ + "label" : "lock", + "action" : "$HOME/.config/hypr/scripts/LockScreen.sh", + "text" : "Lock", + "keybind" : "l" +} +{ + "label" : "reboot", + "action" : "loginctl reboot", + "text" : "Reboot", + "keybind" : "r" +} +{ + "label" : "shutdown", + "action" : "loginctl poweroff", + "text" : "Shutdown", + "keybind" : "s" +} +{ + "label" : "logout", + "action" : "hyprctl dispatch exit 0", + "text" : "Logout", + "keybind" : "e" +} +{ + "label" : "suspend", + "action" : "loginctl suspend", + "text" : "Suspend", + "keybind" : "u" +} diff --git a/install/chroot.sh b/install/chroot.sh new file mode 100755 index 0000000..2bab76d --- /dev/null +++ b/install/chroot.sh @@ -0,0 +1,104 @@ +#!/bin/bash + +# change-root.sh - Gentoo Chroot Entry Script +# Purpose: Set up bind mounts and enter Gentoo chroot environment +# Usage: Run after init.sh + +# --- Colors for Output --- +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[0;33m' +NC='\033[0m' + +# --- Configuration --- +GENTOO_ROOT="/mnt/gentoo" + +set -e + +echo -e "${YELLOW}Gentoo Chroot Setup Script${NC}" +echo -e "${YELLOW}=========================${NC}" + +# --- Verify Gentoo root is mounted --- +if ! mountpoint -q "$GENTOO_ROOT" 2>/dev/null; then + echo -e "${RED}Error: $GENTOO_ROOT is not mounted.${NC}" + echo -e "${RED}Please run init.sh first to set up the Gentoo installation.${NC}" + exit 1 +fi + +# --- Verify essential files exist --- +if [ ! -f "$GENTOO_ROOT/etc/portage/make.conf" ]; then + echo -e "${YELLOW}Warning: $GENTOO_ROOT/etc/portage/make.conf not found.${NC}" + echo -e "${YELLOW}init.sh should have copied this automatically.${NC}" + read -r -p "Continue anyway? (y/n): " continue_confirm + if [[ "$continue_confirm" != "y" ]]; then + echo -e "${RED}Aborting. Please check init.sh output.${NC}" + exit 1 + fi +fi + +if [ ! -f "$GENTOO_ROOT/etc/resolv.conf" ]; then + echo -e "${YELLOW}Copying resolv.conf...${NC}" + if ! cp --dereference /etc/resolv.conf "$GENTOO_ROOT/etc/"; then + echo -e "${RED}Error: Could not copy resolv.conf${NC}" + exit 1 + fi + echo -e "${GREEN}Copied resolv.conf${NC}" +fi + +# --- Set up bind mounts --- +echo -e "${YELLOW}Setting up bind mounts for chroot environment...${NC}" + +# Mount /proc +if ! mountpoint -q "$GENTOO_ROOT/proc" 2>/dev/null; then + echo -e "${YELLOW}Mounting /proc...${NC}" + mount --rbind /proc "$GENTOO_ROOT/proc" + mount --make-rslave "$GENTOO_ROOT/proc" + echo -e "${GREEN}Mounted /proc${NC}" +else + echo -e "${YELLOW}/proc already mounted${NC}" +fi + +# Mount /sys +if ! mountpoint -q "$GENTOO_ROOT/sys" 2>/dev/null; then + echo -e "${YELLOW}Mounting /sys...${NC}" + mount --rbind /sys "$GENTOO_ROOT/sys" + mount --make-rslave "$GENTOO_ROOT/sys" + echo -e "${GREEN}Mounted /sys${NC}" +else + echo -e "${YELLOW}/sys already mounted${NC}" +fi + +# Mount /dev +if ! mountpoint -q "$GENTOO_ROOT/dev" 2>/dev/null; then + echo -e "${YELLOW}Mounting /dev...${NC}" + mount --rbind /dev "$GENTOO_ROOT/dev" + mount --make-rslave "$GENTOO_ROOT/dev" + echo -e "${GREEN}Mounted /dev${NC}" +else + echo -e "${YELLOW}/dev already mounted${NC}" +fi + +# Mount /run +if ! mountpoint -q "$GENTOO_ROOT/run" 2>/dev/null; then + echo -e "${YELLOW}Mounting /run...${NC}" + mount --rbind /run "$GENTOO_ROOT/run" + mount --make-rslave "$GENTOO_ROOT/run" + echo -e "${GREEN}Mounted /run${NC}" +else + echo -e "${YELLOW}/run already mounted${NC}" +fi + +# --- Show mount status --- +echo -e "${GREEN}Bind mounts ready:${NC}" +echo " /proc: $(mountpoint -q "$GENTOO_ROOT/proc" && echo "mounted" || echo "not mounted")" +echo " /sys: $(mountpoint -q "$GENTOO_ROOT/sys" && echo "mounted" || echo "not mounted")" +echo " /dev: $(mountpoint -q "$GENTOO_ROOT/dev" && echo "mounted" || echo "not mounted")" +echo " /run: $(mountpoint -q "$GENTOO_ROOT/run" && echo "mounted" || echo "not mounted")" + +# --- Enter chroot --- +echo "" +echo -e "${GREEN}Entering Gentoo chroot environment...${NC}" +echo -e "${YELLOW}Type 'exit' when done to return to the live environment.${NC}" +echo "" + +exec chroot "$GENTOO_ROOT" /bin/bash -c "source /etc/profile && export PS1='(chroot) \$PS1' && exec /bin/bash" diff --git a/install/init.sh b/install/init.sh new file mode 100755 index 0000000..fde628f --- /dev/null +++ b/install/init.sh @@ -0,0 +1,822 @@ +#!/bin/bash + +# init.sh for Legion S7 15ACH6 +# Gentoo bootstrap script with Btrfs subvolumes + +# --- Script Configuration Variables --- +GENTOO_MIRROR_BASE="https://mirrors.rit.edu/gentoo/" +GENTOO_FALLBACK_MIRRORS=( + "https://distfiles.gentoo.org/" + "https://gentoo.osuosl.org/" + "https://mirror.bytemark.co.uk/gentoo/" +) + +# Default swap size in GB (reduced from 32GB to 16GB) +SWAP_SIZE_GB=16 + +# Init system: "openrc" or "systemd" +INIT_SYSTEM="openrc" + +# --- Colors for Output --- +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[0;33m' +NC='\033[0m' + +set -euo pipefail + +# --- Cleanup Trap --- +cleanup() { + local exit_code=$? + if [[ $exit_code -ne 0 ]] && [[ -n "${GENTOO_ROOT_MOUNT_GLOBAL:-}" ]] && mountpoint -q "$GENTOO_ROOT_MOUNT_GLOBAL" 2>/dev/null; then + echo -e "${YELLOW}Script interrupted. Cleaning up mounts...${NC}" + umount -R "$GENTOO_ROOT_MOUNT_GLOBAL" 2>/dev/null || true + fi + # Close LUKS container if open + if [[ -e "$CRYPT_ROOT_GLOBAL" ]]; then + echo -e "${YELLOW}Closing LUKS container...${NC}" + cryptsetup close cryptroot 2>/dev/null || true + fi + exit $exit_code +} +trap cleanup EXIT + +# --- Global Variables --- +TARGET_DISK_GLOBAL="" +DISK_SIZE_GB_GLOBAL="" +GENTOO_ROOT_MOUNT_GLOBAL="/mnt/gentoo" +BTRFS_TEMP_MOUNT_GLOBAL="/mnt/btrfs_temp" +PART1_GLOBAL="" +PART2_GLOBAL="" +PART3_GLOBAL="" +CRYPT_ROOT_GLOBAL="/dev/mapper/cryptroot" + +# Btrfs mount options (removed redundant ssd and space_cache=v2) +BTRFS_OPTS="noatime,compress=zstd" + +# --- Helper Functions --- + +get_disk_size() { + local disk="$1" + local size_bytes + size_bytes=$(lsblk -b -n -o SIZE "$disk" | head -n 1) + if [ -z "$size_bytes" ]; then + echo "unknown" + return 1 + fi + awk -v bytes="$size_bytes" 'BEGIN { printf "%.2f", bytes / (1024^3) }' + return 0 +} + +force_unmount_and_swapoff_target_disk() { + echo -e "${YELLOW}Attempting to unmount all partitions and deactivate swap on ${TARGET_DISK_GLOBAL}...${NC}" + + local partitions=() + mapfile -t partitions < <(lsblk -rno NAME "$TARGET_DISK_GLOBAL" | tail -n +2) + + local partition_devices=() + for part in "${partitions[@]}"; do + partition_devices+=("/dev/$part") + done + + # Deactivate swap + echo -e "${YELLOW}Checking for active swap partitions...${NC}" + for device in "${partition_devices[@]}"; do + if swapon --show=NAME --noheadings | grep -q "^$device$"; then + echo -e "${YELLOW} Deactivating swap on ${device}...${NC}" + if swapoff "$device" 2>/dev/null; then + echo -e "${GREEN} Successfully deactivated swap on ${device}${NC}" + else + echo -e "${RED} Warning: Could not deactivate swap on ${device}${NC}" + fi + fi + done + + # Unmount partitions (multiple attempts) + echo -e "${YELLOW}Checking for mounted partitions...${NC}" + for attempt in {1..3}; do + local mounted_found=false + + for device in "${partition_devices[@]}"; do + if mount | grep -q "^$device "; then + mounted_found=true + local mountpoint + mountpoint=$(mount | grep "^$device " | awk '{print $3}' | head -n1) + echo -e "${YELLOW} Attempt ${attempt}: Unmounting ${device} from ${mountpoint}...${NC}" + + if [ "$attempt" -eq 1 ]; then + umount "$device" 2>/dev/null && echo -e "${GREEN} Successfully unmounted ${device}${NC}" && continue + elif [ "$attempt" -eq 2 ]; then + umount -f "$device" 2>/dev/null && echo -e "${GREEN} Force unmounted ${device}${NC}" && continue + else + umount -l "$device" 2>/dev/null && echo -e "${YELLOW} Lazy unmounted ${device}${NC}" && continue + fi + echo -e "${RED} Warning: Could not unmount ${device}${NC}" + fi + done + + if ! $mounted_found; then + break + fi + sleep 1 + done + + partprobe "$TARGET_DISK_GLOBAL" 2>/dev/null || true + sync + + echo -e "${GREEN}Verification after unmount/swapoff operations:${NC}" + lsblk "$TARGET_DISK_GLOBAL" || true + mount | grep "$TARGET_DISK_GLOBAL" || echo " No active mounts found for ${TARGET_DISK_GLOBAL}" + swapon --show | grep "$TARGET_DISK_GLOBAL" || echo " No active swap found for ${TARGET_DISK_GLOBAL}" + + return 0 +} + +wipe_disk_signatures() { + echo -e "${YELLOW}Wiping existing filesystem signatures and partition table...${NC}" + + wipefs -af "$TARGET_DISK_GLOBAL" 2>/dev/null || true + + echo -e "${YELLOW}Zeroing beginning and end of disk...${NC}" + dd if=/dev/zero of="$TARGET_DISK_GLOBAL" bs=1M count=10 2>/dev/null || true + + local disk_size_sectors + disk_size_sectors=$(blockdev --getsz "$TARGET_DISK_GLOBAL" 2>/dev/null || echo "0") + if [ "$disk_size_sectors" -gt 20480 ]; then + local last_mb_start=$((disk_size_sectors - 20480)) + dd if=/dev/zero of="$TARGET_DISK_GLOBAL" bs=512 seek="$last_mb_start" count=20480 2>/dev/null || true + fi + + partprobe "$TARGET_DISK_GLOBAL" 2>/dev/null || true + sync + echo -e "${GREEN}Disk wiping complete${NC}" +} + +# --- Main Functions --- + +select_target_disk() { + local disks=() + local i=1 + echo -e "${YELLOW}Identifying available disks...${NC}" + lsblk -p -o NAME,SIZE,MODEL,VENDOR,TYPE + + local root_dev + root_dev=$(findmnt -n -o SOURCE / | awk '{print $1}') + local boot_disk_basename + if [[ "$root_dev" == /dev/sd* ]]; then + boot_disk_basename=$(basename "${root_dev%[0-9]*}") + elif [[ "$root_dev" == /dev/nvme* ]]; then + boot_disk_basename=$(basename "${root_dev%p[0-9]*}") + else + boot_disk_basename=$(basename "$root_dev") + fi + + local all_disks_names=() + mapfile -t all_disks_names < <(lsblk -dno NAME | sort) + + local non_boot_disks_filtered=() + for d_name in "${all_disks_names[@]}"; do + if [[ "$d_name" != "$boot_disk_basename" ]]; then + if [[ -b "/dev/${d_name}" ]]; then + non_boot_disks_filtered+=("$d_name") + fi + fi + done + + if [ ${#non_boot_disks_filtered[@]} -eq 0 ]; then + echo -e "${RED}No suitable internal disks found for installation. Aborting.${NC}" + return 1 + fi + + echo -e "${YELLOW}Select your TARGET DISK:${NC}" + for disk_name in "${non_boot_disks_filtered[@]}"; do + local current_disk_path="/dev/${disk_name}" + local size_val + size_val=$(get_disk_size "$current_disk_path") + local model_val + model_val=$(lsblk -dno MODEL "$current_disk_path" | head -n 1) + + disks+=("$current_disk_path") + echo " ${i}) ${current_disk_path} - ${size_val} GB (${model_val})" + ((i++)) + done + + local choice + while true; do + read -r -p "Enter the number corresponding to your target disk: " choice + if [[ "$choice" =~ ^[0-9]+$ ]] && [ "$choice" -ge 1 ] && [ "$choice" -le ${#disks[@]} ]; then + TARGET_DISK_GLOBAL="${disks[choice-1]}" + DISK_SIZE_GB_GLOBAL=$(get_disk_size "$TARGET_DISK_GLOBAL") + echo -e "${YELLOW}Selected: ${TARGET_DISK_GLOBAL} (${DISK_SIZE_GB_GLOBAL} GB)${NC}" + read -r -p "Are you ABSOLUTELY SURE? This will ERASE ALL DATA! (type 'yes' to confirm): " confirmation + if [[ "$confirmation" == "yes" ]]; then + echo -e "${GREEN}Target disk confirmed.${NC}" + return 0 + else + echo -e "${RED}Disk selection cancelled.${NC}" + return 1 + fi + else + echo -e "${RED}Invalid selection.${NC}" + fi + done +} + +partition_and_format_disk() { + echo -e "${YELLOW}--- Disk Partitioning & Formatting ---${NC}" + echo -e "Target disk: ${TARGET_DISK_GLOBAL} (${DISK_SIZE_GB_GLOBAL} GB)" + echo -e "Swap size: ${SWAP_SIZE_GB} GB" + + # Check for UEFI + if [ ! -d "/sys/firmware/efi/efivars" ]; then + echo -e "${RED}ERROR: UEFI boot mode not detected. This script requires UEFI.${NC}" + return 1 + fi + echo -e "${GREEN}Detected UEFI boot mode.${NC}" + + if ! force_unmount_and_swapoff_target_disk; then + echo -e "${RED}Error during pre-partition cleanup. Aborting.${NC}" + return 1 + fi + + wipe_disk_signatures + + # Create GPT table with 1MiB alignment (optimal for SSDs/NVMe) + if ! sgdisk --clear --mbrtogpt --set-alignment=2048 "$TARGET_DISK_GLOBAL"; then + echo -e "${RED}Error creating GPT table. Aborting.${NC}" + return 1 + fi + + partprobe "$TARGET_DISK_GLOBAL" 2>/dev/null || true + sleep 2 + + # Partition 1: EFI (512MB) + if ! sgdisk --set-alignment=2048 -n 1:0:+512MiB -t 1:EF00 -c 1:"EFI System Partition" "$TARGET_DISK_GLOBAL"; then + echo -e "${RED}Error creating EFI partition. Aborting.${NC}" + return 1 + fi + + # Partition 2: Swap + if ! sgdisk --set-alignment=2048 -n 2:0:+${SWAP_SIZE_GB}GiB -t 2:8200 -c 2:"Linux Swap" "$TARGET_DISK_GLOBAL"; then + echo -e "${RED}Error creating swap partition. Aborting.${NC}" + return 1 + fi + + # Partition 3: Btrfs Root + if ! sgdisk --set-alignment=2048 -n 3:0:0 -t 3:8300 -c 3:"Linux Btrfs Root" "$TARGET_DISK_GLOBAL"; then + echo -e "${RED}Error creating Btrfs partition. Aborting.${NC}" + return 1 + fi + + echo -e "${GREEN}Disk partitioning complete.${NC}" + sgdisk -p "$TARGET_DISK_GLOBAL" + + # Wait for kernel to recognize partitions + partprobe "$TARGET_DISK_GLOBAL" 2>/dev/null || true + sleep 3 + + # Determine partition naming scheme + if [[ "$TARGET_DISK_GLOBAL" == /dev/nvme* ]]; then + PART1_GLOBAL="${TARGET_DISK_GLOBAL}p1" + PART2_GLOBAL="${TARGET_DISK_GLOBAL}p2" + PART3_GLOBAL="${TARGET_DISK_GLOBAL}p3" + elif [[ "$TARGET_DISK_GLOBAL" == /dev/mmcblk* ]]; then + PART1_GLOBAL="${TARGET_DISK_GLOBAL}p1" + PART2_GLOBAL="${TARGET_DISK_GLOBAL}p2" + PART3_GLOBAL="${TARGET_DISK_GLOBAL}p3" + else + PART1_GLOBAL="${TARGET_DISK_GLOBAL}1" + PART2_GLOBAL="${TARGET_DISK_GLOBAL}2" + PART3_GLOBAL="${TARGET_DISK_GLOBAL}3" + fi + + echo -e "${YELLOW}Detected partitions: ${PART1_GLOBAL}, ${PART2_GLOBAL}, ${PART3_GLOBAL}${NC}" + + # Wait for partitions + for part in "$PART1_GLOBAL" "$PART2_GLOBAL" "$PART3_GLOBAL"; do + local wait_count=0 + while [ ! -b "$part" ] && [ $wait_count -lt 10 ]; do + echo -e "${YELLOW}Waiting for ${part}...${NC}" + sleep 1 + partprobe "$TARGET_DISK_GLOBAL" 2>/dev/null || true + ((wait_count++)) + done + if [ ! -b "$part" ]; then + echo -e "${RED}Error: Partition ${part} not found. Aborting.${NC}" + return 1 + fi + done + + echo -e "${YELLOW}Formatting partitions...${NC}" + + # Format EFI + if ! mkfs.fat -F 32 "$PART1_GLOBAL"; then + echo -e "${RED}Error formatting EFI partition. Aborting.${NC}" + return 1 + fi + echo -e "${GREEN}Formatted ${PART1_GLOBAL} as FAT32.${NC}" + + # Skip swap formatting - will be encrypted with random key at boot via fstab + echo -e "${YELLOW}Swap will be encrypted at boot (skipping format now)${NC}" + + # Setup LUKS2 encryption on root partition + echo -e "${YELLOW}Setting up LUKS2 encryption on ${PART3_GLOBAL}...${NC}" + echo -e "${GREEN}>>> Use OnlyKey to enter your LUKS passphrase <<<${NC}" + if ! cryptsetup luksFormat --type luks2 --cipher aes-xts-plain64 --key-size 512 --hash sha512 "$PART3_GLOBAL"; then + echo -e "${RED}Error creating LUKS container. Aborting.${NC}" + return 1 + fi + echo -e "${GREEN}LUKS container created.${NC}" + + echo -e "${YELLOW}Opening LUKS container...${NC}" + echo -e "${GREEN}>>> Enter passphrase again to open LUKS <<<${NC}" + if ! cryptsetup open "$PART3_GLOBAL" cryptroot; then + echo -e "${RED}Error opening LUKS container. Aborting.${NC}" + return 1 + fi + echo -e "${GREEN}LUKS container opened at ${CRYPT_ROOT_GLOBAL}${NC}" + + # Format Btrfs on LUKS container + if ! mkfs.btrfs -f "$CRYPT_ROOT_GLOBAL"; then + echo -e "${RED}Error formatting Btrfs on LUKS. Aborting.${NC}" + return 1 + fi + echo -e "${GREEN}Formatted ${CRYPT_ROOT_GLOBAL} as Btrfs.${NC}" + + echo -e "${YELLOW}Creating Btrfs subvolumes...${NC}" + + mkdir -p "$BTRFS_TEMP_MOUNT_GLOBAL" + if ! mount "$CRYPT_ROOT_GLOBAL" "$BTRFS_TEMP_MOUNT_GLOBAL"; then + echo -e "${RED}Error mounting Btrfs for subvolume creation. Aborting.${NC}" + return 1 + fi + + # Create subvolumes + local subvolumes=("@" "@home" "@var" "@log" "@snapshots") + for subvol in "${subvolumes[@]}"; do + if ! btrfs subvolume create "${BTRFS_TEMP_MOUNT_GLOBAL}/${subvol}"; then + echo -e "${RED}Error creating ${subvol} subvolume. Aborting.${NC}" + umount "$BTRFS_TEMP_MOUNT_GLOBAL" 2>/dev/null || true + return 1 + fi + echo -e "${GREEN}Created subvolume: ${subvol}${NC}" + done + + if ! umount "$BTRFS_TEMP_MOUNT_GLOBAL"; then + echo -e "${RED}Error unmounting Btrfs temp. Aborting.${NC}" + return 1 + fi + rmdir "$BTRFS_TEMP_MOUNT_GLOBAL" 2>/dev/null || true + echo -e "${GREEN}Btrfs subvolumes created.${NC}" + + return 0 +} + +mount_partitions() { + echo -e "${YELLOW}--- Mounting Partitions ---${NC}" + + if mountpoint -q "$GENTOO_ROOT_MOUNT_GLOBAL" 2>/dev/null; then + echo -e "${YELLOW}${GENTOO_ROOT_MOUNT_GLOBAL} already mounted, unmounting...${NC}" + umount -R "$GENTOO_ROOT_MOUNT_GLOBAL" 2>/dev/null || true + fi + + mkdir -p "$GENTOO_ROOT_MOUNT_GLOBAL" + + # Mount @ subvolume (root) + if ! mount -o "${BTRFS_OPTS},subvol=@" "$CRYPT_ROOT_GLOBAL" "$GENTOO_ROOT_MOUNT_GLOBAL"; then + echo -e "${RED}Error mounting @ subvolume. Aborting.${NC}" + return 1 + fi + echo -e "${GREEN}Mounted @ to ${GENTOO_ROOT_MOUNT_GLOBAL}${NC}" + + # Mount @home + mkdir -p "${GENTOO_ROOT_MOUNT_GLOBAL}/home" + if ! mount -o "${BTRFS_OPTS},subvol=@home" "$CRYPT_ROOT_GLOBAL" "${GENTOO_ROOT_MOUNT_GLOBAL}/home"; then + echo -e "${RED}Error mounting @home subvolume. Aborting.${NC}" + return 1 + fi + echo -e "${GREEN}Mounted @home to ${GENTOO_ROOT_MOUNT_GLOBAL}/home${NC}" + + # Mount @var + mkdir -p "${GENTOO_ROOT_MOUNT_GLOBAL}/var" + if ! mount -o "${BTRFS_OPTS},subvol=@var" "$CRYPT_ROOT_GLOBAL" "${GENTOO_ROOT_MOUNT_GLOBAL}/var"; then + echo -e "${RED}Error mounting @var subvolume. Aborting.${NC}" + return 1 + fi + echo -e "${GREEN}Mounted @var to ${GENTOO_ROOT_MOUNT_GLOBAL}/var${NC}" + + # Mount @log + mkdir -p "${GENTOO_ROOT_MOUNT_GLOBAL}/var/log" + if ! mount -o "${BTRFS_OPTS},subvol=@log" "$CRYPT_ROOT_GLOBAL" "${GENTOO_ROOT_MOUNT_GLOBAL}/var/log"; then + echo -e "${RED}Error mounting @log subvolume. Aborting.${NC}" + return 1 + fi + echo -e "${GREEN}Mounted @log to ${GENTOO_ROOT_MOUNT_GLOBAL}/var/log${NC}" + + # Mount @snapshots + mkdir -p "${GENTOO_ROOT_MOUNT_GLOBAL}/.snapshots" + if ! mount -o "${BTRFS_OPTS},subvol=@snapshots" "$CRYPT_ROOT_GLOBAL" "${GENTOO_ROOT_MOUNT_GLOBAL}/.snapshots"; then + echo -e "${RED}Error mounting @snapshots subvolume. Aborting.${NC}" + return 1 + fi + echo -e "${GREEN}Mounted @snapshots to ${GENTOO_ROOT_MOUNT_GLOBAL}/.snapshots${NC}" + + # Mount EFI + mkdir -p "${GENTOO_ROOT_MOUNT_GLOBAL}/boot" + if ! mount "$PART1_GLOBAL" "${GENTOO_ROOT_MOUNT_GLOBAL}/boot"; then + echo -e "${RED}Error mounting EFI partition. Aborting.${NC}" + return 1 + fi + echo -e "${GREEN}Mounted EFI to ${GENTOO_ROOT_MOUNT_GLOBAL}/boot${NC}" + + echo -e "${GREEN}All partitions mounted successfully!${NC}" + echo -e "${YELLOW}Mount verification:${NC}" + findmnt -R "$GENTOO_ROOT_MOUNT_GLOBAL" + return 0 +} + +download_and_extract_stage3() { + echo -e "${YELLOW}--- Downloading & Extracting Stage 3 ---${NC}" + + local stage3_filename="" + local digests_filename="" + local stage3_base_url="" + local successful_mirror="" + + # Determine stage3 variant based on init system + local stage3_variant="stage3-amd64-${INIT_SYSTEM}" + echo -e "${YELLOW}Init system: ${INIT_SYSTEM} (variant: ${stage3_variant})${NC}" + + local all_mirrors=("$GENTOO_MIRROR_BASE" "${GENTOO_FALLBACK_MIRRORS[@]}") + + for mirror in "${all_mirrors[@]}"; do + stage3_base_url="${mirror}releases/amd64/autobuilds/current-${stage3_variant}/" + echo -e "${YELLOW}Trying mirror: ${stage3_base_url}${NC}" + + if ! curl -s --connect-timeout 10 "${stage3_base_url}" >/dev/null; then + echo -e "${RED}Cannot connect to ${mirror}, trying next...${NC}" + continue + fi + + echo -e "${YELLOW}Fetching current Stage 3 filename...${NC}" + local latest_file="${stage3_base_url}latest-${stage3_variant}.txt" + local latest_content + + if ! latest_content=$(curl -s --fail "$latest_file"); then + echo -e "${RED}Could not retrieve latest file from ${mirror}, trying next...${NC}" + continue + fi + + # Parse PGP-signed content + stage3_filename=$(echo "$latest_content" | \ + sed -n '/-----BEGIN PGP SIGNED MESSAGE-----/,/-----BEGIN PGP SIGNATURE-----/p' | \ + grep '\.tar\.xz' | \ + awk '{print $1}' | \ + head -n 1) + + # Fallback: direct pattern matching + if [ -z "$stage3_filename" ]; then + stage3_filename=$(echo "$latest_content" | grep -oE "${stage3_variant}-[0-9T]+Z?\.tar\.xz" | head -n 1) + fi + + if [ -z "$stage3_filename" ] || [[ "$stage3_filename" != *.tar.xz ]]; then + echo -e "${RED}Could not parse stage3 filename from ${mirror}, trying next...${NC}" + continue + fi + + digests_filename="${stage3_filename}.DIGESTS" + successful_mirror="$mirror" + echo -e "${GREEN}Found Stage 3: ${stage3_filename}${NC}" + break + done + + if [ -z "$successful_mirror" ]; then + echo -e "${RED}Error: Could not find working mirror. Check network connection.${NC}" + return 1 + fi + + stage3_base_url="${successful_mirror}releases/amd64/autobuilds/current-${stage3_variant}/" + + # Download in target directory + pushd "$GENTOO_ROOT_MOUNT_GLOBAL" > /dev/null || { + echo -e "${RED}Error: Could not change to ${GENTOO_ROOT_MOUNT_GLOBAL}. Aborting.${NC}" + return 1 + } + + # Verify files exist + echo -e "${YELLOW}Verifying files on mirror...${NC}" + if ! curl -s --head "${stage3_base_url}${stage3_filename}" | grep -q "200 OK"; then + echo -e "${RED}Error: Stage 3 file not found on mirror.${NC}" + popd > /dev/null + return 1 + fi + + # Download stage3 + echo -e "${YELLOW}Downloading ${stage3_filename}...${NC}" + if ! wget --progress=bar:force --timeout=30 --tries=3 -c "${stage3_base_url}${stage3_filename}"; then + echo -e "${RED}Error downloading Stage 3 tarball. Aborting.${NC}" + popd > /dev/null + return 1 + fi + + # Download DIGESTS + echo -e "${YELLOW}Downloading ${digests_filename}...${NC}" + if ! wget --progress=bar:force --timeout=30 --tries=3 -c "${stage3_base_url}${digests_filename}"; then + echo -e "${RED}Error downloading DIGESTS file. Aborting.${NC}" + popd > /dev/null + return 1 + fi + + # Verify checksum + echo -e "${YELLOW}Verifying checksum...${NC}" + local checksum_output + checksum_output=$(sha512sum -c --ignore-missing "$digests_filename" 2>&1) + echo "$checksum_output" + + if echo "$checksum_output" | grep -q "${stage3_filename}: OK"; then + echo -e "${GREEN}Stage 3 checksum VERIFIED.${NC}" + else + echo -e "${RED}Stage 3 checksum verification FAILED.${NC}" + popd > /dev/null + return 1 + fi + + # Check disk space before extraction (need at least 2GB) + echo -e "${YELLOW}Checking available disk space...${NC}" + local available_kb + available_kb=$(df -k --output=avail "$GENTOO_ROOT_MOUNT_GLOBAL" | tail -1) + if [ "$available_kb" -lt 2000000 ]; then + echo -e "${RED}Error: Not enough disk space for extraction (need 2GB+, have ${available_kb}KB).${NC}" + popd > /dev/null + return 1 + fi + echo -e "${GREEN}Disk space OK (${available_kb}KB available)${NC}" + + # Extract + echo -e "${YELLOW}Extracting Stage 3 tarball...${NC}" + if ! tar xpf "$stage3_filename" --xattrs-include='*.*' --numeric-owner; then + echo -e "${RED}Error extracting Stage 3 tarball. Aborting.${NC}" + popd > /dev/null + return 1 + fi + echo -e "${GREEN}Stage 3 extraction complete.${NC}" + + rm -f "$stage3_filename" "$digests_filename" + echo -e "${GREEN}Cleaned up downloaded files.${NC}" + + popd > /dev/null + return 0 +} + +prepare_chroot() { + echo -e "${YELLOW}--- Preparing Chroot Environment ---${NC}" + + # Copy DNS info + cp --dereference /etc/resolv.conf "${GENTOO_ROOT_MOUNT_GLOBAL}/etc/" + echo -e "${GREEN}Copied resolv.conf${NC}" + + # Mount necessary filesystems + mount --rbind /proc "${GENTOO_ROOT_MOUNT_GLOBAL}/proc" + mount --make-rslave "${GENTOO_ROOT_MOUNT_GLOBAL}/proc" + echo -e "${GREEN}Mounted /proc${NC}" + + mount --rbind /sys "${GENTOO_ROOT_MOUNT_GLOBAL}/sys" + mount --make-rslave "${GENTOO_ROOT_MOUNT_GLOBAL}/sys" + echo -e "${GREEN}Mounted /sys${NC}" + + mount --rbind /dev "${GENTOO_ROOT_MOUNT_GLOBAL}/dev" + mount --make-rslave "${GENTOO_ROOT_MOUNT_GLOBAL}/dev" + echo -e "${GREEN}Mounted /dev${NC}" + + mount --rbind /run "${GENTOO_ROOT_MOUNT_GLOBAL}/run" + mount --make-rslave "${GENTOO_ROOT_MOUNT_GLOBAL}/run" + echo -e "${GREEN}Mounted /run${NC}" + + echo -e "${GREEN}Chroot environment prepared.${NC}" + return 0 +} + +# --- Portage Configuration Copy --- + +copy_portage_config() { + echo -e "${YELLOW}--- Copying Portage Configuration ---${NC}" + + local script_dir + script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + local portage_dir="${GENTOO_ROOT_MOUNT_GLOBAL}/etc/portage" + + # Copy make.conf + if [[ -f "${script_dir}/make.conf" ]]; then + cp "${script_dir}/make.conf" "${portage_dir}/make.conf" + echo -e "${GREEN}Copied make.conf${NC}" + else + echo -e "${RED}Warning: make.conf not found in ${script_dir}${NC}" + fi + + # Copy ccache.conf + if [[ -f "${script_dir}/ccache.conf" ]]; then + cp "${script_dir}/ccache.conf" "${GENTOO_ROOT_MOUNT_GLOBAL}/etc/ccache.conf" + echo -e "${GREEN}Copied ccache.conf${NC}" + fi + + # Copy package.accept_keywords/ + if [[ -d "${script_dir}/package.accept_keywords" ]]; then + mkdir -p "${portage_dir}/package.accept_keywords" + cp -r "${script_dir}/package.accept_keywords/"* "${portage_dir}/package.accept_keywords/" 2>/dev/null || true + echo -e "${GREEN}Copied package.accept_keywords/${NC}" + fi + + # Copy package.use/ + if [[ -d "${script_dir}/package.use" ]]; then + mkdir -p "${portage_dir}/package.use" + cp -r "${script_dir}/package.use/"* "${portage_dir}/package.use/" 2>/dev/null || true + echo -e "${GREEN}Copied package.use/${NC}" + fi + + # Copy sets/ + if [[ -d "${script_dir}/sets" ]]; then + mkdir -p "${portage_dir}/sets" + cp -r "${script_dir}/sets/"* "${portage_dir}/sets/" 2>/dev/null || true + echo -e "${GREEN}Copied sets/${NC}" + fi + + # Copy dracut.conf.d/ + if [[ -d "${script_dir}/dracut.conf.d" ]]; then + mkdir -p "${GENTOO_ROOT_MOUNT_GLOBAL}/etc/dracut.conf.d" + cp -r "${script_dir}/dracut.conf.d/"* "${GENTOO_ROOT_MOUNT_GLOBAL}/etc/dracut.conf.d/" 2>/dev/null || true + echo -e "${GREEN}Copied dracut.conf.d/${NC}" + fi + + return 0 +} + +# --- LUKS & Filesystem Configuration --- + +generate_crypttab() { + echo -e "${YELLOW}Generating /etc/crypttab...${NC}" + local luks_uuid + luks_uuid=$(blkid -s UUID -o value "$PART3_GLOBAL") + echo "cryptroot UUID=${luks_uuid} none luks" > "${GENTOO_ROOT_MOUNT_GLOBAL}/etc/crypttab" + echo -e "${GREEN}Generated /etc/crypttab${NC}" +} + +generate_fstab() { + echo -e "${YELLOW}Generating /etc/fstab...${NC}" + local efi_uuid + efi_uuid=$(blkid -s UUID -o value "$PART1_GLOBAL") + + cat > "${GENTOO_ROOT_MOUNT_GLOBAL}/etc/fstab" << EOF +# /etc/fstab - Generated by init.sh +# Gentoo v3 Legion Laptop with LUKS encryption + +# EFI System Partition +UUID=${efi_uuid} /boot vfat noatime,defaults 0 2 + +# Encrypted swap (random key each boot - no hibernate support) +${PART2_GLOBAL} none swap sw,cipher=aes-xts-plain64,size=256 0 0 + +# Btrfs on LUKS (cryptroot) +${CRYPT_ROOT_GLOBAL} / btrfs ${BTRFS_OPTS},subvol=@ 0 0 +${CRYPT_ROOT_GLOBAL} /home btrfs ${BTRFS_OPTS},subvol=@home 0 0 +${CRYPT_ROOT_GLOBAL} /var btrfs ${BTRFS_OPTS},subvol=@var 0 0 +${CRYPT_ROOT_GLOBAL} /var/log btrfs ${BTRFS_OPTS},subvol=@log 0 0 +${CRYPT_ROOT_GLOBAL} /.snapshots btrfs ${BTRFS_OPTS},subvol=@snapshots 0 0 +EOF + echo -e "${GREEN}Generated /etc/fstab${NC}" +} + +# --- Main Execution Flow --- + +echo -e "${YELLOW}Gentoo Bootstrap Script${NC}" +echo -e "${YELLOW}Current time: $(date)${NC}" +echo "" + +# Init system selection +echo -e "${YELLOW}Select init system:${NC}" +echo " 1) OpenRC (default)" +echo " 2) systemd" +read -r -p "Choice [1]: " init_choice +case "$init_choice" in + 2) INIT_SYSTEM="systemd" ;; + *) INIT_SYSTEM="openrc" ;; +esac +echo -e "${GREEN}Using init system: ${INIT_SYSTEM}${NC}" + +# Step 1: Disk Selection +read -r -p "Ready to select the target disk? (y/n): " confirm_step +if [[ "$confirm_step" != "y" ]]; then + echo -e "${RED}Aborting.${NC}" + exit 1 +fi +if ! select_target_disk; then + exit 1 +fi + +# Step 2: Network Setup +echo -e "${YELLOW}--- MANUAL STEP: Network Setup ---${NC}" +echo "Ensure network connectivity before proceeding." +echo "Use 'net-setup' or manual commands (wpa_supplicant, dhcpcd, etc.)." +echo "Test with: ping -c 3 gentoo.org" +read -r -p "Press Enter once network is configured..." + +echo -e "${YELLOW}Testing network...${NC}" +if ping -c 2 gentoo.org >/dev/null 2>&1; then + echo -e "${GREEN}Network connectivity confirmed.${NC}" +else + echo -e "${RED}Warning: Cannot reach gentoo.org.${NC}" + read -r -p "Continue anyway? (y/n): " net_confirm + if [[ "$net_confirm" != "y" ]]; then + exit 1 + fi +fi + +# Step 3: Partitioning +read -r -p "Ready to partition ${TARGET_DISK_GLOBAL}? DESTRUCTIVE! (y/n): " confirm_step +if [[ "$confirm_step" != "y" ]]; then + exit 1 +fi +if ! partition_and_format_disk; then + exit 1 +fi + +# Step 4: Mount Partitions +read -r -p "Ready to mount partitions? (y/n): " confirm_step +if [[ "$confirm_step" != "y" ]]; then + exit 1 +fi +if ! mount_partitions; then + exit 1 +fi + +# Step 5: Download & Extract Stage 3 +read -r -p "Ready to download and extract Stage 3? (y/n): " confirm_step +if [[ "$confirm_step" != "y" ]]; then + exit 1 +fi +if ! download_and_extract_stage3; then + exit 1 +fi + +# Step 6: Prepare Chroot +read -r -p "Ready to prepare chroot environment? (y/n): " confirm_step +if [[ "$confirm_step" != "y" ]]; then + exit 1 +fi +if ! prepare_chroot; then + exit 1 +fi + +# Step 7: Copy Portage Configuration +echo -e "${YELLOW}Copying Portage configuration files...${NC}" +if ! copy_portage_config; then + echo -e "${RED}Warning: Some configuration files may not have been copied.${NC}" +fi + +# Step 8: Generate crypttab and fstab +echo -e "${YELLOW}Generating filesystem configuration...${NC}" +generate_crypttab +generate_fstab + +echo -e "${GREEN}#####################################################################${NC}" +echo -e "${GREEN}### Initial setup complete! ###${NC}" +echo -e "${GREEN}#####################################################################${NC}" +echo "" +echo -e "${YELLOW}Next steps:${NC}" +echo -e " 1. Run change-root.sh (or enter chroot manually):" +echo -e " ${GREEN}./change-root.sh${NC}" +echo -e " Or manually:" +echo -e " ${GREEN}chroot ${GENTOO_ROOT_MOUNT_GLOBAL} /bin/bash${NC}" +echo -e " ${GREEN}source /etc/profile${NC}" +echo "" +echo -e " 2. Sync Portage and select profile:" +echo -e " ${GREEN}emerge --sync${NC}" +echo -e " ${GREEN}eselect profile list${NC}" +echo -e " ${GREEN}eselect profile set ${NC}" +echo "" +echo -e "${YELLOW}Configuration files copied:${NC}" +echo -e " - make.conf" +echo -e " - ccache.conf" +echo -e " - package.accept_keywords/" +echo -e " - package.use/" +echo -e " - sets/" +echo -e " - dracut.conf.d/ (LUKS + NVIDIA)" +echo "" +echo -e "${YELLOW}Generated:${NC}" +echo -e " - /etc/crypttab (LUKS root)" +echo -e " - /etc/fstab (EFI, encrypted swap, Btrfs on LUKS)" +echo "" +echo -e "${YELLOW}LUKS Encryption:${NC}" +echo -e " Partition: ${PART3_GLOBAL}" +echo -e " Mapper: ${CRYPT_ROOT_GLOBAL}" +echo -e " Swap: Encrypted with random key at each boot" +echo "" +echo -e "${YELLOW}Btrfs subvolume layout (on LUKS):${NC}" +echo -e " @ -> / (root)" +echo -e " @home -> /home (user data)" +echo -e " @var -> /var (variable data)" +echo -e " @log -> /var/log (logs)" +echo -e " @snapshots -> /.snapshots (for snapper/timeshift)" +echo "" +echo -e "${YELLOW}Current time: $(date)${NC}" + +exit 0 diff --git a/install/services.sh b/install/services.sh new file mode 100644 index 0000000..7183d34 --- /dev/null +++ b/install/services.sh @@ -0,0 +1,129 @@ +#!/bin/bash + +# services.sh - Configure Essential System Tools and OpenRC +# Run this inside the chroot after emerging @world + +# --- Colors for Output --- +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[0;33m' +NC='\033[0m' + +set -e + +echo -e "${YELLOW}--- Configuring Essential System Tools and OpenRC ---${NC}" + +# --- Part 1: Emerge Essential Service Packages --- +echo -e "${YELLOW}Emerging essential service packages...${NC}" + +PACKAGES_TO_EMERGE=( + app-admin/sysklogd + net-misc/networkmanager + net-misc/chrony + net-wireless/bluez + net-wireless/blueman + sys-fs/udisks + sys-process/cronie + sys-power/power-profiles-daemon + sys-auth/rtkit + gui-libs/greetd + gui-apps/regreet + gui-libs/display-manager-init + net-firewall/iptables + app-backup/snapper + app-containers/podman + app-containers/podman-compose + app-containers/podman-tui +) + +if ! emerge --ask --verbose "${PACKAGES_TO_EMERGE[@]}"; then + echo -e "${RED}Error: Failed to emerge essential service packages.${NC}" + exit 1 +fi +echo -e "${GREEN}Essential service packages emerged successfully.${NC}" + +# --- Part 2: Configure greetd as Display Manager --- +echo -e "${YELLOW}Configuring greetd as display manager...${NC}" + +# Set greetd in display-manager config +if [ -f /etc/conf.d/display-manager ]; then + sed -i 's/^DISPLAYMANAGER=.*/DISPLAYMANAGER="greetd"/' /etc/conf.d/display-manager + echo -e "${GREEN}Set greetd as display manager${NC}" +else + echo -e "${YELLOW}Creating /etc/conf.d/display-manager...${NC}" + echo 'DISPLAYMANAGER="greetd"' > /etc/conf.d/display-manager + echo -e "${GREEN}Created display-manager config with greetd${NC}" +fi + +# Configure greetd - copy config files from repo +# NOTE: Run this script from the repo root directory +echo -e "${YELLOW}Configuring greetd...${NC}" +cp greetd/config.toml /etc/greetd/config.toml +cp greetd/regreet.toml /etc/greetd/regreet.toml +cp greetd/hyprland.conf /etc/greetd/hyprland.conf +cp greetd/greetd.pam /etc/pam.d/greetd + +# Create greeter log file with correct permissions +touch /var/log/hyprland-greeter.log +chown greetd:greetd /var/log/hyprland-greeter.log + +# Install user session launcher script +cp greetd/start-hyprland-dbus /usr/local/bin/start-hyprland-dbus +chmod +x /usr/local/bin/start-hyprland-dbus + +# Update Hyprland desktop entry to use our launcher +if [ -f /usr/share/wayland-sessions/hyprland.desktop ]; then + sed -i 's|^Exec=.*|Exec=/usr/local/bin/start-hyprland-dbus|' /usr/share/wayland-sessions/hyprland.desktop +fi + +echo -e "${GREEN}greetd configured${NC}" + +# --- Part 3: Add Services to OpenRC Runlevels --- +echo -e "${YELLOW}Adding services to OpenRC runlevels...${NC}" + +# NOTE: udisks is D-Bus activated and doesn't need an OpenRC service +# NOTE: wpa_supplicant is managed by NetworkManager, not added separately + +# Boot runlevel - essential services needed early +SERVICES_BOOT=( + dbus + elogind + dmcrypt +) + +# Default runlevel - user services +SERVICES_DEFAULT=( + sysklogd + sshd + NetworkManager + chronyd + cronie + power-profiles-daemon + display-manager + bluetooth + iptables + ip6tables +) + +echo -e "${YELLOW}Adding boot runlevel services...${NC}" +for service in "${SERVICES_BOOT[@]}"; do + echo -e "${YELLOW} Adding ${service} to boot runlevel...${NC}" + if ! rc-update add "$service" boot 2>/dev/null; then + echo -e "${RED} Warning: Could not add ${service} (may not exist or already added)${NC}" + else + echo -e "${GREEN} Added ${service} to boot${NC}" + fi +done + +echo -e "${YELLOW}Adding default runlevel services...${NC}" +for service in "${SERVICES_DEFAULT[@]}"; do + echo -e "${YELLOW} Adding ${service} to default runlevel...${NC}" + if ! rc-update add "$service" default 2>/dev/null; then + echo -e "${RED} Warning: Could not add ${service} (may not exist or already added)${NC}" + else + echo -e "${GREEN} Added ${service} to default${NC}" + fi +done + +echo -e "${GREEN}OpenRC services configured.${NC}" +echo -e "${GREEN}--- Services Setup Complete ---${NC}" diff --git a/portage/make.conf b/portage/make.conf new file mode 100644 index 0000000..d4e8385 --- /dev/null +++ b/portage/make.conf @@ -0,0 +1,54 @@ +# make.conf for Legion S7 15ACH6 +# AMD Ryzen 9 5900HX with Radeon Graphics (16) @ 4.683GHz +# AMD ATI Radeon Vega Series / Radeon Vega Mobile Series +# NVIDIA GeForce RTX 3050 Ti Mobile / Max-Q + +# Compiler Settings +COMMON_FLAGS="-march=znver3 -O2 -pipe" +CFLAGS="${COMMON_FLAGS}" +CXXFLAGS="${COMMON_FLAGS}" +FCFLAGS="${COMMON_FLAGS}" +FFLAGS="${COMMON_FLAGS}" +CHOST="x86_64-pc-linux-gnu" + +# Build Settings +MAKEOPTS="-j16 -l14" +EMERGE_DEFAULT_OPTS="--jobs=2 --load-average=14" + +# Mirrors and Boot +GENTOO_MIRRORS="https://mirrors.rit.edu/gentoo/" +GRUB_PLATFORMS="efi-64" + +# Portage Features +FEATURES="ccache parallel-fetch candy" + +# Cleaner build output +LC_MESSAGES=C + +# Hardware +VIDEO_CARDS="amdgpu nvidia" +INPUT_DEVICES="libinput" + +# USE Flags - Optimized for Hyprland Desktop + +# Core system +USE="btrfs wayland X opengl vulkan egl gbm" +# Graphics - hybrid AMD iGPU + NVIDIA dGPU +USE="${USE} nvidia amdgpu opencl vaapi" +# Audio - PipeWire only +USE="${USE} pipewire alsa" +# Network and connectivity +USE="${USE} networkmanager bluetooth wifi" +# Desktop environment essentials +USE="${USE} udisks cups nls threads ssl crypt zstd" +# GUI toolkits and libraries +USE="${USE} gtk qt5 qt6 ffmpeg webp libnotify harfbuzz icu" +# Wayland/Hyprland specific +USE="${USE} screencast udev" +# Kernel +USE="${USE} dist-kernel" +# Firmware (explicit for linux-firmware) +USE="${USE} redistributable" + +# License Acceptance +ACCEPT_LICENSE="linux-fw-redistributable NVIDIA-r2 BUSL-1.1" diff --git a/portage/package.accept_keywords/hyprland b/portage/package.accept_keywords/hyprland new file mode 100644 index 0000000..dfe5007 --- /dev/null +++ b/portage/package.accept_keywords/hyprland @@ -0,0 +1,80 @@ +# Hyprland ecosystem packages requiring ~amd64 +# Verified against packages.gentoo.org on 2026-01-13 + +# ============================================================================= +# GURU OVERLAY PACKAGES +# ============================================================================= + +# Hyprland core (GURU) +gui-apps/hypridle ~amd64 +gui-apps/hyprlock ~amd64 +gui-apps/quickshell ~amd64 + +# Wayland utilities (GURU) +gui-apps/swaync ~amd64 +gui-apps/awww ~amd64 +gui-apps/wlogout ~amd64 +gui-apps/nwg-displays ~amd64 +app-misc/nwg-look ~amd64 + +# Clipboard (GURU) +app-misc/cliphist ~amd64 + +# Theming (GURU) +x11-themes/kvantum ~amd64 +x11-themes/catppuccin-kvantum ~amd64 +x11-themes/qogir-icon-theme ~amd64 +x11-themes/bibata-xcursors ~amd64 +x11-themes/gtk-engines-murrine ~amd64 + +# D-Bus library (GURU) +dev-cpp/sdbus-c++ ~amd64 + +# GTK4 layer shell (GURU) +gui-libs/gtk4-layer-shell ~amd64 + +# Audio (GURU) +media-sound/pamixer ~amd64 + +# Wallpaper tools (GURU) +x11-misc/wallust ~amd64 + +# XDG portals (GURU) +gui-libs/xdg-desktop-portal-hyprland ~amd64 +# Note: sys-apps/xdg-desktop-portal-gtk is stable in main tree, no keyword needed + +# Brightness control (GURU) +app-misc/brightnessctl ~amd64 + +# Fonts (GURU) +media-fonts/nerdfonts ~amd64 +media-fonts/fontawesome ~amd64 + +# Media plugins (GURU) +mpv-plugin/mpv-mpris ~amd64 + +# NVIDIA VA-API (GURU) +media-libs/nvidia-vaapi-driver ~amd64 + +# Dialogs (GURU) +gnome-extra/yad ~amd64 + +# Shell plugins (GURU) +app-shells/zsh-autosuggestions ~amd64 + +# Libraries +# Note: dev-util/umockdev is stable in main tree, no keyword needed +# Note: dev-libs/libdbusmenu is stable in main tree, no keyword needed + +# Utilities (GURU) +app-misc/bc ~amd64 + +# ============================================================================= +# MAIN TREE PACKAGES (testing only, no stable version) +# ============================================================================= + +# Shell utilities (main tree, ~amd64 only) +app-shells/zoxide ~amd64 + +# Image viewer (main tree, ~amd64 only) +media-gfx/loupe ~amd64 diff --git a/portage/package.accept_keywords/steam b/portage/package.accept_keywords/steam new file mode 100644 index 0000000..65617da --- /dev/null +++ b/portage/package.accept_keywords/steam @@ -0,0 +1,4 @@ +# Steam overlay +*/*::steam-overlay +games-util/game-device-udev-rules +sys-libs/libudev-compat diff --git a/portage/package.license/steam b/portage/package.license/steam new file mode 100644 index 0000000..638a762 --- /dev/null +++ b/portage/package.license/steam @@ -0,0 +1,2 @@ +# Steam license +games-util/steam-launcher ValveSteamLicense diff --git a/portage/package.use/circular-dependencies b/portage/package.use/circular-dependencies new file mode 100644 index 0000000..ee4bf59 --- /dev/null +++ b/portage/package.use/circular-dependencies @@ -0,0 +1,10 @@ +# Circular dependency workarounds for initial @world compile +# +# IMPORTANT: After @world compiles successfully, you should: +# Run: emerge -1 media-libs/freetype media-libs/harfbuzz +# +# This ensures both packages are built with full feature support. + +dev-python/pillow -truetype +media-libs/libwebp -tiff +media-libs/freetype -harfbuzz diff --git a/portage/package.use/initial-use-flags b/portage/package.use/initial-use-flags new file mode 100644 index 0000000..08b2505 --- /dev/null +++ b/portage/package.use/initial-use-flags @@ -0,0 +1,30 @@ +# Package-specific USE flags for Hyprland desktop + +# Python target for nwg-displays +gui-apps/nwg-displays python_targets_python3_12 + +# GTK layer shell for Wayland +gui-libs/gtk-layer-shell introspection vala + +# NerdFonts variants to install +media-fonts/nerdfonts firacode jetbrainsmono fantasque sourcecodepro hack + +# PipeWire extras +media-video/pipewire ffmpeg extra + +# Thunar panel integration +xfce-base/thunar-volman udisks + +# MTP support for phones/devices +gnome-base/gvfs mtp + +# QuickShell Qt6 support +dev-qt/qt5compat qml + +# NVIDIA driver options +x11-drivers/nvidia-drivers modules-sign persistenced + +# Linux firmware redistributable blobs +# Prevent linux-firmware from pulling in gentoo-kernel before @world is compiled +# The global dist-kernel USE flag would otherwise trigger kernel installation +sys-kernel/linux-firmware redistributable -dist-kernel diff --git a/portage/package.use/iptables b/portage/package.use/iptables new file mode 100644 index 0000000..b099c16 --- /dev/null +++ b/portage/package.use/iptables @@ -0,0 +1,2 @@ +# Required by podman for container networking +net-firewall/iptables nftables diff --git a/portage/package.use/podman b/portage/package.use/podman new file mode 100644 index 0000000..6cdc617 --- /dev/null +++ b/portage/package.use/podman @@ -0,0 +1,2 @@ +# Podman container runtime +app-containers/podman wrapper diff --git a/portage/package.use/steam b/portage/package.use/steam new file mode 100644 index 0000000..3bba9d2 --- /dev/null +++ b/portage/package.use/steam @@ -0,0 +1,140 @@ +# Steam 32-bit dependencies +app-accessibility/at-spi2-core abi_x86_32 +app-arch/bzip2 abi_x86_32 +app-arch/lz4 abi_x86_32 +app-arch/xz-utils abi_x86_32 +app-arch/zstd abi_x86_32 +app-crypt/p11-kit abi_x86_32 +dev-db/sqlite abi_x86_32 +dev-lang/rust-bin abi_x86_32 +dev-libs/dbus-glib abi_x86_32 +dev-libs/elfutils abi_x86_32 +dev-libs/expat abi_x86_32 +dev-libs/fribidi abi_x86_32 +dev-libs/glib abi_x86_32 +dev-libs/gmp abi_x86_32 +dev-libs/icu abi_x86_32 +dev-libs/json-glib abi_x86_32 +dev-libs/libevdev abi_x86_32 +dev-libs/libffi abi_x86_32 +dev-libs/libgcrypt abi_x86_32 +dev-libs/libgpg-error abi_x86_32 +dev-libs/libgudev abi_x86_32 +dev-libs/libgusb abi_x86_32 +dev-libs/libpcre2 abi_x86_32 +dev-libs/libtasn1 abi_x86_32 +dev-libs/libunistring abi_x86_32 +dev-libs/libusb abi_x86_32 +dev-libs/libxml2 abi_x86_32 +dev-libs/lzo abi_x86_32 +dev-libs/nettle abi_x86_32 +dev-libs/nspr abi_x86_32 +dev-libs/nss abi_x86_32 +dev-libs/openssl abi_x86_32 +dev-libs/wayland abi_x86_32 +dev-util/directx-headers abi_x86_32 +dev-util/spirv-tools abi_x86_32 +dev-util/sysprof-capture abi_x86_32 +gnome-base/librsvg abi_x86_32 +gui-libs/libdecor abi_x86_32 +llvm-core/clang abi_x86_32 +llvm-core/llvm abi_x86_32 +media-gfx/graphite2 abi_x86_32 +media-libs/alsa-lib abi_x86_32 +media-libs/flac abi_x86_32 +media-libs/fontconfig abi_x86_32 +media-libs/freetype abi_x86_32 +media-libs/glu abi_x86_32 +media-libs/harfbuzz abi_x86_32 +media-libs/lcms abi_x86_32 +media-libs/libepoxy abi_x86_32 +media-libs/libglvnd abi_x86_32 +media-libs/libjpeg-turbo abi_x86_32 +media-libs/libogg abi_x86_32 +media-libs/libpng abi_x86_32 +media-libs/libpulse abi_x86_32 +media-libs/libsdl2 abi_x86_32 +media-libs/libsndfile abi_x86_32 +media-libs/libva abi_x86_32 +media-libs/libvorbis abi_x86_32 +media-libs/libwebp abi_x86_32 +media-libs/mesa abi_x86_32 vulkan +media-libs/openal abi_x86_32 +media-libs/opus abi_x86_32 +media-libs/tiff abi_x86_32 +media-libs/vulkan-loader abi_x86_32 +media-sound/lame abi_x86_32 +media-sound/mpg123-base abi_x86_32 +media-video/pipewire abi_x86_32 +net-dns/c-ares abi_x86_32 +net-dns/libidn2 abi_x86_32 +net-libs/gnutls abi_x86_32 +net-libs/libasyncns abi_x86_32 +net-libs/libndp abi_x86_32 +net-libs/libpsl abi_x86_32 +net-libs/nghttp2 abi_x86_32 +net-libs/nghttp3 abi_x86_32 +net-misc/curl abi_x86_32 +net-misc/networkmanager abi_x86_32 +net-print/cups abi_x86_32 +sys-apps/dbus abi_x86_32 +sys-apps/systemd-utils abi_x86_32 +sys-apps/util-linux abi_x86_32 +sys-libs/gdbm abi_x86_32 +sys-libs/gpm abi_x86_32 +sys-libs/libcap abi_x86_32 +sys-libs/libudev-compat abi_x86_32 +sys-libs/ncurses abi_x86_32 +sys-libs/pam abi_x86_32 +sys-libs/readline abi_x86_32 +sys-libs/zlib abi_x86_32 +virtual/glu abi_x86_32 +virtual/libelf abi_x86_32 +virtual/libiconv abi_x86_32 +virtual/libintl abi_x86_32 +virtual/libudev abi_x86_32 +virtual/libusb abi_x86_32 +virtual/opengl abi_x86_32 +virtual/rust abi_x86_32 +virtual/zlib abi_x86_32 +x11-libs/cairo abi_x86_32 +x11-libs/extest abi_x86_32 +x11-libs/gdk-pixbuf abi_x86_32 +x11-libs/gtk+ abi_x86_32 +x11-libs/libdrm abi_x86_32 +x11-libs/libICE abi_x86_32 +x11-libs/libpciaccess abi_x86_32 +x11-libs/libSM abi_x86_32 +x11-libs/libvdpau abi_x86_32 +x11-libs/libX11 abi_x86_32 +x11-libs/libXau abi_x86_32 +x11-libs/libxcb abi_x86_32 +x11-libs/libXcomposite abi_x86_32 +x11-libs/libXcursor abi_x86_32 +x11-libs/libXdamage abi_x86_32 +x11-libs/libXdmcp abi_x86_32 +x11-libs/libXext abi_x86_32 +x11-libs/libXfixes abi_x86_32 +x11-libs/libXft abi_x86_32 +x11-libs/libXi abi_x86_32 +x11-libs/libXinerama abi_x86_32 +x11-libs/libxkbcommon abi_x86_32 +x11-libs/libXrandr abi_x86_32 +x11-libs/libXrender abi_x86_32 +x11-libs/libXScrnSaver abi_x86_32 +x11-libs/libxshmfence abi_x86_32 +x11-libs/libXtst abi_x86_32 +x11-libs/libXxf86vm abi_x86_32 +x11-libs/pango abi_x86_32 +x11-libs/pixman abi_x86_32 +x11-libs/xcb-util-keysyms abi_x86_32 +x11-misc/colord abi_x86_32 + +# NVIDIA 32-bit support +gui-libs/egl-gbm abi_x86_32 +gui-libs/egl-wayland abi_x86_32 +gui-libs/egl-x11 abi_x86_32 +x11-drivers/nvidia-drivers abi_x86_32 + +# Easy Anti-Cheat support +sys-libs/glibc hash-sysv-compat diff --git a/portage/sets/hyprland b/portage/sets/hyprland new file mode 100644 index 0000000..a58dc74 --- /dev/null +++ b/portage/sets/hyprland @@ -0,0 +1,183 @@ +# Hyprland Desktop Set for Legion S7 15ACH6 +# Based on JaKooLit Arch-Hyprland dotfiles +# For use with: emerge @hyprland + +# ============================================================================= +# HYPRLAND CORE +# ============================================================================= +gui-wm/hyprland +gui-apps/hypridle +gui-apps/hyprlock +gui-apps/quickshell + +# ============================================================================= +# DESKTOP UTILITIES +# ============================================================================= +app-misc/bc +app-misc/cliphist +app-misc/jq +gui-apps/grim +gui-apps/slurp +gui-apps/swappy +gui-apps/swaync +gui-apps/awww +gui-apps/waybar +gui-apps/wl-clipboard +gui-apps/wlogout +x11-misc/rofi +x11-misc/wallust + +# ============================================================================= +# QT/GTK THEMING +# ============================================================================= +dev-qt/qt5compat +dev-qt/qtsvg +dev-qt/qtdeclarative +gui-apps/qt6ct +x11-misc/qt5ct +x11-themes/kvantum + +# ============================================================================= +# SYSTEM UTILITIES +# ============================================================================= +gnome-base/gvfs +gnome-extra/nm-applet +gnome-extra/polkit-gnome +gnome-extra/yad +media-gfx/imagemagick +media-libs/libspng +sys-apps/inxi +x11-misc/xdg-user-dirs +x11-misc/xdg-utils + +# ============================================================================= +# AUDIO +# ============================================================================= +media-sound/pamixer +media-sound/pavucontrol +media-sound/playerctl + +# ============================================================================= +# PYTHON DEPENDENCIES +# ============================================================================= +dev-python/pyquery +dev-python/requests +dev-python/beautifulsoup4 +dev-python/pygments +dev-python/pyyaml +dev-python/secretstorage +dev-python/uv + +# ============================================================================= +# TERMINAL & TOOLS +# ============================================================================= +app-arch/unzip +app-arch/xarchiver +net-misc/curl +net-misc/wget +x11-terms/kitty + +# ============================================================================= +# SHELL ENHANCEMENTS +# ============================================================================= +app-shells/fzf +app-shells/starship +app-shells/zoxide +app-shells/zsh-autosuggestions +app-shells/zsh-syntax-highlighting +sys-apps/lsd + +# ============================================================================= +# MONITORING +# ============================================================================= +app-misc/fastfetch +media-sound/cava +sys-process/btop +sys-process/htop +sys-process/nvtop + +# ============================================================================= +# MEDIA +# ============================================================================= +media-video/mpv +mpv-plugin/mpv-mpris +media-video/ffmpegthumbnailer +net-misc/yt-dlp + +# ============================================================================= +# DESKTOP EXTRAS +# ============================================================================= +app-editors/mousepad +app-text/evince +gnome-extra/gnome-system-monitor +gui-apps/nwg-displays +app-misc/nwg-look +media-gfx/loupe +sci-calculators/qalculate-gtk +app-misc/brightnessctl +sys-power/upower + +# ============================================================================= +# FILE MANAGER +# ============================================================================= +xfce-base/thunar +xfce-base/thunar-volman +xfce-base/tumbler +xfce-extra/thunar-archive-plugin + +# ============================================================================= +# FONTS +# ============================================================================= +media-fonts/fantasque-sans-mono +media-fonts/fira-code +media-fonts/fontawesome +media-fonts/jetbrains-mono +media-fonts/nerdfonts +media-fonts/noto +media-fonts/noto-emoji + +# ============================================================================= +# THEMES & ICONS +# ============================================================================= +lxde-base/lxappearance +x11-themes/gtk-engines-murrine +x11-libs/gtk+:3 +x11-themes/adwaita-qt +x11-themes/bibata-xcursors +x11-themes/catppuccin-kvantum +x11-themes/gtk-engines +x11-themes/papirus-icon-theme +x11-themes/qogir-icon-theme + +# ============================================================================= +# XDG PORTALS +# ============================================================================= +sys-apps/xdg-desktop-portal-gtk +gui-libs/xdg-desktop-portal-hyprland +dev-util/umockdev + +# ============================================================================= +# ADDITIONAL DEV/LIBS +# ============================================================================= +dev-build/meson +dev-cpp/sdbus-c++ +dev-libs/gjs +dev-libs/glib +dev-libs/gobject-introspection +gnome-base/gnome-keyring +gui-libs/gtk4-layer-shell +net-libs/libsoup:3.0 +net-libs/nodejs +dev-libs/libdbusmenu + +# ============================================================================= +# GRAPHICS (NVIDIA/AMD HYBRID) +# ============================================================================= +media-libs/libva +media-libs/nvidia-vaapi-driver + +# ============================================================================= +# POWER MANAGEMENT & FIRMWARE +# ============================================================================= +sys-power/cpupower +sys-apps/fwupd diff --git a/shell/starship.toml b/shell/starship.toml new file mode 100644 index 0000000..c69d78f --- /dev/null +++ b/shell/starship.toml @@ -0,0 +1,146 @@ +## FIRST LINE/ROW: Info & Status +# First param ─┌ +[username] +format = " [╭─$user]($style)@" +show_always = true +style_root = "bold #ff5f5f" +style_user = "bold #61afef" + +# Second param +[hostname] +disabled = false +format = "[$hostname]($style) in " +ssh_only = false +style = "bold #56b6c2" +trim_at = "-" + +# Third param +[directory] +style = "#c678dd" +truncate_to_repo = true +truncation_length = 0 +truncation_symbol = "repo: " + +# Fourth param +[sudo] +disabled = false + +# Before all the version info (python, nodejs, php, etc.) +[git_status] +ahead = "⇡${count}" +behind = "⇣${count}" +deleted = "x" +diverged = "⇕⇡${ahead_count}⇣${behind_count}" +style = "bold #e5c07b" + +# Last param in the first line/row +[cmd_duration] +disabled = false +format = "took [$duration]($style)" +min_time = 1 + +## SECOND LINE/ROW: Prompt +# Somethere at the beginning +[battery] +charging_symbol = "" +disabled = true +discharging_symbol = "" +full_symbol = "" + +[[battery.display]] # "bold red" style when capacity is between 0% and 15% +disabled = false +style = "bold #ff5f5f" +threshold = 15 + +[[battery.display]] # "bold yellow" style when capacity is between 15% and 50% +disabled = true +style = "bold #e5c07b" +threshold = 50 + +[[battery.display]] # "bold green" style when capacity is between 50% and 80% +disabled = true +style = "bold #98c379" +threshold = 80 + +# Prompt: optional param 1 +[time] +disabled = true +format = " 🕙 $time($style)\n" +style = "#abb2bf" +time_format = "%T" + +# Prompt: param 2 +[character] +error_symbol = " [×](bold #ff5f5f)" +success_symbol = " [╰─>](bold #61afef)" + +# SYMBOLS +[status] +disabled = false +format = '[\[$symbol$status_common_meaning$status_signal_name$status_maybe_int\]]($style)' +map_symbol = true +pipestatus = true +symbol = "🔴" + +[aws] +symbol = " " + +[conda] +symbol = " " + +[dart] +symbol = " " + +[docker_context] +symbol = " " + +[elixir] +symbol = " " + +[elm] +symbol = " " + +[git_branch] +symbol = " " + +[golang] +symbol = " " + +[hg_branch] +symbol = " " + +[java] +symbol = " " + +[julia] +symbol = " " + +[nim] +symbol = " " + +[nix_shell] +symbol = " " + +[nodejs] +symbol = " " + +[package] +symbol = " " + +[perl] +symbol = " " + +[php] +symbol = " " + +[python] +symbol = " " + +[ruby] +symbol = " " + +[rust] +symbol = " " + +[swift] +symbol = " " \ No newline at end of file diff --git a/shell/zshrc.example b/shell/zshrc.example new file mode 100644 index 0000000..83096ae --- /dev/null +++ b/shell/zshrc.example @@ -0,0 +1,128 @@ +# ~/.zshrc +# Gentoo + Hyprland zsh configuration + +export TERM="xterm-256color" + +# --- Basic Zsh Configuration --- + +# Set default editor +export EDITOR="nano" # Or "vim", "nvim", etc. + +# History settings +HISTFILE=~/.zsh_history +SAVEHIST=10000 # Number of history entries to save +HISTSIZE=10000 # Number of history entries to keep in memory +setopt appendhistory # Append history to the history file +setopt sharehistory # Share history among all sessions +setopt hist_ignore_dups # Ignore duplicate commands +setopt hist_verify # Ask for confirmation before executing history expansion + +# Autocompletion +autoload -U compinit +compinit + +# Better completion styling +zstyle ':completion:*' menu select +zstyle ':completion:*' matcher-list 'm:{a-zA-Z}={A-Za-z}' 'r:|[._-]=* r:|=*' 'l:|=* r:|=*' +zstyle ':completion:*' list-colors "${(s.:.)LS_COLORS}" +zstyle ':completion:*' group-name '' +zstyle ':completion:*:descriptions' format '%F{yellow}-- %d --%f' +zstyle ':completion:*:warnings' format '%F{red}-- no matches found --%f' + +# Zsh options +setopt autocd # Change directory just by typing directory name +setopt extendedglob # Enable extended globbing +setopt no_beep # Disable the bell +setopt correct # Correct common typos +setopt complete_in_word # Complete from the middle of a word + +# Load any profile environment variables +if [[ -f /etc/zsh/zprofile ]]; then + source /etc/zsh/zprofile +fi +if [[ -f /etc/zsh/zshrc ]]; then + source /etc/zsh/zshrc +fi + +# --- fzf Integration --- + +# Load fzf key bindings and completions (Gentoo paths) +if [[ -f "/usr/share/fzf/key-bindings.zsh" ]]; then + source "/usr/share/fzf/key-bindings.zsh" +fi +if [[ -f "/usr/share/fzf/completion.zsh" ]]; then + source "/usr/share/fzf/completion.zsh" +fi + +# --- Aliases --- + +# General aliases +alias c='clear' +alias df='df -h' +alias du='du -sh' +alias ip='ip -c a' +alias ping='ping -c 5' +alias top='htop' +alias nano='nano -c' + +# Add your SSH aliases here +# alias myserver='ssh user@hostname' + +# Git aliases +alias g='git' +alias gs='git status' +alias ga='git add .' +alias gc='git commit -m' +alias gp='git push' +alias gl='git log --oneline --decorate --all --graph' + +# --- lsd Aliases --- +# Replace ls with lsd for better visuals +alias ls='lsd' +alias l='lsd -F' +alias ll='lsd -l' +alias la='lsd -a' +alias lld='lsd -ld' +alias lla='lsd -la' +alias lt='lsd --tree' + +# --- Prompt --- +PROMPT='%n@%m:%~%# ' + +# Add your VPN function here if using WireGuard/Nebula +# vpn() { +# case "$1" in +# up) sudo wg-quick up ;; +# down) sudo wg-quick down ;; +# status) sudo wg show 2>/dev/null || echo "VPN is down" ;; +# *) echo "Usage: vpn {up|down|status}"; return 1 ;; +# esac +# } + +# Neovide wrapper - backgrounds the process and closes terminal +neovide() { + command neovide "$@" &>/dev/null & + disown + exit +} + +# Initialize starship prompt +eval "$(starship init zsh)" + +# Initialize zoxide (smarter cd) +eval "$(zoxide init zsh)" + +export PATH=$PATH:$HOME/.local/bin + +# Autosuggestions from history (fish-style) +if [[ -f /usr/share/zsh/site-functions/zsh-autosuggestions.zsh ]]; then + source /usr/share/zsh/site-functions/zsh-autosuggestions.zsh + ZSH_AUTOSUGGEST_STRATEGY=(history completion) + ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE='fg=8' + bindkey '^[[1;5C' forward-word # Ctrl+Right accept one word + bindkey '^[f' forward-word # Alt+f accept one word (fallback) +fi + +# Syntax highlighting (must be at the end) +[[ -f /usr/share/zsh/site-functions/zsh-syntax-highlighting.zsh ]] && \ + source /usr/share/zsh/site-functions/zsh-syntax-highlighting.zsh diff --git a/system/ccache.conf b/system/ccache.conf new file mode 100644 index 0000000..b22bde9 --- /dev/null +++ b/system/ccache.conf @@ -0,0 +1,6 @@ +# /etc/ccache.conf for Legion S7 (24GB RAM) + +max_size = 8G +cache_dir = /var/cache/ccache +compression = true +compression_level = 1 diff --git a/system/conf.d/dmcrypt.example b/system/conf.d/dmcrypt.example new file mode 100644 index 0000000..fdd502b --- /dev/null +++ b/system/conf.d/dmcrypt.example @@ -0,0 +1,10 @@ +# /etc/conf.d/dmcrypt - Encrypted swap configuration +# +# Encrypted swap with random key (no hibernate support) +# Key is regenerated each boot from /dev/urandom +# +# CUSTOMIZE: Set source to your swap partition +# Use 'lsblk' to identify your partitions + +swap=cryptswap +source="" # e.g., /dev/nvme0n1p2 or /dev/sda2 diff --git a/system/conf.d/ip6tables b/system/conf.d/ip6tables new file mode 100644 index 0000000..8cb2e8c --- /dev/null +++ b/system/conf.d/ip6tables @@ -0,0 +1,7 @@ +# /etc/conf.d/ip6tables + +# Don't save state on service stop (use static rules file) +SAVE_ON_STOP="no" + +# Rules file location +IP6TABLES_SAVE="/etc/iptables/ip6tables.rules" diff --git a/system/conf.d/iptables b/system/conf.d/iptables new file mode 100644 index 0000000..ac43374 --- /dev/null +++ b/system/conf.d/iptables @@ -0,0 +1,7 @@ +# /etc/conf.d/iptables + +# Don't save state on service stop (use static rules file) +SAVE_ON_STOP="no" + +# Rules file location +IPTABLES_SAVE="/etc/iptables/iptables.rules" diff --git a/system/conf.d/snapper b/system/conf.d/snapper new file mode 100644 index 0000000..1f9f7ac --- /dev/null +++ b/system/conf.d/snapper @@ -0,0 +1,4 @@ +# /etc/conf.d/snapper - Snapper configuration +# List of snapper configs to manage with hourly cron job + +SNAPPER_CONFIGS="root" diff --git a/system/dracut.conf.d/crypt.conf b/system/dracut.conf.d/crypt.conf new file mode 100644 index 0000000..abd9f26 --- /dev/null +++ b/system/dracut.conf.d/crypt.conf @@ -0,0 +1,2 @@ +# LUKS support for encrypted root +add_dracutmodules+=" crypt "