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:
@@ -233,6 +233,7 @@ install_caddy() {
|
||||
echo "[DRY-RUN] Would write a starter $CADDY_DIR/Caddyfile (if none exists)"
|
||||
echo "[DRY-RUN] Would write $CADDY_DIR/README.md"
|
||||
echo "[DRY-RUN] Would open 80/tcp, 443/tcp, 443/udp in UFW (Docker's own iptables rules let this traffic through either way, but ufw status should actually reflect it)"
|
||||
echo "[DRY-RUN] Would configure logrotate for /var/log/caddy/*.log (14 days, copytruncate)"
|
||||
echo "[DRY-RUN] Would optionally start Caddy (docker compose up -d)"
|
||||
return 0
|
||||
fi
|
||||
@@ -385,6 +386,29 @@ CADDYFILE
|
||||
chown -R "$ACTUAL_USER:$ACTUAL_USER" "$CADDY_DIR"
|
||||
echo " ✓ Caddy configured at $CADDY_DIR"
|
||||
|
||||
# Every site's access log (one JSON file per domain, per the "log {}"
|
||||
# block configure_caddy_for_service writes) grows forever otherwise —
|
||||
# nothing in this repo ever rotated them. copytruncate, not the usual
|
||||
# rename+recreate rotation: the log directory is bind-mounted into the
|
||||
# running Caddy container (still holding the file open) and read live
|
||||
# by CrowdSec, so truncating in place avoids both "Caddy keeps writing
|
||||
# to the old, now-unlinked file" and "CrowdSec's tail loses the file"
|
||||
# — neither has to detect or react to a rotation at all this way.
|
||||
if [ -d /etc/logrotate.d ]; then
|
||||
cat > /etc/logrotate.d/caddy << 'LOGROTATE'
|
||||
/var/log/caddy/*.log {
|
||||
daily
|
||||
rotate 14
|
||||
compress
|
||||
delaycompress
|
||||
missingok
|
||||
notifempty
|
||||
copytruncate
|
||||
}
|
||||
LOGROTATE
|
||||
echo " ✓ Access log rotation configured (/var/log/caddy/*.log, 14 days, copytruncate)"
|
||||
fi
|
||||
|
||||
# Every other service in this repo opens its own UFW rule; this file
|
||||
# never did — Docker manipulates iptables directly for published
|
||||
# container ports (the ports: mapping above), which bypasses UFW's own
|
||||
|
||||
Reference in New Issue
Block a user