many fixes and additions but somethings still broken

This commit is contained in:
Dominik Moritz Roth 2025-05-19 01:24:01 +02:00
parent 31f1543fe5
commit 8a39511aea
2 changed files with 273 additions and 583 deletions

View File

@ -74,6 +74,7 @@ After firmware updates (UEFI/BIOS), the TPM bindings need to be updated:
chmod +x install.sh
./install.sh
```
- If the script tells you that no TPM is avaible you probably have to make a support ticket to get a KVM attached and toggle TPM yourself in the BIOS.
- Wait for installation to complete
- Reboot the server

View File

@ -41,13 +41,18 @@ SSH_KEY="ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOkoTn2NreAXMriOUqzyj3YoFW6jMo9B5B+
########################################################
set -euo pipefail
echo -e "\nStarting installation...\n"
alias c="clear"
alias cls="clear"
clear
echo -e "\n$BANNER"
echo -e "\n[+] Starting installation..."
# Check for TPM
echo "Checking for TPM..."
echo "[+] Checking for TPM..."
if [ ! -d "/sys/class/tpm/tpm0" ]; then
echo "WARNING: No TPM detected!"
echo "This system will not be able to use TPM-based boot verification."
echo "You might need to enable TPM in the BIOS. (On Hetzner make a support ticket for KVM access)"
read -p "Continue without TPM? [y/N] " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
@ -72,63 +77,133 @@ if [ -z "${SSH_KEY:-}" ]; then
fi
# Generate secure LUKS passphrase
echo "Generating secure LUKS passphrase..."
LUKS_PASSPHRASE=$(openssl rand -base64 32)
USER_PASSWORD=$(openssl rand -base64 12) # Shorter for easier typing
echo "Generated LUKS passphrase: ${LUKS_PASSPHRASE}"
echo "Generated user password: ${USER_PASSWORD}"
echo "[+] Generating secure LUKS passphrase..."
LUKS_PASSPHRASE=$(openssl rand -base64 30)
echo "----------------------------------------"
echo "Generated LUKS passphrase:"
echo "${LUKS_PASSPHRASE}"
echo "----------------------------------------"
echo "Please save these credentials securely. You will need them for recovery."
echo "Press Enter to continue..."
read
# Install required packages in Rescue System (Debian)
echo "Installing required packages..."
apt-get update
apt-get install -y cryptsetup btrfs-progs mdadm
### End of user interaction
# Clear boot sectors and partition tables
echo "Clearing boot sectors and partition tables..."
# Clear MBR/GPT and first few sectors
dd if=/dev/zero of=/dev/sda bs=512 count=2048
dd if=/dev/zero of=/dev/sdb bs=512 count=2048
# Clear end of disk (where backup GPT might be)
dd if=/dev/zero of=/dev/sda bs=512 seek=$(($(blockdev --getsz /dev/sda) - 2048)) count=2048
dd if=/dev/zero of=/dev/sdb bs=512 seek=$(($(blockdev --getsz /dev/sdb) - 2048)) count=2048
sync
# Install required package
apt-get update
DEBIAN_FRONTEND=noninteractive apt-get install -y genisoimage grub-efi-amd64-bin util-linux
# Detect disk naming scheme and set variables
echo "[+] Detecting disk configuration..."
DISKS=($(lsblk -d -n -o NAME | grep -E '^(sd[a-z]|nvme[0-9]+n[0-9]+)$' | sort))
if [ ${#DISKS[@]} -ne 2 ]; then
echo "Error: Expected exactly 2 disks, found ${#DISKS[@]}"
exit 1
fi
# Set disk variables
DISK1="/dev/${DISKS[0]}"
DISK2="/dev/${DISKS[1]}"
# Stop any existing RAID arrays
echo "[+] Stopping any existing RAID arrays..."
mdadm --stop /dev/md0 2>/dev/null || true
# Unmount any existing partitions
echo "[+] Unmounting partitions..."
for disk in $DISK1 $DISK2; do
umount -f $disk* 2>/dev/null || true
done
# Stop any device mapper devices
echo "[+] Stopping device mapper devices..."
dmsetup remove_all 2>/dev/null || true
# Disconnect NVMe devices if present
if [[ "$DISK1" =~ nvme ]] || [[ "$DISK2" =~ nvme ]]; then
echo "Disconnecting NVMe devices..."
nvme disconnect-all
sleep 2
fi
# Zero out partition tables
echo "[+] Zeroing out partition tables..."
for disk in $DISK1 $DISK2; do
# Use blkdiscard for NVMe drives, dd for others
if [[ "$disk" =~ nvme ]]; then
blkdiscard -f $disk
else
# Zero first 2MB and last 2MB of disk
dd if=/dev/zero of=$disk bs=1M count=2 conv=fsync
dd if=/dev/zero of=$disk bs=1M seek=$(($(blockdev --getsz $disk) / 2048 - 2)) count=2 conv=fsync
fi
sync
done
# Create partitions
echo "Creating partitions..."
# First disk
parted /dev/sda mklabel gpt
parted /dev/sda mkpart primary 1MiB 1000MiB
parted /dev/sda mkpart primary 1000MiB 100%
echo "[+] Creating partitions..."
for disk in $DISK1 $DISK2; do
# Create new GPT partition table
parted -s $disk mklabel gpt
# Create EFI partition (512MB)
parted -s $disk mkpart primary fat32 0% 512MB
# Create boot partition (1GB)
parted -s $disk mkpart primary ext4 512MB 1.5GB
# Create root partition (rest of disk)
parted -s $disk mkpart primary ext4 1.5GB 100%
# Set boot flag on first partition
parted -s $disk set 1 boot on
sync
done
# Second disk
parted /dev/sdb mklabel gpt
parted /dev/sdb mkpart primary 1MiB 1000MiB
parted /dev/sdb mkpart primary 1000MiB 100%
# For NVMe disks, we need to append 'p' to partition numbers
if [[ "$DISK1" =~ nvme ]]; then
PART1="${DISK1}p1"
PART2="${DISK1}p2"
PART3="${DISK1}p3"
PART4="${DISK2}p1"
PART5="${DISK2}p2"
PART6="${DISK2}p3"
else
PART1="${DISK1}1"
PART2="${DISK1}2"
PART3="${DISK1}3"
PART4="${DISK2}1"
PART5="${DISK2}2"
PART6="${DISK2}3"
fi
echo "Detected disks:"
echo "Disk 1: $DISK1 (will make partitions: $PART1, $PART2, $PART3)"
echo "Disk 2: $DISK2 (will make partitions: $PART4, $PART5, $PART6)"
# Create EFI partitions
echo "[+] Creating EFI partitions..."
mkfs.vfat -F 32 $PART1
mkfs.vfat -F 32 $PART4
# Create boot RAID1
echo "Creating boot RAID1 array..."
mdadm --create /dev/md0 --level=1 --raid-devices=2 /dev/sda1 /dev/sdb1
echo "[+] Creating boot RAID1 array..."
mdadm --create /dev/md0 --level=1 --raid-devices=2 --metadata=0.90 --force --run $PART2 $PART5
mkfs.ext4 /dev/md0
# Create LUKS volumes
echo "Setting up LUKS encryption..."
echo "${LUKS_PASSPHRASE}" | cryptsetup luksFormat /dev/sda2 --type luks2
echo "${LUKS_PASSPHRASE}" | cryptsetup luksFormat /dev/sdb2 --type luks2
echo "[+] Setting up LUKS encryption..."
echo "${LUKS_PASSPHRASE}" | cryptsetup luksFormat $PART3 --type luks2
echo "${LUKS_PASSPHRASE}" | cryptsetup luksFormat $PART6 --type luks2
# Open LUKS volumes
echo "Opening LUKS volumes..."
echo "${LUKS_PASSPHRASE}" | cryptsetup luksOpen /dev/sda2 root_a
echo "${LUKS_PASSPHRASE}" | cryptsetup luksOpen /dev/sdb2 root_b
echo "[+] Opening LUKS volumes..."
echo "${LUKS_PASSPHRASE}" | cryptsetup luksOpen $PART3 root_a
echo "${LUKS_PASSPHRASE}" | cryptsetup luksOpen $PART6 root_b
# Create BTRFS RAID1
echo "Creating BTRFS RAID1 filesystem..."
echo "[+] Creating BTRFS RAID1 filesystem..."
mkfs.btrfs -f -d raid1 -m raid1 /dev/mapper/root_a /dev/mapper/root_b
# Create subvolumes
echo "Creating BTRFS subvolumes..."
echo "[+] Creating BTRFS subvolumes..."
mount /dev/mapper/root_a /mnt
btrfs subvolume create /mnt/@root
btrfs subvolume create /mnt/@home
@ -136,17 +211,27 @@ btrfs subvolume create /mnt/@db
chattr +C /mnt/@db
# Download Fedora installer
echo "Downloading Fedora installer..."
wget "https://download.fedoraproject.org/pub/fedora/linux/releases/${FEDORA_VERSION}/Server/x86_64/iso/Fedora-Server-dvd-x86_64-${FEDORA_VERSION}-1.5.iso"
echo "[+] Downloading Fedora installer..."
wget "https://download.fedoraproject.org/pub/fedora/linux/releases/${FEDORA_VERSION}/Server/x86_64/iso/Fedora-Server-netinst-x86_64-${FEDORA_VERSION}-1.1.iso"
# Mount Fedora ISO
echo "Mounting Fedora installer..."
echo "[+] Mounting Fedora installer..."
mkdir -p /mnt/iso
mount -o loop "Fedora-Server-dvd-x86_64-${FEDORA_VERSION}-1.5.iso" /mnt/iso
mount -o loop "Fedora-Server-netinst-x86_64-${FEDORA_VERSION}-1.1.iso" /mnt/iso
# Get current IP address and gateway from first non-loopback interface
echo "[+] Detecting current IP address and gateway..."
INTERFACE=$(ip -o -4 route show to default | awk '{print $5}' | head -n1)
IPV4=$(ip -4 addr show $INTERFACE | grep -oP '(?<=inet\s)\d+(\.\d+){3}')
GATEWAY=$(ip route show default | awk '/default/ {print $3}')
echo "[+] Detected network configuration:"
echo "Interface: $INTERFACE"
echo "IP: $IPV4"
echo "Gateway: $GATEWAY"
# Create kickstart file
echo "Creating kickstart configuration..."
cat > /mnt/ks.cfg << EOF
echo "[+] Creating kickstart configuration..."
cat > /mnt/ks.cfg << KICKSTART
# Fedora Server installation with our secure setup
text
lang en_US.UTF-8
@ -156,13 +241,13 @@ timezone --utc Etc/UTC
# Security settings
selinux --enforcing
rootpw --lock
user --name=${FEDORA_USER} --groups=wheel --shell=/bin/bash --password="${USER_PASSWORD}" --lock
user --name=${FEDORA_USER} --groups=wheel --shell=/bin/bash --lock
# SSH setup
sshkey --username=${FEDORA_USER} "${SSH_KEY}"
# Network
network --bootproto=dhcp --device=link --activate
# Network - let installer detect interface
network --bootproto=static --ip=${IPV4} --netmask=255.255.255.255 --gateway=${GATEWAY} --nameserver=185.12.64.1 --nameserver=185.12.64.2 --activate
# Bootloader
bootloader --timeout=1 --location=mbr --append="no_timer_check console=tty1 console=ttyS0,115200n8"
@ -170,16 +255,10 @@ bootloader --timeout=1 --location=mbr --append="no_timer_check console=tty1 cons
# Services
services --enabled=sshd,clevis-luks-askpass,dropbear
# Partitioning
clearpart --all --initlabel --disklabel=gpt
# Boot RAID1
part /boot --size=1000 --fstype=ext4 --label=boot
raid /boot --level=1 --device=md0 --fstype=ext4 --label=boot /dev/sda1 /dev/sdb1
# LUKS + BTRFS RAID1
part /dev/sda2 --size=2000 --grow --fstype=btrfs --label=root_a
part /dev/sdb2 --size=2000 --grow --fstype=btrfs --label=root_b
# Use existing partitions
part /boot/efi --fstype=vfat --onpart=${PART1}
part /boot --fstype=ext4 --onpart=/dev/md0
part / --fstype=btrfs --onpart=/dev/mapper/root_a
# Packages
%packages
@ -194,99 +273,138 @@ cryptsetup
btrfs-progs
mdadm
dropbear
git
zsh
lsd
bat
tmux
neovim
fortune-mod
cowsay
lolcat
xclip
python3-pip
%end
# Post-installation
%post
# Create BTRFS subvolumes
btrfs subvolume create /@root
btrfs subvolume create /@home
btrfs subvolume create /@db
chattr +C /@db
# Configure network with static IP (Hetzner dedicated server style)
cat > /etc/sysconfig/network-scripts/ifcfg-ens3 << EOF
DEVICE=ens3
ONBOOT=yes
BOOTPROTO=static
IPADDR=${IPV4}
NETMASK=255.255.255.255
SCOPE="peer ${GATEWAY}"
EOF
# Create route file
cat > /etc/sysconfig/network-scripts/route-ens3 << EOF
ADDRESS0=0.0.0.0
NETMASK0=0.0.0.0
GATEWAY0=${GATEWAY}
EOF
# Reload network configuration
nmcli con reload || true
nmcli con up ens3 || true
# Update fstab
cat > /etc/fstab << EOF
/dev/md0 /boot ext4 defaults 1 2
/dev/mapper/root_a / btrfs subvol=@root,defaults,noatime 0 0
/dev/mapper/root_a /home btrfs subvol=@home,defaults,noatime 0 0
/dev/mapper/root_a /db btrfs subvol=@db,defaults,noatime,nodatacow 0 0
EOF
# Save LUKS passphrase
echo "${LUKS_PASSPHRASE}" > /root/luks-passphrase.txt
chmod 600 /root/luks-passphrase.txt
# Configure sudoers
echo "%wheel ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/wheel
# Configure SSH
cat > /etc/ssh/sshd_config.d/99-custom.conf << EOF
PasswordAuthentication no
PermitRootLogin no
PubkeyAuthentication yes
EOF
cat > /etc/fstab << "FSTAB"
${PART1} /boot/efi vfat defaults 1 2
/dev/md0 /boot ext4 defaults 1 2
/dev/mapper/root_a / btrfs subvol=@root,defaults,noatime 0 0
/dev/mapper/root_a /home btrfs subvol=@home,defaults,noatime 0 0
/dev/mapper/root_a /db btrfs subvol=@db,defaults,noatime,nodatacow 0 0
FSTAB
# Configure dropbear for early SSH access
cat > /etc/dropbear-initramfs/config << EOF
DROPBEAR_OPTIONS="-I 60 -j -k -p 2222 -s"
EOF
mkdir -p /etc/dracut.conf.d
cat > /etc/dracut.conf.d/dropbear.conf << "DROPBEAR"
add_drivers+=" dropbear "
install_optional_items=yes
DROPBEAR
# Add SSH key to dropbear for early boot access
mkdir -p /etc/dropbear-initramfs/authorized_keys
echo "${SSH_KEY}" > /etc/dropbear-initramfs/authorized_keys
chmod 600 /etc/dropbear-initramfs/authorized_keys
# Add SSH key to dropbear
mkdir -p /etc/dropbear
echo "${SSH_KEY}" > /etc/dropbear/authorized_keys
chmod 600 /etc/dropbear/authorized_keys
# Regenerate initramfs with dropbear
dracut -f
# Set up MOTD
if [ "$ENABLE_MOTD" = true ]; then
cat > /etc/motd << EOF
${BANNER}
EOF
cat > /etc/motd << "MOTD"
:^7J5GB##&&##GPY?~:
^75B&@@@@@@&&&@@@@@@@#GJ~:
5&@@@&B5?7~^^^^^~!7YP#@@@@#!
Y##P7^ :~JB#B!
:: :
7PP?: :^~!!~^: :?PP7
:B@@B: !5B&@@@@&B5! :#@@B:
:!!: ^G@@@&BPPB@@@@G^ :!!:
:B@@@5^ ^5@@@B:
:7J7: !@@@# :&@@@~ :?J7:
J@@@5 :#@@@Y: :Y@@@B: 5@@@J
!@@@&^ ~B@@@&G55G&@@@B~ ~&@@@~
5@@@G: :7P#@@@@@@#P7: :B@@@Y
:P@@@B~ :~!77!~: ~B@@@P
Y@@@&Y^ ^5@@@@J
!G@@@&P7^ ^7P&@@@G~
!P&@@@&B? :: ?B&@@@&P!
^75#&&Y :P&&5: 5&&B57^
:^^ :P&&5: ^^:
^^
[nullpoint]
MOTD
fi
# Configure Clevis
if [ ${#TANG_SERVERS[@]} -gt 0 ] || [ "$TPM_ENABLED" = true ]; then
if [ ${#TANG_SERVERS[@]} -gt 0 ] || [ "${TPM_ENABLED}" = true ]; then
mkdir -p /etc/clevis
# Build Tang servers JSON array if we have any
if [ ${#TANG_SERVERS[@]} -gt 0 ]; then
TANG_JSON="["
for server in "${TANG_SERVERS[@]}"; do
read -r url thumbprint <<< "$server"
TANG_JSON+="{\"url\":\"$url\",\"thumbprint\":\"$thumbprint\"},"
read -r url thumbprint <<< "\$server"
TANG_JSON+="{\"url\":\"\$url\",\"thumbprint\":\"\$thumbprint\"},"
done
TANG_JSON="${TANG_JSON%,}]" # Remove trailing comma and close array
TANG_JSON="\${TANG_JSON%,}]" # Remove trailing comma and close array
fi
# Create Clevis config
cat > /etc/clevis/clevis.conf << EOF
cat > /etc/clevis/clevis.conf << "CLEVIS"
{
"t": 2,
"pins": {
$([ "$TPM_ENABLED" = true ] && echo "\"tpm2\": {
$([ "${TPM_ENABLED}" = true ] && echo "\"tpm2\": {
\"pcr_bank\": \"${TPM_PCR_BANK}\",
\"pcr_ids\": \"${TPM_PCR_IDS}\"
},")
$([ ${#TANG_SERVERS[@]} -gt 0 ] && echo "\"tang\": {
\"t\": 1,
\"tang\": ${TANG_JSON}
\"tang\": \${TANG_JSON}
}")
}
}
EOF
CLEVIS
# Bind LUKS volumes
clevis luks bind -d /dev/sda2 sss -c /etc/clevis/clevis.conf
clevis luks bind -d /dev/sdb2 sss -c /etc/clevis/clevis.conf
clevis luks bind -d ${PART3} sss -c /etc/clevis/clevis.conf
clevis luks bind -d ${PART6} sss -c /etc/clevis/clevis.conf
else
echo "No Tang servers or TPM available, skipping Clevis setup"
fi
# Enable required services
systemctl enable clevis-luks-askpass
systemctl enable dropbear-initramfs
systemctl enable dropbear
# Create TPM update script
cat > /root/update-tpm-bindings.py << 'TPMSCRIPT'
cat > /root/update-tpm-bindings.py << "TPMSCRIPT"
#!/usr/bin/env python3
import subprocess
import sys
@ -309,7 +427,7 @@ def get_pcr_values():
def update_bindings():
print("\nUpdating TPM bindings...")
devices = ['/dev/sda2', '/dev/sdb2']
devices = ['${PART3}', '${PART6}']
for device in devices:
print(f"\nUpdating bindings for {device}")
@ -328,7 +446,7 @@ def update_bindings():
def verify_bindings():
print("\nVerifying bindings...")
devices = ['/dev/sda2', '/dev/sdb2']
devices = ['${PART3}', '${PART6}']
for device in devices:
print(f"\nBindings for {device}:")
@ -359,484 +477,55 @@ TPMSCRIPT
chmod +x /root/update-tpm-bindings.py
# Install additional packages
dnf install -y git zsh lsd bat tmux neovim fortune-mod cowsay lolcat xclip python3-pip --skip-unavailable
# Set zsh as default shell for root and default user
chsh -s /bin/zsh root
chsh -s /bin/zsh ${FEDORA_USER}
# Install Oh My Zsh
su - ${FEDORA_USER} -c 'sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" "" --unattended'
# Install Powerlevel10k
su - ${FEDORA_USER} -c 'git clone --depth=1 https://github.com/romkatv/powerlevel10k.git "${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/themes/powerlevel10k"'
# Create .zshrc for default user
cat > /home/${FEDORA_USER}/.zshrc << 'ZSHRC'
USE_OH_MY_ZSH=true
if [[ -r "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh" ]]; then
source "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh"
fi
# Path to your oh-my-zsh installation.
if [[ $USE_OH_MY_ZSH == "true" ]]; then
export ZSH="$HOME/.oh-my-zsh"
fi
ZSH_THEME="powerlevel10k/powerlevel10k"
HIST_STAMPS="dd.mm.yyyy"
if [[ $USE_OH_MY_ZSH == "true" ]]; then
plugins=(git)
source $ZSH/oh-my-zsh.sh
fi
if [[ -n $SSH_CONNECTION ]]; then
export EDITOR='vim'
else
export EDITOR='nvim'
fi
if [ $TILIX_ID ] || [ $VTE_VERSION ]; then
source /etc/profile.d/vte.sh
fi
# lang
alias ptpython="python -m ptpython"
alias ptpy="python -m ptpython"
alias py13='python3.13'
alias py12='python3.12'
alias py10='python3.10'
alias bpytop="python -m bpytop"
# python venv
alias pvcreate="python -m venv .venv"
alias pvactivate="source .venv/bin/activate"
alias pvinstall="echo 'Creating Python-venv' && pvcreate && echo 'Entering venv' && pvactivate && echo 'Upgrading pip' && pip install pip --upgrade && echo 'Installing Dependencies' && pip install -r requirements.txt && echo 'Done.'"
# qol
alias cls="clear"
alias root="sudo su --shell /bin/zsh"
alias open="xdg-open"
alias filenum="du -a | cut -d/ -f2 | sort | uniq -c | sort -nr"
alias pg="progress"
alias hist="history"
alias untar="tar -zxvf"
notify() {
$@ && echo "[DONE] $@" || echo "[ERROR] $@"
}
# grep
alias antigrep="grep -v"
alias grep2="grep -A 2 -B 2"
alias grep4="grep -A 4 -B 4"
alias grep8="grep -A 8 -B 8"
alias grep16="grep -A 16 -B 16"
alias grep32="grep -A 32 -B 32"
alias ag="alias | grep"
# packages
alias get="sudo dnf install"
alias upd="sudo dnf check-upgrade"
alias upg="sudo dnf upgrade"
alias upf="sudo flatpak update"
alias upp="pip install --upgrade pip setuptools wheel && pip list --outdated --format=freeze | grep -v '^\-e' | cut -d = -f 1 | xargs -n1 pip install -U"
#clipboard
alias setclip="xclip -selection c"
alias getclip="xclip -selection c -o"
alias pwdclip="pwd | xargs echo -n | xclip -selection c"
# chars
alias c="clear"
alias t="bpytop"
alias p="ptpy"
alias h="history | grep"
alias v="nvim"
alias n="nano"
alias f="nautilus ."
alias o="open"
alias e="\d"
alias ":q"="exit"
# git
alias gs="git status"
alias gt="git log --all --graph --decorate --oneline --abbrev-commit"
alias gnoc='git shortlog -sn | cat'
alias gloc='git ls-files | while read f; do git blame -w -M -C -C --line-porcelain "$f" | grep -I "^author "; done | sort -f | uniq -ic | sort -n --reverse'
alias gpa='gaa && gc -m "." && gp -4'
# extensions
alias sudo="sudo "
alias watch="watch "
alias watch1="watch -n 1 "
# better ls via lsd
alias ls="lsd"
alias l="ls -1"
alias la="ls -A"
alias laa="ls -a"
alias lsa="ls -lA"
alias lla="ls -lA"
alias ltree="ls --tree"
alias d0="ls --tree"
alias d="ls --depth 1 --tree"
alias d1="ls --depth 1 --tree"
alias d2="ls --depth 2 --tree"
alias d3="ls --depth 3 --tree"
alias d4="ls --depth 4 --tree"
alias d5="ls --depth 5 --tree"
alias d6="ls --depth 6 --tree"
# more ls
alias lo="\ls --color=tty"
alias dtree="tree --du -h"
alias gtree="tree --du -h -F -C | grep 'G] ' --color=never"
# better cat via batcat
alias bat="bat --pager ''"
alias pat="bat --pager '' --plain"
alias lat="bat"
# more fancy batcat stuff
alias man="batman"
# tmux
alias s="tmux"
alias sa="tmux attach"
alias sn="tmux new -s"
alias san="tmux attach -t"
alias sl="tmux ls"
alias sk="tmux kill-session -t"
alias ska="tmux kill-session -a"
# Powerlevel10k initialization
[[ ! -f ~/.p10k.zsh ]] || source ~/.p10k.zsh
ZSHRC
# Create .p10k.zsh for default user
cat > /home/${FEDORA_USER}/.p10k.zsh << 'P10K'
# Temporarily change options.
'builtin' 'local' '-a' 'p10k_config_opts'
[[ ! -o 'aliases' ]] || p10k_config_opts+=('aliases')
[[ ! -o 'sh_glob' ]] || p10k_config_opts+=('sh_glob')
[[ ! -o 'no_brace_expand' ]] || p10k_config_opts+=('no_brace_expand')
'builtin' 'setopt' 'no_aliases' 'no_sh_glob' 'brace_expand'
() {
emulate -L zsh
setopt no_unset extended_glob
# Unset all configuration options. This allows you to apply configiguration changes without
# restarting zsh. Edit ~/.p10k.zsh and type `source ~/.p10k.zsh`.
unset -m 'POWERLEVEL9K_*'
autoload -Uz is-at-least && is-at-least 5.1 || return
zmodload zsh/langinfo
if [[ ${langinfo[CODESET]:-} != (utf|UTF)(-|)8 ]]; then
local LC_ALL=${${(@M)$(locale -a):#*.(utf|UTF)(-|)8}[1]:-en_US.UTF-8}
fi
# The list of segments shown on the left. Fill it with the most important segments.
typeset -g POWERLEVEL9K_LEFT_PROMPT_ELEMENTS=(
context
dir # current directory
vcs # git status
)
typeset -g POWERLEVEL9K_RIGHT_PROMPT_ELEMENTS=(
background_jobs # presence of background jobs
direnv # direnv status (https://direnv.net/)
virtualenv # python virtual environment (https://docs.python.org/3/library/venv.html)
kubecontext # current kubernetes context (https://kubernetes.io/)
vim_shell # vim shell indicator (:sh)
vi_mode # vi mode (you don't need this if you've enabled prompt_char)
disk_usage # disk usage
)
typeset -g POWERLEVEL9K_VISUAL_IDENTIFIER_EXPANSION='${P9K_VISUAL_IDENTIFIER// }'
typeset -g POWERLEVEL9K_MODE=nerdfont-complete
typeset -g POWERLEVEL9K_ICON_BEFORE_CONTENT=
typeset -g POWERLEVEL9K_PROMPT_ADD_NEWLINE=false
typeset -g POWERLEVEL9K_MULTILINE_FIRST_PROMPT_PREFIX='%242F╭─'
typeset -g POWERLEVEL9K_MULTILINE_NEWLINE_PROMPT_PREFIX='%242F├─'
typeset -g POWERLEVEL9K_MULTILINE_LAST_PROMPT_PREFIX='%242F╰─'
typeset -g POWERLEVEL9K_MULTILINE_FIRST_PROMPT_SUFFIX='%242F─╮'
typeset -g POWERLEVEL9K_MULTILINE_NEWLINE_PROMPT_SUFFIX='%242F─┤'
typeset -g POWERLEVEL9K_MULTILINE_LAST_PROMPT_SUFFIX='%242F─╯'
typeset -g POWERLEVEL9K_MULTILINE_FIRST_PROMPT_GAP_CHAR=' '
typeset -g POWERLEVEL9K_MULTILINE_FIRST_PROMPT_GAP_BACKGROUND=
if [[ $POWERLEVEL9K_MULTILINE_FIRST_PROMPT_GAP_CHAR != ' ' ]]; then
typeset -g POWERLEVEL9K_MULTILINE_FIRST_PROMPT_GAP_FOREGROUND=242
typeset -g POWERLEVEL9K_EMPTY_LINE_LEFT_PROMPT_FIRST_SEGMENT_END_SYMBOL='%{%}'
typeset -g POWERLEVEL9K_EMPTY_LINE_RIGHT_PROMPT_FIRST_SEGMENT_START_SYMBOL='%{%}'
fi
typeset -g POWERLEVEL9K_LEFT_SUBSEGMENT_SEPARATOR='\uE0B1'
typeset -g POWERLEVEL9K_RIGHT_SUBSEGMENT_SEPARATOR='\uE0B3'
typeset -g POWERLEVEL9K_LEFT_SEGMENT_SEPARATOR='\uE0B0'
typeset -g POWERLEVEL9K_RIGHT_SEGMENT_SEPARATOR='\uE0B2'
typeset -g POWERLEVEL9K_LEFT_PROMPT_LAST_SEGMENT_END_SYMBOL='\uE0B0'
typeset -g POWERLEVEL9K_RIGHT_PROMPT_FIRST_SEGMENT_START_SYMBOL='\uE0B2'
typeset -g POWERLEVEL9K_LEFT_PROMPT_FIRST_SEGMENT_START_SYMBOL=''
typeset -g POWERLEVEL9K_RIGHT_PROMPT_LAST_SEGMENT_END_SYMBOL=''
typeset -g POWERLEVEL9K_EMPTY_LINE_LEFT_PROMPT_LAST_SEGMENT_END_SYMBOL=
#################################[ os_icon: os identifier ]##################################
typeset -g POWERLEVEL9K_OS_ICON_FOREGROUND=232
typeset -g POWERLEVEL9K_OS_ICON_BACKGROUND=7
typeset -g POWERLEVEL9K_OS_ICON_CONTENT_EXPANSION='%B${P9K_CONTENT// }'
################################[ prompt_char: prompt symbol ]################################
typeset -g POWERLEVEL9K_PROMPT_CHAR_BACKGROUND=
typeset -g POWERLEVEL9K_PROMPT_CHAR_OK_{VIINS,VICMD,VIVIS,VIOWR}_FOREGROUND=76
typeset -g POWERLEVEL9K_PROMPT_CHAR_ERROR_{VIINS,VICMD,VIVIS,VIOWR}_FOREGROUND=196
typeset -g POWERLEVEL9K_PROMPT_CHAR_{OK,ERROR}_VIINS_CONTENT_EXPANSION=' ' #''
typeset -g POWERLEVEL9K_PROMPT_CHAR_{OK,ERROR}_VICMD_CONTENT_EXPANSION=' ' #''
typeset -g POWERLEVEL9K_PROMPT_CHAR_{OK,ERROR}_VIVIS_CONTENT_EXPANSION=' ' #''
typeset -g POWERLEVEL9K_PROMPT_CHAR_{OK,ERROR}_VIOWR_CONTENT_EXPANSION=' ' #'▶'
typeset -g POWERLEVEL9K_PROMPT_CHAR_OVERWRITE_STATE=true
typeset -g POWERLEVEL9K_PROMPT_CHAR_LEFT_PROMPT_LAST_SEGMENT_END_SYMBOL=
typeset -g POWERLEVEL9K_PROMPT_CHAR_LEFT_PROMPT_FIRST_SEGMENT_START_SYMBOL=
typeset -g POWERLEVEL9K_PROMPT_CHAR_LEFT_{LEFT,RIGHT}_WHITESPACE=
##################################[ dir: current directory ]##################################
typeset -g POWERLEVEL9K_DIR_BACKGROUND=234
typeset -g POWERLEVEL9K_DIR_FOREGROUND=39
typeset -g POWERLEVEL9K_SHORTEN_STRATEGY=truncate_to_unique
typeset -g POWERLEVEL9K_SHORTEN_DELIMITER=
typeset -g POWERLEVEL9K_DIR_SHORTENED_FOREGROUND=103
typeset -g POWERLEVEL9K_DIR_ANCHOR_FOREGROUND=39
typeset -g POWERLEVEL9K_DIR_ANCHOR_BOLD=false
local anchor_files=(
.bzr
.citc
.git
.hg
.node-version
.python-version
.ruby-version
.shorten_folder_marker
.svn
.terraform
CVS
Cargo.toml
composer.json
go.mod
package.json
)
typeset -g POWERLEVEL9K_SHORTEN_FOLDER_MARKER="(${(j:|:)anchor_files})"
typeset -g POWERLEVEL9K_SHORTEN_DIR_LENGTH=1
typeset -g POWERLEVEL9K_DIR_MAX_LENGTH=80
typeset -g POWERLEVEL9K_DIR_MIN_COMMAND_COLUMNS=40
typeset -g POWERLEVEL9K_DIR_MIN_COMMAND_COLUMNS_PCT=50
typeset -g POWERLEVEL9K_DIR_HYPERLINK=false
typeset -g POWERLEVEL9K_DIR_SHOW_WRITABLE=true
typeset -g POWERLEVEL9K_DIR_CLASSES=()
#####################################[ vcs: git status ]######################################
# Version control system colors.
typeset -g POWERLEVEL9K_VCS_CLEAN_FOREGROUND=10
typeset -g POWERLEVEL9K_VCS_CLEAN_BACKGROUND=235 #2
typeset -g POWERLEVEL9K_VCS_MODIFIED_FOREGROUND=10
typeset -g POWERLEVEL9K_VCS_MODIFIED_BACKGROUND=235 #3
typeset -g POWERLEVEL9K_VCS_UNTRACKED_FOREGROUND=10
typeset -g POWERLEVEL9K_VCS_UNTRACKED_BACKGROUND=235 #2
typeset -g POWERLEVEL9K_VCS_CONFLICTED_FOREGROUND=9
typeset -g POWERLEVEL9K_VCS_CONFLICTED_BACKGROUND=235 #3
typeset -g POWERLEVEL9K_VCS_LOADING_FOREGROUND=15
typeset -g POWERLEVEL9K_VCS_LOADING_BACKGROUND=255
# Branch icon. Set this parameter to '\uF126 ' for the popular Powerline branch icon. Disabled because bug
typeset -g POWERLEVEL9K_VCS_BRANCH_ICON='\uF126 '
POWERLEVEL9K_VCS_BRANCH_ICON=${(g::)POWERLEVEL9K_VCS_BRANCH_ICON}
# Untracked files icon. It's really a question mark, your font isn't broken.
# Change the value of this parameter to show a different icon.
typeset -g POWERLEVEL9K_VCS_UNTRACKED_ICON='?'
POWERLEVEL9K_VCS_UNTRACKED_ICON=${(g::)POWERLEVEL9K_VCS_UNTRACKED_ICON}
# Formatter for Git status.
#
# Example output: master ⇣42⇡42 *42 merge ~42 +42 !42 ?42.
#
# You can edit the function to customize how Git status looks.
#
# VCS_STATUS_* parameters are set by gitstatus plugin. See reference:
# https://github.com/romkatv/gitstatus/blob/master/gitstatus.plugin.zsh.
function my_git_formatter() {
emulate -L zsh
if [[ -n $P9K_CONTENT ]]; then
# If P9K_CONTENT is not empty, use it. It's either "loading" or from vcs_info (not from
# gitstatus plugin). VCS_STATUS_* parameters are not available in this case.
typeset -g my_git_format=$P9K_CONTENT
return
fi
# Styling for different parts of Git status.
local meta='' #'%7F' # white foreground
local clean='' #'%0F' # black foreground
local modified='' #'%0F' # black foreground
local untracked='' #'%0F' # black foreground
local conflicted='' #'%1F' # red foreground
local res
local where # branch or tag
if [[ -n $VCS_STATUS_LOCAL_BRANCH ]]; then
res+="${clean}${POWERLEVEL9K_VCS_BRANCH_ICON}"
where=${(V)VCS_STATUS_LOCAL_BRANCH}
elif [[ -n $VCS_STATUS_TAG ]]; then
res+="${meta}#"
where=${(V)VCS_STATUS_TAG}
fi
# If local branch name or tag is at most 32 characters long, show it in full.
# Otherwise show the first 12 … the last 12.
(( $#where > 32 )) && where[13,-13]="…"
res+="${clean}${where//\%/%%}" # escape %
# Display the current Git commit if there is no branch or tag.
# Tip: To always display current Git commit, remove `[[ -z $where ]] &&` from the next line.
[[ -z $where ]] && res+="${meta}@${clean}${VCS_STATUS_COMMIT[1,8]}"
# Show tracking branch name if it differs from local branch.
if [[ -n ${VCS_STATUS_REMOTE_BRANCH:#$VCS_STATUS_LOCAL_BRANCH} ]]; then
res+="${meta}:${clean}${(V)VCS_STATUS_REMOTE_BRANCH//\%/%%}" # escape %
fi
# ⇣42 if behind the remote.
(( VCS_STATUS_COMMITS_BEHIND )) && res+=" ${clean}${VCS_STATUS_COMMITS_BEHIND}"
# ⇡42 if ahead of the remote; no leading space if also behind the remote: ⇣42⇡42.
(( VCS_STATUS_COMMITS_AHEAD && !VCS_STATUS_COMMITS_BEHIND )) && res+=" "
(( VCS_STATUS_COMMITS_AHEAD )) && res+="${clean}${VCS_STATUS_COMMITS_AHEAD}"
# *42 if have stashes.
(( VCS_STATUS_STASHES )) && res+=" ${clean}*${VCS_STATUS_STASHES}"
# 'merge' if the repo is in an unusual state.
[[ -n $VCS_STATUS_ACTION ]] && res+=" ${conflicted}${VCS_STATUS_ACTION}"
# ~42 if have merge conflicts.
(( VCS_STATUS_NUM_CONFLICTED )) && res+=" ${conflicted}~${VCS_STATUS_NUM_CONFLICTED}"
# +42 if have staged changes.
(( VCS_STATUS_NUM_STAGED )) && res+=" ${modified}+${VCS_STATUS_NUM_STAGED}"
# !42 if have unstaged changes.
(( VCS_STATUS_NUM_UNSTAGED )) && res+=" ${modified}!${VCS_STATUS_NUM_UNSTAGED}"
# ?42 if have untracked files. It's really a question mark, your font isn't broken.
# See POWERLEVEL9K_VCS_UNTRACKED_ICON above if you want to use a different icon.
# Remove the next line if you don't want to see untracked files at all.
(( VCS_STATUS_NUM_UNTRACKED )) && res+=" ${untracked}${POWERLEVEL9K_VCS_UNTRACKED_ICON}${VCS_STATUS_NUM_UNTRACKED}"
typeset -g my_git_format=$res
}
functions -M my_git_formatter 2>/dev/null
# Disable the default Git status formatting.
typeset -g POWERLEVEL9K_VCS_DISABLE_GITSTATUS_FORMATTING=true
# Install our own Git status formatter.
typeset -g POWERLEVEL9K_VCS_CONTENT_EXPANSION='${$((my_git_formatter()))+${my_git_format}}'
# Enable counters for staged, unstaged, etc.
typeset -g POWERLEVEL9K_VCS_{STAGED,UNSTAGED,UNTRACKED,CONFLICTED,COMMITS_AHEAD,COMMITS_BEHIND}_MAX_NUM=-1
# Custom icon.
# typeset -g POWERLEVEL9K_VCS_VISUAL_IDENTIFIER_EXPANSION='⭐'
# Custom prefix.
# typeset -g POWERLEVEL9K_VCS_PREFIX='on '
# Show status of repositories of these types. You can add svn and/or hg if you are
# using them. If you do, your prompt may become slow even when your current directory
# isn't in an svn or hg reposotiry.
typeset -g POWERLEVEL9K_VCS_BACKENDS=(git)
##################################[ disk_usgae: disk usage ]##################################
typeset -g POWERLEVEL9K_DISK_USAGE_WARNING_LEVEL=95
typeset -g POWERLEVEL9K_DISK_USAGE_CRITICAL_LEVEL=98
typeset -g POWERLEVEL9K_DISK_USAGE_ONLY_WARNING=true
###########[ vi_mode: vi mode (you don't need this if you've enabled prompt_char) ]###########
typeset -g POWERLEVEL9K_VI_MODE_FOREGROUND=0
typeset -g POWERLEVEL9K_VI_COMMAND_MODE_STRING=NORMAL
typeset -g POWERLEVEL9K_VI_MODE_NORMAL_BACKGROUND=2
typeset -g POWERLEVEL9K_VI_VISUAL_MODE_STRING=VISUAL
typeset -g POWERLEVEL9K_VI_MODE_VISUAL_BACKGROUND=4
typeset -g POWERLEVEL9K_VI_OVERWRITE_MODE_STRING=OVERTYPE
typeset -g POWERLEVEL9K_VI_MODE_OVERWRITE_BACKGROUND=3
typeset -g POWERLEVEL9K_VI_INSERT_MODE_STRING=
typeset -g POWERLEVEL9K_VI_MODE_INSERT_FOREGROUND=8
######################################[ ram: free RAM ]#######################################
# RAM color.
# typeset -g POWERLEVEL9K_RAM_FOREGROUND=0
# typeset -g POWERLEVEL9K_RAM_BACKGROUND=3
# Custom icon.
# typeset -g POWERLEVEL9K_RAM_VISUAL_IDENTIFIER_EXPANSION='⭐'
#####################################[ swap: used swap ]######################################
# Swap color.
# typeset -g POWERLEVEL9K_SWAP_FOREGROUND=0
# typeset -g POWERLEVEL9K_SWAP_BACKGROUND=3
# Custom icon.
# typeset -g POWERLEVEL9K_SWAP_VISUAL_IDENTIFIER_EXPANSION='⭐'
######################################[ load: CPU load ]######################################
typeset -g POWERLEVEL9K_LOAD_WHICH=5
##################################[ context: user@hostname ]##################################
typeset -g POWERLEVEL9K_CONTEXT_ROOT_FOREGROUND=1
typeset -g POWERLEVEL9K_CONTEXT_ROOT_BACKGROUND=0
typeset -g POWERLEVEL9K_CONTEXT_{REMOTE,REMOTE_SUDO}_FOREGROUND=3
typeset -g POWERLEVEL9K_CONTEXT_{REMOTE,REMOTE_SUDO}_BACKGROUND=0
typeset -g POWERLEVEL9K_CONTEXT_FOREGROUND=3
typeset -g POWERLEVEL9K_CONTEXT_BACKGROUND=0
typeset -g POWERLEVEL9K_CONTEXT_ROOT_TEMPLATE='%n@%m'
typeset -g POWERLEVEL9K_CONTEXT_{REMOTE,REMOTE_SUDO}_TEMPLATE='%n@%m'
typeset -g POWERLEVEL9K_CONTEXT_TEMPLATE='%n'
###[ virtualenv: python virtual environment (https://docs.python.org/3/library/venv.html) ]###
typeset -g POWERLEVEL9K_VIRTUALENV_SHOW_PYTHON_VERSION=false
typeset -g POWERLEVEL9K_VIRTUALENV_{LEFT,RIGHT}_DELIMITER=
#############[ kubecontext: current kubernetes context (https://kubernetes.io/) ]#############
typeset -g POWERLEVEL9K_KUBECONTEXT_SHOW_ON_COMMAND='kubectl|helm|kubens|kubectx|oc'
typeset -g POWERLEVEL9K_KUBECONTEXT_CLASSES=(
# '*prod*' PROD # These values are examples that are unlikely
# '*test*' TEST # to match your needs. Customize them as needed.
'*' DEFAULT)
typeset -g POWERLEVEL9K_KUBECONTEXT_DEFAULT_FOREGROUND=7
typeset -g POWERLEVEL9K_KUBECONTEXT_DEFAULT_BACKGROUND=5
typeset -g POWERLEVEL9K_KUBECONTEXT_DEFAULT_CONTENT_EXPANSION=
POWERLEVEL9K_KUBECONTEXT_DEFAULT_CONTENT_EXPANSION+='${P9K_KUBECONTEXT_CLOUD_CLUSTER:-${P9K_KUBECONTEXT_NAME}}'
POWERLEVEL9K_KUBECONTEXT_DEFAULT_CONTENT_EXPANSION+='${${:-/$P9K_KUBECONTEXT_NAMESPACE}:#/default}'
####################################[ time: current time ]####################################
typeset -g POWERLEVEL9K_TIME_FORMAT='%D{%H:%M:%S}'
typeset -g POWERLEVEL9K_TIME_UPDATE_ON_COMMAND=false
typeset -g POWERLEVEL9K_TRANSIENT_PROMPT=off
typeset -g POWERLEVEL9K_INSTANT_PROMPT=verbose
typeset -g POWERLEVEL9K_DISABLE_HOT_RELOAD=true
(( ! $+functions[p10k] )) || p10k reload
}
(( ${#p10k_config_opts} )) && setopt ${p10k_config_opts[@]}
'builtin' 'unset' 'p10k_config_opts'
P10K
# Set correct permissions
chown -R ${FEDORA_USER}:${FEDORA_USER} /home/${FEDORA_USER}/.oh-my-zsh
chown ${FEDORA_USER}:${FEDORA_USER} /home/${FEDORA_USER}/.zshrc
chown ${FEDORA_USER}:${FEDORA_USER} /home/${FEDORA_USER}/.p10k.zsh
# Install Python packages
pip3 install --user ptpython bpytop
%end
# Force SELinux relabel on next boot
touch /.autorelabel
# Cleanup
echo "[+] Now rebooting..."
reboot
EOF
KICKSTART
# Start Fedora installation
echo "Starting Fedora installation..."
echo "This will take some time. Please wait..."
/mnt/iso/isolinux/vmlinuz initrd=/mnt/iso/isolinux/initrd.img inst.ks=file:///mnt/ks.cfg inst.stage2=hd:LABEL=Fedora-S-42-1-5-x86_64
echo -e "\nInstallation started! Please wait for completion and reboot."
echo "SSH access will be available on port 2222"
# Create ALL needed directories
mkdir -p /mnt/boot
mount /dev/md0 /mnt/boot
mkdir -p /mnt/boot/efi
mount $PART1 /mnt/boot/efi
mkdir -p /mnt/boot/efi/EFI/fedora
mkdir -p /mnt/boot/grub
mkdir -p /mnt/boot/installer
mkdir -p /mnt/iso
# Now mount and copy
cp /mnt/iso/images/pxeboot/vmlinuz /mnt/boot/installer/
cp /mnt/iso/images/pxeboot/initrd.img /mnt/boot/installer/
cp /mnt/ks.cfg /mnt/boot/installer/
# Get actual ISO label
ISO_LABEL=$(isoinfo -d -i "Fedora-Server-netinst-x86_64-${FEDORA_VERSION}-1.1.iso" | grep "Volume id:" | cut -d: -f2 | tr -d ' ')
# Set IP-related kernel boot params for installer
KERNEL_NET_PARAMS="ip=${IPV4}::${GATEWAY}:255.255.255.255::ens3:none nameserver=185.12.64.1 nameserver=185.12.64.2"
cat > /mnt/boot/grub/grub.cfg << "GRUBCFG"
set timeout=5
set default=0
menuentry "Fedora Installer" {
linux /installer/vmlinuz inst.ks=file:///installer/ks.cfg inst.stage2=hd:LABEL=${ISO_LABEL} ${KERNEL_NET_PARAMS} inst.sshd inst.ssh.port=2222 inst.ssh.key=${SSH_KEY}
initrd /installer/initrd.img
}
GRUBCFG
# Install GRUB EFI
grub-install --target=x86_64-efi --boot-directory=/mnt/boot --efi-directory=/mnt/boot/efi --removable $DISK1
grub-install --target=x86_64-efi --boot-directory=/mnt/boot --efi-directory=/mnt/boot/efi --removable $DISK2
umount /mnt/boot/efi
umount /mnt/boot
umount /mnt/iso
#reboot