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 |
|
[ ] PENDING |
Package list |
|
[ ] PENDING |
Dotfiles |
Verify dotfiles repo is current |
[ ] PENDING |
SSH keys |
Copy |
[ ] PENDING |
GPG keys |
|
[ ] PENDING |
Browser bookmarks |
Export from Firefox/Chrome |
[ ] PENDING |
Game saves |
|
[ ] 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
-
Boot from USB
-
Select "Try or Install Ubuntu"
-
Installation type: Erase disk and install Ubuntu
-
Click Advanced Features
-
Select Use LVM with the new Ubuntu installation
-
Check Encrypt the new Ubuntu installation for security
-
Set strong passphrase (12+ chars, mixed case, numbers, symbols)
-
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. |
Option A: Use Ubuntu’s Hyprland 0.41.2 (Recommended)
# 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
This is documented at: wiki.hyprland.org/Getting-Started/Installation/
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:
-
Use ROOT CA only (not chain, not intermediate)
-
Set
802-1x.private-key-password-flags 4at connection creation time -
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 |
ISE 12520 "unknown CA" |
Use ROOT CA ( |
Connection hangs |
Check if MAC is on ISE rejected list: |
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
Step 4: Add Admin User (recommended)
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:
-
Boot from Arch Linux ISO
-
Mount backup drive
-
Reinstall Arch using backed-up configs
-
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 |
|
[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 |
|
[ ] IN PROGRESS - cert issued from Vault |
802.1X ISE session |
|
[ ] PENDING |
nvim-domus installed |
|
[x] PASS (gabriel user, neovim 0.12.0-dev) |
v alias works |
|
[x] PASS (in /home/gabriel/.zshrc) |
domus-gabriel alias |
|
[x] PASS (in /home/gabriel/.zshrc) |
dots-quantum stowed |
|
[x] PASS (symlink to dots-quantum) |
domus-gabriel-docs |
Antora site in |
[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 |
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 |
|
2026-03-16 |
Gabriel: aliases added |
|
2026-03-16 |
Gabriel: dots-quantum stowed |
|
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 |
|
2026-03-16 |
ISSUE: Hyprland not installed |
|
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 |
|
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 |
|
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 |
|
2026-03-16 |
Volume controls added |
pamixer, pavucontrol, playerctl + keybinds in hyprland.conf |
2026-03-16 |
casecurebrowser held |
|
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 |
|
2026-03-16 |
PENDING: Steam Flatpak test |
User to run |
Related Documentation
-
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) |