x/crypto/ssh only supports aes256-ctr/cbc for private key encryption,
so keys exported from 1Password (aes256-gcm) could not be decrypted even
with the correct passphrase. Decrypt the openssh-key-v1 blob ourselves
(bcrypt_pbkdf ported from x/crypto's internal package, AES-256-GCM via
stdlib, auth tag stored as raw bytes after the encrypted block) and
re-marshal it as an unencrypted key for ssh.ParsePrivateKey.
ParsePrivateKey failures were silently skipped, so a passphrase-protected
~/.ssh/id_ed25519 was reported as 'no key files found' on hosts without
an SSH agent. Detect PassphraseMissingError and ask for the passphrase
interactively (up to 3 attempts) before the TUI starts; make the final
error distinguish missing files from unloadable ones.
Runner mel valid_volumes: [], takze mount /root/.ssh se tise zahazoval
a job container klic nikdy nedostal. Klic presunut do vyhrazeneho
adresare /opt/runner/keys, ktery je jako jediny povoleny v runner configu.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- Cache current log file incrementally by line count/inode to avoid
re-processing the whole file every refresh.
- Collect 4xx/5xx errors during aggregation and add [4] ERRORS tab.
- Update README URLs and brew tap to point to git.janvete.com.
- Replace GitHub Actions workflow with Forgejo Actions release workflow.
Tap was renamed from homebrew-caddyview to homebrew-tools and now
hosts formulae for multiple tools. Workflow URL updated.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
History was effectively frozen: the find pattern 'access.log*' never
matched Caddy's native rotation naming (access-<ts>.log.gz), so rotated
files were invisible and the server-side cache - invalidated only by new
.gz files - never refreshed after the first load.
- match both Caddy native (access-*.log.gz) and logrotate (access.log.N)
rotation naming
- cache aggregation per rotated file (immutable, scanned exactly once);
always scan the current log fresh, so history never goes stale
- always bucket hourly on the server, re-bucket client-side so all tabs
share the same caches
- cap IPs at top 50 per file so output stays small on busy servers
- aggregate request duration so history shows real avg response time
- tail -F instead of -f: Caddy rotates by rename, which silently killed
the live stream at every rotation on high-traffic servers
- process live lines in batches instead of one Update cycle per line
- fetch CPU/MEM stats every 5s instead of every second
- stable sort in topN: equal counts no longer flicker and swap rows
- drop the 1 Month tab (Live / 1 Day / 1 Week remain)
- retro green-phosphor CRT look: double borders, ▓░ bars, amber accents
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Cache awk output in /tmp on the remote server, keyed by log path and
bucket size. Cache is invalidated only when a new rotated .gz file
appears, making repeated loads instant (0.001s vs 4s cold run).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
High-traffic servers (100+ req/s) generated millions of log lines
per day. Transferring raw lines over SSH was impractical (GB of data).
Instead, run an awk script on the server that aggregates all matching
log files (including .gz rotated ones) into time buckets and returns
only a ~50-line summary. For a server doing 180 req/s this reduces
SSH transfer from ~7GB to <1KB per history request.
The awk script filters by timestamp, groups by bucket, and outputs:
- per-bucket request counts, bytes, and status code groups
- top hosts and IPs with counts
- overall totals
Files are pre-filtered with find -mtime to skip archives older than
the requested window.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
History tabs were loaded once at first visit and never updated,
causing 1 Day/Week/Month to show fewer requests than the live view.
- Silent background refresh every 5 min for the active history tab
- Re-check on tab switch: reload if data is older than 5 min
- Spinner only on first load; subsequent refreshes keep old data visible
- Chart title shows "updated X ago" so freshness is always visible
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Try SSH_AUTH_SOCK agent first (handles macOS Keychain, ssh-add, and
custom key paths configured in the shell). Fall back to common key
file names (id_ed25519, id_ecdsa, id_rsa) if no agent is available.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
On git tag v*, builds darwin-arm64/amd64 and linux-amd64 binaries,
creates GitHub Release, and auto-updates homebrew-caddyview formula.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Tabs 1-4 switch between Live, 1 Day, 1 Week, 1 Month views.
History loads on demand via SSH by reading rotated log files
(access.log, access.log.1, access.log.2.gz, ...) filtered by
timestamp on the remote side using awk.
Bar chart shows requests per time bucket (1h/6h/24h depending
on window). Bottom panels show period stats, top hosts, top IPs,
and status codes — consistent across all views.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
SSH-connected TUI monitor for Caddy web server logs.
Live view with 1s refresh, request stats, top hosts/IPs,
status codes, transfer speed, CPU and RAM from /proc.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>