Add automatic tab-completion setup and old config-backup pruning
Two things surfaced from actual use this session: 1. Tab completion (tools/setup-completion.bash, added earlier) required manually editing ~/.bashrc — easy to skip or get wrong (confirmed live: the source line never actually landed the first time). base now wires it in automatically (idempotent, checked by grep first), matching how it already touches ~/.bashrc for SSH Host aliases. 2. No pruning existed anywhere for the *.backup.<timestamp> files ~60 different services create before overwriting a live config (Caddyfile, /etc/fstab, etc) — every one of them backs up, none clean up, so they accumulate forever on a box reconfigured regularly. tools/prune-old-backups.sh prunes by file mtime (not by parsing the timestamp out of the filename — robust to the %Y%m%d-%H%M%S vs %Y%m%d_%H%M%S inconsistency across services), always keeping the single newest backup per distinct file regardless of age. Verified both the normal case (mixed old/new, prunes only the old ones) and the edge case (every backup for a file is old, keeps the newest one anyway) against real fixtures. base offers it as a daily systemd timer (prompted, since it deletes files — unlike the tab-completion wiring, which doesn't). Also added logrotate for Caddy's own access logs (/var/log/caddy/*.log), which had no rotation at all and grow unbounded on an active box. Uses copytruncate specifically: the log directory is bind-mounted into the running Caddy container and read live by CrowdSec, so truncating in place avoids either of them needing to notice or react to a rotation happening. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01H4k6J1qXXyYxhGEgnJaMvn
This commit is contained in:
@@ -22,6 +22,8 @@ install_base() {
|
||||
echo "[DRY-RUN] Would offer Caddy reverse proxy install (full repo only)"
|
||||
echo "[DRY-RUN] Would offer CrowdSec intrusion prevention install (full repo only)"
|
||||
echo "[DRY-RUN] Would offer to add SSH Host aliases to ~/.ssh/config"
|
||||
echo "[DRY-RUN] Would add setup.sh tab completion to ~/.bashrc (if not already there)"
|
||||
echo "[DRY-RUN] Would offer daily pruning of old *.backup.* config files (systemd timer)"
|
||||
return 0
|
||||
fi
|
||||
|
||||
@@ -82,6 +84,82 @@ install_base() {
|
||||
|
||||
# ── SSH Host aliases ─────────────────────────────────────────────────────
|
||||
_base_setup_ssh_aliases
|
||||
|
||||
# ── setup.sh tab completion ─────────────────────────────────────────────
|
||||
_base_setup_tab_completion
|
||||
|
||||
# ── Old config-backup pruning ────────────────────────────────────────────
|
||||
_base_setup_backup_pruning
|
||||
}
|
||||
|
||||
# Wires tools/setup-completion.bash into ACTUAL_USER's shell automatically —
|
||||
# no reason to make everyone find and run this by hand when base already
|
||||
# touches ~/.bashrc for other things. Idempotent (checked by grep before
|
||||
# appending), so reruns don't pile up duplicate source lines.
|
||||
_base_setup_tab_completion() {
|
||||
local comp_script="$HERE/tools/setup-completion.bash"
|
||||
[ -f "$comp_script" ] || return 0
|
||||
|
||||
local bashrc="$ACTUAL_HOME/.bashrc"
|
||||
[ -f "$bashrc" ] || return 0
|
||||
grep -qF "$comp_script" "$bashrc" 2>/dev/null && return 0
|
||||
|
||||
# No DRY_RUN check here — install_base()'s own top-level one (above)
|
||||
# already returns before this helper is ever called in that mode,
|
||||
# unlike install_glow()'s check further down, which is independently
|
||||
# invokable (sudo ./setup.sh glow --dry-run) and genuinely reachable.
|
||||
{
|
||||
echo ""
|
||||
echo "# ubuntu-post-install: setup.sh tab completion"
|
||||
echo "source $comp_script"
|
||||
} >> "$bashrc"
|
||||
chown "$ACTUAL_USER:$ACTUAL_USER" "$bashrc" 2>/dev/null || true
|
||||
log_success "setup.sh tab completion added to $bashrc (takes effect in new shells, or: source $bashrc)"
|
||||
}
|
||||
|
||||
# Every service in this repo backs up a live config before overwriting it
|
||||
# (Caddyfile, /etc/fstab, ...) but none of them ever clean those up
|
||||
# afterward — see tools/prune-old-backups.sh's own header for the full
|
||||
# reasoning. Offers a daily systemd timer that prunes anything older than
|
||||
# 30 days, always keeping at least the single newest backup per file
|
||||
# regardless of age.
|
||||
_base_setup_backup_pruning() {
|
||||
command -v systemctl >/dev/null 2>&1 || return 0
|
||||
systemctl list-unit-files prune-old-backups.timer --no-legend 2>/dev/null | grep -q . && return 0
|
||||
|
||||
local prune_script="$HERE/tools/prune-old-backups.sh"
|
||||
[ -f "$prune_script" ] || return 0
|
||||
|
||||
echo ""
|
||||
local ENABLE_PRUNE=""
|
||||
prompt_yn "Automatically prune old config backups (Caddyfile.backup.*, fstab.backup.*, etc — keeps 30 days, always keeps at least the newest one)? (y/n):" "y" ENABLE_PRUNE
|
||||
[[ "$ENABLE_PRUNE" =~ ^[Yy]$ ]] || return 0
|
||||
|
||||
cat > /etc/systemd/system/prune-old-backups.service << UNIT
|
||||
[Unit]
|
||||
Description=Prune old *.backup.* config backups (Caddyfile, fstab, etc)
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=/bin/bash ${prune_script} 30
|
||||
UNIT
|
||||
cat > /etc/systemd/system/prune-old-backups.timer << 'UNIT'
|
||||
[Unit]
|
||||
Description=Daily backup pruning
|
||||
|
||||
[Timer]
|
||||
OnCalendar=daily
|
||||
Persistent=true
|
||||
|
||||
[Install]
|
||||
WantedBy=timers.target
|
||||
UNIT
|
||||
systemctl daemon-reload
|
||||
if systemctl enable --now prune-old-backups.timer >/dev/null 2>&1; then
|
||||
log_success "Old config backups will be pruned daily, keeping 30 days (systemd timer: prune-old-backups)"
|
||||
else
|
||||
log_warning "Couldn't enable the pruning timer — run $prune_script manually to prune old backups."
|
||||
fi
|
||||
}
|
||||
|
||||
_base_setup_nvidia_gpu() {
|
||||
|
||||
Reference in New Issue
Block a user