Last update: Nov 2024
Motivation
I am using this for noting my snippets for everyday use. Mostly those commands are tested and developed on latest Ubuntu.
Warning
Many of those commands here are dangerous and will potentially mess up your system. Be warned: Don‘t use them if you do not know what you‘re doing!
Secure Boot SBAT Fail
Sometimes when I try boot up Ventoy on an older Dell machine with UEFI and Secure Boot enabled, I‘m getting the following errors, because Ventoy‘s bootloader is not signed – therefore not trusted by the system:
Cannot reset SBAT policy: Secure Boot is enabled.
Failed to open \EFI\Boot\ – Invalid Parameter
Failed to load image : Invalid Parameter
start_image() returned Invalid Parameter, falling back to default loader
ERROR
Verification failed: (0x1A) Security Violation
Failed to load image: Security Policy Violation
start_image() returned Security Policy Violation
Fix: Boot up some current Ubuntu from USB and open up a terminal
sudo mokutil --reset
sudo mokutil --set-sbat-policy delete
sudo reboot
Afterwards you should be able to perform MOK key management.
Troubleshooting:
- Some people say you need to disable Secure Boot first, run the commands and enable it again. In my case it works always without this limitation.
How to clear TPM if it is owned (Windows only)
# check state in powershell
Get-Tpm
# open powershell as admin
Disable-TpmAutoProvisioning
# open TPM management as admin
tpm.msc
# and click on "Clear TPM"
If you cannot perform MOK management afterwards, try to boot Linux Mint or Ubuntu and the linux commands above. In my case that worked.
Restore Image with Partclone
# install package
sudo apt install partclone
# run as root:
# for compressed image with gzip
cat dir/sda1.ntfs-ptcl-img.gz.* | gunzip | partclone.restore --restore_raw_file -C -s - -o sda1.img
# for compressed image with zstd
zstdcat dir/sda1.ntfs-ptcl-img.zst.* | partclone.restore --restore_raw_file -C -s - -o sda1.img
# mount extracted image
mount -o loop sda1.img /mnt -t ntfs -o ro
Check if drive has GPT or MBR
# install package
sudo apt-get install gdisk
# show drive info
sudo gdisk -l /dev/sda
# MBR if output is like:
Partition table scan:
MBR: MBR only
BSD: not present
APM: not present
GPT: not present
# GPT if output is like:
MBR: protective
BSD: not present
APM: not present
GPT: present
# if you are sure you want to have only MBR, you can delete the GPT part
sudo sgdisk -z /dev/sda
# if you are sure you want to have only GPT, delete the MBR part
sudo dd of=/dev/zero of=/dev/sda bs=512 count=1
Secure erase of SSD and NVMe
Works only if drive is not in frozen state. (sudo hdparm -I /dev/sdX | grep frozen)
# check for "not frozen"
sudo hdparm -I /dev/sda
# if drive is "frozen" then issue this command and wait some seconds before powering the computer on again
sudo systemctl suspend
# setting password is needed before issueing command
sudo hdparm --user-master u --security-set-pass password /dev/sdX
# option 1: erase drive (overwrites all user data areas with binary zeroes)
sudo hdparm --user-master u --security-erase password /dev/sdX
# option 2: erase drive (writes predetermined data patterns (set by the manufacturer) to all user data areas, including sectors that are no longer in use due to reallocation)
sudo hdparm --user-master u --security-erase-enhanced password /dev/sdX
Wiping securely
# First we want to fill up our pendrive with zeroes
sudo cat /dev/zero > /dev/your_pendrive
# After completion we can check if our flash drive is really wiped with zeros by installing and using a text-based Hex-editor
# Remember: We trust nobody so we check manually if zeros have been written to the drive. If you see weird characters something went wrong.
sudo apt install ht
sudo hte /dev/your_pendrive
# Wipe just a file with zeros:
shred -fvzun 0 file
# Wipe a whole directory recursively with zeros:
srm -rvs directory
Compare binary files
# Compare binary files within the console and highlight those areas which differ. Vim and Colordiff have to be installed before.
diff -y <(xxd file.one) <(xxd file.two) | colordiff
Help! Ubuntu installed something encrypted into LVM and I have no idea how do deal with that..
First of all: LVM (Logical Volume Manager) consists always of three parts with the following hierarchy:
- Physical Volume (PV): highest element / “system” of LVM
- Volume Group (VG): kind of a virtual drive / can reside on multiple partitions, disks, name should be unique
- Logical Volume (LV): your usable partitions within your VG above
For the sake of explanation we’ll use a default Ubuntu 24.04 encrypted LVM installation on a 50GB (VM) drive.
First we boot up the system and run some commands from inside in order to get some more information about our current system:
lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
...
sda 8:0 0 50G 0 disk
├─sda1 8:1 0 1G 0 part /boot/efi
├─sda2 8:2 0 2G 0 part /boot
└─sda3 8:3 0 46.9G 0 part
└─dm_crypt-0 252:0 0 46.9G 0 crypt
└─ubuntu--vg-ubuntu--lv 252:1 0 46.9G 0 lvm /
df -Th
Filesystem Type Size Used Avail Use% Mounted on
...
/dev/mapper/ubuntu--vg-ubuntu--lv ext4 46G 9.5G 35G 22% /
...
sudo gparted
# we want some info about the PV (physical volume):
# 1. sudo pvscan
PV /dev/mapper/dm_crypt-0 VG ubuntu-vg lvm2 [<46.93 GiB / 0 free]
Total: 1 [<46.93 GiB] / in use: 1 [<46.93 GiB] / in no VG: 0 [0 ]
# 2. sudo pvs
PV VG Fmt Attr PSize PFree
/dev/mapper/dm_crypt-0 ubuntu-vg lvm2 a-- <46.93g 0
# 3. sudo pvdisplay
--- Physical volume ---
PV Name /dev/mapper/dm_crypt-0
VG Name ubuntu-vg
PV Size 46.93 GiB / not usable 3.00 MiB
Allocatable yes (but full)
PE Size 4.00 MiB
Total PE 12014
Free PE 0
Allocated PE 12014
PV UUID zofURa-qyMQ-1hza-DRax-8nvs-mhUR-zZhKgo
What do we learn about the PV? (Reminder: LVM top level 1 out of 3)
- There is an encrypted partition /dev/sda3 (size 49,95 GiB) and this partition has been opened and accessible at /dev/mapper/dm_crypt-0 (size 46,93 GiB).
# now we want info about the VG (volume group):
# 1. sudo vgscan
Found volume group "ubuntu-vg" using metadata type lvm2
# 2. sudo vgs
VG #PV #LV #SN Attr VSize VFree
ubuntu-vg 1 1 0 wz--n- <46.93g 0
# 3. sudo vgdisplay
--- Volume group ---
VG Name ubuntu-vg
System ID
Format lvm2
Metadata Areas 1
Metadata Sequence No 2
VG Access read/write
VG Status resizable
MAX LV 0
Cur LV 1
Open LV 1
Max PV 0
Cur PV 1
Act PV 1
VG Size <46.93 GiB
PE Size 4.00 MiB
Total PE 12014
Alloc PE / Size 12014 / <46.93 GiB
Free PE / Size 0 / 0
VG UUID 55tDXa-6TTg-ccDx-UCCV-UaQX-mnSl-FyP1hi
What do we learn about the VG? (Reminder: LVM level 2 out of 3)
- Inside the PV there is a VG named ubuntu-vg (size 49,93 GiB).
# now we want info about the LV (logical volumes)
# 1. sudo lvscan
ACTIVE '/dev/ubuntu-vg/ubuntu-lv' [<46.93 GiB] inherit
# 2. sudo lvs
LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert
ubuntu-lv ubuntu-vg -wi-ao---- <46.93g
# 3. sudo lvdisplay
--- Logical volume ---
LV Path /dev/ubuntu-vg/ubuntu-lv
LV Name ubuntu-lv
VG Name ubuntu-vg
LV UUID 0RjrOz-HkVm-03XG-GKc7-6YUD-bejn-5kUB54
LV Write Access read/write
LV Creation host, time ubuntu, 2024-11-26 22:11:39 +0100
LV Status available
# open 1
LV Size <46.93 GiB
Current LE 12014
Segments 1
Allocation inherit
Read ahead sectors auto
- currently set to 256
Block device 252:1
What do we learn about the LV? (Reminder: LVM level 3 out of 3)
- There is a logical volume (“usable partition”) named ubuntu-lv (size 46,93 GiB).
- We keep in mind that the filesystem of /dev/ubuntu-vg/ubuntu-lv is ext4.
Scenario: Imagine that during installation the Ubuntu installer was using all free space available on our 50GB disk. So now we to find a way to shink this whole stuff (LV+VG+PV).
For the purpose of showing how that works, we will try to shrink the 50GB filesystem to 30GB. For this we need to boot up a live Linux like Ubuntu from a pendrive. Keep in mind 1G = 1.000.000.000 Bytes; while 1g = 1.073.741.824 Bytes.
The steps are:
- opening the /dev/sda3 partition holding our data, LVM etc.
- shrinking the ext4 filesystem within ubuntu-lv
- shrinking the LV: ubuntu-lv
- shrinking the VG: ubuntu-vg
- shrinking the PV: /dev/mapper/dm_crypt-0
- shrinking the LUKS holding partition: /dev/sda3
# step 1: opening the partition
sudo cryptsetup open /dev/sda3 cryptedpartition
# we will find it opened now
ls /dev/mapper
... cryptedpartition ubuntu--vg-ubuntu--lv
# lets check it again
sudo fdisk -l /dev/mapper/ubuntu--vg-ubuntu--lv
>>>
Disk /dev/mapper/ubuntu--vg-ubuntu--lv: 46.93 GiB, ...
# step 2: shrinking the ext4 filesystem within ubuntu-lv
# run the mandatory check first
sudo e2fsck -f /dev/mapper/ubuntu--vg-ubuntu--lv
# shrink it, -p stands for showing a progress bar
sudo resize2fs -p /dev/mapper/ubuntu--vg-ubuntu--lv 30g
>>>
The filesystem on /dev/mapper/ubuntu--vg-ubuntu--lv is now 7864320 (4k) blocks long.
# now the filesystem ext4 has a size of 30G (7864320 * 4096 Bytes = 32212254720 Bytes = 30 GiB)
# step 3: shrinking the LV: ubuntu-lv
# now we reduce the size of the LV to fixed 30GiB
sudo lvreduce -L 30g /dev/mapper/ubuntu--vg-ubuntu--lv
>>>
Size of logical volume ubuntu-vg/ubuntu-lv changed from 46.93 GiB (12014 extents) to 30.00 GiB (7680 extents).
Logical volume ubuntu-vg/ubuntu-lv successfully resized.
# if you look on gparted now, then you ll notice that /dev/sda3 is not filled 100% anymore but shows only 30GiB of usage.
# command not tested but should do the same:
# sudo lvresize --resizefs -L 30g /dev/ubuntu-vg/ubuntu-lv
# step 4: shrinking the VG: ubuntu-vg
# now we need to shink the VG from 46.93 GiB to 30.00 GiB
# if we check the size it should show some free space now
sudo vgs
>>>
VG #PV #LV #SN Attr VSize VFree
ubuntu-vg 1 0 0 wz--n- <49.93g <16.93g
# the only way I found to do steps 4, 5 and 6 at once is to use gparted now to shrink the /dev/sda3 partition manually
sudo gparted
# as mentioned gparted did also take care of this steps:
# step 5: shrinking the PV: /dev/mapper/dm_crypt-0
# step 6: shrinking the LUKS holding partition: /dev/sda3
Ok, what if we want to access that partition from another system?! Boot up a Linux from pendrive and then you can access it in that way:
# other stuff, todo
# now you can mount it like any other partition
# /test ist just my random mountpoint
sudo mkdir /test
sudo mount /dev/mapper/ubuntu--vg-ubuntu--lv /test
# unmounting works also
sudo umount /test
# and do not forget to close the encrypted partition again
sudo cryptsetup close nvme0n1p5_crypt
# sometimes you get an error on closing:
Device nvme0n1p5_crypt is still in use.
# lsof will show you nothing useful:
sudo lsof /dev/mapper/nvme0n1p5_crypt
lsof: WARNING: cant state() fuse.gvfsd-fuse file system /run/user/1000/gvfs
# but dmsetup does:
sudo dmsetup info -C
Open Targ UUID
nvme0n1p5_crypt 1 1 CRYPT-LUKS2-....
ubuntu--vg-ubuntu--lv 0 1 LVM-...
# something still holds the nvme0n1p5_crypt active..
# and that is the LVM! so we need to deactivate the VG within the LVM BEFORE we close LUKS!
# find out the name of your VG first:
sudo vgdisplay
VG Name ubuntu-vb
# and then deactivate it:
sudo vgchange -a n ubuntu-vg
0 logical volume(s) in volume group "ubuntu-vg" now active
# now we can close the encrypted partition
# todo
Harddisk encryption with LUKS
# creating luks partition
sudo cryptsetup luksFormat -c aes-xts-plain64 -s 512 -h sha512 -y /dev/sdX
# mount luks partition
sudo cryptsetup luksOpen /dev/sdX yourDeviceName
# create a filesystem within this luks partition
sudo mkfs.btrfs -L yourLabel /dev/mapper/yourDeviceName #(if you want btrfs)
sudo mkfs.ext4 /dev/mapper/yourDeviceName #(if you want ext4)
# if you want to mount it
sudo mount /dev/mapper/yourDeviceName /yourMountPoint
# generally speaking: mounting your filesystem
sudo cryptsetup luksOpen /dev/sdX yourDeviceName
sudo mount /dev/mapper/yourDeviceName /yourMountPoint
# generally speaking: unmounting your filesystem
sudo umount /dev/yourMountPoint
sudo cryptsetup luksClose yourDeviceName
Rsync
# Mirroring with rsync from /source to /destination. Compression is great when backing up over the Internet.
rsync --compress --compress-level=9 --human-readable -av --progress --delete --log-file=/path/to/log.file /source /destination
# Rsync command which doesn’t copy everything every time while preserving times:
rsync -avP source destination
#a = archive mode
#v = verbose
#P = show progress
Harddisk backup
# Backup of harddisks into compressed image file. Due to its multithreading capability pigz is much faster than gzip during compression.
sudo dd if=/dev/sdX status=progress bs=1M | pigz > harddisk.img.gz
# Restore this prior zipped image file and write it directly to disk:
sudo gunzip -c image.gz | sudo dd of=/dev/sdX status=progress bs=1M
Recovering Software-RAID
# Recover a Linux Soft-RAID md/5:
sudo mdadm --assemble --scan
sudo cryptsetup luksOpen /dev/md/5 temp
sudo mount /dev/mapper/temp /your_path
# Mount a Linux Soft-RAID manually:
sudo mdadm --examine /dev/sdX
sudo mdadm -A -R /dev/md9 /dev/sdX
sudo mount /dev/md9 /openedRaidPartition
# And close it again:
sudo umount /openedRaidPartition
sudo mdadm -S /dev/md9
Available kernel modules
# List all loadable kernel modules:
find /lib/modules/$(uname -r) -type f -name \*.ko
Manjaro XFCE configuration
# Template for configuring a fresh manjaro xfce installation:
#update system
sudo pacman -Syyu
#install zshell
sh -c "$(curl -fsSL https://raw.github.com/robbyrussell/oh-my-zsh/master/tools/install.sh)"
sudo pacman -S powerline-fonts
#install virtualbox
sudo pacman -S virtualbox
#copy fonts which you need into /usr/share/fonts and run
sudo fc-cache
#fixing the Manjaro Linux XFCE text shadow problem on the desktop
xfconf-query -c xfce4-desktop -p /desktop-icons/center-text -n -t bool -s false
# Nice to have Manjaro packages:
gufw (firewall gui)
chromium (browser)
synapse (launcher)
psensor (temperature)
ether (pendrive tool)
file-roller
p7zip zip unzip unrar
tilda (background terminal)
Laravel
# Laravel development quickstart:
git clone project.git
cd project
composer install
composer update
cp .env.example .env
php artisan key:generate
php artisan serve --port=8000
Restricting sFTP
# Add to /etc/ssh/sshd_config:
Subsystem sftp internal-sftp
Match Group sftpusers
ChrootDirectory %h
ForceCommand internal-sftp
AllowTcpForwarding no
X11Forwarding no
# Adding user and change configuration:
useradd newuser
usermod -s /bin/false newuser
chown root:root /home/newuser
chmod 755 /home/newuser
mkdir /home/newuser/writablefolder
chown newuser:newuser /home/newuser/writeablefolder
chmod 755 /home/newuser/writeablefolder
groupadd sftpusers
usermod -G sftpusers newuser
service sshd restart
service vsftpd restart
Replace a broken harddisk in RAID1
# Replacing a broken harddisk (/dev/sda) with two partitions with RAID1 (md0 + md1):
# after having replaced the harddisk; copying MBR partition table
sfdisk -d /dev/sdb | sfdisk /dev/sda
# adding partitions to existing RAID-array md0 and md1:
sudo mdadm /dev/md0 -a /dev/sda1
sudo mdadm /dev/md1 -a /dev/sda2
# reinstalling grub on both disks again, leave options empty, select two disks (/dev/sda + /dev/sdb)
sudo dpkg-reconfigure grub-pc
Count files
# Bash: iterate through all files within a specific folder and count its files
for i in /folderpath /folderpath ; do
echo -n $i": " ;
(find "$i" -type f | wc -l) ;
done
Proxmox: Copy KVM to Proxmox
# converting image
qemu-img convert -f qcow2 -O raw image.qcow2 image.img
# creating VM in proxmox
qm create 120 --bootdisk scsi0
# importing disk to someStorage (as named in "pvesm status")
# importdisk adds the image as unused disk
qm importdisk 120 someImage.img someStorage
# attaching the image to the VM. still needs to be marked as boot device by hand
qm set 120 --scsi0 someStorage:vm-120-disk-0
Proxmox: Repair ZFS
# "zpool status" output during normal operation
pool: rpool
state: ONLINE
scan: none requested
config:
NAME STATE READ WRITE CKSUM
rpool ONLINE 0 0 0
mirror-0 ONLINE 0 0 0
ata-SanDisk_SDSSDH3_2T00_193732800276-part3 ONLINE 0 0 0
ata-SanDisk_SDSSDH32000G_192970802134-part3 ONLINE 0 0 0
errors: No known data errors
# "zpool status" of degraded state if we unplug /dev/sdb manually
pool: rpool
state: DEGRADED
status: One or more devices could not be used because the label is missing or
invalid. Sufficient replicas exist for the pool to continue
functioning in a degraded state.
action: Replace the device using 'zpool replace'.
see: http://zfsonlinux.org/msg/ZFS-8000-4J
scan: none requested
config:
NAME STATE READ WRITE CKSUM
rpool DEGRADED 0 0 0
mirror-0 DEGRADED 0 0 0
ata-SanDisk_SDSSDH3_2T00_193732800276-part3 ONLINE 0 0 0
ata-SanDisk_SDSSDH32000G_192970802134-part3 UNAVAIL 3 212 0
errors: No known data errors
We see that the disk with ID ata-SanDisk_SDSSDH32000G_192970802134-part3 is not available any more. We have to do the following steps:
- shutdown the server
- plug in a brand new replacement disk
- boot the server up again
You’ll see now another status:
pool: rpool
state: DEGRADED
status: One or more devices could not be used because the label is missing or
invalid. Sufficient replicas exist for the pool to continue
functioning in a degraded state.
action: Replace the device using 'zpool replace'.
see: http://zfsonlinux.org/msg/ZFS-8000-4J
scan: none requested
config:
NAME STATE READ WRITE CKSUM
rpool DEGRADED 0 0 0
mirror-0 DEGRADED 0 0 0
ata-SanDisk_SDSSDH3_2T00_193732800276-part3 ONLINE 0 0 0
14464946144281260868 UNAVAIL 0 0 0 was /dev/disk/by-id/ata-SanDisk_SDSSDH32000G_192970802134-part3
We need to prepare the new drive and replace it:
# copy partition table from good /dev/sda to new /dev/sdb
sgdisk -R /dev/sdb /dev/sda
sgdisk -G /dev/sdb
# copy the bios and efi boot partitions
dd if=/dev/sda1 of=/dev/sdb1 bs=512
dd if=/dev/sda2 of=/dev/sdb2 bs=512
# replace command
zpool replace rpool ata-SanDisk_SDSSDH32000G_192970802134-part3 /dev/sdb3
Keep in mind: Never use the detach command to remove a disk from a pool, because by adding it again you might be not careful enough to add it in mirror function. The default behaviour is to add a disk in striping mode (raid0)! You’ll have to backup everything and to reinstall a mirrored array again from scratch. Useful commands are:
# show raid status
zpool status
# show all your disk IDs
ls -l /dev/disk/by-id/
Fix the issue with locale
Issue looks like:
perl: warning: Setting locale failed.
perl: warning: Please check that your locale settings:
LANGUAGE = (unset),
LC_ALL = (unset),
LC_CTYPE = "UTF-8",
LANG = "en_US.UTF-8"
are supported and installed on your system.
perl: warning: Falling back to a fallback locale ("en_US.UTF-8").
# fixing it
sudo locale-gen en_US.UTF-8
sudo localedef -i en_US -f UTF-8 en_US.UTF-8
sudo nano /etc/environment
+export LANGUAGE=en_US.UTF-8
+export LANG=en_US.UTF-8
+export LC_ALL=en_US.UTF-8
Replacing a faulty disk in Software-RAID1
Assumption: We have a running software RAID1 at moint point /dev/md0 consisting of the following partitions:
- /dev/sda1
- /dev/sdb1
# You can get some detailed information about the fitness of /dev/md0 by issuing:
cat /proc/mdstat
# An exemplary entry looks like this:
Personalities : [raid1]
md0 : active raid1 sdb1[1] sda1[0]
136448 blocks [2/2] [UU]
It tells us that:
- it’s a raid1 array
- md0 consists of sda1 (first part) and sdb1 (second part)
- the raid1 is running synchronously > [UU]
If one partition of your raid fails then you will see underscores instead of the character ‘U’: [U_] or [_U] (depends on which partition is faulty).
Replacing a failed partition
For explanatory purposes we assume /dev/sdb1 to be faulty. If you want to replace the disk you have to follow the following steps:
(Optional) If your partition isn’t already marked failed you have to mark it failed:
sudo mdadm --manage /dev/md0 --fail /dev/sdb1
Then you can remove the faulty partition from the array md0:
sudo mdadm --manage /dev/md0 --remove
Remember: In our example we just have one partition per disk. If you have more than one partition belonging to multiple arrays, be sure to remove all partitions of that one particular disk which you want to replace. Example: another additional /dev/sdb2 could belong to /dev/md1.
Once all your partitions from the faulty disk are removed from all raid arrays you can replace the disk by replacing it with a new one. You should shutdown the system before 😉 Since this new one won’t be partitioned like the old one, we need to copy the partition structure from the disk which is still active in our array (/dev/sda). For copying a GTP partition structure from /dev/sda to our new /dev/sdb and creating a new UUID we can use:
# copy sda to sdb (GPT)
sudo sgdisk -R /dev/sdb /dev/sda
# create UUID
sudo sgdisk -G /dev/sdb
If you use classical MBR for disks below 2TB:
# copy sda to sdb (MBR)
sudo sfdisk -d /dev/sda | sudo sfdisk /dev/sdb
After having copied the partition structure we need to add the partition /dev/sdb1 back again to our array /dev/md0:
sudo mdadm --manage /dev/md0 --add /dev/sdb1
Now you can watch the progress of rebuilding your software array which is running completely transparent in the background until the target state of [UU] is reached again:
Personalities : [raid1]
md0 : active raid1 sdb1[1] sda1[0]
1464725760 blocks level 5, 64k chunk, algorithm 2 [6/5] [U_]
[==>..................] recovery = 12.6% (37043392/292945152) finish=127.5min speed=33440K/sec
If you replaced a bootable disk (for instance /dev/sda) think about installing GRUB again. It might be helpful to copy the full boot partition (let’s say /dev/sda0) to /dev/sdb0 and to install GRUB also on /dev/sdb in order to allow booting from both disks.
# installing GRUB
sudo grub-install /dev/sda
Things to do after installing Ubuntu 24.04
# update the system
sudo apt update && sudo apt upgrade && sudo apt autoremove
# useful stuff
sudo apt install curl htop neofetch ncdu wget unrar git p7zip-full vlc
# install vbox according to https://freundschafter.com/how-to-install-virtualbox-7-1-on-ubuntu-24-04/
# install media codecs
sudo apt install ubuntu-restricted-extras
# enable minimize on click (on a symbol in dock)
gsettings set org.gnome.shell.extensions.dash-to-dock click-action 'minimize'
# further stuff if needed
# https://kskroyal.com/ubuntu-24-04-post-install-steps