No description
Find a file
Nikki Claude a66fe2df6c refactor: rewrite keystore.sh, add README, env.example
- fix MOUNT_PONT typo (mount point check was never reached)
- set -euo pipefail, proper .env sourcing via set -a
- rsync_if_exists helper: skip missing dirs gracefully
- USB copy: auto-detect /media/$USER, /run/media/$USER or via USB_MOUNT/USB_LABEL from .env
- remote SCP: non-fatal if host unreachable
- add ~/.step, ~/.kube, ~/.config/gh, ~/.config/borg to backup sources
- remove dead commented-out cp -r code
- add README.md with setup/usage/restore notes
- fill env.example with all variables
- gitignore: *.img glob, encrypted-key-backup.html
2026-03-29 02:35:56 +07:00
.gitignore refactor: rewrite keystore.sh, add README, env.example 2026-03-29 02:35:56 +07:00
env.example refactor: rewrite keystore.sh, add README, env.example 2026-03-29 02:35:56 +07:00
keystore.sh refactor: rewrite keystore.sh, add README, env.example 2026-03-29 02:35:56 +07:00
README.md refactor: rewrite keystore.sh, add README, env.example 2026-03-29 02:35:56 +07:00

keystore-backup

Encrypted local backup of sensitive key material — SSH, GPG, passwords, certs, VPN configs.

Creates a LUKS-encrypted disk image, syncs key directories into it, then ships the image to a remote server and/or USB flash drive.


What gets backed up

Source Contents
~/.ssh SSH keys and config
~/.gnupg GPG keyring
~/.password-store pass password store
~/.borg / ~/.config/borg BorgBackup keys and config
~/.step step-ca client certs and config
~/.kube Kubernetes config
~/.config/gh GitHub CLI auth
~/.local/share/MikroTik WinBox addresses and workspaces
~/.local/share/remmina Remmina connection profiles
~/.ga-cmd ga-cmd config
~/.nx NoMachine sessions (no cache/logs)

Setup

cp env.example .env
$EDITOR .env

Required variables:

REMOTE_SRV    — SSH alias (from ~/.ssh/config) or user@host
REMOTE_HOST   — IP for reachability check (nmap)
REMOTE_DIR    — destination path on remote
PORT1/2/3     — ports to probe for availability check

Optional for USB:

USB_MOUNT     — explicit mount point (e.g. /media/user/FLASHDRIVE)
USB_LABEL     — volume label (alternative to USB_MOUNT)

If neither is set, script auto-detects from /media/$USER and /run/media/$USER.


Usage

sudo ./keystore.sh

Needs sudo for cryptsetup, mount, umount.

First run: creates keystore.img (64MB LUKS + ext4), prompts for passphrase. Subsequent runs: opens existing image, re-syncs all sources, closes, ships.


Destinations

  1. Remote server — SCP to $REMOTE_SRV:$REMOTE_DIR/keystore.img Before sending, probes $REMOTE_HOST ports via nmap. If remote is unreachable — warns and skips (non-fatal).

  2. USB flash — copies keystore.img to detected USB mount. If no USB found — warns and skips (non-fatal).


Files

keystore.sh              — main script
env.example              — config template (copy to .env)
encrypted-key-backup.html — BorgBackup paper key printable template (offline, self-contained)

keystore.img and .env are gitignored — never commit them.


Paper key backup

Open encrypted-key-backup.html in a browser (no internet needed). Load your BorgBackup keyfile → generates printable paper key + QR code. Print and store offline.


Notes

  • LUKS passphrase is the only protection — choose a strong one and store it separately
  • keystore.img is portable: open on any Linux with cryptsetup luksOpen
  • Test restore periodically: mount the image and verify contents