feat: add pos system backup — encrypted folder snapshots with --service picker
This commit is contained in:
@@ -43,6 +43,7 @@ Linux_post_install/
|
||||
│ ├── pos-media-mp3 # Audio downloader (yt-dlp → MP3)
|
||||
│ ├── pos-media-mp4 # Video downloader (yt-dlp → MP4, interactive format select)
|
||||
│ ├── pos-system-firewall # Interactive UFW manager (menu-driven, 284 lines)
|
||||
│ ├── pos-system-backup # Encrypted folder snapshots (tar + gpg AES-256, --service) (115 lines)
|
||||
│ ├── pos-ssh-load-keys # Load SSH keys into ssh-agent
|
||||
│ ├── pos-vbox # Disposable Docker-based "VMs"
|
||||
│ ├── pos-network-hotspot # Wi-Fi hotspot (create_ap + wihotspot-gui)
|
||||
@@ -198,6 +199,7 @@ All non-interactive `pos` commands log output to `~/.local/share/linux_post_inst
|
||||
| media | mp3 | `pos-media-mp3` | Download audio as MP3 |
|
||||
| media | mp4 | `pos-media-mp4` | Download video with format select |
|
||||
| system | firewall | `pos-system-firewall` | Interactive UFW management |
|
||||
| system | backup | `pos-system-backup` | Encrypted folder snapshots (`tar` + gpg AES-256; `--service` picks from `/srv` and `~/srv`) |
|
||||
| ssh | load-keys | `pos-ssh-load-keys` | Load SSH keys into agent |
|
||||
| vbox | create | `pos-vbox create` | Create disposable VM (asks "Enter now?") |
|
||||
| vbox | enter | `pos-vbox enter` | Start and exec into container |
|
||||
@@ -445,6 +447,7 @@ Use conventional prefixes: `feat:`, `fix:`, `docs:`, `refactor:`, `chore:`
|
||||
| `bin/pos` | 146 | CLI dispatcher with smart arg matching + logging |
|
||||
| `bin/pos-docker-compose` | 363 | Largest script — full compose management |
|
||||
| `bin/pos-system-firewall` | 284 | Interactive UFW manager |
|
||||
| `bin/pos-system-backup` | 115 | Encrypted folder snapshots: path mode + `--service` (`/srv`, `~/srv` picker), tar + gpg AES-256 |
|
||||
| `bin/pos-docker-ps` | 127 | Enhanced container overview |
|
||||
| `bin/pos-docker-health` | 109 | Quick health dashboard |
|
||||
| `bin/pos-vbox` | 156 | Docker-based disposable VMs (label-filtered, auto-enter prompt) |
|
||||
|
||||
+3
-1
@@ -40,7 +40,7 @@ Every non-interactive `pos` invocation logs to `~/.local/share/linux_post_instal
|
||||
|
||||
- Per-command files: `YYYYMMDD_HHMMSS_pos_<args>.log` (full stdout + stderr).
|
||||
- `pos.log`: one line per invocation — command, log file, exit code.
|
||||
- **Interactive** commands (`pos system firewall`, `pos media mp4`) only log the invocation, not their output.
|
||||
- **Interactive** commands (`pos system firewall`, `pos media mp4`, `pos system backup`) only log the invocation, not their output.
|
||||
|
||||
---
|
||||
|
||||
@@ -136,6 +136,8 @@ Global config keys:
|
||||
| Command | File | Purpose | Configuration |
|
||||
|---------|------|---------|---------------|
|
||||
| `sudo pos system firewall` | `bin/pos-system-firewall` | Interactive UFW ("UFW POWER") menu: add/delete rules, status, enable/disable/reset, default policies | Must run as root. Every command is previewed and confirmed before execution; supports `--dry-run`; keeps a history of executed commands |
|
||||
| `pos system backup <folder-path>` | `bin/pos-system-backup` | Create a gpg-encrypted (AES-256) `tar.gz` snapshot of a folder and verify it | Prompts twice for a password (never stored). Uses `sudo tar`; needs `gnupg` (in `preinstall.sh` PACKAGES). Artifact `<name>_<date>.tar.gz.gpg` in the current directory, `chmod 600` |
|
||||
| `pos system backup --service` | `bin/pos-system-backup` | Lists folders under `/srv` and `~/srv`, lets you pick one, then runs the same backup | Roots via `BACKUP_SERVICE_ROOTS` (space-separated, default `/srv $HOME/srv`) |
|
||||
|
||||
### ssh
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ CATEGORIES
|
||||
network ip | checkport | scan | hotspot
|
||||
docker ps | compose
|
||||
media mp3 | mp4
|
||||
system firewall
|
||||
system firewall | backup
|
||||
ssh load-keys
|
||||
vbox create | enter | stop | start | rm | ls
|
||||
|
||||
@@ -58,6 +58,8 @@ EXAMPLES
|
||||
pos media mp4 <url> Download video as MP4
|
||||
|
||||
pos system firewall Interactive UFW manager
|
||||
pos system backup /srv/project Encrypted (AES-256) folder snapshot
|
||||
pos system backup --service Pick a folder from /srv or ~/srv
|
||||
|
||||
pos ssh load-keys Load all SSH keys into agent
|
||||
|
||||
@@ -110,7 +112,7 @@ MAIN_LOG="$LOG_DIR/pos.log"
|
||||
log_cmd() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $* → exit $2" >> "$MAIN_LOG"; }
|
||||
|
||||
# Commands that read from stdin interactively — only log invocation
|
||||
INTERACTIVE_CMDS="system-firewall media-mp4"
|
||||
INTERACTIVE_CMDS="system-firewall media-mp4 system-backup"
|
||||
|
||||
for ((i=n-1; i>=0; i--)); do
|
||||
cmd="pos"
|
||||
|
||||
Executable
+115
@@ -0,0 +1,115 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
source "$(dirname "$0")/../lib/common.sh" 2>/dev/null || source "$(dirname "$0")/common.sh"
|
||||
|
||||
usage() {
|
||||
cat <<EOF
|
||||
Usage: pos system backup <folder-path>
|
||||
pos system backup --service
|
||||
|
||||
Create a gpg-encrypted (AES-256) tar.gz snapshot of a folder and verify it.
|
||||
The archive password is prompted twice and never stored.
|
||||
|
||||
Modes:
|
||||
<folder-path> Back up that folder directly.
|
||||
--service List folders under /srv and ~/srv, pick one, back it up.
|
||||
|
||||
The final artifact <name>_<date>.tar.gz.gpg is written to the current directory.
|
||||
|
||||
Environment:
|
||||
BACKUP_SERVICE_ROOTS Space-separated roots for --service
|
||||
(default: /srv \$HOME/srv)
|
||||
EOF
|
||||
exit 0
|
||||
}
|
||||
|
||||
command -v tar &>/dev/null || err "tar not found"
|
||||
command -v gpg &>/dev/null || err "gpg not found (install gnupg)"
|
||||
|
||||
SERVICE=0
|
||||
case "${1:-}" in
|
||||
-h|--help) usage ;;
|
||||
--service) SERVICE=1 ;;
|
||||
"") err "Missing folder path (or use --service)" ;;
|
||||
*) FOLDER="$1" ;;
|
||||
esac
|
||||
|
||||
if [ "$SERVICE" -eq 1 ]; then
|
||||
if [ -n "${BACKUP_SERVICE_ROOTS:-}" ]; then
|
||||
read -r -a roots <<< "$BACKUP_SERVICE_ROOTS"
|
||||
else
|
||||
roots=(/srv "$HOME/srv")
|
||||
fi
|
||||
|
||||
idx=0
|
||||
for root in "${roots[@]}"; do
|
||||
[ -d "$root" ] || { warn "Root not found: $root"; continue; }
|
||||
|
||||
dirs=()
|
||||
while IFS= read -r d; do
|
||||
dirs+=("$d")
|
||||
done < <(find "$root" -maxdepth 1 -mindepth 1 -type d | sort)
|
||||
|
||||
[ ${#dirs[@]} -gt 0 ] || { warn "No folders in $root"; continue; }
|
||||
|
||||
echo
|
||||
echo "${root}:"
|
||||
for d in "${dirs[@]}"; do
|
||||
idx=$((idx + 1))
|
||||
names[$idx]="$d"
|
||||
printf "%2d) %s\n" "$idx" "$d"
|
||||
done
|
||||
done
|
||||
|
||||
[ "$idx" -gt 0 ] || err "No folders found under: ${roots[*]}"
|
||||
|
||||
read -rp "Select folder number: " choice
|
||||
if ! [[ "$choice" =~ ^[0-9]+$ ]] || (( choice < 1 || choice > idx )); then
|
||||
err "Invalid selection: $choice"
|
||||
fi
|
||||
FOLDER="${names[$choice]}"
|
||||
fi
|
||||
|
||||
[ -d "$FOLDER" ] || err "Folder not found: $FOLDER"
|
||||
|
||||
NAME="$(basename "$FOLDER")"
|
||||
DATE="$(date +%Y-%m-%d_%H-%M-%S)"
|
||||
ARCHIVE="${NAME}_${DATE}.tar.gz"
|
||||
|
||||
echo
|
||||
log "Creating backup..."
|
||||
echo "Source : $FOLDER"
|
||||
echo "Output : $ARCHIVE"
|
||||
|
||||
sudo tar -czvf "$ARCHIVE" -C "$(dirname "$FOLDER")" "$NAME"
|
||||
|
||||
log "Verifying archive..."
|
||||
tar -tzf "$ARCHIVE" > /dev/null
|
||||
log "Archive verified"
|
||||
|
||||
while true; do
|
||||
read -s -rp "Enter backup password: " PASS
|
||||
echo
|
||||
read -s -rp "Confirm backup password: " CONFIRM
|
||||
echo
|
||||
if [ -n "$PASS" ] && [ "$PASS" = "$CONFIRM" ]; then
|
||||
break
|
||||
fi
|
||||
warn "Passwords are empty or do not match — try again"
|
||||
done
|
||||
unset CONFIRM
|
||||
|
||||
log "Encrypting backup..."
|
||||
gpg --batch --yes --passphrase "$PASS" --symmetric --cipher-algo AES256 "$ARCHIVE"
|
||||
|
||||
rm -f "$ARCHIVE"
|
||||
ARCHIVE="${ARCHIVE}.gpg"
|
||||
chmod 600 "$ARCHIVE"
|
||||
|
||||
log "Verifying encrypted backup..."
|
||||
gpg --batch --quiet --passphrase "$PASS" --decrypt "$ARCHIVE" | tar -tzf - > /dev/null
|
||||
|
||||
unset PASS
|
||||
echo
|
||||
log "Backup completed: $ARCHIVE"
|
||||
Reference in New Issue
Block a user