Skip to content

Instantly share code, notes, and snippets.

@nerun
Last active June 27, 2026 13:42
Show Gist options
  • Select an option

  • Save nerun/cc053edec6715421c2ddd2aec77c6580 to your computer and use it in GitHub Desktop.

Select an option

Save nerun/cc053edec6715421c2ddd2aec77c6580 to your computer and use it in GitHub Desktop.
Keeper of Mythos, a graphical frontend for the basic commands of cryptsetup / dm-crypt / LUKS for creating encrypted containers in files.
#!/bin/bash
#
# keeper.sh - version 3 - June 27, 2026
# Copyright (c) 2025-2026 Daniel Dias Rodrigues. No rights reserved.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the Creative Commons Zero 1.0 Universal (CC0 1.0) Public
# Domain Dedication (https://creativecommons.org/publicdomain/zero/1.0/).
#
readme="# Keeper of Mythos
# Copyright (c) 2025 Daniel Dias Rodrigues. No rights reserved.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the Creative Commons Zero 1.0 Universal (CC0 1.0) Public
# Domain Dedication (https://creativecommons.org/publicdomain/zero/1.0/).
Welcome to your Tome of Arcane Lore!
This secure storage space was created using Keeper of Mythos, a graphical
frontend for managing encrypted containers on Linux.
## What is this?
This is an encrypted, rewritable disk image file that functions as a secure
digital vault. You can store confidential files, documents, or any data you
wish to keep secret.
## Technical Details
- **Encryption**: LUKS2 (Linux Unified Key Setup)
- **File System**: ext4
- **Access Method**: Password-based encryption
## How to Use
1. Use Keeper of Mythos or cryptsetup tools to open this container
2. Remember to properly close/seal the container after use
## Security Notes
- Keep your password safe and secure. The security of your data depends on
keeping your password confidential.
- Always close/seal the container when not in use.
- Consider backing up important files stored here.
- The container file itself should be stored in a safe location.
## About
I created this frontend purely as a fun exercise to simplify the basics of
creating and managing encrypted containers.
It covers the essential creation, opening, and closing commands present in
cryptsetup. If you need a more capable frontend, I recommend \"Tomb, the
Crypto Undertaker\" <https://www.dyne.org/software/tomb>.
Since this is a frontend for cryptsetup, you can use all cryptsetup commands
to manage this container, including those not covered in this tool, such as
\"luksAddKey\" and others.
The \".tome\" extension is arbitrary and could be replaced with \".img\" or any
other extension.
## The Joke Explained
The names follow a Cthulhu/Lovecraftian theme:
- \"Keeper of Mythos\" alludes both to the Game Master and to Cthulhu Mythos in
Chaosium's Call of Cthulhu RPG
- A \"tome\" is an ancient book of spells and arcane knowledge
- The password is a \"secret spell\"
- Entering the password is \"casting the spell\" to open the magically sealed
tome
- \"Sealing\" the tome means unmounting and closing (re-encrypting) it
May your secrets remain forever hidden from prying eyes!"
authenticate_sudo() {
local password attempts=0 max_attempts=3
while [ $attempts -lt $max_attempts ]; do
password=$(zenity --password --title="Superuser Privileges Required")
[ $? -ne 0 ] || [ -z "$password" ] && { zenity --error --text="Authentication canceled."; exit 1; }
if echo "$password" | sudo -S -v 2>/dev/null; then
( while true; do sleep 60; sudo -n true 2>/dev/null || break; done ) &
zenity --info --text="Authentication successful!" --timeout=2
return 0
else
attempts=$((attempts + 1))
remaining=$((max_attempts - attempts))
[ $remaining -gt 0 ] && zenity --error --text="Incorrect password. Remaining attempts: $remaining" \
|| { zenity --error --text="Maximum attempts exceeded."; exit 1; }
fi
done
}
show_progress() {
PROGRESS_FIFO=$(mktemp -u)
mkfifo "$PROGRESS_FIFO"
zenity --progress --title="Keeper of Mythos" \
--text="Inscribing arcane seals... Please wait." \
--pulsate --auto-close --no-cancel < "$PROGRESS_FIFO" &
PROGRESS_PID=$!
exec 3>"$PROGRESS_FIFO"
sleep 0.2
}
kill_progress() {
exec 3>&-
wait "$PROGRESS_PID" 2>/dev/null
rm -f "$PROGRESS_FIFO"
}
generate_mapper_name() {
local base mapper n
base=$(basename "$1" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/-/g')
mapper="$base"
n=1
while [ -e "/dev/mapper/$mapper" ]; do
mapper="${base}-$n"
n=$((n + 1))
done
echo "$mapper"
}
scribe_tome() {
local file size pass
file=$(zenity --file-selection --save --title="Scribe Tome")
[ -z "$file" ] && return
size=$(zenity --entry --title="Tome Size" --text="Enter tome size (e.g. 50M, 2G):")
[ -z "$size" ] && return
pass=$(zenity --password --title="Inscribe a Secret Spell")
[ -z "$pass" ] && return
show_progress
truncate -s "$size" "$file"
echo -n "$pass" | sudo -S cryptsetup --batch-mode --key-file=- luksFormat --type luks2 "$file"
echo -n "$pass" | sudo -S cryptsetup --batch-mode --key-file=- open "$file" tome_tmp
sudo mkfs.ext4 /dev/mapper/tome_tmp
sudo mkdir -p /mnt/tome_tmp
sudo mount /dev/mapper/tome_tmp /mnt/tome_tmp
sudo chown "$USER": /mnt/tome_tmp
echo "$readme" > /mnt/tome_tmp/README.txt
sudo umount /mnt/tome_tmp
sudo rm -rf /mnt/tome_tmp
sudo cryptsetup close tome_tmp
kill_progress
zenity --info --title="Keeper" --text="Tome created successfully."
}
open_tome() {
local file mapper pass
file=$(zenity --file-selection --title="Open Tome")
[ -z "$file" ] && return
mapper=$(generate_mapper_name "$file")
pass=$(zenity --password --title="Cast Secret Spell")
[ -z "$pass" ] && return
echo -n "$pass" | sudo cryptsetup --batch-mode --key-file=- open "$file" "$mapper"
success=$?
sudo mkdir -p /mnt/"$mapper"
sudo mount /dev/mapper/"$mapper" /mnt/"$mapper"
if [ $success -eq 0 ]; then
zenity --info --title="Keeper" --text="Tome opened as:\n /dev/mapper/$mapper\nand mounted as:\n /mnt/$mapper"
else
zenity --error --title="Keeper" --text="Failed to open tome. Wrong spell?"
fi
}
seal_tome() {
local list choice
list=$(ls /dev/mapper | grep -E 'tome($|-)' || true)
[ -z "$list" ] && { zenity --info --title="Keeper" --text="There are no open tomes."; return; }
choice=$(zenity --list --title="Seal Tome" --text="Select a tome to close:" --column="Open Tomes" $list)
[ -z "$choice" ] && return
sudo umount /mnt/"$choice"
sudo rm -rf /mnt/"$choice"
sudo cryptsetup close "$choice"
zenity --info --title="Keeper" --text="Tome sealed."
}
main_menu() {
local choice
while true; do
choice=$(zenity --list --title="Keeper of Mythos" --text="Choose an action:" \
--column="Action" "Scribe Tome" "Open Tome" "Seal Tome")
[ -z "$choice" ] && exit 0
case "$choice" in
"Scribe Tome") scribe_tome ;;
"Open Tome") open_tome ;;
"Seal Tome") seal_tome ;;
esac
done
}
authenticate_sudo
main_menu
@nerun

nerun commented Jun 27, 2026

Copy link
Copy Markdown
Author

Suggestion of keeper.desktop. Replace YOUR_USER by your user's path. Save in ~/.local/share/applications.

[Desktop Entry]
Name=Keeper of Mythos
Exec=/home/YOUR_USER/.local/bin/keeper
Comment=
Terminal=false
PrefersNonDefaultGPU=false
Icon=/home/YOUR_USER/Images/keeper.png
Type=Application
Categories=Utility;

Choose any icon you wish. I use this one:
keeper

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment