New directory and icons
This commit is contained in:
		@@ -49,6 +49,18 @@
 | 
				
			|||||||
    max-width: var(--elements-container-maxWidth);
 | 
					    max-width: var(--elements-container-maxWidth);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.has-parent-icon .icon {
 | 
				
			||||||
 | 
					    color: #ADA9A4;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.has-parent-icon.active .icon {
 | 
				
			||||||
 | 
					    color: var(--color-primary-500) !important;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.card:hover{
 | 
				
			||||||
 | 
					    color:#00304a;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
p img {
 | 
					p img {
 | 
				
			||||||
    border-radius:7px;
 | 
					    border-radius:7px;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,5 @@
 | 
				
			|||||||
---
 | 
					---
 | 
				
			||||||
 | 
					icon: lucide:home
 | 
				
			||||||
title: Welcome
 | 
					title: Welcome
 | 
				
			||||||
main:
 | 
					main:
 | 
				
			||||||
  fluid: false
 | 
					  fluid: false
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										2
									
								
								content/2.general/1.networking/_dir.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								content/2.general/1.networking/_dir.yml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,2 @@
 | 
				
			|||||||
 | 
					navigation.title: Networking
 | 
				
			||||||
 | 
					icon: lucide:network
 | 
				
			||||||
							
								
								
									
										2
									
								
								content/2.general/2.storage/_dir.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								content/2.general/2.storage/_dir.yml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,2 @@
 | 
				
			|||||||
 | 
					navigation.title: Storage
 | 
				
			||||||
 | 
					icon: lucide:hard-drive
 | 
				
			||||||
@@ -1,4 +1,5 @@
 | 
				
			|||||||
---
 | 
					---
 | 
				
			||||||
 | 
					icon: lucide:bookmark
 | 
				
			||||||
navigation: true
 | 
					navigation: true
 | 
				
			||||||
title: Introduction
 | 
					title: Introduction
 | 
				
			||||||
main:
 | 
					main:
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1 +1,2 @@
 | 
				
			|||||||
navigation.title: Server core
 | 
					navigation.title: Server core
 | 
				
			||||||
 | 
					icon: lucide:server-cog
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1 +1,2 @@
 | 
				
			|||||||
navigation.title: Security
 | 
					navigation.title: Security
 | 
				
			||||||
 | 
					icon: lucide:shield
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1 +1,2 @@
 | 
				
			|||||||
navigation.title: Monitoring
 | 
					navigation.title: Monitoring
 | 
				
			||||||
 | 
					icon: lucide:chart-no-axes-column
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1 +1,2 @@
 | 
				
			|||||||
navigation.title: Media & Seedbox
 | 
					navigation.title: Media & Seedbox
 | 
				
			||||||
 | 
					icon: lucide:list-video
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1 +1,2 @@
 | 
				
			|||||||
navigation.title: Cloud Drive & Photos
 | 
					navigation.title: Cloud Drive & Photos
 | 
				
			||||||
 | 
					icon: lucide:cloud-upload
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1 +1,2 @@
 | 
				
			|||||||
navigation.title: File & share
 | 
					navigation.title: File & share
 | 
				
			||||||
 | 
					icon: lucide:folder-tree
 | 
				
			||||||
@@ -1 +1,2 @@
 | 
				
			|||||||
navigation.title: Developpement
 | 
					navigation.title: Developpement
 | 
				
			||||||
 | 
					icon: lucide:code-xml
 | 
				
			||||||
@@ -1 +1,2 @@
 | 
				
			|||||||
navigation.title: Useful Apps
 | 
					navigation.title: Useful Apps
 | 
				
			||||||
 | 
					icon: lucide:award
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,5 @@
 | 
				
			|||||||
---
 | 
					---
 | 
				
			||||||
 | 
					icon: lucide:bookmark
 | 
				
			||||||
navigation: true
 | 
					navigation: true
 | 
				
			||||||
title: Introduction
 | 
					title: Introduction
 | 
				
			||||||
main:
 | 
					main:
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										39
									
								
								content/5.nonsense/1.python/1.nvidia-stock-bot.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								content/5.nonsense/1.python/1.nvidia-stock-bot.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,39 @@
 | 
				
			|||||||
 | 
					---
 | 
				
			||||||
 | 
					navigation: true
 | 
				
			||||||
 | 
					title: Nvidia Stock Bot
 | 
				
			||||||
 | 
					main:
 | 
				
			||||||
 | 
					  fluid: false
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					:ellipsis{left=0px width=40rem top=10rem blur=140px}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# 🤖 Nvidia Stock Bot
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					For the past four years, the electronics hardware shortage has been relentless. Graphics cards are no exception. In 2020, I had to wait two months to get my RTX 3080. To manage it, I joined [JV Hardware](https://discord.gg/gxffg3GA96), where a small group of geeks had set up a bot that pinged users when GPUs became available.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Four years later and with 5,000 members on the server, the RTX 5000 series is being released. Yet, no working stock bot seems to exist. Not to mention a certain “influencer” who charges users for access to a bot that doesn’t even work. He manually copies alerts from other servers like ours, which have already solved the issue.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Anyway, eager to get an RTX 5090 for my AI-dedicated machine, I decided it was time to dive into Python—with a little help from ChatGPT. Along with another member, KevOut, who helped guide me through the APIs and initial architecture, I ended up building a clean and functional bot that sends different kinds of Discord alerts—all deployable in a simple Docker container.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					After many setbacks, I went from this:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					To this:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					And more recently :
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					And I was also lucky enough to be referenced in the famous [selfhost newsletter](https://selfh.st/weekly/2025-07-11/) !
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					More info directly on the repo:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					::card
 | 
				
			||||||
 | 
					#title
 | 
				
			||||||
 | 
					  🐋 __Nvidia Stock Bot__
 | 
				
			||||||
 | 
					#description
 | 
				
			||||||
 | 
					  [Nvidia GPU stock alert bot](https://git.djeex.fr/Djeex/nvidia-stock-bot)
 | 
				
			||||||
 | 
					::
 | 
				
			||||||
@@ -1,47 +1,12 @@
 | 
				
			|||||||
---
 | 
					---
 | 
				
			||||||
navigation: true
 | 
					navigation: true
 | 
				
			||||||
title: Python Scripts
 | 
					title: Adguard CIDRE
 | 
				
			||||||
main:
 | 
					main:
 | 
				
			||||||
  fluid: false
 | 
					  fluid: false
 | 
				
			||||||
---
 | 
					---
 | 
				
			||||||
:ellipsis{left=0px width=40rem top=10rem blur=140px}
 | 
					:ellipsis{left=0px width=40rem top=10rem blur=140px}
 | 
				
			||||||
# Python Scripts
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
My messy Python creations
 | 
					# 🤖 Adguard CIDRE Sync
 | 
				
			||||||
 | 
					 | 
				
			||||||
## 🤖 Nvidia Stock Bot
 | 
					 | 
				
			||||||
---
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
For the past four years, the electronics hardware shortage has been relentless. Graphics cards are no exception. In 2020, I had to wait two months to get my RTX 3080. To manage it, I joined [JV Hardware](https://discord.gg/gxffg3GA96), where a small group of geeks had set up a bot that pinged users when GPUs became available.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Four years later and with 5,000 members on the server, the RTX 5000 series is being released. Yet, no working stock bot seems to exist. Not to mention a certain “influencer” who charges users for access to a bot that doesn’t even work. He manually copies alerts from other servers like ours, which have already solved the issue.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Anyway, eager to get an RTX 5090 for my AI-dedicated machine, I decided it was time to dive into Python—with a little help from ChatGPT. Along with another member, KevOut, who helped guide me through the APIs and initial architecture, I ended up building a clean and functional bot that sends different kinds of Discord alerts—all deployable in a simple Docker container.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
After many setbacks, I went from this:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||

 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
To this:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||

 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
And more recently :
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||

 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
And I was also lucky enough to be referenced in the famous [selfhost newsletter](https://selfh.st/weekly/2025-07-11/) !
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
More info directly on the repo:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
::card
 | 
					 | 
				
			||||||
#title
 | 
					 | 
				
			||||||
  🐋 __Nvidia Stock Bot__
 | 
					 | 
				
			||||||
#description
 | 
					 | 
				
			||||||
  [Nvidia GPU stock alert bot](https://git.djeex.fr/Djeex/nvidia-stock-bot)
 | 
					 | 
				
			||||||
::
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
## 🤖 Adguard CIDRE Sync
 | 
					 | 
				
			||||||
---
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Adguard Home is a fantastic solution for DNS-level ad blocking and rewriting requests—perfect for removing ISP DNS trackers or intrusive ads.
 | 
					Adguard Home is a fantastic solution for DNS-level ad blocking and rewriting requests—perfect for removing ISP DNS trackers or intrusive ads.
 | 
				
			||||||
							
								
								
									
										2
									
								
								content/5.nonsense/1.python/_dir.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								content/5.nonsense/1.python/_dir.yml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,2 @@
 | 
				
			|||||||
 | 
					navigation.title: Python
 | 
				
			||||||
 | 
					icon: lucide:file-code-2
 | 
				
			||||||
@@ -5,11 +5,7 @@ main:
 | 
				
			|||||||
  fluid: false
 | 
					  fluid: false
 | 
				
			||||||
---
 | 
					---
 | 
				
			||||||
:ellipsis{left=0px width=40rem top=10rem blur=140px}
 | 
					:ellipsis{left=0px width=40rem top=10rem blur=140px}
 | 
				
			||||||
# Bash Scripts
 | 
					# Servarr duplicates corrector
 | 
				
			||||||
 | 
					 | 
				
			||||||
A few random scripts that saved my life.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
## Detecting Duplicates and Replacing Them with Hardlinks
 | 
					 | 
				
			||||||
---
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Six months after downloading terabytes of media, I realized that Sonarr and Radarr were copying them into my Plex library instead of creating hardlinks. This happens due to a counterintuitive mechanism: if you mount multiple folders in Sonarr/Radarr, it sees them as different filesystems and thus cannot create hardlinks. That’s why you should mount only one parent folder containing all child folders (like `downloads`, `movies`, `tvseries` inside a `media` parent folder).
 | 
					Six months after downloading terabytes of media, I realized that Sonarr and Radarr were copying them into my Plex library instead of creating hardlinks. This happens due to a counterintuitive mechanism: if you mount multiple folders in Sonarr/Radarr, it sees them as different filesystems and thus cannot create hardlinks. That’s why you should mount only one parent folder containing all child folders (like `downloads`, `movies`, `tvseries` inside a `media` parent folder).
 | 
				
			||||||
@@ -143,84 +139,3 @@ So, in conclusion, I:
 | 
				
			|||||||
- Learned never to blindly copy-paste a ChatGPT script without understanding and dry-running it
 | 
					- Learned never to blindly copy-paste a ChatGPT script without understanding and dry-running it
 | 
				
			||||||
- Learned that Qwen on a RTX 5090 is more coherent than ChatGPT-4o on server farms (not even mentioning “normal” ChatGPT)
 | 
					- Learned that Qwen on a RTX 5090 is more coherent than ChatGPT-4o on server farms (not even mentioning “normal” ChatGPT)
 | 
				
			||||||
- Learned that even with 100TB of storage, monitoring it would’ve alerted me much earlier to the 12TB of duplicates lying around
 | 
					- Learned that even with 100TB of storage, monitoring it would’ve alerted me much earlier to the 12TB of duplicates lying around
 | 
				
			||||||
 | 
					 | 
				
			||||||
## Backup of LUKS Headers for Encrypted Disks/Volumes
 | 
					 | 
				
			||||||
---
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
I recently realized that having just the password is not enough to unlock a LUKS volume after a failure or corruption. I learned how to dump the LUKS headers from disks/volumes and to use the serial numbers along with partition names to accurately identify which header corresponds to which disk/partition (I have 10 of them!).
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
After struggling to do this manually, I asked Qwen3 (an LLM running on my RTX 5090) to create a script that automates the listing and identification of disks, dumps the headers, and stores them in an encrypted archive ready to be backed up on my backup server.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
This script:
 | 
					 | 
				
			||||||
* Lists and identifies disks with their serial numbers
 | 
					 | 
				
			||||||
* Lists partitions
 | 
					 | 
				
			||||||
* Dumps headers into a secured folder under `/root`
 | 
					 | 
				
			||||||
* Creates a temporary archive
 | 
					 | 
				
			||||||
* Prompts for a password
 | 
					 | 
				
			||||||
* Encrypts the archive with that password
 | 
					 | 
				
			||||||
* Deletes the unencrypted archive
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
```bash
 | 
					 | 
				
			||||||
#!/bin/bash
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Directory where LUKS headers will be backed up
 | 
					 | 
				
			||||||
DEST="/root/luks-headers-backup"
 | 
					 | 
				
			||||||
mkdir -p "$DEST"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
echo "🔍 Searching for LUKS containers on all partitions..."
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Loop through all possible disk partitions (including NVMe and SATA)
 | 
					 | 
				
			||||||
for part in /dev/sd? /dev/sd?? /dev/nvme?n?p?; do
 | 
					 | 
				
			||||||
    # Skip if the device doesn't exist
 | 
					 | 
				
			||||||
    if [ ! -b "$part" ]; then
 | 
					 | 
				
			||||||
        continue
 | 
					 | 
				
			||||||
    fi
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # Check if the partition is a LUKS encrypted volume
 | 
					 | 
				
			||||||
    if cryptsetup isLuks "$part"; then
 | 
					 | 
				
			||||||
        # Find the parent disk device (e.g. nvme0n1p4 → nvme0n1)
 | 
					 | 
				
			||||||
        disk=$(lsblk -no pkname "$part" | head -n 1)
 | 
					 | 
				
			||||||
        full_disk="/dev/$disk"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        # Get the serial number of the parent disk
 | 
					 | 
				
			||||||
        SERIAL=$(udevadm info --query=all --name="$full_disk" | grep ID_SERIAL= | cut -d= -f2)
 | 
					 | 
				
			||||||
        if [ -z "$SERIAL" ]; then
 | 
					 | 
				
			||||||
            SERIAL="unknown"
 | 
					 | 
				
			||||||
        fi
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        # Extract the partition name (e.g. nvme0n1p4)
 | 
					 | 
				
			||||||
        PART_NAME=$(basename "$part")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        # Build the output filename with partition name and disk serial
 | 
					 | 
				
			||||||
        OUTPUT="$DEST/luks-header-${PART_NAME}__${SERIAL}.img"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        echo "🔐 Backing up LUKS header of $part (Serial: $SERIAL)..."
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        # Backup the LUKS header to the output file
 | 
					 | 
				
			||||||
        cryptsetup luksHeaderBackup "$part" --header-backup-file "$OUTPUT"
 | 
					 | 
				
			||||||
        if [[ $? -eq 0 ]]; then
 | 
					 | 
				
			||||||
            echo "✅ Backup successful → $OUTPUT"
 | 
					 | 
				
			||||||
        else
 | 
					 | 
				
			||||||
            echo "❌ Backup failed for $part"
 | 
					 | 
				
			||||||
        fi
 | 
					 | 
				
			||||||
    fi
 | 
					 | 
				
			||||||
done
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Create a timestamped compressed tar archive of all header backups
 | 
					 | 
				
			||||||
ARCHIVE_NAME="/root/luks-headers-$(date +%Y%m%d_%H%M%S).tar.gz"
 | 
					 | 
				
			||||||
echo "📦 Creating archive $ARCHIVE_NAME..."
 | 
					 | 
				
			||||||
tar -czf "$ARCHIVE_NAME" -C "$DEST" .
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Encrypt the archive symmetrically using GPG with AES256 cipher
 | 
					 | 
				
			||||||
echo "🔐 Encrypting the archive with GPG..."
 | 
					 | 
				
			||||||
gpg --symmetric --cipher-algo AES256 "$ARCHIVE_NAME"
 | 
					 | 
				
			||||||
if [[ $? -eq 0 ]]; then
 | 
					 | 
				
			||||||
    echo "✅ Encrypted archive created: ${ARCHIVE_NAME}.gpg"
 | 
					 | 
				
			||||||
    # Remove the unencrypted archive for security
 | 
					 | 
				
			||||||
    rm -f "$ARCHIVE_NAME"
 | 
					 | 
				
			||||||
else
 | 
					 | 
				
			||||||
    echo "❌ Encryption failed"
 | 
					 | 
				
			||||||
fi
 | 
					 | 
				
			||||||
```
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
**Don’t forget to back up `/etc/fstab` and `/etc/crypttab` as well!**
 | 
					 | 
				
			||||||
							
								
								
									
										88
									
								
								content/5.nonsense/2.bash/2.luks- backup.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								content/5.nonsense/2.bash/2.luks- backup.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,88 @@
 | 
				
			|||||||
 | 
					---
 | 
				
			||||||
 | 
					navigation: true
 | 
				
			||||||
 | 
					title: LUKS Backup
 | 
				
			||||||
 | 
					main:
 | 
				
			||||||
 | 
					  fluid: false
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					:ellipsis{left=0px width=40rem top=10rem blur=140px}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Backup of LUKS Headers for Encrypted Disks/Volumes
 | 
				
			||||||
 | 
					---
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					I recently realized that having just the password is not enough to unlock a LUKS volume after a failure or corruption. I learned how to dump the LUKS headers from disks/volumes and to use the serial numbers along with partition names to accurately identify which header corresponds to which disk/partition (I have 10 of them!).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					After struggling to do this manually, I asked Qwen3 (an LLM running on my RTX 5090) to create a script that automates the listing and identification of disks, dumps the headers, and stores them in an encrypted archive ready to be backed up on my backup server.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This script:
 | 
				
			||||||
 | 
					* Lists and identifies disks with their serial numbers
 | 
				
			||||||
 | 
					* Lists partitions
 | 
				
			||||||
 | 
					* Dumps headers into a secured folder under `/root`
 | 
				
			||||||
 | 
					* Creates a temporary archive
 | 
				
			||||||
 | 
					* Prompts for a password
 | 
				
			||||||
 | 
					* Encrypts the archive with that password
 | 
				
			||||||
 | 
					* Deletes the unencrypted archive
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```bash
 | 
				
			||||||
 | 
					#!/bin/bash
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Directory where LUKS headers will be backed up
 | 
				
			||||||
 | 
					DEST="/root/luks-headers-backup"
 | 
				
			||||||
 | 
					mkdir -p "$DEST"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					echo "🔍 Searching for LUKS containers on all partitions..."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Loop through all possible disk partitions (including NVMe and SATA)
 | 
				
			||||||
 | 
					for part in /dev/sd? /dev/sd?? /dev/nvme?n?p?; do
 | 
				
			||||||
 | 
					    # Skip if the device doesn't exist
 | 
				
			||||||
 | 
					    if [ ! -b "$part" ]; then
 | 
				
			||||||
 | 
					        continue
 | 
				
			||||||
 | 
					    fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Check if the partition is a LUKS encrypted volume
 | 
				
			||||||
 | 
					    if cryptsetup isLuks "$part"; then
 | 
				
			||||||
 | 
					        # Find the parent disk device (e.g. nvme0n1p4 → nvme0n1)
 | 
				
			||||||
 | 
					        disk=$(lsblk -no pkname "$part" | head -n 1)
 | 
				
			||||||
 | 
					        full_disk="/dev/$disk"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Get the serial number of the parent disk
 | 
				
			||||||
 | 
					        SERIAL=$(udevadm info --query=all --name="$full_disk" | grep ID_SERIAL= | cut -d= -f2)
 | 
				
			||||||
 | 
					        if [ -z "$SERIAL" ]; then
 | 
				
			||||||
 | 
					            SERIAL="unknown"
 | 
				
			||||||
 | 
					        fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Extract the partition name (e.g. nvme0n1p4)
 | 
				
			||||||
 | 
					        PART_NAME=$(basename "$part")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Build the output filename with partition name and disk serial
 | 
				
			||||||
 | 
					        OUTPUT="$DEST/luks-header-${PART_NAME}__${SERIAL}.img"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        echo "🔐 Backing up LUKS header of $part (Serial: $SERIAL)..."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Backup the LUKS header to the output file
 | 
				
			||||||
 | 
					        cryptsetup luksHeaderBackup "$part" --header-backup-file "$OUTPUT"
 | 
				
			||||||
 | 
					        if [[ $? -eq 0 ]]; then
 | 
				
			||||||
 | 
					            echo "✅ Backup successful → $OUTPUT"
 | 
				
			||||||
 | 
					        else
 | 
				
			||||||
 | 
					            echo "❌ Backup failed for $part"
 | 
				
			||||||
 | 
					        fi
 | 
				
			||||||
 | 
					    fi
 | 
				
			||||||
 | 
					done
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Create a timestamped compressed tar archive of all header backups
 | 
				
			||||||
 | 
					ARCHIVE_NAME="/root/luks-headers-$(date +%Y%m%d_%H%M%S).tar.gz"
 | 
				
			||||||
 | 
					echo "📦 Creating archive $ARCHIVE_NAME..."
 | 
				
			||||||
 | 
					tar -czf "$ARCHIVE_NAME" -C "$DEST" .
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Encrypt the archive symmetrically using GPG with AES256 cipher
 | 
				
			||||||
 | 
					echo "🔐 Encrypting the archive with GPG..."
 | 
				
			||||||
 | 
					gpg --symmetric --cipher-algo AES256 "$ARCHIVE_NAME"
 | 
				
			||||||
 | 
					if [[ $? -eq 0 ]]; then
 | 
				
			||||||
 | 
					    echo "✅ Encrypted archive created: ${ARCHIVE_NAME}.gpg"
 | 
				
			||||||
 | 
					    # Remove the unencrypted archive for security
 | 
				
			||||||
 | 
					    rm -f "$ARCHIVE_NAME"
 | 
				
			||||||
 | 
					else
 | 
				
			||||||
 | 
					    echo "❌ Encryption failed"
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					**Don’t forget to back up `/etc/fstab` and `/etc/crypttab` as well!**
 | 
				
			||||||
							
								
								
									
										2
									
								
								content/5.nonsense/2.bash/_dir.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								content/5.nonsense/2.bash/_dir.yml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,2 @@
 | 
				
			|||||||
 | 
					navigation.title: Bash
 | 
				
			||||||
 | 
					icon: lucide:file-terminal
 | 
				
			||||||
		Reference in New Issue
	
	Block a user