public-ready-init

This commit is contained in:
Damien Coles 2026-01-24 20:47:35 -05:00
commit 9a4a970f76
38 changed files with 3297 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/.idea/

21
LICENSE Normal file
View File

@ -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.

159
README.md Normal file
View File

@ -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/<user>/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

205
docs/greetd-setup.md Normal file
View File

@ -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,<your-cursor-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
```

169
docs/hybrid-gpu.md Normal file
View File

@ -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 <application>
```
Or set environment variables:
```bash
__NV_PRIME_RENDER_OFFLOAD=1 __GLX_VENDOR_LIBRARY_NAME=nvidia <application>
```
## 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
```

351
docs/installation.md Normal file
View File

@ -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/<user>/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 <number>
```
### 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 <number> # en_US.utf8
echo "LANG=en_US.UTF-8" > /etc/locale.conf
env-update && source /etc/profile
```
### 13. Set Hostname
```bash
echo "<your-hostname>" > /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=<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 <username>
passwd <username>
# Copy shell configs for user
cp shell/zshrc.example /home/<username>/.zshrc
mkdir -p /home/<username>/.config
cp shell/starship.toml /home/<username>/.config/starship.toml
chown -R <username>:<username> /home/<username>
```
---
## 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 <operation>"
```
**Service management (OpenRC):**
```bash
rc-service <service> start|stop|restart|status
rc-update add|del <service> <runlevel>
loginctl reboot|poweroff|suspend # NOT systemctl
```

256
docs/troubleshooting.md Normal file
View File

@ -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 <service> status
```
2. Check dependencies:
```bash
rc-service <service> start --verbose
```
3. Review logs:
```bash
cat /var/log/messages | grep <service>
```
### OpenRC vs systemd Commands
| Task | OpenRC | systemd |
|------|--------|---------|
| Start service | `rc-service <name> start` | `systemctl start <name>` |
| Stop service | `rc-service <name> stop` | `systemctl stop <name>` |
| Enable at boot | `rc-update add <name> default` | `systemctl enable <name>` |
| Check status | `rc-service <name> status` | `systemctl status <name>` |
| 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/<category>
<package> ~amd64
```
### USE Flag Conflicts
Check required USE flags:
```bash
emerge -pv <package>
```
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/`

42
firewall/ip6tables.rules Normal file
View File

@ -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

View File

@ -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 <vpn-interface> -j ACCEPT
# Trusted local network (uncomment and customize to your network)
# -A INPUT -s <your-network>/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

6
greetd/config.toml Normal file
View File

@ -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"

13
greetd/greetd.pam Normal file
View File

@ -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

36
greetd/hyprland.conf Normal file
View File

@ -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
}

10
greetd/regreet.toml Normal file
View File

@ -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"]

2
greetd/start-hyprland-dbus Executable file
View File

@ -0,0 +1,2 @@
#!/bin/bash
exec dbus-run-session /usr/bin/start-hyprland > ~/.local/log/hyprland.log 2>&1

55
hypr/ENVariables.conf Normal file
View File

@ -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

View File

@ -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=<name>, disable
# Example: Mirror displays
# monitor=HDMI-A-1, 1920x1080@60, 0x0, 1, mirror, eDP-1
# Your configuration:
monitor=eDP-1, preferred, auto, 1

30
hypr/wlogout-layout Normal file
View File

@ -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"
}

104
install/chroot.sh Executable file
View File

@ -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"

822
install/init.sh Executable file
View File

@ -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 <number>${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

129
install/services.sh Normal file
View File

@ -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}"

54
portage/make.conf Normal file
View File

@ -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"

View File

@ -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

View File

@ -0,0 +1,4 @@
# Steam overlay
*/*::steam-overlay
games-util/game-device-udev-rules
sys-libs/libudev-compat

View File

@ -0,0 +1,2 @@
# Steam license
games-util/steam-launcher ValveSteamLicense

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,2 @@
# Required by podman for container networking
net-firewall/iptables nftables

View File

@ -0,0 +1,2 @@
# Podman container runtime
app-containers/podman wrapper

140
portage/package.use/steam Normal file
View File

@ -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

183
portage/sets/hyprland Normal file
View File

@ -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

146
shell/starship.toml Normal file
View File

@ -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 = " "

128
shell/zshrc.example Normal file
View File

@ -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 <config-name> ;;
# down) sudo wg-quick down <config-name> ;;
# status) sudo wg show <config-name> 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

6
system/ccache.conf Normal file
View File

@ -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

View File

@ -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="<swap-partition>" # e.g., /dev/nvme0n1p2 or /dev/sda2

7
system/conf.d/ip6tables Normal file
View File

@ -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"

7
system/conf.d/iptables Normal file
View File

@ -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"

4
system/conf.d/snapper Normal file
View File

@ -0,0 +1,4 @@
# /etc/conf.d/snapper - Snapper configuration
# List of snapper configs to manage with hourly cron job
SNAPPER_CONFIGS="root"

View File

@ -0,0 +1,2 @@
# LUKS support for encrypted root
add_dracutmodules+=" crypt "