CR-2026-03-12: P50 Migration from Arch to Ubuntu

Change Summary

Field Value

Change ID

CR-2026-03-12-P50-UBUNTU

System

Lenovo ThinkPad P50 (modestus-p50)

Current State

Arch Linux (rolling release)

Target State

Ubuntu 25.10 with LUKS full disk encryption

Requestor

Evan Rosado

Scheduled

2026-03-12

Risk Level

Medium (data loss if backup fails)

Context

Personal infrastructure

Business Justification

Why Ubuntu over Arch?

Factor Arch Linux Ubuntu 25.10

Stability

Rolling release, occasional breakage

Interim release - 9 months support, newer packages

Gaming

Manual Steam/Proton setup

Steam officially supported, easier NVIDIA

Maintenance

Frequent updates, manual intervention

Automatic security updates

Learning Curve

High (user maintains everything)

Lower (good for student handoff)

Secure Browser

May have compatibility issues

Better school software support

Use Case

This P50 will be used by a student who needs:

  • School secure browser software

  • Gaming (Steam, Proton)

  • Stable, low-maintenance system

  • Full disk encryption for data protection

Pre-Change Checklist

Backup Verification

Item Command/Action Status

Home directory backup

rsync -avP /home/user/ /mnt/backup/p50-home/

[ ] PENDING

Package list

pacman -Qqe > ~/pkglist.txt

[ ] PENDING

Dotfiles

Verify dotfiles repo is current

[ ] PENDING

SSH keys

Copy ~/.ssh/ to secure location

[ ] PENDING

GPG keys

gpg --export-secret-keys > ~/gpg-backup.key

[ ] PENDING

Browser bookmarks

Export from Firefox/Chrome

[ ] PENDING

Game saves

~/.local/share/Steam/ backed up

[ ] PENDING

802.1X certificates

Backup client cert, key, CA cert (see below)

[ ] PENDING

NetworkManager 802.1X profiles

Export connection profiles (see below)

[ ] PENDING

802.1X Certificate Backup

CRITICAL: EAP-TLS certificates must be backed up OR reissued from Vault.

# List current 802.1X connections
nmcli -t -f NAME,TYPE connection show | grep -E "Domus-Wired|DomusWifi"

# Find certificate paths in connection profile
sudo cat /etc/NetworkManager/system-connections/Domus-Wired-EAP-TLS.nmconnection | grep -E "ca-cert|client-cert|private-key"

# Backup certificates (typical locations)
mkdir -p /mnt/backup/p50-$(date +%Y-%m-%d)/certs
sudo cp /etc/ssl/certs/domus-ca.crt /mnt/backup/p50-$(date +%Y-%m-%d)/certs/
sudo cp /etc/ssl/certs/p50-client.crt /mnt/backup/p50-$(date +%Y-%m-%d)/certs/
sudo cp /etc/ssl/private/p50-client.key /mnt/backup/p50-$(date +%Y-%m-%d)/certs/

# Backup NetworkManager connection profiles
sudo cp /etc/NetworkManager/system-connections/Domus-Wired*.nmconnection /mnt/backup/p50-$(date +%Y-%m-%d)/certs/
sudo cp /etc/NetworkManager/system-connections/DomusWifi*.nmconnection /mnt/backup/p50-$(date +%Y-%m-%d)/certs/

Option: Reissue from Vault (if certs expired or prefer fresh):

# On admin workstation with Vault access
vault write pki_int/issue/domus-client \
    common_name="p50.inside.domusdigitalis.dev" \
    ttl="8760h"

Hardware Verification

Item Expected Status

UEFI Mode

Enabled

[ ] VERIFY

Secure Boot

Disabled (for initial install)

[ ] VERIFY

Drive

NVMe SSD

[ ] VERIFY

RAM

16GB+ recommended

[ ] VERIFY

Implementation Plan

Phase 1: Backup (Pre-Install)

# Create backup directory on external drive
mkdir -p /mnt/backup/p50-$(date +%Y-%m-%d)

# Backup home directory
rsync -avP --progress /home/ /mnt/backup/p50-$(date +%Y-%m-%d)/home/

# Backup package list
pacman -Qqe > /mnt/backup/p50-$(date +%Y-%m-%d)/pkglist-arch.txt

# Backup /etc (configs)
sudo tar -czvf /mnt/backup/p50-$(date +%Y-%m-%d)/etc-backup.tar.gz /etc/

# Verify backup integrity
ls -la /mnt/backup/p50-$(date +%Y-%m-%d)/

Phase 2: Create Bootable USB

Reference: CR-2026-03-12: P50 Migration from Arch to Ubuntu OR include::example$codex/linux/ubuntu-install-encrypted.adoc[tag=write-usb]

Check Available Ubuntu Releases

# List available versions (typed by hand 2026-03-12)
curl -s https://releases.ubuntu.com/ | grep -oP 'href="\K[0-9]+\.[0-9]+' | sort -Vu

# With point releases
curl -s https://releases.ubuntu.com/ | grep -oP '<a href="[0-9]+\.[0-9]+[^"]*">[^<]+' | sed 's/<a href="//;s/">/ /'

Download Ubuntu ISO

# wget with -P (prefix directory) - wget determines filename
wget -P ~/Downloads https://releases.ubuntu.com/25.10/ubuntu-25.10-desktop-amd64.iso

# OR curl with -o (full path INCLUDING filename required)
curl -L -o ~/Downloads/ubuntu-25.10-desktop-amd64.iso https://releases.ubuntu.com/25.10/ubuntu-25.10-desktop-amd64.iso
Match the version in the path AND filename. 25.10/ubuntu-24.04…​ = 404 error.

Verify and Write

# Verify checksum
wget -P ~/Downloads https://releases.ubuntu.com/25.10/SHA256SUMS
cd ~/Downloads && sha256sum -c SHA256SUMS 2>&1 | grep ubuntu-25.10-desktop-amd64.iso

# Write to USB (VERIFY DEVICE!)
lsblk -d -o NAME,SIZE,MODEL
USB_DEV="/dev/sdX"  # CHANGE THIS
sudo dd if=~/Downloads/ubuntu-25.10-desktop-amd64.iso of=${USB_DEV} bs=4M status=progress conv=fsync
sync

Phase 3: Install Ubuntu with LUKS

  1. Boot from USB

  2. Select "Try or Install Ubuntu"

  3. Installation type: Erase disk and install Ubuntu

  4. Click Advanced Features

  5. Select Use LVM with the new Ubuntu installation

  6. Check Encrypt the new Ubuntu installation for security

  7. Set strong passphrase (12+ chars, mixed case, numbers, symbols)

  8. WRITE DOWN PASSPHRASE - cannot recover if lost

Phase 4: Post-Install Configuration

# Update system
sudo apt update && sudo apt upgrade -y

# Install essential packages
sudo apt install -y \
    build-essential \
    git \
    curl \
    wget \
    vim \
    htop \
    neofetch \
    timeshift

# Enable 32-bit architecture (for gaming)
sudo dpkg --add-architecture i386
sudo apt update

# Install NVIDIA drivers
sudo ubuntu-drivers autoinstall

# Install Steam
sudo apt install steam

# Install Lutris (non-Steam games)
sudo apt install lutris

Phase 4a: Replace Firefox Snap with Deb (Required for Wayland)

Ubuntu’s default Firefox is a snap package that does NOT work properly with Hyprland/Wayland. It will fail to launch from wofi with no error message.
# Remove snap Firefox (both the wrapper and the snap itself)
sudo apt remove firefox
sudo snap remove firefox

# Add Mozilla Team PPA
sudo add-apt-repository ppa:mozillateam/ppa
sudo apt update

# Install deb version from Mozilla PPA
sudo apt install -t 'o=LP-PPA-mozillateam' firefox

# Verify it's the deb version (should show ~mt1 suffix)
apt policy firefox
# Expected: 148.x.x+build1-0ubuntu0.25.10.1~mt1 from mozillateam PPA

Phase 4b: Hyprland Tiling Window Manager

Per user request - replicate Arch Hyprland experience on Ubuntu.

Ubuntu 25.10 repos have Hyprland 0.41.2. Arch has 0.54.2. The Hyprland PPA does not exist. Building from source requires many dependencies (aquamarine, glslang, etc.) and is complex.
# Install Hyprland and ecosystem
sudo apt install -y hyprland kitty waybar mako-notifier wofi \
    swaybg swaylock wl-clipboard grim slurp

The dots-quantum config uses 0.54 features (glob, etc.). Create a compatible config:

# Backup dots-quantum config
mv ~/.config/hypr/hyprland.conf ~/.config/hypr/hyprland.conf.054

# Create 0.41-compatible minimal config
cat > ~/.config/hypr/hyprland.conf << 'EOF'
monitor=,preferred,auto,1

exec-once = waybar
exec-once = mako

input {
    kb_layout = us
    follow_mouse = 1
}

general {
    gaps_in = 5
    gaps_out = 10
    border_size = 2
}

decoration {
    rounding = 10
}

$mod = SUPER
bind = $mod, Return, exec, kitty
bind = $mod, D, exec, wofi --show drun
bind = $mod, Q, killactive
bind = $mod, M, exit
bind = $mod, V, togglefloating
bind = $mod, F, fullscreen
bind = $mod, h, movefocus, l
bind = $mod, l, movefocus, r
bind = $mod, k, movefocus, u
bind = $mod, j, movefocus, d
bind = $mod, 1, workspace, 1
bind = $mod, 2, workspace, 2
bind = $mod, 3, workspace, 3
bind = $mod, 4, workspace, 4
bind = $mod, 5, workspace, 5
bind = $mod SHIFT, 1, movetoworkspace, 1
bind = $mod SHIFT, 2, movetoworkspace, 2
bind = $mod SHIFT, 3, movetoworkspace, 3
bind = $mod SHIFT, 4, movetoworkspace, 4
bind = $mod SHIFT, 5, movetoworkspace, 5
EOF

Install Nerd Fonts (for waybar icons)

Ubuntu repos don’t have Nerd Fonts. Install manually:

# Install font-awesome (available in repos)
sudo apt install -y fonts-font-awesome

# Install Hack Nerd Font manually
mkdir -p ~/.local/share/fonts
cd ~/.local/share/fonts
curl -fLO https://github.com/ryanoasis/nerd-fonts/releases/download/v3.3.0/Hack.zip
unzip Hack.zip
rm Hack.zip
fc-cache -fv

Volume Controls

# Install volume tools (hold casecurebrowser first if installed)
echo "casecurebrowser hold" | sudo dpkg --set-selections
sudo apt install -y pavucontrol pamixer playerctl

# Add keybinds to hyprland.conf
cat >> ~/.config/hypr/hyprland.conf << 'EOF'

# Volume controls
bind = , XF86AudioRaiseVolume, exec, pamixer -i 5
bind = , XF86AudioLowerVolume, exec, pamixer -d 5
bind = , XF86AudioMute, exec, pamixer -t

# Pavucontrol (Super+A)
bind = $mod, A, exec, pavucontrol
EOF

# Reload
hyprctl reload

Option B: Build from Source (Complex - Future)

Building Hyprland 0.54 from source requires building multiple dependencies first: - aquamarine, hyprutils, hyprlang, hyprcursor, hyprgraphics

If PPA unavailable for 25.10, build from source:

# Install build dependencies
sudo apt install -y \
    meson ninja-build cmake-extras cmake gettext gettext-base fontconfig \
    libfontconfig-dev libffi-dev libxml2-dev libdrm-dev libxkbcommon-x11-dev \
    libxkbregistry-dev libxkbcommon-dev libpixman-1-dev libudev-dev libseat-dev \
    seatd libxcb-dri3-dev libvulkan-dev libvulkan-vk-layer-mesa-overlay-dev \
    libvkfft-dev libgulkan-dev libegl-dev libgles2 libegl1-mesa-dev glslang-tools \
    libinput-bin libinput-dev libxcb-composite0-dev libavutil-dev libavcodec-dev \
    libavformat-dev libxcb-ewmh2 libxcb-ewmh-dev libxcb-present-dev libxcb-icccm4-dev \
    libxcb-render-util0-dev libxcb-res0-dev libxcb-xinput-dev libtomlplusplus3

# Clone and build (~10 min)
git clone --recursive https://github.com/hyprwm/Hyprland
cd Hyprland
make all
sudo make install
Existing ~/.config/hypr/hyprland.conf from Arch will work. Restore from backup.

Phase 5: Data Restoration

# Restore dotfiles
git clone <dotfiles-repo> ~/dotfiles
cd ~/dotfiles && stow <packages>

# Restore SSH keys
cp /mnt/backup/p50-*/home/.ssh ~/.
chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_*

# Restore GPG keys
gpg --import /mnt/backup/p50-*/gpg-backup.key

# Restore game saves (if applicable)
cp -r /mnt/backup/p50-*/home/.local/share/Steam ~/.local/share/

Phase 5b: 802.1X Certificate Issuance (Fresh Install)

Certificates were not backed up - reissue from Vault.

Step 1: Issue Certificate from Vault (on modestus-razer)

# Load Vault credentials
dsource d000 lab/vault

# Issue new client certificate
vault write pki_int/issue/domus-client \
    common_name="p50.inside.domusdigitalis.dev" \
    ttl="8760h" \
    -format=json > /tmp/p50-cert.json

# Extract cert, key, CA chain
jq -r '.data.certificate' /tmp/p50-cert.json > /tmp/p50-client.crt
jq -r '.data.private_key' /tmp/p50-cert.json > /tmp/p50-client.key
jq -r '.data.issuing_ca' /tmp/p50-cert.json > /tmp/domus-ca.crt

# Verify certificate
openssl x509 -in /tmp/p50-client.crt -noout -subject -dates

Step 2: Transfer Certificates to P50

# From modestus-razer (adjust IP/hostname as needed)
scp /tmp/p50-client.crt /tmp/p50-client.key /tmp/domus-ca.crt user@p50:/tmp/

# Clean up local copies
rm /tmp/p50-cert.json /tmp/p50-client.* /tmp/domus-ca.crt

Step 3: Install Certificates on P50

# On P50 - install to standard locations
sudo cp /tmp/domus-ca.crt /etc/ssl/certs/
sudo cp /tmp/p50-client.crt /etc/ssl/certs/
sudo cp /tmp/p50-client.key /etc/ssl/private/

# Set correct permissions
sudo chmod 644 /etc/ssl/certs/domus-ca.crt
sudo chmod 644 /etc/ssl/certs/p50-client.crt
sudo chmod 600 /etc/ssl/private/p50-client.key
sudo chown root:root /etc/ssl/private/p50-client.key

# Verify installation
ls -la /etc/ssl/certs/domus-ca.crt /etc/ssl/certs/p50-client.crt
ls -la /etc/ssl/private/p50-client.key

# Clean up /tmp
rm /tmp/p50-client.* /tmp/domus-ca.crt

Step 4: Create 802.1X Wired Connection

# Find ethernet interface name
ip link show | grep -E "^[0-9]+: e"

# Create EAP-TLS wired connection (adjust interface name)
sudo nmcli connection add \
    con-name "Domus-Wired-EAP-TLS" \
    type ethernet \
    ifname enp0s31f6 \
    802-1x.eap tls \
    802-1x.identity "p50.inside.domusdigitalis.dev" \
    802-1x.ca-cert /etc/ssl/certs/domus-ca.crt \
    802-1x.client-cert /etc/ssl/certs/p50-client.crt \
    802-1x.private-key /etc/ssl/private/p50-client.key \
    802-1x.private-key-password ""

# Bring up the connection
nmcli connection up "Domus-Wired-EAP-TLS"

Step 5: Create 802.1X WiFi Connection (Optional)

# Create EAP-TLS WiFi connection
# SSID must be "Domus-Secure" (802.1X enabled), NOT "Domus-IoT" (MAB)
sudo nmcli connection add \
    con-name "Domus-WiFi-EAP-TLS" \
    type wifi \
    ssid "Domus-Secure" \
    wifi-sec.key-mgmt wpa-eap \
    802-1x.eap tls \
    802-1x.identity "p50.inside.domusdigitalis.dev" \
    802-1x.ca-cert /etc/ssl/certs/domus-ca.crt \
    802-1x.client-cert /etc/ssl/certs/p50-client.crt \
    802-1x.private-key /etc/ssl/private/p50-client.key

# Connect to WiFi
nmcli connection up "Domus-WiFi-EAP-TLS"

Step 5b: Working 802.1X WiFi EAP-TLS Setup (MODEL)

This is the verified working process. Use as model for other Ubuntu/Linux EAP-TLS deployments.

Key requirements:

  1. Use ROOT CA only (not chain, not intermediate)

  2. Set 802-1x.private-key-password-flags 4 at connection creation time

  3. Certificate files must exist before creating connection

On admin workstation - get ROOT CA from Vault:

dsource d000 dev/vault
vault read -field=certificate pki/cert/ca > /tmp/domus-root-ca.crt

Transfer ROOT CA and client certs to target machine:

# Transfer ROOT CA
scp -i ~/.ssh/id_ed25519_d000 /tmp/domus-root-ca.crt gabriel@10.50.40.106:/tmp/

# Client cert/key should already be on target from Step 1

On target machine - install ROOT CA:

sudo cp /tmp/domus-root-ca.crt /etc/ssl/certs/DOMUS-ROOT-CA.pem

Create connection with correct flags:

# Delete any existing broken connection
sudo nmcli con delete "Domus-WiFi-EAP-TLS" 2>/dev/null

# Create with ALL flags set at creation time
sudo nmcli connection add \
    con-name "Domus-WiFi-EAP-TLS" \
    type wifi \
    ssid "Domus-Secure" \
    wifi-sec.key-mgmt wpa-eap \
    802-1x.eap tls \
    802-1x.identity "p50.inside.domusdigitalis.dev" \
    802-1x.ca-cert /etc/ssl/certs/DOMUS-ROOT-CA.pem \
    802-1x.client-cert /etc/ssl/certs/p50-client.crt \
    802-1x.private-key /etc/ssl/private/p50-client.key \
    802-1x.private-key-password-flags 4

# Connect
sudo nmcli con up "Domus-WiFi-EAP-TLS"

Common errors and fixes:

Error Fix

"Secrets were required, but not provided"

Must set 802-1x.private-key-password-flags 4 at creation, not after

ISE 12520 "unknown CA"

Use ROOT CA (DOMUS-ROOT-CA.pem), not intermediate or chain

Connection hangs

Check if MAC is on ISE rejected list: netapi ise get-rejected-endpoints

Step 5c: Fix WiFi SSID (if wrong SSID was used)

If WiFi connection was created with wrong SSID (e.g., DomusWifi instead of Domus-Secure):

# List current WiFi connections - regex: case-insensitive match on 'wifi' OR 'eap'
nmcli -t con show | grep -iE 'wifi|eap'
# Delete the wrong connection (if exists)
nmcli con delete "DomusWifi-EAP-TLS" 2>/dev/null || echo "Not found"
# Create correct WiFi 802.1X connection with proper SSID
sudo nmcli connection add \
    con-name "Domus-WiFi-EAP-TLS" \
    type wifi \
    ssid "Domus-Secure" \
    wifi-sec.key-mgmt wpa-eap \
    802-1x.eap tls \
    802-1x.identity "p50.inside.domusdigitalis.dev" \
    802-1x.ca-cert /etc/ssl/certs/domus-ca.crt \
    802-1x.client-cert /etc/ssl/certs/p50-client.crt \
    802-1x.private-key /etc/ssl/private/p50-client.key
# Disconnect from IoT and connect to 802.1X
nmcli con down "Domus-IoT" 2>/dev/null
nmcli con up "Domus-WiFi-EAP-TLS"
# Verify - regex: extract IP from connection that matches 'WiFi.*EAP'
nmcli -t con show --active | grep -E 'WiFi.*EAP' && ip -4 -o addr show wlp4s0 | awk '{print $4}'

Phase 5c: SSH Key and Vault Certificate Setup (MODEL)

After 802.1X is working, configure SSH with multiple auth methods.

Step 1: Initial SSH Access (bootstrap)

# First connection requires explicit key
ssh -i ~/.ssh/id_ed25519_d000 -o IdentitiesOnly=yes gabriel@10.50.10.107

Step 2: Add All SSH Public Keys

# From admin workstation - copy all public keys at once
cat ~/.ssh/id_ed25519_vault.pub ~/.ssh/id_ed25519_sk_rk_d000*.pub | \
    ssh -i ~/.ssh/id_ed25519_d000 -o IdentitiesOnly=yes gabriel@10.50.10.107 \
    "cat >> ~/.ssh/authorized_keys"

# Verify count
ssh -i ~/.ssh/id_ed25519_d000 -o IdentitiesOnly=yes gabriel@10.50.10.107 \
    "wc -l ~/.ssh/authorized_keys"

Step 3: Configure Vault SSH CA Trust

# Get Vault SSH CA public key
dsource d000 dev/vault
vault read -field=public_key ssh/config/ca > /tmp/vault-ssh-ca.pub

# Transfer to target
scp -i ~/.ssh/id_ed25519_d000 -o IdentitiesOnly=yes \
    /tmp/vault-ssh-ca.pub gabriel@10.50.10.107:/tmp/

On target machine:

sudo cp /tmp/vault-ssh-ca.pub /etc/ssh/vault-ssh-ca.pub
echo "TrustedUserCAKeys /etc/ssh/vault-ssh-ca.pub" | sudo tee -a /etc/ssh/sshd_config
sudo systemctl restart sshd

Add your standard admin user for consistent SSH config across infrastructure:

# On target machine
sudo adduser evanusmodestus
sudo usermod -aG sudo evanusmodestus

# Copy SSH authorized_keys
sudo mkdir -p /home/evanusmodestus/.ssh
sudo cp /home/gabriel/.ssh/authorized_keys /home/evanusmodestus/.ssh/
sudo chown -R evanusmodestus:evanusmodestus /home/evanusmodestus/.ssh
sudo chmod 700 /home/evanusmodestus/.ssh
sudo chmod 600 /home/evanusmodestus/.ssh/authorized_keys

Step 5: Update SSH Config

# In ~/.ssh/config - add IdentitiesOnly to prevent "too many auth failures"
Host modestus-p50 gabriel-workstation
    HostName 10.50.10.107
    User evanusmodestus
    IdentitiesOnly yes

Now standard SSH works:

ssh modestus-p50

Step 6: Verify 802.1X Authentication

# Check connection status
nmcli connection show --active

# Check authentication in journal
journalctl -u NetworkManager --since "5 minutes ago" | grep -i eap

# Verify on ISE (from modestus-razer)
netapi ise -f json mnt sessions | jq -r '.[] | select(.user_name | test("p50"; "i"))'

Phase 6: Gabriel’s Development Environment (MODEL)

Configure development environment for schoolwork and productivity.

Step 1: Install Essential Development Tools

# Install neovim and dependencies
sudo apt install -y neovim ripgrep fd-find fzf bat stow zsh git curl

# Install additional tools
sudo apt install -y \
    nodejs npm \
    python3 python3-pip python3-venv \
    tree jq htop tmux unzip

Step 1b: Upgrade Neovim to 0.11+ (Required for domus-nvim)

Ubuntu 25.10 ships neovim 0.10.x. domus-nvim requires 0.11+ for mason-lspconfig.

# Add unstable PPA for latest neovim
sudo add-apt-repository ppa:neovim-ppa/unstable
sudo apt update
sudo apt install neovim

# Verify version
nvim --version | head -1
# Expected: NVIM v0.11.x or higher

Step 1c: Install oh-my-posh

# Install oh-my-posh
curl -s https://ohmyposh.dev/install.sh | bash -s

# Add PATH and init to .zshrc (oh-my-posh installs to ~/.local/bin)
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.zshrc
echo 'eval "$(oh-my-posh init zsh --config ~/.config/omp-theme.toml)"' >> ~/.zshrc

# Copy theme from admin workstation (run on admin machine)
# scp ~/.config/omp-theme.toml gabriel@modestus-p50:~/.config/

# Reload shell
source ~/.zshrc

Step 2: Set Up nvim-domus Configuration

# Clone the domus-nvim config (custom neovim setup)
git clone https://github.com/EvanusModestus/domus-nvim ~/.config/nvim-domus

# Create v alias in .zshrc
echo 'alias v="NVIM_APPNAME=nvim-domus nvim"' >> ~/.zshrc

# Reload shell
source ~/.zshrc

# Test - should launch nvim with domus config
v --version
NVIM_APPNAME=nvim-domus tells neovim to use ~/.config/nvim-domus/ instead of ~/.config/nvim/. This allows multiple neovim configs side-by-side.

Step 3: Set Up domus-gabriel-docs

Transfer from admin workstation (has full Antora site):

# From admin machine - rsync the docs site
rsync -avP ~/atelier/_bibliotheca/domus-gabriel-docs/ gabriel@modestus-p50:~/atelier/_bibliotheca/domus-gabriel-docs/

On P50:

# Install npm dependencies
cd ~/atelier/_bibliotheca/domus-gabriel-docs
npm install

# Add convenience alias to .zshrc
echo 'alias domus-gabriel="cd ~/atelier/_bibliotheca/domus-gabriel-docs"' >> ~/.zshrc
echo 'alias gabriel-build="cd ~/atelier/_bibliotheca/domus-gabriel-docs && npx antora antora-playbook.yml"' >> ~/.zshrc

# Reload
source ~/.zshrc

# Test build
gabriel-build

Step 4: Clone and Stow dots-quantum (Dotfiles)

This is the stow-based dotfiles system.

# Clone dots-quantum (as gabriel)
sudo -u gabriel git clone https://github.com/EvanusModestus/dots-quantum /home/gabriel/dots-quantum

Structure:

dots-quantum/
├── dots/
│   └── .config/
│       ├── hypr/      # Hyprland config
│       ├── waybar/    # Status bar
│       ├── kitty/     # Terminal
│       ├── wofi/      # App launcher
│       └── mako/      # Notifications
└── setup/             # Setup scripts
# Stow the dots package (creates symlinks to ~/.config/*)
sudo -u gabriel bash -c 'cd /home/gabriel/dots-quantum && stow -t ~ dots'

# Verify symlinks
sudo -u gabriel ls -la /home/gabriel/.config/hypr
# Expected: lrwxrwxrwx ... /home/gabriel/.config/hypr -> ../dots-quantum/dots/.config/hypr

Step 5: Install School and Productivity Apps

# Office suite
sudo apt install -y libreoffice

# PDF viewer
sudo apt install -y zathura zathura-pdf-poppler

# Image viewer
sudo apt install -y imv feh

# Screenshot tools (Hyprland)
sudo apt install -y grim slurp swappy

# File manager
sudo apt install -y thunar

# Browser (if not installed)
sudo apt install -y firefox

# Media player
sudo apt install -y mpv

Step 6: Install Secure Browser (for school testing)

For CA Secure Browser (CAASPP testing):

# Download CASecureBrowser from school or:
# https://www.caaspp.org/administration/secure-browsers/

# Install dependencies (Ubuntu 25.10 compatibility)
sudo apt install -y dbus-x11 sox libdbus-glib-1-2 libgdk-pixbuf-xlib-2.0-0

# Create symlink for old library name
sudo ln -s /usr/lib/x86_64-linux-gnu/libgdk_pixbuf-2.0.so.0 /usr/lib/x86_64-linux-gnu/libgdk-pixbuf-2.0.so.0

# Force install (bypasses missing libgdk-pixbuf2.0-0 package check)
sudo dpkg --force-depends -i ~/Downloads/CASecureBrowser*.deb

# Add alias (binary not in PATH by default)
echo 'alias casecurebrowser="/usr/lib/CASecureBrowser/CASecureBrowser"' >> ~/.zshrc
source ~/.zshrc

# Test
casecurebrowser

For other secure browsers (LockDown Browser, Safe Exam Browser), check school requirements.

Step 7: Verify Environment

# Test nvim-domus
v ~/.bashrc

# Test aliases
type v
type domus-gabriel

# Test Hyprland (from TTY, not terminal)
# Press Ctrl+Alt+F2, login, then:
# Hyprland

# Verify stow symlinks
ls -la ~/.config/hypr
ls -la ~/.config/waybar

Step 8: Reload Hyprland (if running)

# Reload config without restarting
hyprctl reload

# Check for errors
hyprctl clients

Phase 7: Verification

#!/bin/bash
echo "=== P50 Ubuntu Installation Verification ==="

echo -e "\n=== Encryption ==="
lsblk -f | grep -q crypt && echo "PASS: LUKS active" || echo "FAIL: No encryption"

echo -e "\n=== LVM ==="
sudo lvs --noheadings | wc -l | xargs -I{} echo "LVM volumes: {}"

echo -e "\n=== Graphics ==="
glxinfo | grep "OpenGL renderer"

echo -e "\n=== Vulkan ==="
vulkaninfo --summary 2>/dev/null | grep "GPU" || echo "Vulkan not configured"

echo -e "\n=== Steam ==="
which steam && echo "PASS: Steam installed" || echo "INFO: Steam not installed"

echo -e "\n=== System ==="
neofetch --stdout | head -15

Rollback Plan

If installation fails or system is unusable:

  1. Boot from Arch Linux ISO

  2. Mount backup drive

  3. Reinstall Arch using backed-up configs

  4. Restore from /mnt/backup/p50-*/

Risk Assessment

Risk Impact Mitigation Probability

Data loss

High - lose personal files

Full backup before install

Low (with backup)

Hardware incompatibility

Medium - drivers don’t work

Ubuntu has good ThinkPad support

Low

LUKS passphrase forgotten

Critical - unrecoverable

Write down and store securely

Low

Gaming performance

Low - games run slower

NVIDIA drivers, Proton tested

Low

Post-Change Verification

Check Expected Result Status

Boot with LUKS prompt

Passphrase accepted, system boots

[x] PASS

Desktop loads

Ubuntu desktop functional

[x] PASS

WiFi works

Can connect to network

[x] PASS - Domus-IoT, IP 10.50.40.106

SSH access

Remote administration working

[x] PASS - openssh-server installed, key added

Steam runs

Steam client launches

[ ] PENDING

Test game runs

Proton game playable

[ ] PENDING

Secure browser works

CA Secure Browser launches

[x] PASS (dpkg --force-depends + alias)

Hyprland launches

Hyprland from TTY starts compositor

[x] PASS (0.41.2 with minimal config)

Hyprland config works

Keybinds, waybar, wofi functional

[x] PASS (Super+Return, Super+D, etc.)

802.1X wired auth

nmcli con up Domus-Wired-EAP-TLS succeeds

[ ] IN PROGRESS - cert issued from Vault

802.1X ISE session

netapi ise mnt sessions | grep p50 shows active

[ ] PENDING

nvim-domus installed

v --version launches neovim

[x] PASS (gabriel user, neovim 0.12.0-dev)

v alias works

type v shows alias

[x] PASS (in /home/gabriel/.zshrc)

domus-gabriel alias

domus-gabriel && pwd shows correct path

[x] PASS (in /home/gabriel/.zshrc)

dots-quantum stowed

ls -la ~/.config/hypr shows symlink

[x] PASS (symlink to dots-quantum)

domus-gabriel-docs

Antora site in ~/atelier/_bibliotheca/

[x] PASS (transferred from backup)

School apps installed

LibreOffice, browser available

[ ] IN PROGRESS

Implementation Log

Date Action Notes

2026-03-16

Ubuntu 25.10 installed

LUKS encryption, user gabriel

2026-03-16

WiFi connected

Domus-IoT (MAB), VLAN 40, IP 10.50.40.106

2026-03-16

SSH configured

openssh-server installed, ed25519_d000 key added

2026-03-16

802.1X cert issued

Vault PKI: p50.inside.domusdigitalis.dev, 1yr TTL

2026-03-16

Certs transferred to P50

scp to /tmp/ via ed25519_d000 key

2026-03-16

Certs installed on P50

/etc/ssl/certs/, /etc/ssl/private/

2026-03-16

Wired 802.1X created

Domus-Wired-EAP-TLS on enp0s31f6

2026-03-16

WiFi 802.1X SSID fix

Wrong: DomusWifi → Correct: Domus-Secure

2026-03-16

WiFi EAP-TLS failing

ISE error 12520: client rejected ISE cert - "unknown CA"

2026-03-16

Root cause identified

P50 has intermediate CA only, needs ROOT CA

2026-03-16

WiFi 802.1X working

ROOT CA + private-key-password-flags 4 at creation time

2026-03-16

P50 on VLAN 10 (Data)

IP: 10.50.10.107, SSH accessible

2026-03-16

Phase 6 documented

Gabriel’s dev environment: nvim-domus, dots-quantum, school apps

2026-03-16

domus-nvim public

Renamed domus-instrumentum → domus-nvim, made public

2026-03-16

Gabriel: domus-nvim cloned

/home/gabriel/.config/nvim-domus

2026-03-16

Gabriel: aliases added

v and domus-gabriel in /home/gabriel/.zshrc

2026-03-16

Gabriel: dots-quantum stowed

stow -t ~ dots from /home/gabriel/dots-quantum

2026-03-16

Gabriel: domus-gabriel-docs transferred

Full Antora site with school math, links, journal, vim-adventures

2026-03-16

Gabriel: README.adoc added

Standalone build instructions (no domus-docs dependency)

2026-03-16

Gabriel: rsync updates

rsync -avP to sync README and any future changes

2026-03-16

ISSUE: Hyprland not installed

start-hyprland command not found - needs Phase 4b

2026-03-16

ISSUE: oh-my-posh missing

Gabriel needs shell prompt configuration

2026-03-16

oh-my-posh installed

Added PATH to .zshrc, copied omp-theme.toml

2026-03-16

Hyprland version mismatch

Ubuntu 25.10 has 0.41.2, Arch has 0.54.2 - PPA unavailable

2026-03-16

Hyprland build from source failed

Missing aquamarine, glslang deps - too complex

2026-03-16

Hyprland deps installed

sudo apt install kitty waybar mako-notifier wofi

2026-03-16

Hyprland minimal config

Created 0.41-compatible config (dots-quantum backup as .054)

2026-03-16

Nerd Fonts installed

Manual install Hack.zip to ~/.local/share/fonts, fc-cache -fv

2026-03-16

Hyprland working

Waybar icons visible, keybinds functional

2026-03-16

Firefox snap broken on Wayland

Would not launch from wofi, no error displayed

2026-03-16

Firefox replaced with deb

sudo apt remove firefox && sudo snap remove firefox then install from Mozilla PPA

2026-03-16

domus-gabriel-docs fixed

Makefile and antora-playbook.yml made standalone (no domus-docs/Kroki dependency)

2026-03-16

CA Secure Browser installed

dpkg --force-depends, add alias to .zshrc for /usr/lib/CASecureBrowser/CASecureBrowser

2026-03-16

Volume controls added

pamixer, pavucontrol, playerctl + keybinds in hyprland.conf

2026-03-16

casecurebrowser held

dpkg --set-selections to stop apt complaining about broken dep

2026-03-16

ISSUE: Steam installation failed

Ubuntu 25.10 i386 library conflicts, dpkg --force-depends cascade

2026-03-16

Steam i386 deps attempted

libc6:i386, libgcc-s1:i386, libgl1:i386, libdrm2:i386, libglvnd0:i386, libglx0:i386

2026-03-16

ISSUE: libglx-mesa0 version mismatch

i386 (25.2.8) vs amd64 (25.2.3) cannot coexist

2026-03-16

ISSUE: Cascading xcb/mesa/glibc deps

Each i386 lib needs 10+ more i386 libs

2026-03-16

Steam via Flatpak installed

flatpak install flathub com.valvesoftware.Steam - sandboxed, no system lib conflicts

2026-03-16

PENDING: Steam Flatpak test

User to run flatpak run com.valvesoftware.Steam and verify login

  • Case Studies Index

  • examples/codex/linux/ubuntu-install-encrypted.adoc - Full installation guide

Lessons Learned

To be completed after migration

Sign-Off

Role Name Date

Requestor

Evan Rosado

2026-03-12

Approver

Self-approved (personal)

2026-03-12

Implementer

Evan Rosado

2026-03-16 (in progress)