# Aegis Linux — manual install commands

This is the transparent, copy-paste version of what `aegis-install` does. It is
for experienced Arch users who want to inspect or customise every step. The
guided installer is the supported path; this page is the reference and recovery
path.

> **Warning:** these commands erase a disk. Check `lsblk`, `blkid`, and
> `findmnt` before running anything. Never run them on a disk that holds data
> you need. The examples use `/dev/nvme0n1`; substitute your disk and partition
> names.

The manual path assumes you booted the Aegis live ISO in UEFI mode and have an
internet connection. The live environment runs as root.

## 1. Identify the target

```bash
lsblk -o NAME,SIZE,TYPE,MODEL,SERIAL,TRAN,MOUNTPOINTS
findmnt -R /run/archiso
```

Confirm that the target is not the live medium and that none of its partitions
are mounted. Aegis requires a whole disk of at least 20 GiB.

```bash
DISK=/dev/nvme0n1
ESP="${DISK}1"
ROOT="${DISK}2"
```

Partition naming differs on some devices:

- `/dev/sda` → `/dev/sda1`, `/dev/sda2`
- `/dev/vda` → `/dev/vda1`, `/dev/vda2`
- `/dev/nvme0n1` → `/dev/nvme0n1p1`, `/dev/nvme0n1p2`
- `/dev/mmcblk0` → `/dev/mmcblk0p1`, `/dev/mmcblk0p2`

## 2. Partition, encrypt, and format

```bash
wipefs --all --force "${DISK}"
sgdisk --zap-all "${DISK}"
sgdisk \
  --new=1:0:+1G --typecode=1:ef00 --change-name=1:AEGIS_ESP \
  --new=2:0:0 --typecode=2:8309 --change-name=2:AEGIS_ROOT \
  "${DISK}"
partprobe "${DISK}"
udevadm settle
```

Format the ESP and create the LUKS2 container. The passphrase is entered
interactively and is never placed on the command line.

```bash
mkfs.fat -F32 -n AEGIS_ESP "${ESP}"

cryptsetup luksFormat \
  --type luks2 \
  --cipher aes-xts-plain64 \
  --key-size 512 \
  --hash sha512 \
  --pbkdf argon2id \
  --iter-time 3000 \
  --label AEGIS_ROOT \
  "${ROOT}"

cryptsetup open "${ROOT}" aegis_root
LUKS_UUID="$(blkid -s UUID -o value "${ROOT}")"
ESP_UUID="$(blkid -s UUID -o value "${ESP}")"
```

TRIM pass-through is intentionally not enabled by default. If you enable
`discard` on the LUKS mapping, document the metadata leak trade-off.

## 3. Btrfs subvolumes

```bash
mkfs.btrfs --force --label AEGIS_ROOT /dev/mapper/aegis_root
mount -o noatime,compress=zstd:3,ssd,subvolid=5 /dev/mapper/aegis_root /mnt
btrfs subvolume create /mnt/@
btrfs subvolume create /mnt/@home
btrfs subvolume create /mnt/@log
btrfs subvolume create /mnt/@snapshots
umount /mnt

MOUNT_OPTS="noatime,compress=zstd:3,ssd"
mount -o "${MOUNT_OPTS},subvol=@" /dev/mapper/aegis_root /mnt
mkdir -p /mnt/home /mnt/var/log /mnt/.snapshots /mnt/boot
mount -o "${MOUNT_OPTS},subvol=@home" /dev/mapper/aegis_root /mnt/home
mount -o "${MOUNT_OPTS},subvol=@log" /dev/mapper/aegis_root /mnt/var/log
mount -o "${MOUNT_OPTS},subvol=@snapshots" /dev/mapper/aegis_root /mnt/.snapshots
mount "${ESP}" /mnt/boot
```

## 4. Base packages

```bash
pacstrap -K /mnt \
  base linux linux-firmware intel-ucode \
  btrfs-progs cryptsetup tpm2-tss tpm2-tools systemd-ukify \
  efibootmgr dosfstools gptfdisk util-linux e2fsprogs \
  sudo polkit plymouth zram-generator snapper snap-pac \
  networkmanager bluez bluez-utils \
  pipewire pipewire-pulse pipewire-alsa wireplumber \
  man-db man-pages bash-completion nano neovim git rsync btop fastfetch \
  jq curl wget unzip zip 7zip tar usbutils pciutils less \
  pacman-contrib reflector libpwquality

# On AMD systems use amd-ucode instead of intel-ucode.
```

If you booted the Aegis ISO, install the Aegis metapackages too:

```bash
pacstrap -K /mnt aegis-meta
# Minimal base + security only:
# pacstrap -K /mnt aegis-base aegis-security
```

`aegis-meta` pulls in the desktop. The live ISO's local `[aegis]` repository is
not retained in the installed system; Aegis packages are already installed and
there is deliberately no remote unsigned repository.

## 5. fstab

Write `/mnt/etc/fstab` explicitly. UUIDs survive device reordering; subvolume
paths survive snapshot operations.

```bash
cat >/mnt/etc/fstab <<EOF
UUID=${LUKS_UUID}  /             btrfs  rw,noatime,compress=zstd:3,ssd,subvol=/@          0 0
UUID=${LUKS_UUID}  /home         btrfs  rw,noatime,compress=zstd:3,ssd,subvol=/@home      0 0
UUID=${LUKS_UUID}  /var/log      btrfs  rw,noatime,compress=zstd:3,ssd,subvol=/@log       0 0
UUID=${LUKS_UUID}  /.snapshots   btrfs  rw,noatime,compress=zstd:3,ssd,subvol=/@snapshots 0 0
UUID=${ESP_UUID}   /boot         vfat   rw,noatime,umask=0077                             0 2
EOF
```

Do not add a disk swapfile or swap partition. Aegis uses zram only and does not
configure hibernation.

## 6. Chroot basics

```bash
arch-chroot /mnt

ln -sf /usr/share/zoneinfo/Europe/Berlin /etc/localtime
hwclock --systohc

# Uncomment your locale in /etc/locale.gen, then:
locale-gen
echo 'LANG=en_US.UTF-8' >/etc/locale.conf
echo 'KEYMAP=us' >/etc/vconsole.conf

echo 'aegis' >/etc/hostname
cat >/etc/hosts <<'EOF'
127.0.0.1   localhost
::1         localhost
127.0.1.1   aegis.localdomain aegis
EOF
```

Create the user and lock root:

```bash
useradd --create-home --groups wheel --shell /bin/bash jay
passwd jay
passwd --lock root

cat >/etc/sudoers.d/10-aegis <<'EOF'
%wheel ALL=(ALL:ALL) ALL
EOF
chmod 440 /etc/sudoers.d/10-aegis
```

## 7. Initramfs

Edit `/etc/mkinitcpio.conf` so the systemd hooks unlock LUKS before mounting
root:

```bash
sed -i 's/^MODULES=.*/MODULES=(btrfs)/' /etc/mkinitcpio.conf
sed -i 's|^HOOKS=.*|HOOKS=(base systemd autodetect microcode modconf kms keyboard sd-vconsole block plymouth sd-encrypt filesystems fsck)|' /etc/mkinitcpio.conf
mkinitcpio -P
```

Kernel command line for both bootloaders:

```bash
cat >/etc/kernel/cmdline <<EOF
rd.luks.name=${LUKS_UUID}=aegis_root root=/dev/mapper/aegis_root rootflags=subvol=/@ rw quiet splash audit=1 apparmor=1 security=apparmor lockdown=integrity init_on_alloc=1 init_on_free=1 slab_nomerge vsyscall=none
EOF
```

The recovery entry should remove `quiet splash` and add
`systemd.unit=rescue.target`. If a required out-of-tree module (for example an
NVIDIA DKMS module) fails under `lockdown=integrity`, add a separate
compatibility entry with `lockdown=none`; do not silently remove lockdown from
the default entry.

## 8. systemd-boot

```bash
bootctl --esp-path=/boot install
mkdir -p /boot/loader/entries

cat >/boot/loader/loader.conf <<'EOF'
default aegis-linux.conf
timeout 3
console-mode max
editor no
auto-entries no
auto-firmware yes
EOF

cat >/boot/loader/entries/aegis-linux.conf <<EOF
title   Aegis Linux
linux   /vmlinuz-linux
initrd  /initramfs-linux.img
options rd.luks.name=${LUKS_UUID}=aegis_root root=/dev/mapper/aegis_root rootflags=subvol=/@ rw quiet splash audit=1 apparmor=1 security=apparmor lockdown=integrity init_on_alloc=1 init_on_free=1 slab_nomerge vsyscall=none
EOF

cat >/boot/loader/entries/aegis-linux-fallback.conf <<EOF
title   Aegis Linux (fallback initramfs)
linux   /vmlinuz-linux
initrd  /initramfs-linux-fallback.img
options rd.luks.name=${LUKS_UUID}=aegis_root root=/dev/mapper/aegis_root rootflags=subvol=/@ rw quiet splash audit=1 apparmor=1 security=apparmor lockdown=integrity init_on_alloc=1 init_on_free=1 slab_nomerge vsyscall=none
EOF

cat >/boot/loader/entries/aegis-linux-recovery.conf <<EOF
title   Aegis Linux (recovery shell)
linux   /vmlinuz-linux
initrd  /initramfs-linux.img
options rd.luks.name=${LUKS_UUID}=aegis_root root=/dev/mapper/aegis_root rootflags=subvol=/@ rw audit=1 apparmor=1 security=apparmor init_on_alloc=1 init_on_free=1 slab_nomerge vsyscall=none systemd.unit=rescue.target
EOF

efibootmgr -c -d "${DISK}" -p 1 -L "Aegis Linux" \
  -l '\EFI\systemd\systemd-bootx64.efi'
```

The fallback EFI binary at `/boot/EFI/BOOT/BOOTX64.EFI` still boots if NVRAM is
lost. Sign it if Secure Boot is enabled.

## 9. GRUB (alternative)

```bash
pacman -S grub
grub-install --target=x86_64-efi --efi-directory=/boot \
  --bootloader-id=Aegis --recheck --no-nvram

mkdir -p /boot/grub/themes
cp -a /usr/share/aegis/bootloader/grub/aegis /boot/grub/themes/

cat >/etc/default/grub <<EOF
GRUB_DEFAULT=0
GRUB_TIMEOUT=3
GRUB_DISTRIBUTOR="Aegis Linux"
GRUB_CMDLINE_LINUX_DEFAULT="quiet splash"
GRUB_CMDLINE_LINUX="rd.luks.name=${LUKS_UUID}=aegis_root root=/dev/mapper/aegis_root rootflags=subvol=/@ rw audit=1 apparmor=1 security=apparmor lockdown=integrity init_on_alloc=1 init_on_free=1 slab_nomerge vsyscall=none"
GRUB_PRELOAD_MODULES="part_gpt luks2"
GRUB_ENABLE_CRYPTODISK=n
GRUB_THEME="/boot/grub/themes/aegis/theme.txt"
GRUB_GFXMODE=auto
GRUB_DISABLE_OS_PROBER=true
EOF

grub-mkconfig -o /boot/grub/grub.cfg
efibootmgr -c -d "${DISK}" -p 1 -L "Aegis Linux" \
  -l '\EFI\Aegis\grubx64.efi'
```

## 10. Services, snapshots, and hardening

```bash
systemctl enable NetworkManager systemd-resolved systemd-timesyncd
systemctl enable bluetooth greetd nftables auditd apparmor
systemctl enable snapper-timeline.timer snapper-cleanup.timer
systemctl enable aegis-scrub.timer fstrim.timer
systemctl disable sshd
systemctl set-default graphical.target

ln -sf /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf

snapper --no-dbus -c root create-config /
snapper -c root set-config \
  TIMELINE_CREATE=yes TIMELINE_CLEANUP=yes \
  TIMELINE_LIMIT_HOURLY=5 TIMELINE_LIMIT_DAILY=7 \
  NUMBER_CLEANUP=yes NUMBER_LIMIT=50 NUMBER_LIMIT_IMPORTANT=10

# Apply the packaged Aegis baseline (PAM faillock, sysctl, firewall include,
# SSH policy, DNS-over-TLS, journald, scrub timer, and service defaults).
/usr/share/aegis/scripts/apply-system-config
```

Configure zram:

```bash
cat >/etc/systemd/zram-generator.conf <<'EOF'
[zram0]
zram-size = min(ram / 2, 8192)
compression-algorithm = zstd
EOF
```

`aegis-config` installs the nftables, sysctl, audit, AppArmor, and SSH files.
`apply-system-config` makes the package-owned files active without overwriting
user changes it does not own.

## 11. Optional TPM2 auto-unlock

Only after the system boots normally with the passphrase:

```bash
systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs=0+7 "${ROOT}"
```

Keep the passphrase slot. A firmware update or Secure Boot change alters PCR 7
and makes TPM unlock fail; the passphrase remains the recovery path. Re-enroll
with `aegis-enroll-tpm` after such changes. Do not enroll TPM2 while Secure Boot
keys are still being changed; finish Secure Boot first, then enroll.

## 12. Optional Secure Boot

Only in firmware Setup Mode, and only with recovery media available:

```bash
pacman -S sbctl sbsigntools
sbctl create-keys
sbctl enroll-keys --microsoft
sbctl sign -s /boot/EFI/systemd/systemd-bootx64.efi
sbctl sign -s /boot/EFI/BOOT/BOOTX64.EFI
sbctl sign -s /boot/vmlinuz-linux
sbctl verify
```

For GRUB, sign `/boot/EFI/Aegis/grubx64.efi` instead of the systemd-boot
binaries. Re-sign kernels after every kernel update before rebooting if Secure
Boot is enforcing; `sbctl`'s pacman hook handles this for its managed files.

## 13. Finish

```bash
exit
umount -R /mnt
cryptsetup close aegis_root
sync
reboot
```

Remove the installation medium. The firmware should offer **Aegis Linux**. The
LUKS passphrase prompt appears before the Aegis Plymouth splash. At the greeter,
choose **Aegis Linux** and log in with the user created above.

After the first boot:

```bash
aegis-selftest
sudo systemctl status nftables auditd apparmor
hyprctl configerrors
```

The full automated installer is preferable for new installs because it performs
the target verification checks in section 6 of the plan and refuses unsafe
disks automatically.
