Compare commits

..

246 Commits

Author SHA1 Message Date
jasonwitty a09b69a4b5 chore: bump all crates to 1.60.1
CI / build (ubuntu-latest) (push) Has been cancelled
CI / build (windows-latest) (push) Has been cancelled
The 1.60.0 debs were built against glibc 2.39 and never installed on the
bookworm fleet; rather than force-moving the tag, the rebuilt release
ships as 1.60.1. Nothing was published to crates.io at 1.60.0.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-23 09:39:58 -07:00
jasonwitty 98833ab3b7 fix(ci): extract the libc6 version, not the 6 in 'libc6'
The floor gate's second grep matched the trailing digit of the package
name before the version ('libc6 (>= 2.34)' -> '6'), failing every
target. sed capture group instead; verified against realistic Depends
strings.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-23 09:10:44 -07:00
jasonwitty b25adcb4a8 fix(ci): pin deb builds to ubuntu-22.04 and enforce the fleet glibc floor
The v1.60.0 debs failed to install on Raspberry Pi OS bookworm:

  socktop : Depends: libc6 (>= 2.39) but 2.36-9+rpt2+deb12u14 is to be installed

Cross-compiled binaries link against the RUNNER's (multiarch) glibc, so
the runner picks the minimum glibc the packages demand. ubuntu-latest
migrated from 22.04 (glibc 2.35) to 24.04 (glibc 2.39) between the
1.50.x releases and now, silently raising the requirement past the
Debian-12 fleet.

Pin the build job to ubuntu-22.04 (2.35 — satisfied by bookworm's 2.36)
and add a post-build gate that reads each .deb's computed libc6
requirement and fails the run if it exceeds the fleet floor, so the next
runner migration turns into a red build instead of a fleet-wide apt
error.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-23 08:59:36 -07:00
jason 4c59716610 Kill a local process from the TUI, and stop the agent reporting dead ones (#40)
Build Debian Packages / Build .deb for x86_64-unknown-linux-gnu (push) Has been cancelled
Build Debian Packages / Build .deb for aarch64-unknown-linux-gnu (push) Has been cancelled
Build Debian Packages / Build .deb for armv7-unknown-linux-gnueabihf (push) Has been cancelled
Build Debian Packages / Build .deb for riscv64gc-unknown-linux-gnu (push) Has been cancelled
CI / build (ubuntu-latest) (push) Has been cancelled
CI / build (windows-latest) (push) Has been cancelled
Build Debian Packages / Combine all .deb packages (push) Has been cancelled
Build Debian Packages / Publish to APT Repository (push) Has been cancelled
Build Debian Packages / Create GitHub Release (push) Has been cancelled
* fix(agent): drop processes that no longer exist

`refresh_processes_specifics` was called with remove_dead_processes = false
against a long-lived System, so the agent accumulated every process it had
ever seen and went on reporting them. Measured on a Pi 5 after a few hours of
build churn: 21,648 processes reported, 289 actually running, growing a few
every poll.

Three consequences, in ascending order of how confusing they are:

  * unbounded memory growth, and every poll iterating ~75x more entries than
    it should
  * process_count — the client's "Top Processes (N total)" — is meaningless
  * a process you kill keeps its row forever, because the agent keeps sending
    it. Killing it again reports "no longer exists", since the kernel is
    telling the truth and the agent is not.

The third is how this was found: no amount of client-side reconciliation could
fix a list whose producer never forgets anything.

Passing `true` is only correct because these two sites use
ProcessesToUpdate::All. With `Some(pids)` sysinfo treats every process outside
the list as dead and removes it, so the per-PID refresh in
collect_process_metrics must keep `false` — noted in a comment there.

Verified by driving the TUI against a rebuilt agent: reported count 292 vs 290
real, and a killed row is removed once and never reappears.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* feat(socktop): kill a local process from the TUI

btop-style process termination, for local agents only. The signal is sent by
socktop itself through a direct sysinfo call — nothing is transmitted to the
agent, and the agent and connector have no kill capability at all.

Why local-only: the PIDs on screen are reported by the agent, and the signal is
sent with socktop's own OS privileges. A PID is therefore only meaningful, and
only safe to act on, when the agent lives on this machine; acting on a remote
agent's PIDs would signal whatever unrelated local process happened to share
that number. local::agent_is_local treats an address as local when it is
loopback or when an ephemeral bind succeeds (which only works for an address on
one of our own interfaces, so it also covers reaching our own agent by LAN IP),
requires every address a hostname resolves to to be local, and fails closed.

  * `t` on the selected process, and `t` inside Process Details. One key for
    both: `k` scrolls the thread table in the modal, so it could not be reused
    there.
  * The confirmation offers Terminate (focused first, so a reflexive Enter is
    the safe one), Force kill, and Cancel. Keeping SIGKILL behind a second
    button rather than a second keybinding means the destructive option has to
    be chosen deliberately.
  * The selection hint gained the key, but only for a local agent — advertising
    a key that deliberately does nothing is worse than no hint. Same for the
    details modal's help line.

The list is reconciled after a signal rather than left to the next poll. A
signalled PID goes on a watch list re-checked each metrics tick, because SIGTERM
is a request: the process is usually still alive at signal time, and its row
should go when it actually exits (or stay, if it ignores the signal). PIDs
confirmed gone are remembered briefly, since the agent serves Processes from a
1500ms cache and would otherwise hand back a pre-kill snapshot. A selection
whose process has left the list is dropped, and the details view closes for a
process that no longer exists — including when it dies on its own, which
previously flipped that modal to "Agent Update Required" because the wire cannot
distinguish "no such PID" from "endpoint unsupported".

Also fixes two pre-existing UI faults found on the way:

  * The selection hint was sized from its full label including the process name
    and skipped entirely when that exceeded the pane width — so it vanished
    exactly when a long-named process was selected. The name is now the elastic
    part, and widths are measured in columns rather than bytes.
  * Confirmation and Info dialogs laid their content out over the whole modal
    rect instead of the block's inner rect, putting the first line of text on
    the border row, and fell into the catch-all 70%x50% sizing arm, so a
    one-line question got half the screen. They now size to their content and
    use the theme's colors like the connection-error modal does.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* fix(kill): close stacked details view, guard PID reuse, scale settle with interval

Review fixes for the process-kill feature:

1. Killing from INSIDE the details view left it open forever, frozen on
   the dead process (reproduced live): the 'Signal sent' Info modal sits
   on top when the death is confirmed on the next tick, the old top-only
   close_process_details missed it, gone-PIDs are processed once, and the
   details-poll fallback was gated on the selection the kill had just
   cleared. The close now removes the dead PID's view wherever it sits in
   the stack — which also retires a dead parent's view from under a child
   in a navigation chain, so backing out lands on the process list rather
   than a frozen corpse view. Tests updated to the new semantics, plus a
   regression test for the Info-stacked case.

2. PID-reuse guard: the PID comes from an agent snapshot and the
   confirmation can sit open indefinitely, so by signal time the kernel
   may have recycled the number. kill_local_process now takes the name
   the user confirmed and refuses to signal a PID whose current owner
   does not match ('PID N now belongs to X, not Y').

3. A transient request error no longer closes the details view: with
   process_details_answered set, any Err was read as 'process gone',
   including socket blips. The view now closes only when the PID is also
   absent from the agent's own process list.

4. PROC_CACHE_SETTLE scales with the user's processes interval (floor at
   the old 1.6s default-TTL value), and the tombstone lifetime rides on
   top of it — users who raise the agent's Processes TTL raise the client
   interval to match, so the interval is the best client-side signal for
   how stale an agent snapshot can be.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(kill): resume polling for the details view that resurfaces from a chain

Reported: kill still orphaned a window via Enter (child details) -> P
(parent details) -> t (terminate parent). The parent's view closed
correctly, but the child's view underneath resurfaced with no selection
(forget_process_row had cleared it — it pointed at the parent) and wiped
data; the selection-gated details poll never refilled it.

close_details_for_gone_process now retargets the selection to the
uppermost remaining ProcessDetails view (looking through stacked
Info/Confirmation modals) and makes the poll due immediately — the same
retarget SwitchToParentProcess performs on the way down the chain.

Same class of hole in plain navigation, fixed alongside: Esc-ing back
from a parent view left the selection on the PARENT, so the resurfaced
child-titled view refilled with the parent's data. The dismiss arm now
retargets the selection to whatever details view it lands on.

Both verified live: child -> P -> kill parent -> child view resurfaces
populated and updating; child -> P -> Esc -> child view shows the child.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs: changelog section for the process-kill feature and agent dead-process fix

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-23 08:11:17 -07:00
jason 0322308896 housekeeping-p2: security, correctness, and performance pass before 1.51 (#39)
* chore: dead-code sweep

- Delete socktop_connector/src/connector.rs: orphaned since 08f248c removed
  'pub mod connector;' during the modularization refactor. Never compiled
  (verified under default, wasm, and workspace feature combos) but shipped
  in the crates.io tarball and contained an outdated copy of the TLS
  verifier — a trap for anyone patching the pinning bug in the dead copy.
- Delete empty socktop/src/ws.rs, tracked editor backup ui/.modal.rs.backup,
  and stray test_thiserror.rs at the repo root.
- Delete the two LEGACY #[allow(dead_code)] process input handlers; the
  header-click render test now exercises the live _with_selection handler
  instead (better coverage of the real path).
- Drop unused sysinfo dependency from the socktop client.
- Replace stale 'temporarily increased for testing' comment on
  COMPRESSION_THRESHOLD (it already held the production value).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(connector): make certificate pinning real; disable Nagle

Security: with --verify-hostname off (the default), the old NoVerify
verifier accepted ANY server certificate — the CA loaded from --tls-ca
was never consulted, so the documented pinning was a no-op and the
connection was trivially MITM-able. Replace it with PinnedCertVerifier:
the presented end-entity cert must be byte-identical to a cert in the
--tls-ca file (any cert in a multi-cert PEM matches, supporting
rotation). Signature validation now uses the ring provider's full
algorithm set instead of a hardcoded 3-scheme list. Empty PEM files
fail fast instead of failing closed per-handshake.

The --verify-hostname path is unchanged (WebPki root-store validation).

Also: the third argument of connect_async_tls_with_config is
tungstenite's disable_nagle flag, not a verification toggle — we were
passing verify_hostname there, leaving Nagle ON for default users. Pass
true unconditionally, and disable Nagle on the plain ws:// path too;
socktop exchanges small request/response frames where Nagle only adds
latency.

Client now consumes the connector via a dual path+version dep so these
fixes are in local builds and CI before the crates.io publish (cargo
strips the path on publish). Connector version -> 1.51.0.

Verified E2E: agent A's cert connects to agent A; agent B's cert
against agent A fails the handshake (the rpi-worker-1 wrong-PEM
scenario); --verify-hostname against a 127.0.0.1 SAN still connects.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(agent): GPU worker thread, async journalctl, correctness + cache fixes

Lightweight:
- GPU collection moves to a dedicated worker thread that owns the gfxinfo
  handle for the process lifetime. gfxinfo's active_gpu() runs a full NVML
  init/teardown (~20ms, blocking) and we were paying it on the async
  runtime for every collect — measured at ~80% of the agent's entire
  active CPU on a GPU machine. The handle holds Rc<Nvml> (not Send), so a
  thread + mpsc/oneshot channel pair confines it; a zero-total-VRAM reply
  is treated as a dead session (driver reload) and re-probed.
- journalctl now runs via tokio::process instead of blocking one of the
  two runtime workers for the duration of the subprocess.
- TtlCell (state.rs) replaces the four hand-rolled static TTL caches; a
  cached negative result now counts as fresh, so hosts with no matching
  temp sensor or GPU stop rescanning every request. Single lock+clone on
  the GPU cache hit path (was two).

Correctness:
- Process/child CPU times are now microseconds as documented; they were
  milliseconds, rendering 1000x too small next to (correct) thread times.
- Non-Linux per-process CPU%% clamps AFTER dividing by core count; a
  4-cores-busy process on an 8-core box reported 12.5% instead of 50%.
- Journal timestamps are real RFC 3339 UTC plus an additive timestamp_us
  field (sorting is now numeric); the old strings were Debug-formatted
  SystemTime mangled by string replace.
- Partition detection uses /sys/block on Linux: whole-disk filesystems on
  names like nvme0n1 or zram1 are no longer misclassified as partitions.
  One shared parent_disk_name() replaces two inline copies.
- New sampled_at_ms on the metrics payload (additive) records when the
  snapshot was actually collected, so clients can compute exact rates
  across the agent's TTL cache.

Security/robustness:
- key.pem is created 0600 (was umask default 0644, world-readable) and
  pre-1.51 keys are tightened on startup.
- Per-PID detail/journal caches now evict (60s max age, 64 entries max);
  they previously grew without bound under PID-walking clients.
- The two per-PID ws handlers collapse into one generic helper.
- /proc/<pid>/stat parsing unified in one comm-safe module.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(tui): responsive input, request timeouts, poisoned-stream reconnect

R1 — input latency: the event loop drained input once per iteration, then
slept the whole metrics interval; keys and wheel events queued for up to
500ms (or the full interval at slower rates) and applied in bursts. The
input block is extracted to drain_input() and the tail sleep replaced by
a deadline wait in <=33ms poll slices that handles and repaints input the
moment it arrives. Verified: help modal opens <150ms into a 2000ms tick.

R2 — freeze-proofing: metrics/processes/disks requests had no timeout; a
half-dead connection left ws.next() pending forever and froze the TUI
with no way to quit (raw mode eats Ctrl+C as an unread key event). All
requests now carry a 5s budget.

C3 — desync: replies are matched to requests by order alone, so a timed-
out request's late reply would shift every subsequent reply off by one.
Any timeout now treats the stream as poisoned and goes through the
reconnect flow — a fresh stream is aligned by construction. The modal
endpoints additionally mark process details unsupported (flag resets on
modal close/selection change) so a detail-less agent doesn't cause a
reconnect loop. While disconnected the fetch path idles: recovery belongs
to the manual/auto retry paths instead of 5s-timeout hammering.

C7 — fit::truncate_middle_cols replaces util::truncate_middle: display-
width aware and char-boundary safe; the byte-slicing version panicked the
draw loop on non-ASCII device names.

Verified live: agent kill -9 mid-session -> error modal in <3s, q exits
while disconnected, r reconnects and resumes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* chore: version 1.51.0, path-dep the wasm examples, README notes

- socktop, socktop_agent, socktop_connector -> 1.51.0.
- socktop_wasm_test and zellij_socktop_plugin consume the in-repo
  connector via path deps so wasm-feature API drift is caught at PR time
  instead of after publish. Immediately proved out: the wasm requests
  module needed the new sampled_at_ms field, invisible to native builds.
- zellij plugin gains the standalone [workspace] marker (it could not be
  cargo-checked in-tree at all before). NOTE: its lib.rs has pre-existing
  compile errors unrelated to the connector (static mut STATE conflicts
  with register_plugin!, missing BTreeMap import) — needs its own rework,
  out of scope here.
- README: sampled_at_ms in the example payload.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(review): restore Agent Update Required flow, command field, axis alignment

Fixes from Jason's hands-on verification of the branch:

1. Old-agent messaging regression (this branch): a detail-request timeout
   went through the loud poison/reconnect flow, burying the ProcessDetails
   modal's 'Agent Update Required' message under a connection-error modal.
   Old agents IGNORE unknown messages (no late reply, no desync), so the
   optional per-PID endpoints now use quiet_reconnect(): swap the stream
   silently (still safe against merely-slow agents) and let the modal show
   its message. Only a failed reconnect surfaces loudly. Verified against
   a real v1.40.0 agent: message shows, session stays healthy.

2. Draw starvation (this branch): an agent that never answers get_metrics
   put the loop in fetch->timeout->poison->restart cycles that never
   reached the draw call — permanently blank TUI. The iteration now paints
   before fetching, and a second consecutive metrics timeout trips a
   circuit breaker: persistent 'Agent is not responding' error, recovery
   left to the manual/30s retry paths. Verified against a 0.9-era agent.

3. Command & Details pane blank (pre-existing on master): the minimal-
   refresh optimization dropped cmd/exe/cwd from the detail endpoint's
   ProcessRefreshKind, so process.cmd() had nothing to return. Restored
   with UpdateKind::OnlyIfNotSet — immutable values, read once per PID.
   Regression test added; journal E2E re-verified (100 entries render).

4. Scatter-plot axis misalignment: Y labels used a fixed 4-char field from
   the era when CPU times were 1000x too small; honest millisecond values
   (e.g. 136114) blew through it. Labels now right-align to the widest
   value per frame and X labels/titles share the dynamic padding.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* feat: journal access notice, 1.60.0, install script, changelog, riscv protoc fallback

- Journal pane now distinguishes 'no entries' from 'no journal access':
  journalctl exits 0 with empty output when the agent's user simply can't
  see the target's entries (demo mode / user-run agents), explaining
  itself only on stderr. The agent forwards that hint as an additive
  JournalResponse.notice and the client renders it with practical advice.
  Verified E2E via a stub journalctl emulating the unprivileged case.
- Version 1.60.0 across all crates (1.51 would read fine, but the repo's
  scheme is 1.40/1.50/…, and a literal 1.6.0 would sort BELOW 1.50.0 in
  semver). All user-facing version strings already come from
  CARGO_PKG_VERSION — a stale binary was the only way to see an old one.
- scripts/install.sh: build-from-source install/upgrade for the test
  fleet (Linux + macOS). Detects in-repo checkouts, installs rustup when
  missing, replaces a systemd socktop-agent service binary in place and
  restarts it, requires system protoc on riscv64.
- build.rs (agent + connector): fall back to $PROTOC / PATH when
  protoc-bin-vendored has no binary for the host (riscv64) — native SBC
  builds previously panicked in the build script.
- CHANGELOG.md covering v1.50.0 -> 1.60.0.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* test: add notice field to cache test initializer

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix: untrack zellij plugin build dir; installer updates all PATH copies

- Remove zellij_socktop_plugin/target from git (3,577 files committed by
  accident in bf6ac87): the root .gitignore anchors /target to the repo
  root, so the standalone plugin's own build dir wasn't covered. Ignore
  target/ at any depth (also fixes the pre-existing
  '/socktop-wasm-test/target' entry, which pointed at a hyphenated path
  that doesn't exist).

- install.sh now updates EVERY copy of socktop/socktop_agent on PATH,
  not just $PREFIX: a stale 'cargo install' in ~/.cargo/bin shadows
  /usr/local/bin on most PATHs, so an install could 'succeed' while
  'socktop --version' kept reporting the old release. Extra copies that
  can't be written are warned about, not fatal, and the script now
  prints which binary is actually active on PATH at the end.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* feat(installer): manage the socktop-agent systemd service

Upgrade path (unit already present): NEVER touch the unit file — it is
the operator's config (SSL, tokens, ports live there as Environment=
lines). Only the binary at the unit's own ExecStart path is replaced,
then the service restarts. Flags/args preserved by construction.

Fresh path (no unit): full first-time setup mirroring the deb postinst
and the agent-service docs — create the socktop system user/group and
/var/lib/socktop, install docs/socktop-agent.service (ExecStart rewritten
to wherever this run installed the agent; embedded fallback for old
refs), daemon-reload, enable --now, and print how to turn on TLS/token.

Also: system-level operations get their own sudo decision (SYS_SUDO) —
previously they inherited the PREFIX sudo flag, so a writable --prefix
made the service section run groupadd/systemctl unprivileged and die.
No sudo at all now skips service management with a warning instead of
failing the install.

Both branches dry-run verified with stubbed systemctl/sudo.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(installer): don't bind fresh agent services onto occupied ports

The Orange Pi install put the new service straight into a crash-restart
loop: the unit's default --port 3000 collided with a Docker service
already publishing 3000 (Umami; Gitea and friends default there too).
Fresh installs now scan 3000/3001/3010/3231/3232 via ss and configure
the unit on the first free port, warning loudly when 3000 was taken and
printing the resulting ws:// URL. Upgrades still never touch the unit.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(agent): detect NVIDIA GPUs on distros without the unversioned NVML soname

On Debian and derivatives the NVIDIA driver ships only libnvidia-ml.so.1
(the unversioned symlink belongs to the dev package), and nvml-wrapper's
default init dlopens the unversioned name — so gfxinfo reported 'No GPU
found' on a fully functional RTX A2000 host while nvidia-smi worked
fine. Arch-family distros ship the symlink, which is why the desktop
never showed this.

The GPU worker now falls back to initializing NVML directly with the
versioned soname when gfxinfo's probe fails, collecting name/util/vram
through the same handle-caching path. nvml-wrapper was already in the
tree via gfxinfo — same version, no new build cost.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(agent): box the NVML handle variant (clippy large_enum_variant)

CI clippy runs with -D warnings; Nvml is a large struct next to the
16-byte Box<dyn Gpu> variant.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(installer): survive self-modification mid-run; sturdier unit detection

Root cause of the mixed-up second install on the A2000 host: when run
from the clone it manages, the script's own git checkout/merge REPLACES
scripts/install.sh while bash is still executing it. Bash reads scripts
lazily by byte offset, so it resumed parsing the NEW file at the OLD
offset and executed an arbitrary tail of it — observed as the fresh-
service path running on a host whose unit already existed: the port scan
saw the still-running old service on 3000 and silently wrote a new unit
on 3001, while enable --now on the already-active service changed
nothing until a manual daemon-reload.

Fix: the whole script now runs inside main(), invoked as
'main "$@"; exit $?' so bash parses everything up front and never
reads the file again after main returns (the exit lives in the same
parse unit — demonstrated necessary: with a bare 'main "$@"' ending,
bash still executed the swapped file's trailing content after main
returned).

Also: unit existence is now checked with 'systemctl cat' instead of
grepping the full list-unit-files output.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs(installer): use a durable ref in the usage example

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-08-21 12:45:10 -07:00
jason ebda3c51af fix(ui): keep the important text visible on narrow terminals (#38)
Three panes painted two independent pieces of text onto one row with nothing
reserving space between them, so below roughly 105 columns the right-hand piece
was simply drawn over the tail of the left one:

  socktop — host: cachyos-gaming | 🔒✗ TLS | (a: about⏱ 500ms metrics | 2000ms

The width arithmetic used str::len(), a byte count, so the emoji in these strings
overstated their width and left orphaned glyphs at the right edge as well. The
process table had the same problem in a different form: it handed the layout
solver a fixed, over-constrained column set, so a narrow pane crushed the
percentage-sized Name column to nothing while fixed-width PID and Mem % kept
their full width — losing the one field that identifies a process.

Add ui::fit (measure in terminal columns, truncate on character boundaries, pick
the richest wording that fits) and give each pane a priority ladder:

- Header: drop the key hints, then the TLS/token badges, then the
  "socktop — host:" prefix, then the metrics/procs words, and only then shorten
  the hostname. Hostname and intervals are what survive longest.
- CPU pane: drop the "CPU Temp:" label, then the now:/avg: labels, then the
  average, then the temperature's decimal, and the temperature itself last — a
  thermal warning outranks a second decimal place.
- Process table: Name is unconditional; CPU %, then Mem, then PID, then Mem %
  are added as the pane widens, so Mem % is the first to go and Name the last.

Also fixes sort-header clicks, which resolved against a Layout that omitted the
column spacing the Table renders with, so a click landed off by up to four
columns. Covered by a test that clicks each label where it is actually drawn.

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-08-18 22:47:03 -07:00
jason 623a6e5f85 feat(ui): compact layout for small terminal windows (#37)
In a short window the fixed root layout runs out of rows and the CPU graph and
per-core bars are what collapse first: the header, gauges and process table hold
fixed heights, so at ~18 rows the top row is left with no drawable interior and
both panes disappear entirely.

Add a second layout, entered automatically once the Disks pane can no longer show
even one complete disk card:

- Disks is dropped — it is the pane that degrades worst when partly drawn.
- Memory and Swap move side by side into the row Disks vacated.
- GPU collapses to a single full-width line (utilisation and VRAM, no device
  name), and is omitted entirely on a host that reports no GPU.
- The reclaimed rows go to the CPU panes, with the surplus above their floor
  shared with the bottom half so the process table still grows with the window.

`--compact` pins the layout at any size.

The root layout was duplicated in three places (the draw path and both input
hit-testing paths), which would have drifted the moment a second layout existed.
Move it into ui::layout as the single source of truth and have all three callers
go through it.

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-08-18 22:29:54 -07:00
jason 20966d0c94 fix(socktop): explain how to install socktop_agent when demo mode can't find it (#36)
Demo mode spawns a socktop_agent child process, but the agent is a separate
crate that `cargo install socktop` does not pull in. When it was missing, the
raw spawn error propagated to main and printed as
`Error: Os { code: 2, kind: NotFound, message: "No such file or directory" }`,
which gives the user nothing to act on.

Introduce DemoAgentError so a NotFound spawn failure is distinguishable from
other io errors, and print the path we looked for plus the `cargo install
socktop_agent` fix. Other spawn errors still propagate as before.

Co-authored-by: Jason Witty <jason@localhost-live.localdomain>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-18 21:10:46 -07:00
jason f95a64a18b fix(deps): bump aws-lc-rs 1.15.0 -> 1.17.1 to patch aws-lc-sys advisories (#34)
Resolves all five open Dependabot alerts (GHSA-9f94-5g5w-gf6r,
GHSA-394x-vwmw-crm3, GHSA-hfpc-8r3f-gw53, GHSA-65p9-r9h6-22vj,
GHSA-vw5v-4f2q-w9xf) by moving aws-lc-sys from 0.33.0 to 0.42.0.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 13:52:37 -07:00
jason 1c0c44ec3c fix(agent): gate now binding to logging feature
The Windows CI matrix surfaced an `unused_variables` warning at
metrics.rs:846 — `let now = std::time::Instant::now();` was bound
unconditionally but only consumed inside a `#[cfg(feature = "logging")]`
tracing::debug! call.

This block lives in the non-Linux `collect_processes_all`, so the Linux
CI never compiles it and never sees the warning. Same shape as the
`processes_ttl_ms` Windows fix from earlier: a binding whose only
consumer is cfg-gated needs to be cfg-gated too.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-03 11:15:45 -07:00
jason ee4468ca23 Add Debian packaging support for socktop-agent (#25)
* Add Debian packaging support with cargo-deb

- Add cargo-deb metadata to socktop and socktop_agent Cargo.toml
- Create systemd service file for socktop_agent
- Add postinst/postrm maintainer scripts for user/group management
- Create GitHub Actions workflow to build .deb packages for AMD64 and ARM64
- Add comprehensive documentation in docs/DEBIAN_PACKAGING.md
- Packages will be available as artifacts on every push
- Automatic GitHub releases for version tags

* Add summary documentation for debian packaging

* fix unit test, move to macro cargo_bin!

* hotfix for issue with socktop agent not creating ssl certificate on first launch after upgrade of axum server version.

* Add helpful post-install message to guide users on enabling socktop-agent service

* Fix CI build by installing libdrm development dependencies

* Fix package rename script - cargo-deb already includes architecture in filename

* Make GPU support optional to enable RISC-V builds without libdrm

- Add 'gpu' feature flag (enabled by default)
- Make gfxinfo dependency optional
- Provide no-op GPU metrics when gpu feature disabled
- Disable GPU support for RISC-V builds in CI (libdrm unavailable)
- All other architectures (amd64, arm64, armhf) still get GPU support

* feature gate GPU stats for arm v7

* specify correct package names.

* install aarch64-linux-gnu-gcc build dep

* specify correct package name

* add RISC-V GCC compiler

* add .cargo to gitignore to elimicate issue with riscv64-linux-gnu-gcc linker in config.toml

* add gcc-arm-linux-gnueabihf linker fore armv7

* set correct x-compile lib gcc-aarch64-linux-gnu for arm64 builds.

* add ports.ubuntu.com to sources

* Add ARM64 as a foreign architecture

* fixe for ARM64 build.

* security.ubuntu.com` aNNOYING

* apt repo github page

* copy output to apt repo

* fix secrets path

* fix secrets path

* change build dep

* Fix postinst message box alignment

* ci(deb): restrict APT publish to v* release tags

Previously the workflow built and published on every push to master
and feature/debian-packaging in addition to v* tags. That meant the
gh-pages APT repo got overwritten on every commit with same-version
.debs, causing apt clients to see a phantom "update available" each
time and burning ~5-10 min of cross-compile CI per merge.

After this change:
  - PRs into master still cross-build .debs as a sanity check.
  - v* tags build, publish to gh-pages, and create a GitHub release.
  - workflow_dispatch remains as the manual escape hatch.
  - master pushes no longer trigger this workflow (ci.yml still runs).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-02 13:12:51 -07:00
jason 697a77bdab chore: update ratatui from 0.28 to 0.30 (#33)
* chore: update ratatui from 0.28 to 0.30

* style: cargo fmt

* fix: replace manual zero-guarded divisions with checked_div

* fix: collapse nested if into match guard

* style: cargo fmt

* bump crossterm and optimize various types, remove stale code.

* fix windows build

* only show parent level processes on main tui
2026-06-02 13:02:25 -07:00
dependabot[bot] 8f452a35e6 Bump rand from 0.8.5 to 0.8.6 (#31)
Bumps [rand](https://github.com/rust-random/rand) from 0.8.5 to 0.8.6.
- [Release notes](https://github.com/rust-random/rand/releases)
- [Changelog](https://github.com/rust-random/rand/blob/0.8.6/CHANGELOG.md)
- [Commits](https://github.com/rust-random/rand/compare/0.8.5...0.8.6)

---
updated-dependencies:
- dependency-name: rand
  dependency-version: 0.8.6
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-02 13:01:57 -07:00
dependabot[bot] 1d285c3c4e Bump rustls-webpki from 0.103.10 to 0.103.13 (#32)
Bumps [rustls-webpki](https://github.com/rustls/webpki) from 0.103.10 to 0.103.13.
- [Release notes](https://github.com/rustls/webpki/releases)
- [Commits](https://github.com/rustls/webpki/compare/v/0.103.10...v/0.103.13)

---
updated-dependencies:
- dependency-name: rustls-webpki
  dependency-version: 0.103.13
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-02 13:01:30 -07:00
dependabot[bot] 0fb45f6c50 Bump rustls-webpki from 0.103.8 to 0.103.10 (#30)
Bumps [rustls-webpki](https://github.com/rustls/webpki) from 0.103.8 to 0.103.10.
- [Release notes](https://github.com/rustls/webpki/releases)
- [Commits](https://github.com/rustls/webpki/compare/v/0.103.8...v/0.103.10)

---
updated-dependencies:
- dependency-name: rustls-webpki
  dependency-version: 0.103.10
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-13 09:43:38 -07:00
dependabot[bot] be24fa3859 Bump bytes from 1.10.1 to 1.11.1 in /socktop_wasm_test (#27)
Bumps [bytes](https://github.com/tokio-rs/bytes) from 1.10.1 to 1.11.1.
- [Release notes](https://github.com/tokio-rs/bytes/releases)
- [Changelog](https://github.com/tokio-rs/bytes/blob/master/CHANGELOG.md)
- [Commits](https://github.com/tokio-rs/bytes/compare/v1.10.1...v1.11.1)

---
updated-dependencies:
- dependency-name: bytes
  dependency-version: 1.11.1
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-25 16:14:57 -08:00
dependabot[bot] 39619b2845 Bump bytes from 1.11.0 to 1.11.1 (#28)
Bumps [bytes](https://github.com/tokio-rs/bytes) from 1.11.0 to 1.11.1.
- [Release notes](https://github.com/tokio-rs/bytes/releases)
- [Changelog](https://github.com/tokio-rs/bytes/blob/master/CHANGELOG.md)
- [Commits](https://github.com/tokio-rs/bytes/compare/v1.11.0...v1.11.1)

---
updated-dependencies:
- dependency-name: bytes
  dependency-version: 1.11.1
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-25 16:14:46 -08:00
dependabot[bot] 40c925e7f9 Bump time from 0.3.44 to 0.3.47 (#29)
Bumps [time](https://github.com/time-rs/time) from 0.3.44 to 0.3.47.
- [Release notes](https://github.com/time-rs/time/releases)
- [Changelog](https://github.com/time-rs/time/blob/main/CHANGELOG.md)
- [Commits](https://github.com/time-rs/time/compare/v0.3.44...v0.3.47)

---
updated-dependencies:
- dependency-name: time
  dependency-version: 0.3.47
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-25 16:14:29 -08:00
jason 8f69e469e6 Update README with website link 2025-11-30 10:21:26 -08:00
jason 3024816525 hotfix for issue with socktop agent not creating ssl certificate on first launch after upgrade of axum server version.
CI / build (ubuntu-latest) (push) Has been cancelled
CI / build (windows-latest) (push) Has been cancelled
2025-11-21 00:21:05 -08:00
jason 1d7bc42d59 fix unit test, move to macro cargo_bin! 2025-11-21 00:07:44 -08:00
jason 518ae8c2bf update axum server version
CI / build (ubuntu-latest) (push) Has been cancelled
CI / build (windows-latest) (push) Has been cancelled
2025-11-17 15:09:53 -08:00
jason 6eb1809309 set connector back to crate version 2025-11-17 14:15:39 -08:00
jason 1c01902a71 update cargo version number 2025-11-17 14:13:48 -08:00
jason 9d302ad475 patch header for small monitors and increase cargo version in advance of publish. 2025-11-17 11:52:22 -08:00
jason 7875f132f7 Make help modal scrollable for small resolutions
- Add Up/Down arrow key handling in help modal
- Display scrollbar when content exceeds viewport
- Update title to indicate scrollability
- Fixes content cutoff on small terminal windows
2025-11-17 11:29:23 -08:00
jason 0d789fb97c Add TUI improvements: CPU averaging, max memory tracking, and fuzzy process search (#23)
This commit implements several major improvements to the TUI experience:

1. CPU Average Display in Main Window
   - Show average CPU usage over monitoring period alongside current value
   - Format: "CPU avg (now: 45.2% | avg: 52.3%)"
   - Helps identify sustained vs momentary CPU spikes

2. Max Memory Tracking in Process Details Modal
   - Track and display peak memory usage since monitoring started
   - Shown as "Max Memory: 67.8 MB" in yellow for emphasis
   - Helps identify memory leaks and usage patterns
   - Resets when switching to different process

3. Fuzzy Process Search
   - Press / to activate search mode with bordered search box
   - Type to fuzzy-match process names (case-insensitive)
   - Press Enter to auto-select first result
   - Navigate results with arrow keys while typing
   - Press c to clear filter
   - Press / again to edit existing search

   Search box features:
   - Yellow bordered box for high visibility
   - Active mode: "Search: query_"
   - Filter mode: "Filter: query (press / to edit, c to clear)"

   Technical implementation:
   - Centralized filtering with get_filtered_sorted_indices()
   - Consistent filtering across display, navigation, mouse, and auto-scroll
   - Proper content area offset calculation for search box
   - Real-time filtering as user types

4. Code Quality Improvements
   - Created ProcessDisplayParams and ProcessKeyParams structs
   - Created MemoryIoParams struct for process modal rendering
   - Reduced function arguments to stay under clippy limits
   - Exported get_filtered_sorted_indices for reuse

Files Modified:
- socktop/src/app.rs: Search state, auto-scroll with filtering, max memory tracking
- socktop/src/ui/cpu.rs: CPU average calculation and display
- socktop/src/ui/processes.rs: Fuzzy search, filtering, parameter structs
- socktop/src/ui/modal.rs: Updated help modal with new shortcuts
- socktop/src/ui/modal_process.rs: Max memory display, MemoryIoParams struct
- socktop/src/ui/modal_types.rs: Added max_mem_bytes field

Testing:
- All tests pass
- No clippy warnings
- Cargo fmt applied
- Tested search, navigation, mouse clicks, and auto-scroll
- Verified on both filtered and unfiltered process lists

Breaking Changes:
- None (all changes are additive features)

Closes: (performance monitoring improvements)
2025-11-17 11:24:32 -08:00
jason 5ddaed298b Optimize socktop_agent for reduced binary size and memory footprint (#22)
This commit implements several optimizations to make socktop_agent
significantly more lightweight without sacrificing functionality.

Changes:

1. Reduced Tokio Runtime Thread Pool (main.rs)
   - Changed from default (num_cpus) to 2 worker threads
   - Configurable via SOCKTOP_WORKER_THREADS environment variable
   - Rationale: Agent is I/O-bound, not CPU-intensive
   - Memory savings: ~6-12 MB on typical 8-core systems

2. Minimal Tokio Features (Cargo.toml)
   - Changed from features = ["full"] to minimal set:
     ["rt-multi-thread", "net", "sync", "macros"]
   - Removed unused features: io, fs, process, signal, time
   - Binary size reduction: ~200-300 KB
   - Faster compile times

3. Optional Tracing (Cargo.toml, main.rs, metrics.rs)
   - Made tracing dependencies optional with "logging" feature flag
   - Disabled by default for production builds
   - Binary size reduction: 1.5 MB (27%!)
   - Enable with: cargo build --features logging

4. Cleanup (Cargo.toml)
   - Removed unused tokio-process dependency

Results:
- Binary size: 5.6 MB → 4.0 MB (28% reduction)
- Memory usage: 25-40 MB → 15-25 MB (30-40% reduction)
- Worker threads: 8+ → 2 (75% reduction on 8-core systems)

Testing:
- All tests pass with and without logging feature
- No clippy warnings
- Functionality unchanged
- Production-ready

Breaking Changes:
- None (all changes are backward compatible)
- Default behavior is now more lightweight
- Logging can be re-enabled with --features logging

To build with logging for debugging:
  cargo build --package socktop_agent --release --features logging
2025-11-17 09:51:41 -08:00
jason 1528568c30 Merge pull request #21 from jasonwitty/feature/about-modal
Feature/about modal
2025-11-17 00:18:55 -08:00
jason 6f238cdf25 tweak hotkeys, add info panel, optimize fonts and hotkeys for about and info panel.
CI / build (ubuntu-latest) (push) Has been cancelled
CI / build (windows-latest) (push) Has been cancelled
2025-11-17 00:05:02 -08:00
jason ffe451edaa cargo fmt 2025-10-26 02:32:11 -07:00
jason c9bde52cb1 move logo to them file. 2025-10-26 02:30:46 -07:00
jason 0603746d7c cargo fmt 2025-10-26 02:18:01 -07:00
jason 25632f3427 Add About modal with sock ASCII art 2025-10-26 02:16:42 -07:00
jason e51cdb0c50 display tweaks
CI / build (ubuntu-latest) (push) Has been cancelled
CI / build (windows-latest) (push) Has been cancelled
make it more pretty
2025-10-06 12:05:12 -07:00
jason 1cb05d404b fix: add backward compatibility for DiskInfo fields 2025-10-06 11:43:58 -07:00
jason 4196066e57 fix: NVMe temperature detection - contains() check and /dev/ prefix 2025-10-06 11:40:49 -07:00
jason 47e96c7d92 fix: refresh component values to collect NVMe temperatures 2025-10-06 11:15:36 -07:00
jason bae2ecb79a fix: lookup temperature for parent disk, not partition 2025-10-06 11:06:30 -07:00
jason bd0d15a1ae fix: correct disk size aggregation and nvme temperature detection 2025-10-06 10:52:44 -07:00
jason 689498c5f4 fix: show parent disks with aggregated partition stats 2025-10-06 10:46:51 -07:00
jason 34e260a612 feat: disk section enhancements - temperature, partition indentation, duplicate filtering 2025-10-06 10:30:55 -07:00
jason 47eff3a75c remove unused import. / clippy cleanup
CI / build (ubuntu-latest) (push) Has been cancelled
CI / build (windows-latest) (push) Has been cancelled
2025-10-06 10:01:40 -07:00
jason 0210b49219 cargo fmt 2025-10-06 09:52:36 -07:00
jason 70a150152c fix for windows build error 2025-10-06 09:51:11 -07:00
jason f4b54db399 fix for windows build error. 2025-10-06 09:50:38 -07:00
jason e857cfc665 add processes window cleanup
- refactor code
- add unit test
- fix warnings.
2025-10-05 00:07:27 -07:00
jason e66008f341 initial check for process summary screen
This check in offers alpha support for per process metrics, you can view threads, process CPU usage over time, IO, memory, CPU time, parent process, command, uptime and journal entries. This is unfinished but all major functionality is available and I wanted to make it available to feedback and testing.
2025-10-02 16:54:27 -07:00
jason a238ce320b Merge pull request #15 from jasonwitty/feature/connection-error-modal
feature - add error modal support and retry
2025-09-15 10:34:50 -07:00
jason b635f5d7f4 feature - add error modal support and retry
CI / build (ubuntu-latest) (push) Has been cancelled
CI / build (windows-latest) (push) Has been cancelled
2025-09-15 10:16:47 -07:00
jason 18b41c1b45 Merge pull request #14 from jasonwitty/feature/extract-socktop-connector
Refactor for additional socktop connector library
2025-09-10 15:01:17 -07:00
jason b4ed036357 bump version
CI / build (ubuntu-latest) (push) Has been cancelled
CI / build (windows-latest) (push) Has been cancelled
2025-09-10 13:05:50 -07:00
jason ec0e409488 fix clippy warnings. 2025-09-10 11:43:12 -07:00
jason 08f248c696 Housekeeping and QOL
non functional update:

- refactor stream of consciousness into separate files.
- combine equivelent functions used in networking and wasm features.
- cleanups and version bumps.
2025-09-10 10:39:21 -07:00
jason cea133b7da show actual metrics 2025-09-10 09:32:00 -07:00
jason e679896ca0 Add AI generated zliij plugin scafold 2025-09-09 15:51:44 -07:00
jason 5e5fde190a add screenshot 2025-09-09 13:49:06 -07:00
jason 8286d21a2a Merge branch 'feature/extract-socktop-connector' of https://github.com/jasonwitty/socktop into feature/extract-socktop-connector 2025-09-09 13:43:48 -07:00
jason b91fc7b016 allow user to easily override location with text entry. 2025-09-09 13:43:45 -07:00
jason f936767835 Update README.md 2025-09-09 02:57:32 -07:00
jason 5f2777cdb2 Update README.md 2025-09-09 02:53:50 -07:00
jason 49164da105 docs: Complete WASM documentation update - reflect full networking capabilities 2025-09-09 02:42:12 -07:00
jason 22c1f80e70 docs(connector): update README to reflect full WASM support 2025-09-09 02:38:35 -07:00
jason a486225008 fix: formatting from cargo fmt 2025-09-09 02:32:20 -07:00
jason d97f7507e8 feat(connector): implement gzipped protobuf support for WASM and fix all warnings 2025-09-09 02:30:16 -07:00
jason e4186a7ec0 WASM compatibilty 2025-09-08 12:29:03 -07:00
jason f59c28d966 WASM compatibility update
Related to: Usage as a lib #8

1.  feature gating of TLS and other features not supported with WASM.
2. updated documentation.
3. creation of AI slop WASM example for verification.
2025-09-08 12:28:44 -07:00
jason 06cd6d0c82 Reference: Usage as a lib #8
- Implement protocol versioning
- migrate to thisError
- general error handling improvements in socktop_connector lib
- improve documentation
- increment  version
2025-09-07 18:55:23 -07:00
jason ffc246b705 Add WASM compatibility documentation and minimal tokio features 2025-09-04 14:49:39 -07:00
jason cd2816915d cargo fmt 2025-09-04 06:19:16 -07:00
jason 7cd5941434 Add continuous monitoring examples to documentation 2025-09-04 06:17:23 -07:00
jason 76c7fe1d6f Fix CI: Update test path for WebSocket integration test 2025-09-04 06:11:59 -07:00
jason eed04f1d5c Fix remaining clippy warnings in socktop_agent 2025-09-04 06:04:57 -07:00
jason 764c25846f Fix clippy warnings: collapse nested if statements using let-else patterns 2025-09-04 05:58:17 -07:00
jason a9bf4208ab cargo fmt 2025-09-04 05:53:59 -07:00
jason 9c1416eabf Fix build script to use vendored protoc binary for CI 2025-09-04 05:52:57 -07:00
jason e7350f8908 Update Cargo.lock with protoc-bin-vendored dependency 2025-09-04 05:50:17 -07:00
jason 2647b611d2 Fix build script to use protoc-bin-vendored for CI compatibility 2025-09-04 05:48:02 -07:00
jason a359f17367 fix for failed CI build 2025-09-04 05:45:13 -07:00
jason d93b7aca5a remove invalid slug 2025-09-04 05:41:59 -07:00
jason e51054811c Refactor for additional socktop connector library
- socktop connector allows you to communicate with socktop agent directly from you code without needing to implement the agent API directly.
- will also be used for non tui implementation of "socktop collector" in the future.
- moved to rust 2024 to take advantage of some new features that helped with refactor.
- fixed everything that exploded with update.
- added rust docs for lib.
2025-09-04 05:30:25 -07:00
jason b74242e6d9 Merge pull request #13 from jasonwitty/6-accessibility-cross-compile-guide
add license file
2025-09-03 23:11:59 -07:00
jason 4e378b882a add license file
CI / build (ubuntu-latest) (push) Has been cancelled
CI / build (windows-latest) (push) Has been cancelled
2025-09-03 23:10:48 -07:00
jason 622767a605 Merge pull request #7 from jasonwitty/6-accessibility-cross-compile-guide
re: Accessibility: Cross-compile guide
2025-08-30 02:00:13 -07:00
jason 0c5a1d7553 update readme 2025-08-30 01:59:25 -07:00
jason 0bd709d2a7 slipsteam note for rpi users on kernel version 2025-08-29 11:28:59 -07:00
jason 31f5f9ce76 re: Accessibility: Cross-compile guide 2025-08-29 11:23:41 -07:00
jason df2308e6e9 code optimizations to reduce cpu usage of agent on all platforms and additional unit test. 2025-08-28 16:03:05 -07:00
jason 7592709a43 clamp then divide by cores for more accurate statistics 2025-08-28 13:11:48 -07:00
jason 61fe1cc38e socktop_agent: bump version to 1.40.65 2025-08-28 12:27:48 -07:00
jason eed346abb6 scripts: add publish_socktop_agent.sh job 2025-08-28 12:07:03 -07:00
jason ab3bb33711 socktop_agent: bump version to 1.40.64 2025-08-28 12:03:45 -07:00
jason 7caf2f4bfb remove ununused var 2025-08-27 17:15:35 -07:00
jason b249c7ba99 Update metrics.rs 2025-08-27 16:55:12 -07:00
jason f0858525e8 fix for macos defect where processes less than .01% were being filtered 2025-08-27 16:55:09 -07:00
jason 2fe005ed90 ProcessesToUpdate::All enum 2025-08-27 16:20:55 -07:00
jason ca6a5cbdfa use ProcessesToUpdate::All ENUM 2025-08-27 16:20:41 -07:00
jason 56301d61fd fixes for non linux compilation issues. 2025-08-27 16:11:17 -07:00
jason 55e5c708fe MACOS / NON LINUX metrics optimizations. 2025-08-27 16:00:29 -07:00
jason 2d17cf1598 additional optimizations for macos 2025-08-27 15:05:38 -07:00
jason 353c08c35e increment version and macos performance 2025-08-26 12:14:32 -07:00
jason f13ea45360 increment version 2025-08-26 10:57:01 -07:00
jason 8ce00a5dad non linux optimizations for macbook 2025-08-26 10:14:14 -07:00
jason f37b8d9ff4 chore(agent): fix clippy unused mut on non-linux process list 2025-08-26 00:22:29 -07:00
jason 322981ada7 cargo fmt and version bump 2025-08-26 00:20:52 -07:00
jason 3394beab67 chore: make pre-commit resilient when cargo absent 2025-08-26 00:18:10 -07:00
jason c9ebea92f5 perf(agent,non-linux): enable CPU core normalization by default; tighter scaling threshold 2025-08-25 23:50:26 -07:00
jason e2dc5e8ac9 perf(agent,non-linux): add per-process CPU scaling heuristic to reduce overreporting 2025-08-25 23:47:31 -07:00
jason beddba0072 perf(agent,non-linux): reduce process collection overhead; configurable CPU sample delay 2025-08-25 23:44:28 -07:00
jason cacc4cba9f cargo fmt 2025-08-25 23:24:50 -07:00
jason 66270c16b7 perf(agent): windows/mac cpu collection tweak; add optional normalization; silence linux dead_code 2025-08-25 22:59:07 -07:00
jason 00d5777d05 Merge branch 'master' of https://github.com/jasonwitty/socktop 2025-08-25 22:35:02 -07:00
jason f62b5274d2 optimize non linux metrics collection 2025-08-25 22:35:01 -07:00
jason bbbe35111a Update README.md 2025-08-25 01:33:40 -07:00
jason a4356b5ece update readme with animated demo 2025-08-24 20:35:56 -07:00
jason b6e656738b chore(release): bump to 1.40.0
CI / build (ubuntu-latest) (push) Has been cancelled
CI / build (windows-latest) (push) Has been cancelled
2025-08-24 18:56:40 -07:00
jason f83cb07d57 Release candidate 1.4
increment version, support version flag on socktop
2025-08-24 18:03:45 -07:00
jason 7697c7dc2b docs: add per-crate README.md and link via Cargo.toml readme field 2025-08-24 17:56:22 -07:00
jason 1043fffc8d Merge pull request #5 from jasonwitty/feature/housekeeping
Feature/housekeeping
2025-08-24 17:46:26 -07:00
jason ce59dd9dfe chore(agent): fix clippy needless_return for non-linux process collection
CI / build (ubuntu-latest) (push) Has been cancelled
CI / build (windows-latest) (push) Has been cancelled
2025-08-24 12:52:56 -07:00
jason 8d48fa4c3b increment version 2025-08-24 12:47:49 -07:00
jason 51e702368e cargo fmt 2025-08-24 12:40:35 -07:00
jason 85f9a44e46 perf(agent): add hostname + TTL caches (metrics/disks/processes) and reuse sys for processes 2025-08-24 12:38:32 -07:00
jason b2468a5936 refactor(agent): remove unused background sampler infrastructure (request-driven only) 2025-08-24 12:29:23 -07:00
jason 8de5943f34 test(agent): move inline port parsing test to tests/port_parse.rs 2025-08-24 12:15:32 -07:00
jason e624751f56 chore: align sysinfo to 0.37 across workspace 2025-08-24 12:11:38 -07:00
jason 8bd1af7a27 chore: remove unused deps (thiserror, chrono, futures, nvml-wrapper, tungstenite, bytes, prost-types) 2025-08-24 12:08:52 -07:00
jason 5c32d15156 first run messaging.
display welcome message on first run when a profile file is not created and remote server not specified.
2025-08-24 12:01:17 -07:00
jason 471d547b5d cargo fmt and increment version 2025-08-23 02:18:09 -07:00
jason d3aff590bc client: fully disable hostname verification by custom ServerCertVerifier unless --verify-hostname used 2025-08-23 02:15:45 -07:00
jason 47910725a8 increment version 2025-08-22 22:48:41 -07:00
jason a8e3f4ef26 docs: describe --verify-hostname flag and default relaxed SAN behavior 2025-08-22 22:39:18 -07:00
jason fab1e5a104 client: default skip hostname verification; add --verify-hostname to enable 2025-08-22 22:39:06 -07:00
jason d0455611d5 cargo fmt 2025-08-22 14:09:02 -07:00
jason 4c45b85c98 fix san and increment version 2025-08-22 14:07:41 -07:00
jason d9fdc31e8f docs: document SOCKTOP_AGENT_EXTRA_SANS for additional certificate SANs 2025-08-22 13:48:07 -07:00
jason dc9aa4c026 agent: support extra SANs via SOCKTOP_AGENT_EXTRA_SANS env var 2025-08-22 13:47:51 -07:00
jason c2e91bd20c docs: document TLS cert expiry and manual regeneration procedure 2025-08-22 12:57:48 -07:00
jason 25229d6b03 cargo fmt 2025-08-22 12:49:12 -07:00
jason 290e2a8fb2 fix for expired certificate 2025-08-22 12:46:01 -07:00
jason 30d263c71e agent: dynamic self-signed cert validity (~397d from now) to avoid immediate expiry 2025-08-22 12:43:48 -07:00
jason 9b177f3206 cargo fmt 2025-08-22 11:55:41 -07:00
jason 8a6ae3fcd7 increment version 2025-08-22 11:53:27 -07:00
jason 5b8ec7efc1 agent: add --version / -V flag 2025-08-22 11:52:51 -07:00
jason 155c420a1a cargo fmt all check ins 2025-08-22 11:10:11 -07:00
jason d3fa55e572 chore: ignore .vscode and remove from repo 2025-08-22 11:09:33 -07:00
jason faf2861b29 cargo fmt 2025-08-22 10:53:47 -07:00
jason 59432ab1d3 agent: fix rcgen usage for self-signed cert generation 2025-08-22 10:48:01 -07:00
jason d1c8a64418 agent: replace openssl self-signed cert generation with rcgen (pure Rust) 2025-08-22 10:46:29 -07:00
jason 8def4b2d06 Publish: include proto in each crate and fix build.rs paths 2025-08-22 10:44:56 -07:00
jason a42ca71a9f update version prior to cargo publish 2025-08-22 10:41:17 -07:00
jason 9f675fa804 Merge pull request #4 from jasonwitty/feature/connection-profiles
Feature/connection profiles
2025-08-22 09:31:28 -07:00
jason 3ac03c07ba enable GPU polling only when GPU is present 2025-08-22 09:27:05 -07:00
jason e53d0ab98d Add TLS / Token, polling interval indicators.
CI / build (ubuntu-latest) (push) Has been cancelled
CI / build (windows-latest) (push) Has been cancelled
2025-08-21 17:38:26 -07:00
jason 2ca51adc61 tui: refine header icons (crossed TLS when disabled, spacing fix) 2025-08-21 17:28:21 -07:00
jason 67ecf36883 feat(tui): header shows TLS/token status and polling intervals 2025-08-21 17:24:41 -07:00
jason 9a35306340 cargo fmt 2025-08-21 16:19:49 -07:00
jason a4bb6f170a feat(client): configurable metrics/process intervals with profile persistence; docs updated 2025-08-21 16:18:41 -07:00
jason 384953d5d5 Merge pull request #3 from jasonwitty/feature/connection-profiles
Feature/connection profiles
2025-08-21 16:17:49 -07:00
jason f9114426cc add unit tests for profile creation and update readme 2025-08-21 14:42:15 -07:00
jason 8ee2a03a2c chore(client): clean up demo mode integration and add stop log line 2025-08-21 13:55:02 -07:00
jason 0275b1871d cargo fmt 2025-08-21 13:49:36 -07:00
jason 9491dc50a8 feat(client): demo mode (--demo or select demo) auto-spawns local agent on 3231 2025-08-21 13:47:28 -07:00
jason e7eb3e6557 cargo fmt 2025-08-21 13:18:36 -07:00
jason a596acfb72 chore(client): refactor profile overwrite logic to satisfy clippy 2025-08-21 13:17:53 -07:00
jason b727e54589 feat(client): prompt for URL/CA when specifying a new profile name 2025-08-21 12:56:11 -07:00
jason 2af08c455a fix(client): correct profile overwrite prompt logic (only save on confirm or --save) 2025-08-21 12:48:53 -07:00
jason d049846564 docs: add connection profiles section to README 2025-08-21 12:41:46 -07:00
jason 97308f9d15 feat(client): connection profiles (--profile/-P, --save) with JSON persistence 2025-08-21 12:39:21 -07:00
jason 4cef273e57 Merge pull request #2 from jasonwitty/feature/protobuf-processes
Feature/protobuf processes
2025-08-21 11:50:27 -07:00
jason 660474a6ce ci cleanup
CI / build (ubuntu-latest) (push) Has been cancelled
CI / build (windows-latest) (push) Has been cancelled
2025-08-20 20:36:49 -07:00
jason 93dd14967d try/fix windows again ! 2025-08-20 16:32:51 -07:00
jason 923a3872fe add logging to help debug windows problems 2025-08-20 15:47:28 -07:00
jason 5f10e34341 windows try/fix 2025-08-20 15:20:07 -07:00
jason b80d322650 cargo fmt 2025-08-20 11:29:22 -07:00
jason fff386f9d5 fixing windows build problems. i hate windows !
Agent:
Added GET /healthz that returns 200 immediately.
File: main.rs (router now includes /healthz).
CI workflow:
Start agent from target/release on both OSes.
Set SOCKTOP_ENABLE_SSL=0 explicitly.
Ubuntu: wait on curl http://127.0.0.1:3000/healthz (60s), log tail and ss/netstat on failure.
Windows: wait on Invoke-WebRequest to /healthz (60s), capture stdout/stderr, print netstat on failure.
File: .github/workflows/ci.yml.
2025-08-20 11:26:09 -07:00
jason 93f4e1feea fix windows build after ssl feature and optimize build 2025-08-20 10:24:24 -07:00
jason 97255b42fb fix windows build 2025-08-20 00:14:21 -07:00
jason 554a2c349f protobuff Process list
BREAKING: Process list over WS is now Protocol Buffers; client required.
Agent: returns all processes (no server-side top-k); large payloads gzip-compressed.
Client: decodes protobuf (gz/raw), moves sorting/pagination to TUI.
Build: add prost/prost-build with vendored protoc; enable thin LTO, panic=abort, strip symbols.
Cleanup: cfg-gate Linux-only code; fix Clippy across platforms; tests updated (ws probe TLS CA).
2025-08-19 23:24:36 -07:00
jason 10501168c5 clippy fixes. 2025-08-19 15:52:30 -07:00
jason d346c61c28 Merge pull request #1 from jasonwitty/feature/wss-selfsigned
SSL Support
2025-08-19 15:33:50 -07:00
jason 7652095109 cargo fmt
CI / build (ubuntu-latest) (push) Has been cancelled
CI / build (windows-latest) (push) Has been cancelled
2025-08-19 15:33:11 -07:00
jason 6b58ac67f6 Merge branch 'master' into feature/wss-selfsigned 2025-08-19 15:31:10 -07:00
jason 3ad1d52fe2 fix windows build.
CI / build (ubuntu-latest) (push) Has been cancelled
CI / build (windows-latest) (push) Has been cancelled
Gate Linux-specific imports and fields to avoid Windows dead-code/unused warnings.
Ensure Linux-only proc CPU tracker is not referenced on non-Linux builds.
2025-08-16 17:42:18 -07:00
jason 2e8cc24e81 remove dead code and increment version 2025-08-16 17:31:32 -07:00
jason 36e73fd9ed cargo fmt 2025-08-16 01:25:03 -07:00
jason 3d14e4a370 SSL Support
Add WSS/TLS (self‑signed) with client cert pinning; auto ws→wss on --tls-ca/-t; add -p/-t flags; harden TLS test; fix clippy; update README.

feat: WSS/TLS support (self‑signed + pinning), auto ws→wss when CA provided, new -p/-t flags; tests + clippy cleanup; docs updated.

Add TLS: self‑signed certs on agent, client pin via --tls-ca/-t (auto‑upgrade to wss), CLI/tests/README updates, clippy fixes.

12 files changed
Cargo.toml
README.md
Cargo.tomlsocktop_agent
main.rssocktop_agent/src
tls.rssocktop_agent/src
cli_args.rssocktop_agent/tests
Add Context...
README.md
2025-08-16 01:23:20 -07:00
jason c6b8c9c905 patch for macbook compatibility issues. 2025-08-15 19:21:34 -07:00
jason f980b6ace9 Update README.md 2025-08-13 20:17:36 -07:00
jason 6a27280f8d Merge branch 'master' of https://github.com/jasonwitty/socktop
CI / build (ubuntu-latest) (push) Has been cancelled
CI / build (windows-latest) (push) Has been cancelled
2025-08-12 17:12:38 -07:00
jason 38b0cdcf0e update screenshot 2025-08-12 17:12:27 -07:00
jason 268627ed63 Update README.md 2025-08-12 17:10:12 -07:00
jason 55a663cf7a Update README.md 2025-08-12 17:09:31 -07:00
jason 8b76ccb742 Merge branch 'master' of https://github.com/jasonwitty/socktop 2025-08-12 17:07:36 -07:00
jason d0f6cb0e70 fix screenshot 2025-08-12 17:07:25 -07:00
jason 56ebe6bbab Rename tmux_4_rpis_v2jpg to tmux_4_rpis_v2.jpg 2025-08-12 17:05:40 -07:00
jason dc90de7ff1 update readme and add new screenshots 2025-08-12 17:02:01 -07:00
jason 319f47eb73 Update README.md 2025-08-12 16:48:35 -07:00
jason fd2889ccca Update cargo versions in prep for publish. 2025-08-12 16:12:08 -07:00
jason 0859f50897 multiple feature and performance improvements (see description)
Here are concise release notes you can paste into your GitHub release.

Release notes — 2025-08-12

Highlights

Agent back to near-zero CPU when idle (request-driven, no background samplers).
Accurate per-process CPU% via /proc deltas; only top-level processes (threads hidden).
TUI: processes pane gets scrollbar, click-to-sort (CPU% or Mem) with indicator, stable total count.
Network panes made taller; disks slightly reduced.
README revamped: rustup prereqs, crates.io install, update/systemd instructions.
Clippy cleanups across agent and client.
Agent

Reverted precompressed caches and background samplers; WebSocket path is request-driven again.
Ensured on-demand gzip for larger replies; no per-request overhead when small.
Processes: switched to refresh_processes_specifics with ProcessRefreshKind::everything().without_tasks() to exclude threads.
Per-process CPU% now computed from /proc jiffies deltas using a small ProcCpuTracker (fixes “always 0%”/scaling issues).
Optional metrics and light caching:
CPU temp and GPU metrics gated by env (SOCKTOP_AGENT_TEMP=0, SOCKTOP_AGENT_GPU=0).
Tiny TTL caches via once_cell to avoid rescanning sensors every tick.
Dependencies: added once_cell = "1.19".
No API changes to WS endpoints.
Client (TUI)

Processes pane:
Scrollbar (mouse wheel, drag; keyboard arrows/PageUp/PageDown/Home/End).
Click header to sort by CPU% or Mem; dot indicator on active column.
Preserves process_count across fast metrics updates to avoid flicker.
UI/theme:
Shared scrollbar colors moved to ui/theme.rs; both CPU and Processes reuse them.
Cached pane rect to fix input handling; removed unused vars.
Layout: network download/upload get more vertical space; disks shrink slightly.
Clippy fixes: derive Default for ProcSortBy; style/import cleanups.
Docs

README: added rustup install steps (with proper shell reload), install via cargo install socktop and cargo install socktop_agent, and a clear Updating section (systemd service steps included).
Features list updated; roadmap marks independent cadences as done.
Upgrade notes

Agent: cargo install socktop_agent --force, then restart your systemd service; if unit changed, systemctl daemon-reload.
TUI: cargo install socktop --force.
Optional envs to trim overhead: SOCKTOP_AGENT_GPU=0, SOCKTOP_AGENT_TEMP=0.
No config or API breaking changes.
2025-08-12 15:52:46 -07:00
jason 5c002f0b2b Update README.md 2025-08-12 00:01:21 -07:00
jason 5a824c2098 only run apt command if build box is linux 2025-08-11 23:49:45 -07:00
jason ffb381e40e install deps libdrm-dev libdrm-amdgpu1 on build box 2025-08-11 23:46:08 -07:00
jason 0a70d7fd39 rustfmt 2025-08-11 23:41:23 -07:00
jason 8d81ee1f7e clippy clean ups 2025-08-11 23:37:50 -07:00
jason 1e248306a6 clippy clean up multiple files 2025-08-11 23:27:18 -07:00
jason 7cd6a6e0a1 gpu clippy cleanup 2025-08-11 23:08:35 -07:00
jason 8f58feffbe clippy clean up app.rs 2025-08-11 22:59:36 -07:00
jason 5790ef753b clippy cleanup 2025-08-11 22:56:35 -07:00
jason 9a49fd6b24 clippy cleanup main 2025-08-11 22:50:15 -07:00
jason b35e431200 clippy clean up 2025-08-11 22:46:58 -07:00
jason 4b52382326 another clippy cleanup 2025-08-11 22:45:24 -07:00
jason 11506699e3 clippy clean up 2025-08-11 22:44:43 -07:00
jason 4c6c707dd0 struct cleanup 2025-08-11 22:41:12 -07:00
jason d69a4104fc performance improvements and formatting cleanup 2025-08-11 22:37:46 -07:00
jason c3f81eef25 clippy code clean up
clippy code clean up
2025-08-11 20:47:21 -07:00
jason 05276f9eea fix clippy issues causing workflow failure. 2025-08-11 14:39:19 -07:00
jason 0105b29bfc fix additional clippy warnings. 2025-08-11 14:34:45 -07:00
jason 0cbba6b290 fix clippy format warnings 2025-08-11 14:30:41 -07:00
jason 250f7bf93a remove unused vendor field. 2025-08-11 14:25:58 -07:00
jason 4efeb3b60f update screenshots 2025-08-11 14:17:04 -07:00
jason d20061614c update default screenshot 2025-08-11 13:47:23 -07:00
jason 289c9f7ebe add cargo install documentation and enable release artifacts in actions
add cargo install documentation and enable release artifacts in actions
2025-08-11 13:38:26 -07:00
jason bdfa74be54 add license for socktop_agent 2025-08-11 12:10:40 -07:00
jason 6efdc35b19 add license so we can publish to cargo 2025-08-11 12:09:14 -07:00
jason 20278d67f1 new feature: gpu support 2025-08-11 12:04:55 -07:00
jason a4f69a5f7d Add scrollbar to CPU per core area. 2025-08-10 23:32:44 -07:00
jason 9b1643afac add screenshot and information abotu running as service. 2025-08-09 22:40:44 -07:00
jason a9086eac84 Create 14900KS_arch_alacritty.jpg 2025-08-08 21:27:27 -07:00
jason 4bd6744df4 fix clippy command 2025-08-08 17:33:30 -07:00
jason 274a485f8d fmt: apply rustfmt 2025-08-08 17:25:15 -07:00
jason 747aef0005 Merge branch 'master' of https://github.com/jasonwitty/socktop 2025-08-08 16:51:22 -07:00
jason a0e17c6e22 fix build warning and add ghostty screenshot 2025-08-08 16:46:46 -07:00
jason 19973c24d8 Update README.md 2025-08-08 14:15:28 -07:00
jason 9a4c8b703e Update README.md 2025-08-08 13:24:32 -07:00
jason 968a25eaf1 Update README.md 2025-08-08 13:22:57 -07:00
jason 13fb22c7ee add rustup installer line for lazy people 2025-08-08 13:14:33 -07:00
jason 6c867774f7 correct path in docs 2025-08-08 13:09:53 -07:00
jason 7c3e4a6e39 fix executable in documentation readme (socktop_agent) 2025-08-08 13:06:15 -07:00
jason 466a32a90a add tmux instructions to readme 2025-08-08 13:00:36 -07:00
jason cb4882e983 patch for ci failure. 2025-08-08 12:55:48 -07:00
jason 87378e49ac Merge branch 'master' of https://github.com/jasonwitty/socktop
CI / build (ubuntu-latest) (push) Has been cancelled
CI / build (windows-latest) (push) Has been cancelled
2025-08-08 12:42:37 -07:00
jason 100434fc3c Major refactor, additional comments, performance improvements, idle performance improvements, access token, port specification
Release highlights

Introduced split client/agent architecture with a ratatui-based TUI and a lightweight WebSocket agent.
Added adaptive (idle-aware) sampler: agent samples fast only when clients are connected; sleeps when idle.
Implemented metrics JSON caching for instant ws replies; cold-start does one-off collection.
Port configuration: --port/-p, positional PORT, or SOCKTOP_PORT env (default 3000).
Optional token auth: SOCKTOP_TOKEN on agent, ws://HOST:PORT/ws?token=VALUE in client.
Logging via tracing with RUST_LOG control.
CI workflow (fmt, clippy, build) for Linux and Windows.
Systemd unit example for always-on agent.
TUI features

CPU: overall sparkline + per-core history with trend arrows and color thresholds.
Memory/Swap gauges with humanized labels.
Disks panel with per-device usage and icons.
Network download/upload sparklines (KB/s) with peak tracking.
Top processes table (PID, name, CPU%, mem, mem%).
Header with hostname and CPU temperature indicator.
Agent changes

sysinfo 0.36.1 targeted refresh: refresh_cpu_all, refresh_memory, refresh_processes_specifics(ProcessesToUpdate::All, ProcessRefreshKind::new().with_cpu().with_memory(), true).
WebSocket handler: client counting with wake notifications, cold-start handling, proper Response returns.
Sampler uses MissedTickBehavior::Skip to avoid catch-up bursts.
Docs

README updates: running instructions, port configuration, optional token auth, platform notes, example JSON.
Added socktop-agent.service systemd unit.
Platform notes

Linux (AMD/Intel) supported; tested on AMD, targeting Intel next.
Raspberry Pi supported (availability of temps varies by model).
Windows builds/run; CPU temperature may be unavailable (shows N/A).
Known/next

Roadmap includes configurable refresh interval, TUI filtering/sorting, TLS/WSS, and export to file.
Add Context...
README.md
2025-08-08 12:41:32 -07:00
jason deef4702f4 Update README.md 2025-08-08 01:08:02 -07:00
jason 1c2415bc1b correct readme 2025-08-08 01:06:43 -07:00
jasonwitty fac09b381f initial checkin 2025-08-08 01:03:35 -07:00
208 changed files with 28602 additions and 1829 deletions
+39
View File
@@ -0,0 +1,39 @@
#!/usr/bin/env bash
# This repository uses a custom hooks directory (.githooks). To enable this pre-commit hook run:
# git config core.hooksPath .githooks
# Ensure this file is executable: chmod +x .githooks/pre-commit
set -euo pipefail
echo "[pre-commit] Running cargo fmt --all" >&2
if ! command -v cargo >/dev/null 2>&1; then
# Try loading rustup environment (common install path)
if [ -f "$HOME/.cargo/env" ]; then
# shellcheck source=/dev/null
. "$HOME/.cargo/env"
fi
fi
if ! command -v cargo >/dev/null 2>&1; then
echo "[pre-commit] cargo not found in PATH; skipping fmt (install Rust or adjust PATH)." >&2
exit 0
fi
cargo fmt --all
# Stage any Rust files that were reformatted
changed=$(git diff --name-only --diff-filter=M | grep -E '\\.rs$' || true)
if [ -n "$changed" ]; then
echo "$changed" | xargs git add
echo "[pre-commit] Added formatted files" >&2
fi
# Fail if further diffs remain (shouldn't happen normally)
unfmt=$(git diff --name-only --diff-filter=M | grep -E '\\.rs$' || true)
if [ -n "$unfmt" ]; then
echo "[pre-commit] Some Rust files still differ after formatting:" >&2
echo "$unfmt" >&2
exit 1
fi
exit 0
+446
View File
@@ -0,0 +1,446 @@
name: Build Debian Packages
on:
# APT publishing is release-driven: we build + publish only on `v*` tag
# pushes. PRs into master still build the .debs as a sanity check (no
# publish). Manual dispatch is kept as an escape hatch.
push:
tags:
- "v*"
pull_request:
branches:
- master
workflow_dispatch:
env:
CARGO_TERM_COLOR: always
jobs:
build-deb:
name: Build .deb for ${{ matrix.target }}
# PINNED, not ubuntu-latest: the binaries link against this runner's
# (multiarch) glibc, so the runner sets the MINIMUM glibc the .debs demand
# at install time. ubuntu-latest moved to 24.04/glibc 2.39 and the packages
# stopped installing on Debian 12/RPi OS bookworm (glibc 2.36). 22.04 links
# 2.35, which bookworm satisfies. The "enforce glibc floor" step below
# turns any future violation into a red build instead of a fleet-wide apt
# failure — if this pin ever has to move past bookworm's glibc, that step
# is the contract to renegotiate first.
runs-on: ubuntu-22.04
strategy:
matrix:
include:
- target: x86_64-unknown-linux-gnu
arch: amd64
- target: aarch64-unknown-linux-gnu
arch: arm64
- target: armv7-unknown-linux-gnueabihf
arch: armhf
- target: riscv64gc-unknown-linux-gnu
arch: riscv64
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.target }}
- name: Install cargo-deb
run: cargo install cargo-deb
- name: Install build dependencies
run: |
sudo apt-get update
sudo apt-get install -y dpkg-dev
- name: Install cross-compilation tools (ARM64)
if: matrix.target == 'aarch64-unknown-linux-gnu'
run: |
sudo dpkg --add-architecture arm64
# Disable all existing sources and create new ones with proper arch specifications
sudo mv /etc/apt/sources.list /etc/apt/sources.list.backup
sudo mv /etc/apt/sources.list.d /etc/apt/sources.list.d.backup || true
sudo mkdir -p /etc/apt/sources.list.d
# Clear APT cache and lists
sudo rm -rf /var/lib/apt/lists/*
sudo mkdir -p /var/lib/apt/lists/partial
# Create new sources.list with both amd64 and arm64
cat << EOF | sudo tee /etc/apt/sources.list
deb [arch=amd64] http://archive.ubuntu.com/ubuntu $(lsb_release -sc) main universe restricted multiverse
deb [arch=amd64] http://archive.ubuntu.com/ubuntu $(lsb_release -sc)-updates main universe restricted multiverse
deb [arch=amd64] http://archive.ubuntu.com/ubuntu $(lsb_release -sc)-backports main universe restricted multiverse
deb [arch=amd64] http://security.ubuntu.com/ubuntu $(lsb_release -sc)-security main universe restricted multiverse
deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports $(lsb_release -sc) main universe restricted multiverse
deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports $(lsb_release -sc)-updates main universe restricted multiverse
deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports $(lsb_release -sc)-backports main universe restricted multiverse
deb [arch=arm64] http://ports.ubuntu.com/ubuntu-ports $(lsb_release -sc)-security main universe restricted multiverse
EOF
echo "=== Contents of /etc/apt/sources.list ==="
cat /etc/apt/sources.list
echo "=== Contents of /etc/apt/sources.list.d/ ==="
ls -la /etc/apt/sources.list.d/ || true
sudo apt-get update
sudo apt-get install -y gcc-aarch64-linux-gnu libdrm-dev:arm64 libdrm-amdgpu1:arm64
- name: Install cross-compilation tools (ARMhf)
if: matrix.target == 'armv7-unknown-linux-gnueabihf'
run: |
sudo apt-get update
sudo apt-get install -y gcc-arm-linux-gnueabihf
- name: Install cross-compilation tools (RISC-V)
if: matrix.target == 'riscv64gc-unknown-linux-gnu'
run: |
sudo apt-get update
sudo apt-get install -y gcc-riscv64-linux-gnu
- name: Install GPU libraries (x86_64)
if: matrix.target == 'x86_64-unknown-linux-gnu'
run: |
sudo apt-get update
sudo apt-get install -y libdrm-dev libdrm-amdgpu1
- name: Configure cross-compilation (ARM64)
if: matrix.target == 'aarch64-unknown-linux-gnu'
run: |
mkdir -p .cargo
cat >> .cargo/config.toml << EOF
[target.aarch64-unknown-linux-gnu]
linker = "aarch64-linux-gnu-gcc"
EOF
- name: Configure cross-compilation (ARMhf)
if: matrix.target == 'armv7-unknown-linux-gnueabihf'
run: |
mkdir -p .cargo
cat >> .cargo/config.toml << EOF
[target.armv7-unknown-linux-gnueabihf]
linker = "arm-linux-gnueabihf-gcc"
EOF
- name: Configure cross-compilation (RISC-V)
if: matrix.target == 'riscv64gc-unknown-linux-gnu'
run: |
mkdir -p .cargo
cat >> .cargo/config.toml << EOF
[target.riscv64gc-unknown-linux-gnu]
linker = "riscv64-linux-gnu-gcc"
EOF
- name: Cache cargo registry
uses: actions/cache@v4
with:
path: ~/.cargo/registry
key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }}
- name: Cache cargo index
uses: actions/cache@v4
with:
path: ~/.cargo/git
key: ${{ runner.os }}-cargo-index-${{ hashFiles('**/Cargo.lock') }}
- name: Cache target directory
uses: actions/cache@v4
with:
path: target
key: ${{ runner.os }}-target-${{ matrix.target }}-${{ hashFiles('**/Cargo.lock') }}
- name: Build socktop .deb package
run: |
cargo deb --package socktop --target ${{ matrix.target }} --no-strip
- name: Build socktop_agent .deb package (with GPU support)
if: matrix.target == 'x86_64-unknown-linux-gnu' || matrix.target == 'aarch64-unknown-linux-gnu'
run: |
cargo deb --package socktop_agent --target ${{ matrix.target }} --no-strip
- name: Build socktop_agent .deb package (without GPU support)
if: matrix.target == 'armv7-unknown-linux-gnueabihf' || matrix.target == 'riscv64gc-unknown-linux-gnu'
run: |
cargo deb --package socktop_agent --target ${{ matrix.target }} --no-strip --no-default-features
- name: Copy packages to debs directory
run: |
mkdir -p debs
cp target/${{ matrix.target }}/debian/*.deb debs/
- name: Enforce glibc floor (Debian 12 / RPi OS bookworm fleet)
run: |
# The fleet's oldest supported glibc. A .deb that demands newer libc6
# than this will not install on the Pis — fail HERE, not at apt time.
FLOOR="2.36"
fail=0
for deb in debs/*.deb; do
req=$(dpkg-deb -f "$deb" Depends | sed -n 's/.*libc6 (>= \([0-9.]*\)).*/\1/p' | head -1)
echo "$deb -> libc6 >= ${req:-none}"
if [ -n "$req" ] && [ "$(printf '%s\n' "$req" "$FLOOR" | sort -V | tail -1)" != "$FLOOR" ]; then
echo "::error::$deb requires libc6 >= $req, exceeding the fleet floor $FLOOR (bookworm). The build runner's glibc is too new — see the runs-on pin comment."
fail=1
fi
done
exit $fail
- name: List generated packages
run: ls -lh debs/
- name: Upload .deb packages as artifacts
uses: actions/upload-artifact@v4
with:
name: debian-packages-${{ matrix.arch }}
path: debs/*.deb
if-no-files-found: error
retention-days: 90
# Combine all artifacts into a single downloadable archive
combine-artifacts:
name: Combine all .deb packages
needs: build-deb
runs-on: ubuntu-latest
steps:
- name: Download AMD64 packages
uses: actions/download-artifact@v4
with:
name: debian-packages-amd64
path: all-debs
- name: Download ARM64 packages
uses: actions/download-artifact@v4
with:
name: debian-packages-arm64
path: all-debs
- name: Download ARMhf packages
uses: actions/download-artifact@v4
with:
name: debian-packages-armhf
path: all-debs
- name: Download RISC-V packages
uses: actions/download-artifact@v4
with:
name: debian-packages-riscv64
path: all-debs
- name: List all packages
run: |
echo "All generated .deb packages:"
ls -lh all-debs/
- name: Upload combined artifacts
uses: actions/upload-artifact@v4
with:
name: all-debian-packages
path: all-debs/*.deb
if-no-files-found: error
retention-days: 90
- name: Generate checksums
run: |
cd all-debs
sha256sum *.deb > SHA256SUMS
cat SHA256SUMS
- name: Upload checksums
uses: actions/upload-artifact@v4
with:
name: checksums
path: all-debs/SHA256SUMS
retention-days: 90
# Publish packages to gh-pages APT repository
publish-apt-repo:
name: Publish to APT Repository
needs: combine-artifacts
runs-on: ubuntu-latest
# Publish only on `v*` release tags — keep gh-pages stable between
# releases instead of overwriting same-version .debs on every commit.
if: startsWith(github.ref, 'refs/tags/v')
permissions:
contents: write
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Download all packages
uses: actions/download-artifact@v4
with:
name: all-debian-packages
path: debs
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y dpkg-dev gpg
- name: Checkout gh-pages branch
run: |
git fetch origin gh-pages:gh-pages || echo "gh-pages branch doesn't exist yet"
if git show-ref --verify --quiet refs/heads/gh-pages; then
git checkout gh-pages
else
git checkout --orphan gh-pages
git rm -rf . 2>/dev/null || true
# Create basic structure
mkdir -p dists/stable/main/{binary-amd64,binary-arm64,binary-armhf,binary-riscv64}
mkdir -p pool/main
fi
- name: Copy packages to pool
run: |
mkdir -p pool/main
cp debs/*.deb pool/main/
ls -lh pool/main/
- name: Generate Packages files
run: |
for arch in amd64 arm64 armhf riscv64; do
mkdir -p dists/stable/main/binary-$arch
dpkg-scanpackages --arch $arch pool/main /dev/null > dists/stable/main/binary-$arch/Packages 2>/dev/null || true
if [ -s dists/stable/main/binary-$arch/Packages ]; then
gzip -9 -k -f dists/stable/main/binary-$arch/Packages
echo "Generated Packages file for $arch"
fi
done
- name: Generate Release file
run: |
cat > dists/stable/Release << EOF
Origin: socktop
Label: socktop
Suite: stable
Codename: stable
Architectures: amd64 arm64 armhf riscv64
Components: main
Description: socktop APT repository
Date: $(date -Ru)
EOF
# Add MD5Sum
echo "MD5Sum:" >> dists/stable/Release
for arch in amd64 arm64 armhf riscv64; do
for file in dists/stable/main/binary-$arch/Packages*; do
if [ -f "$file" ]; then
md5sum "$file" | awk '{print " " $1, "'$(stat -c%s "$file" 2>/dev/null || stat -f%z "$file" 2>/dev/null)'", "'"${file#dists/stable/}"'"}' >> dists/stable/Release
fi
done
done
# Add SHA256
echo "SHA256:" >> dists/stable/Release
for arch in amd64 arm64 armhf riscv64; do
for file in dists/stable/main/binary-$arch/Packages*; do
if [ -f "$file" ]; then
sha256sum "$file" | awk '{print " " $1, "'$(stat -c%s "$file" 2>/dev/null || stat -f%z "$file" 2>/dev/null)'", "'"${file#dists/stable/}"'"}' >> dists/stable/Release
fi
done
done
- name: Set GPG available flag
id: check_gpg
env:
GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }}
run: |
if [ -n "$GPG_PRIVATE_KEY" ]; then
echo "available=true" >> $GITHUB_OUTPUT
else
echo "available=false" >> $GITHUB_OUTPUT
fi
- name: Import GPG key
if: steps.check_gpg.outputs.available == 'true'
env:
GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }}
run: |
echo "$GPG_PRIVATE_KEY" | gpg --batch --import
gpg --list-secret-keys
- name: Sign repository
if: steps.check_gpg.outputs.available == 'true'
env:
GPG_KEY_ID: ${{ secrets.GPG_KEY_ID }}
GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
run: |
if [ -n "$GPG_PASSPHRASE" ]; then
echo "$GPG_PASSPHRASE" | gpg --batch --yes --no-tty --pinentry-mode loopback --passphrase-fd 0 \
--default-key "$GPG_KEY_ID" \
-abs -o dists/stable/Release.gpg dists/stable/Release
echo "$GPG_PASSPHRASE" | gpg --batch --yes --no-tty --pinentry-mode loopback --passphrase-fd 0 \
--default-key "$GPG_KEY_ID" \
--clearsign -o dists/stable/InRelease dists/stable/Release
else
gpg --batch --yes --no-tty --pinentry-mode loopback \
--default-key "$GPG_KEY_ID" \
-abs -o dists/stable/Release.gpg dists/stable/Release
gpg --batch --yes --no-tty --pinentry-mode loopback \
--default-key "$GPG_KEY_ID" \
--clearsign -o dists/stable/InRelease dists/stable/Release
fi
gpg --armor --export "$GPG_KEY_ID" > KEY.gpg
echo "✓ Repository signed"
- name: Create unsigned repository notice
if: steps.check_gpg.outputs.available == 'false'
run: |
echo "⚠️ Warning: GPG_PRIVATE_KEY not set. Repository will be UNSIGNED."
echo "⚠️ Add GPG secrets to sign the repository automatically."
echo "To add secrets: Settings → Secrets and variables → Actions → Repository secrets"
- name: Copy index.html if exists
run: |
git checkout ${{ github.ref_name }} -- index.html 2>/dev/null || echo "No index.html in source branch"
- name: Commit and push to gh-pages
run: |
git config user.name "GitHub Actions"
git config user.email "actions@github.com"
git add .
if git diff --staged --quiet; then
echo "No changes to commit"
else
COMMIT_MSG="Update APT repository"
if [[ "${{ github.ref }}" == refs/tags/* ]]; then
COMMIT_MSG="$COMMIT_MSG - Release ${{ github.ref_name }}"
else
COMMIT_MSG="$COMMIT_MSG - $(date -u +'%Y-%m-%d %H:%M:%S UTC')"
fi
git commit -m "$COMMIT_MSG"
git push origin gh-pages
echo "✓ Published to gh-pages"
fi
# Optional: Create a release with the .deb files if this is a tag
create-release:
name: Create GitHub Release
needs: combine-artifacts
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/v')
permissions:
contents: write
steps:
- name: Download all packages
uses: actions/download-artifact@v4
with:
name: all-debian-packages
path: release-debs
- name: Download checksums
uses: actions/download-artifact@v4
with:
name: checksums
path: release-debs
- name: Create Release
uses: softprops/action-gh-release@v1
with:
files: release-debs/*
draft: false
prerelease: false
generate_release_notes: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+129
View File
@@ -0,0 +1,129 @@
name: CI
on:
push:
pull_request:
jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest]
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
components: clippy, rustfmt
- name: Install system dependencies (Linux)
if: matrix.os == 'ubuntu-latest'
run: sudo apt-get update && sudo apt-get install -y libdrm-dev libdrm-amdgpu1
- name: Cargo fmt
run: cargo fmt --all -- --check
- name: Clippy
run: cargo clippy --all-targets --all-features -- -D warnings
- name: Build (release)
run: cargo build --release --workspace
- name: "Linux: start agent and run WS probe"
if: matrix.os == 'ubuntu-latest'
shell: bash
run: |
set -euo pipefail
RUST_LOG=info SOCKTOP_ENABLE_SSL=0 SOCKTOP_AGENT_GPU=0 SOCKTOP_AGENT_TEMP=0 ./target/release/socktop_agent -p 3000 > agent.log 2>&1 &
AGENT_PID=$!
for i in {1..60}; do
if curl -fsS http://127.0.0.1:3000/healthz >/dev/null; then break; fi
sleep 1
done
if ! curl -fsS http://127.0.0.1:3000/healthz >/dev/null; then
echo "--- agent.log (tail) ---"
tail -n 200 agent.log || true
(command -v ss >/dev/null && ss -ltnp || netstat -ltnp) || true
kill $AGENT_PID || true
exit 1
fi
SOCKTOP_WS=ws://127.0.0.1:3000/ws cargo test -p socktop_connector --test integration_test -- --nocapture
kill $AGENT_PID || true
- name: "Windows: start agent and run WS probe"
if: matrix.os == 'windows-latest'
shell: pwsh
run: |
$env:SOCKTOP_ENABLE_SSL = "0"
$env:SOCKTOP_AGENT_GPU = "0"
$env:SOCKTOP_AGENT_TEMP = "0"
$out = Join-Path $PWD "agent.out.txt"
$err = Join-Path $PWD "agent.err.txt"
$p = Start-Process -FilePath "${PWD}\target\release\socktop_agent.exe" -ArgumentList "-p 3000" -RedirectStandardOutput $out -RedirectStandardError $err -PassThru -NoNewWindow
$ready = $false
for ($i = 0; $i -lt 60; $i++) {
$pinfo = New-Object System.Diagnostics.ProcessStartInfo
$pinfo.FileName = "curl.exe"
$pinfo.Arguments = "-fsS http://127.0.0.1:3000/healthz"
$pinfo.RedirectStandardOutput = $true
$pinfo.RedirectStandardError = $true
$pinfo.UseShellExecute = $false
$proc = [System.Diagnostics.Process]::Start($pinfo)
$proc.WaitForExit()
if ($proc.ExitCode -eq 0) { $ready = $true; break }
Start-Sleep -Seconds 1
}
if (-not $ready) {
Write-Warning "TCP connect to (127.0.0.1 : 3000) failed"
if (Test-Path $out) { Write-Host "--- agent.out (full) ---"; Get-Content $out }
if (Test-Path $err) { Write-Host "--- agent.err (full) ---"; Get-Content $err }
Write-Host "--- netstat ---"
netstat -ano | Select-String ":3000" | ForEach-Object { $_.Line }
if ($p -and !$p.HasExited) { Stop-Process -Id $p.Id -Force -ErrorAction SilentlyContinue }
throw "agent did not become ready"
}
$env:SOCKTOP_WS = "ws://127.0.0.1:3000/ws"
try {
cargo test -p socktop_connector --test integration_test -- --nocapture
} finally {
if ($p -and !$p.HasExited) { Stop-Process -Id $p.Id -Force -ErrorAction SilentlyContinue }
}
- name: Smoke test (client --help)
run: cargo run -p socktop -- --help
- name: Package artifacts (Linux)
if: matrix.os == 'ubuntu-latest'
shell: bash
run: |
set -e
mkdir -p dist
cp target/release/socktop dist/
cp target/release/socktop_agent dist/
tar czf socktop-${{ matrix.os }}.tar.gz -C dist .
- name: Package artifacts (Windows)
if: matrix.os == 'windows-latest'
shell: pwsh
run: |
New-Item -ItemType Directory -Force -Path dist | Out-Null
Copy-Item target\release\socktop.exe dist\
Copy-Item target\release\socktop_agent.exe dist\
Compress-Archive -Path dist\* -DestinationPath socktop-${{ matrix.os }}.zip -Force
- name: Upload build artifacts (ephemeral)
uses: actions/upload-artifact@v4
with:
name: socktop-${{ matrix.os }}
path: |
*.tar.gz
*.zip
- name: Upload to rolling GitHub Release (main only)
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
uses: softprops/action-gh-release@v2
with:
tag_name: latest
name: Latest build
prerelease: true
draft: false
files: |
*.tar.gz
*.zip
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+17
View File
@@ -0,0 +1,17 @@
# Any crate's build directory, including standalone sub-crates
# (zellij_socktop_plugin, socktop_wasm_test) that live outside the workspace.
target/
.vscode/
/.cargo/
# Documentation files from development sessions (context-specific, not for public repo)
/OPTIMIZATION_PROCESS_DETAILS.md
/THREAD_SUPPORT.md
# APT Repository - Safety: Never commit private keys!
*.asc
*-private.key
*-secret.key
gpg-private-backup.key
secring.gpg
# Note: Release.gpg, InRelease, and KEY.gpg (public) ARE safe to commit
-423
View File
@@ -1,423 +0,0 @@
# APT Repository Setup Summary
## 🎉 What You Now Have
You now have a complete system for creating and hosting your own APT repository for socktop packages, **without needing a sponsor or official Debian/Ubuntu approval**.
## 📁 Files Created
### Scripts (in `scripts/`)
- **`init-apt-repo.sh`** - Initializes the APT repository directory structure
- **`add-package-to-repo.sh`** - Adds .deb packages to the repository and generates metadata
- **`sign-apt-repo.sh`** - Signs the repository with your GPG key
- **`setup-apt-repo.sh`** - All-in-one interactive wizard to set everything up
### Documentation
- **`QUICK_START_APT_REPO.md`** - Quick start guide (< 10 minutes)
- **`docs/APT_REPOSITORY.md`** - Comprehensive 600+ line guide covering everything
- **`APT_REPO_SUMMARY.md`** - This file
### GitHub Actions
- **`.github/workflows/publish-apt-repo.yml`** - Automated building, signing, and publishing
## 🚀 Quick Start (Choose One)
### Option 1: Interactive Setup (Recommended for First Time)
Run the setup wizard:
```bash
./scripts/setup-apt-repo.sh
```
This walks you through:
1. ✅ Checking prerequisites
2. 🔑 Setting up GPG key
3. 📦 Finding/building packages
4. 📝 Creating repository structure
5. ✍️ Signing the repository
6. 📋 Next steps to publish to gh-pages
### Option 2: Manual Step-by-Step
```bash
# 1. Initialize
./scripts/init-apt-repo.sh
# 2. Build packages
cargo deb --package socktop
cargo deb --package socktop_agent
# 3. Add packages
./scripts/add-package-to-repo.sh target/debian/socktop_*.deb
./scripts/add-package-to-repo.sh target/debian/socktop-agent_*.deb
# 4. Sign (replace YOUR-KEY-ID)
./scripts/sign-apt-repo.sh apt-repo stable YOUR-KEY-ID
# 5. Update URLs
sed -i 's/YOUR-USERNAME/your-github-username/g' apt-repo/*.{md,html}
# 6. Publish to gh-pages (see below)
```
### Option 3: Fully Automated (After Initial Setup)
Once gh-pages branch exists, just tag releases:
```bash
git tag v1.50.0
git push --tags
# GitHub Actions will:
# - Build packages for AMD64 and ARM64
# - Update APT repository
# - Sign with your GPG key
# - Push to gh-pages branch automatically
```
## 📤 Publishing to GitHub Pages (gh-pages branch)
**Why gh-pages branch?**
- ✅ Keeps main branch clean (source code only)
- ✅ Separate branch for published content
- ✅ GitHub Actions can auto-update it
- ✅ You can customize the landing page
**Initial Setup:**
```bash
# Create gh-pages branch
git checkout --orphan gh-pages
git rm -rf .
# Copy apt-repo CONTENTS to root (not the folder!)
cp -r apt-repo/* .
rm -rf apt-repo
# Commit and push
git add .
git commit -m "Initialize APT repository"
git push -u origin gh-pages
# Return to main
git checkout main
```
**Enable in GitHub:**
1. Settings → Pages
2. Source: **gh-pages****/ (root)**
3. Save
Your repo will be at: `https://your-username.github.io/socktop/`
**Note:** GitHub Pages only allows `/` (root) or `/docs`. Since we use gh-pages branch, contents go in the root of that branch.
See `SETUP_GITHUB_PAGES.md` for detailed step-by-step instructions.
### Alternative: Self-Hosted Server
Copy `apt-repo/` contents to your web server:
```bash
rsync -avz apt-repo/ user@example.com:/var/www/apt/
```
Configure Apache/Nginx to serve the directory. See `docs/APT_REPOSITORY.md` for details.
## 🤖 GitHub Actions Automation
### Required Secrets
Add these in GitHub Settings → Secrets → Actions:
1. **GPG_PRIVATE_KEY**
```bash
gpg --armor --export-secret-key YOUR-KEY-ID
# Copy entire output including BEGIN/END lines
```
2. **GPG_KEY_ID**
```bash
gpg --list-secret-keys --keyid-format LONG
# Use the ID after "rsa4096/"
```
3. **GPG_PASSPHRASE**
```bash
# Your GPG passphrase (leave empty if no passphrase)
```
### Triggers
The workflow runs on:
- **Version tags**: `git tag v1.50.0 && git push --tags`
- **Manual dispatch**: Actions tab → "Publish APT Repository" → Run workflow
### What It Does
1. ✅ Builds packages for AMD64 and ARM64
2. ✅ Initializes or updates APT repository
3. ✅ Generates Packages files and metadata
4. ✅ Signs with your GPG key
5. ✅ Commits and pushes to gh-pages branch
6. ✅ Creates GitHub Release with artifacts
7. ✅ Generates summary with installation instructions
## 👥 User Installation
Once published, users install with:
```bash
# Add repository
curl -fsSL https://your-username.github.io/socktop/KEY.gpg | \
sudo gpg --dearmor -o /usr/share/keyrings/socktop-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/socktop-archive-keyring.gpg] https://your-username.github.io/socktop stable main" | \
sudo tee /etc/apt/sources.list.d/socktop.list
# Install
sudo apt update
sudo apt install socktop socktop-agent
# The agent service is automatically installed and configured
sudo systemctl enable --now socktop-agent
```
## 🔧 Maintenance
### Release New Version (Automated)
```bash
# Update version in Cargo.toml, commit changes
git add . && git commit -m "Bump version to 1.51.0"
git tag v1.51.0
git push origin main --tags
# GitHub Actions automatically:
# - Builds packages for AMD64 and ARM64
# - Updates apt-repo
# - Signs with GPG
# - Pushes to gh-pages branch
```
### Manual Update (if needed)
```bash
# On main branch
cargo deb --package socktop
./scripts/add-package-to-repo.sh target/debian/socktop_*.deb
./scripts/sign-apt-repo.sh
# Switch to gh-pages and update
git checkout gh-pages
cp -r apt-repo/* .
git add . && git commit -m "Release v1.51.0" && git push
git checkout main
```
### Remove Old Versions
```bash
# On gh-pages branch
git checkout gh-pages
rm pool/main/socktop_1.50.0_*.deb
# Regenerate metadata (re-add remaining packages)
git add . && git commit -m "Remove old versions" && git push
git checkout main
```
## 🎯 Key Benefits
✅ **No sponsor needed** - Host your own repository
✅ **Full control** - You decide when to release
✅ **Free hosting** - GitHub Pages at no cost
✅ **Automated** - GitHub Actions does the work
✅ **Professional** - Just like official repos
✅ **Multi-arch** - AMD64, ARM64 support built-in
✅ **Secure** - GPG signed packages
✅ **Easy updates** - Users get updates via `apt upgrade`
## 📊 Repository Structure
```
apt-repo/
├── dists/
│ └── stable/
│ ├── Release # Main metadata (checksums)
│ ├── Release.gpg # Detached signature
│ ├── InRelease # Clearsigned release
│ └── main/
│ ├── binary-amd64/
│ │ ├── Packages # Package list
│ │ ├── Packages.gz # Compressed
│ │ └── Release # Component metadata
│ ├── binary-arm64/
│ └── binary-armhf/
├── pool/
│ └── main/
│ ├── socktop_1.50.0_amd64.deb
│ ├── socktop-agent_1.50.1_amd64.deb
│ ├── socktop_1.50.0_arm64.deb
│ └── socktop-agent_1.50.1_arm64.deb
├── KEY.gpg # Public GPG key
├── README.md # Repository info
├── index.html # Web interface
└── packages.html # Package listing
```
## 🔑 GPG Key Management
### Create New Key
```bash
gpg --full-generate-key
# Choose RSA 4096, no expiration (or 2 years)
```
### Export Keys
```bash
# Public key (for users)
gpg --armor --export YOUR-KEY-ID > KEY.gpg
# Private key (for GitHub Secrets)
gpg --armor --export-secret-key YOUR-KEY-ID
```
### Backup Keys
```bash
# Backup to safe location
gpg --export-secret-keys YOUR-KEY-ID > gpg-private-backup.key
gpg --export YOUR-KEY-ID > gpg-public-backup.key
```
### Key Rotation
If your key expires or is compromised:
```bash
./scripts/sign-apt-repo.sh apt-repo stable NEW-KEY-ID
gpg --armor --export NEW-KEY-ID > apt-repo/KEY.gpg
# Users need to re-import the key
```
## 🐛 Troubleshooting
### "Repository not signed"
```bash
./scripts/sign-apt-repo.sh apt-repo stable YOUR-KEY-ID
ls apt-repo/dists/stable/Release* # Should show 3 files
```
### "Package not found"
```bash
cd apt-repo
dpkg-scanpackages --arch amd64 pool/main /dev/null > dists/stable/main/binary-amd64/Packages
gzip -9 -k -f dists/stable/main/binary-amd64/Packages
cd ..
./scripts/sign-apt-repo.sh
```
### "404 Not Found" on GitHub Pages
- Wait 2-3 minutes after pushing
- Check Settings → Pages is enabled
- Verify source branch/directory
### GitHub Actions not signing
- Check all 3 secrets are set correctly
- GPG_PRIVATE_KEY must include BEGIN/END lines
- Test signing locally first
## 📚 Documentation
| File | Purpose | Length |
|------|---------|--------|
| `QUICK_START_APT_REPO.md` | Get started in < 10 minutes | Quick |
| `SETUP_GITHUB_PAGES.md` | Detailed gh-pages setup guide | Step-by-step |
| `docs/APT_REPOSITORY.md` | Complete guide with all options | Comprehensive |
| `docs/DEBIAN_PACKAGING.md` | How .deb packages are built | Technical |
| `DEBIAN_PACKAGING_SUMMARY.md` | Overview of packaging work | Summary |
| `APT_REPO_SUMMARY.md` | This file | Overview |
## 🎓 Learning Path
1. **Start here**: `QUICK_START_APT_REPO.md` (10 min)
2. **Set up**: Run `./scripts/setup-apt-repo.sh` (15 min)
3. **Publish**: Follow `SETUP_GITHUB_PAGES.md` (5 min)
4. **Automate**: Set up GitHub Actions secrets (10 min)
5. **Advanced**: Read `docs/APT_REPOSITORY.md` as needed
## 🚦 Next Steps
Choose your path:
### Just Getting Started?
1. ✅ Read `QUICK_START_APT_REPO.md`
2. ✅ Run `./scripts/setup-apt-repo.sh`
3. ✅ Follow `SETUP_GITHUB_PAGES.md` to publish
4. ✅ Test installation on a VM
### Want Automation?
1. ✅ Generate/export GPG key
2. ✅ Add GitHub Secrets
3. ✅ Tag a release: `git tag v1.50.0 && git push --tags`
4. ✅ Watch GitHub Actions magic happen
### Want to Understand Everything?
1. ✅ Read `docs/APT_REPOSITORY.md` (comprehensive)
2. ✅ Study the scripts in `scripts/`
3. ✅ Examine `.github/workflows/publish-apt-repo.yml`
4. ✅ Learn about Debian repository format
### Ready for Production?
1. ✅ Set up monitoring/analytics
2. ✅ Create PPA for Ubuntu (Launchpad)
3. ✅ Apply to Debian mentors for official inclusion
4. ✅ Set up repository mirrors
5. ✅ Document best practices for users
## 🌟 Success Criteria
You'll know you're successful when:
- [ ] Users can `apt install socktop`
- [ ] Updates work with `apt upgrade`
- [ ] Multiple architectures supported
- [ ] Repository is GPG signed
- [ ] GitHub Actions publishes automatically
- [ ] Installation instructions in README
- [ ] Zero sponsor or approval needed
## 💡 Pro Tips
1. **Test first**: Always test on a fresh VM before publishing
2. **Keep versions**: Don't delete old .deb files immediately
3. **Backup GPG key**: Store it safely offline
4. **Monitor downloads**: Use GitHub Insights or server logs
5. **Document everything**: Help users troubleshoot
6. **Version consistently**: Use semantic versioning
7. **Sign always**: Never publish unsigned repositories
## 🔗 Resources
- [Debian Repository Format](https://wiki.debian.org/DebianRepository/Format)
- [GitHub Pages Docs](https://docs.github.com/en/pages)
- [cargo-deb](https://github.com/kornelski/cargo-deb)
- [Ubuntu PPA Guide](https://help.launchpad.net/Packaging/PPA)
- [Debian Mentors](https://mentors.debian.net/)
## 🎊 Congratulations!
You now have everything you need to:
- ✅ Create your own APT repository
- ✅ Host it for free on GitHub Pages
- ✅ Automate the entire process
- ✅ Distribute packages professionally
- ✅ Provide easy installation for users
**No sponsor required. No approval needed. You're in control!** 🚀
---
**Questions?** Check the docs or open an issue.
**Ready to publish?** Run `./scripts/setup-apt-repo.sh` and follow the wizard!
+70
View File
@@ -0,0 +1,70 @@
# Changelog
## 1.60.1 — unreleased
Identical to 1.60.0 plus rebuilt Debian packages: the 1.60.0 debs were linked
against glibc 2.39 (a GitHub runner migration) and would not install on
Debian 12 / Raspberry Pi OS bookworm. CI now pins the build environment and
gates every package against the fleet's glibc floor. 1.60.0 was never
published to crates.io.
Everything since `v1.50.0`. Applies to all three crates (`socktop`, `socktop_agent`, `socktop_connector`), which move to 1.60.1 together.
### Security
- **Certificate pinning is now real.** With `--verify-hostname` off (the default), the client previously accepted *any* server certificate — the `--tls-ca` file was never consulted. The presented certificate must now be byte-identical to one in the pinned PEM (multi-cert files supported for rotation). If you use TLS, update the client: earlier versions are MITM-able despite the pinning documentation. (housekeeping-p2)
- `key.pem` is created with mode 0600 (was world-readable 0644); agents also tighten existing keys on startup. (housekeeping-p2)
- The agent's per-PID caches now evict (60s age / 64 entries); previously they grew without bound. (housekeeping-p2)
### Performance
- Agent CPU on GPU machines cut ~6× (measured 23.5 → 4.0 ms/s at default polling): GPU collection moved to a dedicated worker thread that keeps the NVML session open instead of re-initializing it every 1.5 s on the async runtime. (housekeeping-p2)
- `journalctl` no longer blocks the agent's async workers. (housekeeping-p2)
- Cached "no temp sensor / no GPU" results count as fresh — no more per-request rescans on hosts without them. (housekeeping-p2)
- Nagle disabled on all connection paths (small request/response frames). (housekeeping-p2)
### TUI
- **Compact layout for small windows**: when the window is too short for the Disks pane, Disks is dropped, Memory/Swap go side by side, GPU collapses to one line (omitted if absent), and the reclaimed rows keep the CPU graph and per-core bars visible. `--compact` pins it. (#37)
- **Width-aware text**: header, CPU title, and process table shed detail by priority as the terminal narrows instead of overwriting each other; process Name column is now the last to go, not the first. Fixed sort-header clicks landing up to 4 columns off. (#38)
- **Responsive input**: keys and mouse are handled within ~30 ms instead of queueing for a full metrics interval. (housekeeping-p2)
- **No more freezes**: all requests carry a 5 s timeout; a dead connection shows the reconnect modal (with working `q`) instead of hanging the UI. Consecutive timeouts surface a persistent "agent not responding" error. (housekeeping-p2)
- Old agents without the per-process endpoints once again show "Agent Update Required" instead of a reconnect loop. (housekeeping-p2)
- Journal pane distinguishes "no entries" from "no journal access" (e.g. user-run/demo agents) and shows journalctl's hint plus the fix. (housekeeping-p2)
- Scatter-plot axes align correctly for large CPU-time values. (housekeeping-p2)
- Demo mode explains how to install `socktop_agent` when the binary is missing. (#36)
### Correctness
- Process/child CPU times were sent as ms but displayed as µs — values rendered 1000× too small in the details modal. (housekeeping-p2)
- Non-Linux per-process CPU% no longer truncates multi-core usage (clamp after divide). (housekeeping-p2)
- Journal timestamps are real RFC 3339 UTC with numeric sorting (additive `timestamp_us`). (housekeeping-p2)
- Partition detection uses `/sys/block` on Linux — whole-disk filesystems (`nvme0n1`, `zram1`) are no longer misclassified as partitions. (housekeeping-p2)
- Network rates use agent-side sample timestamps (additive `sampled_at_ms`), eliminating rate sawtooth from TTL-cached snapshots; falls back to the client clock with older agents. (housekeeping-p2)
- The details modal's Command/exe/cwd fields are populated again (dropped by an earlier refresh optimization). (housekeeping-p2)
- Non-ASCII device names no longer panic the disk pane. (housekeeping-p2)
### Wire format (additive only — old/new client-agent pairs keep working)
- `Metrics.sampled_at_ms` (epoch ms of actual collection)
- `JournalEntry.timestamp_us` (epoch µs), `JournalEntry.timestamp` now RFC 3339
- `JournalResponse.notice` (journal-access hint)
### Internal / packaging
- ratatui 0.28 → 0.30 (#33); aws-lc-rs advisories patched (#34); Debian packaging for the agent (#25); assorted dependabot bumps.
- ~3,100 lines of dead code removed, including an orphaned pre-refactor copy of the connector.
- `socktop` consumes `socktop_connector` via a path+version dep — connector changes are testable in-repo before publishing.
- wasm examples build against the in-repo connector; note `zellij_socktop_plugin` has pre-existing compile errors and needs its own rework.
### Process kill (PR #40)
- **Kill a local process from the TUI** (`t` on a selected process, or inside Process Details): btop-style Terminate/Force-kill confirmation. Local agents only — the signal is sent by socktop itself with its own privileges, never over the wire; remote agents never show the option. PID-reuse guarded (the confirmed name must still own the PID at signal time).
- **Agent no longer reports dead processes**: a long-lived sysinfo `System` accumulated every process ever seen (21k+ entries on a 289-process host), inflating memory, per-poll work, and the process count — and keeping killed processes on screen forever. Update agent and client together on machines where the kill feature will be used.
- Killed rows leave the list when the process actually exits and cannot be resurrected by cached agent snapshots; details views for dead processes close themselves, including through parent-navigation chains.
- Selection hint no longer vanishes for long process names; confirmation/info dialogs size to their content.
### Upgrade notes
- **Release/publish order**: `socktop_connector``socktop` → agent packages.
- Clients older than 1.60 work against 1.60 agents and vice versa; the security fix is client-side, so prioritize client updates where TLS is used.
Generated
+3940
View File
File diff suppressed because it is too large Load Diff
+51
View File
@@ -0,0 +1,51 @@
[workspace]
resolver = "2"
members = [
"socktop",
"socktop_agent",
"socktop_connector"
]
[workspace.dependencies]
# async + streams
tokio = { version = "1", features = ["full"] }
futures-util = "0.3"
anyhow = "1.0"
# websocket
tokio-tungstenite = { version = "0.24", features = ["__rustls-tls", "connect"] }
url = "2.5"
# JSON + error handling
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
# system stats (align across crates)
sysinfo = "0.37"
# CLI UI
ratatui = "0.30"
crossterm = "0.29"
unicode-width = "0.2"
# web server (remote-agent)
axum = { version = "0.7", features = ["ws"] }
# protobuf
prost = "0.13"
dirs-next = "2"
# compression
flate2 = "1.0"
# TLS
rustls = { version = "0.23", features = ["ring"] }
rustls-pemfile = "2.1"
[profile.release]
# Favor smaller, simpler binaries with good runtime perf
lto = "thin"
codegen-units = 1
panic = "abort"
opt-level = 3
strip = "symbols"
+156
View File
@@ -0,0 +1,156 @@
# Debian Packaging Implementation Summary
## Overview
Successfully implemented Debian packaging for socktop using `cargo-deb`, with GitHub Actions automation for building packages for both AMD64 and ARM64 architectures.
## Branches Created
1. **`feature/debian-packaging`** - Main branch with debian packaging implementation
2. **`feature/man-pages`** - Separate branch for man pages work (to be researched further)
## What Was Added
### 1. Cargo.toml Updates
Both `socktop/Cargo.toml` and `socktop_agent/Cargo.toml` were updated with:
- `[package.metadata.deb]` sections
- Package metadata (maintainer, description, dependencies)
- Asset definitions (binaries, documentation)
- Systemd service configuration (agent only)
### 2. Systemd Service
**File**: `socktop_agent/socktop-agent.service`
- Runs as `socktop` user/group
- Listens on port 3000 by default
- Security hardening enabled
- Disabled by default (user must explicitly enable)
### 3. Maintainer Scripts
**Directory**: `socktop_agent/debian/`
- **`postinst`**: Creates `socktop` user/group, sets up `/var/lib/socktop` directory
- **`postrm`**: Cleanup on package removal/purge
### 4. GitHub Actions Workflow
**File**: `.github/workflows/build-deb.yml`
Features:
- Builds for both x86_64 and ARM64
- Triggered on:
- Push to `master` or `feature/debian-packaging`
- Pull requests to `master`
- Version tags (v*)
- Manual workflow dispatch
- Creates artifacts:
- `debian-packages-amd64`
- `debian-packages-arm64`
- `all-debian-packages` (combined)
- `checksums` (SHA256SUMS)
- Automatic GitHub releases for version tags
### 5. Documentation
**File**: `docs/DEBIAN_PACKAGING.md`
Comprehensive guide covering:
- Building packages locally
- Cross-compilation for ARM64
- Installation and configuration
- Using GitHub Actions artifacts
- Creating local APT repositories
- Troubleshooting
## Package Details
### socktop (TUI Client)
- **Binary**: `/usr/bin/socktop`
- **Size**: ~3.5 MB (x86_64)
- **Dependencies**: Auto-detected
### socktop_agent (Daemon)
- **Binary**: `/usr/bin/socktop_agent`
- **Service**: `socktop-agent.service`
- **User/Group**: `socktop` (created automatically)
- **State directory**: `/var/lib/socktop`
- **Size**: ~6.7 MB (x86_64)
- **Dependencies**: Auto-detected
## Testing
Both packages successfully built locally:
```
✓ socktop_1.50.0-1_amd64.deb
✓ socktop-agent_1.50.1-1_amd64.deb
```
Verified:
- Package contents (dpkg -c)
- Package metadata (dpkg -I)
- Systemd service file inclusion
- Maintainer scripts inclusion
- Documentation inclusion
## Usage
### For Users
Download pre-built packages from GitHub Actions artifacts:
1. Go to Actions tab
2. Select latest "Build Debian Packages" run
3. Download architecture-specific artifact
4. Install: `sudo dpkg -i socktop*.deb`
### For Developers
Build locally:
```bash
cargo install cargo-deb
cargo deb --package socktop
cargo deb --package socktop_agent
```
Cross-compile for ARM64:
```bash
rustup target add aarch64-unknown-linux-gnu
sudo apt install gcc-aarch64-linux-gnu libc6-dev-arm64-cross
cargo deb --package socktop --target aarch64-unknown-linux-gnu
```
## Next Steps
To get packages in official APT repositories:
1. **Short term**: Host packages on GitHub Releases (automated)
2. **Medium term**: Create PPA for Ubuntu users
3. **Long term**: Submit to Debian/Ubuntu official repositories
## Files Modified/Created
```
Modified:
socktop/Cargo.toml
socktop_agent/Cargo.toml
Created:
.github/workflows/build-deb.yml
docs/DEBIAN_PACKAGING.md
socktop_agent/socktop-agent.service
socktop_agent/debian/postinst
socktop_agent/debian/postrm
```
## Commit
```
532ed16 Add Debian packaging support with cargo-deb
```
## Resources
- [cargo-deb documentation](https://github.com/kornelski/cargo-deb)
- [Debian Policy Manual](https://www.debian.org/doc/debian-policy/)
- Full documentation in `docs/DEBIAN_PACKAGING.md`
-109
View File
@@ -1,109 +0,0 @@
# 🚀 Get Your APT Repository Live in 5 Minutes
## You're Here Because...
You want to publish socktop packages via APT, but GitHub Pages won't let you select `apt-repo/` folder. Here's why and how to fix it:
**The Issue:** GitHub Pages only serves from `/` (root) or `/docs`, not custom folders like `/apt-repo`.
**The Solution:** Use a `gh-pages` branch where `apt-repo` contents go in the root.
## Quick Setup (5 Steps)
### 1. Create apt-repo locally (if you haven't)
```bash
./scripts/setup-apt-repo.sh
```
This creates `apt-repo/` with your packages and signs them.
### 2. Create gh-pages branch
```bash
git checkout --orphan gh-pages
git rm -rf .
```
### 3. Copy apt-repo to root
```bash
cp -r apt-repo/* .
rm -rf apt-repo
ls
# You should see: dists/ pool/ KEY.gpg index.html README.md
```
### 4. Push to GitHub
```bash
git add .
git commit -m "Initialize APT repository"
git push -u origin gh-pages
git checkout main
```
### 5. Enable GitHub Pages
1. Go to: **Settings → Pages**
2. Source: **gh-pages****/ (root)**
3. Click **Save**
**Done!** ✅ Your repo will be live at `https://your-username.github.io/socktop/` in 1-2 minutes.
## Test It
```bash
curl -I https://your-username.github.io/socktop/KEY.gpg
# Should return: HTTP/2 200
```
## Install It (On Any Debian/Ubuntu System)
```bash
curl -fsSL https://your-username.github.io/socktop/KEY.gpg | \
sudo gpg --dearmor -o /usr/share/keyrings/socktop-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/socktop-archive-keyring.gpg] https://your-username.github.io/socktop stable main" | \
sudo tee /etc/apt/sources.list.d/socktop.list
sudo apt update
sudo apt install socktop socktop-agent
```
## What's Next?
### Now (Optional):
- Customize `index.html` on gh-pages for a nice landing page
- Add installation instructions to your main README
### Later:
- Set up GitHub Actions automation (see `QUICK_START_APT_REPO.md`)
- Add more architectures (ARM64, ARMv7)
## Understanding the Setup
```
main branch: gh-pages branch:
├── src/ ├── dists/
├── Cargo.toml ├── pool/
├── scripts/ ├── KEY.gpg
└── apt-repo/ (local) └── index.html ← GitHub Pages serves this
Work here ↑ Published here ↑
```
- **main**: Your development work
- **gh-pages**: What users see/download
- **apt-repo/**: Local folder (ignored in git, see `.gitignore`)
## Need More Help?
- **Quick start**: `QUICK_START_APT_REPO.md`
- **Detailed setup**: `SETUP_GITHUB_PAGES.md`
- **Why gh-pages?**: `WHY_GHPAGES_BRANCH.md`
- **Full guide**: `docs/APT_REPOSITORY.md`
---
**You got this!** 🎉
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2025 Witty One Off
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
-221
View File
@@ -1,221 +0,0 @@
# Quick Start: Setting Up Your socktop APT Repository
This guide will get your APT repository up and running in **under 10 minutes**.
## Prerequisites
- [ ] Debian packages built (or use GitHub Actions to build them)
- [ ] GPG key for signing
- [ ] GitHub repository with Pages enabled
## Step 1: Create GPG Key (if needed)
```bash
# Generate a new key
gpg --full-generate-key
# Select:
# - RSA and RSA (default)
# - 4096 bits
# - Key does not expire (or 2 years)
# - Your name and email
# Get your key ID
gpg --list-secret-keys --keyid-format LONG
# Look for the part after "rsa4096/" - that's your KEY-ID
```
## Step 2: Initialize Repository Locally
```bash
cd socktop
# Create the repository structure
./scripts/init-apt-repo.sh
# Build packages (or download from GitHub Actions)
cargo install cargo-deb
cargo deb --package socktop
cargo deb --package socktop_agent
# Add packages to repository
./scripts/add-package-to-repo.sh target/debian/socktop_*.deb
./scripts/add-package-to-repo.sh target/debian/socktop-agent_*.deb
# Sign the repository (replace YOUR-KEY-ID with actual key ID)
./scripts/sign-apt-repo.sh apt-repo stable YOUR-KEY-ID
# Update URLs with your GitHub username
sed -i 's/YOUR-USERNAME/your-github-username/g' apt-repo/README.md apt-repo/index.html
```
## Step 3: Publish to GitHub Pages (gh-pages branch)
```bash
# Create gh-pages branch
git checkout --orphan gh-pages
git rm -rf .
# Copy apt-repo CONTENTS to root (not the folder itself)
cp -r apt-repo/* .
rm -rf apt-repo
# Commit and push
git add .
git commit -m "Initialize APT repository"
git push -u origin gh-pages
# Go back to main branch
git checkout main
```
Then in GitHub:
1. Go to **Settings → Pages**
2. Source: **Deploy from a branch**
3. Branch: **gh-pages****/ (root)** → **Save**
Wait 1-2 minutes, then visit: `https://your-username.github.io/socktop/`
## Step 4: Automate with GitHub Actions
Add these secrets to your repository (Settings → Secrets → Actions):
```bash
# Export your private key
gpg --armor --export-secret-key YOUR-KEY-ID
# Copy the ENTIRE output and save as secret: GPG_PRIVATE_KEY
```
Add these three secrets:
- **GPG_PRIVATE_KEY**: Your exported private key
- **GPG_KEY_ID**: Your key ID (e.g., `ABC123DEF456`)
- **GPG_PASSPHRASE**: Your key passphrase (leave empty if no passphrase)
The workflow in `.github/workflows/publish-apt-repo.yml` will now:
- Build packages for AMD64 and ARM64
- Update the APT repository
- Sign with your GPG key
- Push to gh-pages automatically
Trigger it by:
- Creating a version tag: `git tag v1.50.0 && git push --tags`
- Manual dispatch from GitHub Actions tab
## Step 5: Test It
On any Debian/Ubuntu system:
```bash
# Add your repository
curl -fsSL https://your-username.github.io/socktop/KEY.gpg | \
sudo gpg --dearmor -o /usr/share/keyrings/socktop-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/socktop-archive-keyring.gpg] https://your-username.github.io/socktop stable main" | \
sudo tee /etc/apt/sources.list.d/socktop.list
# Install
sudo apt update
sudo apt install socktop socktop-agent
# Verify
socktop --version
socktop_agent --version
```
## Maintenance
### Add a New Version
```bash
# Build new packages
cargo deb --package socktop
cargo deb --package socktop_agent
# Add to repository
./scripts/add-package-to-repo.sh target/debian/socktop_*.deb
./scripts/add-package-to-repo.sh target/debian/socktop-agent_*.deb
# Re-sign
./scripts/sign-apt-repo.sh apt-repo stable YOUR-KEY-ID
# Publish
cd docs/apt # or wherever your apt-repo is
git add .
git commit -m "Release v1.51.0"
git push origin main
```
### Or Just Tag and Let GitHub Actions Do It
```bash
# Update version in Cargo.toml
# Commit changes
git add .
git commit -m "Bump version to 1.51.0"
# Tag and push
git tag v1.51.0
git push origin main --tags
# GitHub Actions will:
# - Build packages for AMD64 and ARM64
# - Update gh-pages branch automatically
# - Sign and publish!
```
## Troubleshooting
### "Repository not signed" error
Make sure you signed it:
```bash
./scripts/sign-apt-repo.sh apt-repo stable YOUR-KEY-ID
ls apt-repo/dists/stable/Release*
# Should show: Release, Release.gpg, InRelease, KEY.gpg
```
### "404 Not Found" on GitHub Pages
1. Check Settings → Pages is enabled
2. Wait 2-3 minutes for GitHub to deploy
3. Verify the URL structure matches your settings
### GitHub Actions not signing
Check that all three secrets are set correctly:
- Settings → Secrets and variables → Actions
- Make sure GPG_PRIVATE_KEY includes the BEGIN/END lines
- Test locally first
## What's Next?
✅ You now have a working APT repository!
**Share it:**
- Add installation instructions to your main README
- Tweet/blog about it
- Submit to awesome-rust lists
**Improve it:**
- Customize your GitHub Pages site (it's just HTML!)
- Add more architectures (ARMv7)
- Create multiple distributions (stable, testing)
- Set up download statistics
- Apply to Ubuntu PPA (Launchpad)
- Eventually submit to official Debian repos
## Full Documentation
For detailed information, see:
- `docs/APT_REPOSITORY.md` - Complete APT repository guide
- `docs/DEBIAN_PACKAGING.md` - Debian packaging details
- `DEBIAN_PACKAGING_SUMMARY.md` - Quick summary
## Questions?
Open an issue on GitHub or check the full documentation.
---
**Happy packaging! 📦**
+579 -23
View File
@@ -1,38 +1,594 @@
# socktop APT Repository
# socktop
This repository contains Debian packages for socktop and socktop-agent.
socktop is a remote system monitor with a rich TUI, inspired by top/btop, talking to a lightweight agent over WebSockets.
## Adding this repository
- Linux agent: near-zero CPU when idle (request-driven, no always-on sampler)
- TUI: smooth graphs, sortable process table, scrollbars, readable colors
Add the repository to your system:
[socktop.io](https://www.socktop.io)
<img src="./docs/socktop_demo.apng" width="100%">
---
## Features
- Remote monitoring via WebSocket (JSON over WS)
- Optional WSS (TLS): agent autogenerates a selfsigned cert on first run; client pins the cert via --tls-ca/-t
- TUI built with ratatui
- CPU
- Overall sparkline + per-core mini bars
- Accurate per-process CPU% (Linux /proc deltas), normalized to 0100%
- Memory/Swap gauges with human units
- Disks: per-device usage
- Network: per-interface throughput with sparklines and peak markers
- Temperatures: CPU (optional)
- Top processes (top 50)
- PID, name, CPU%, memory, and memory%
- Click-to-sort by CPU% or Mem (descending)
- Scrollbar and mouse/keyboard scrolling
- Total process count shown in the header
- Only top-level processes listed (threads hidden) — matches btop/top
- Optional GPU metrics (can be disabled)
- Optional auth token for the agent
- Compact layout for small windows: automatically drops the panes that no longer fit so
the CPU graph and per-core bars stay visible (see [Compact mode](#compact-mode))
---
## Prerequisites: Install Rust (rustup)
Rust is fast, safe, and crossplatform. Installing it will make your machine better. Consider yourself privileged.
Linux/macOS:
```bash
# Add the GPG key
curl -fsSL https://jasonwitty.github.io/socktop/KEY.gpg | sudo gpg --dearmor -o /usr/share/keyrings/socktop-archive-keyring.gpg
# Add the repository
echo "deb [signed-by=/usr/share/keyrings/socktop-archive-keyring.gpg] https://jasonwitty.github.io/socktop stable main" | sudo tee /etc/apt/sources.list.d/socktop.list
# Update and install
sudo apt update
sudo apt install socktop socktop-agent
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
# load cargo for this shell
source "$HOME/.cargo/env"
# ensure stable is up to date
rustup update stable
rustc --version
cargo --version
# after install you may need to reload your shell, e.g.:
exec bash # or: exec zsh / exec fish
```
## Manual Installation
Windows (for the brave): install from https://rustup.rs with the MSVC toolchain. Yes, youll need Visual Studio Build Tools. You chose Windows — enjoy the ride.
You can also download and install packages manually from the `pool/main/` directory.
### Raspberry Pi / Ubuntu / PopOS (required for GPU support)
**Note:** GPU monitoring is only supported on x86_64 and aarch64 (64-bit ARM) platforms. ARMv7 (32-bit) and RISC-V builds do not include GPU support.
For 64-bit systems with GPU support:
```bash
wget https://jasonwitty.github.io/socktop/pool/main/socktop_VERSION_ARCH.deb
sudo dpkg -i socktop_VERSION_ARCH.deb
sudo apt-get update
sudo apt-get install libdrm-dev libdrm-amdgpu1
```
## Supported Architectures
For ARMv7 (32-bit Raspberry Pi), build with `--no-default-features` to disable GPU support:
- amd64 (x86_64)
- arm64 (aarch64)
- armhf (32-bit ARM)
```bash
cargo build --release -p socktop_agent --no-default-features
```
## Building from Source
_Additional note for Raspberry Pi users. Please update your system to use the newest kernel available through app, kernel version 6.6+ will use considerably less overall CPU to run the agent. For example on a rpi4 the kernel < 6.6 the agent will consume .8 cpu but on the same hardware on > 6.6 the agent will consume only .2 cpu. (these numbers indicate continuous polling at web socket endpoints, when not in use the usage is 0)_
See the main repository at https://github.com/jasonwitty/socktop
---
## Architecture
Two components:
1) Agent (remote): small Rust WS server using sysinfo + /proc. It collects metrics only when the client requests them over the WebSocket (request-driven). No background sampling loop.
2) Client (local): TUI that connects to ws://HOST:PORT/ws (or wss://HOST:PORT/ws when TLS is enabled) and renders updates.
---
## Quick start
- Build both binaries:
```bash
git clone https://github.com/jasonwitty/socktop.git
cd socktop
cargo build --release
```
- Start the agent on the target machine (default port 3000):
```bash
./target/release/socktop_agent --port 3000
```
- Connect with the TUI from your local machine:
```bash
./target/release/socktop ws://REMOTE_HOST:3000/ws
```
### Cross-compiling for Raspberry Pi
For Raspberry Pi and other ARM devices, you can cross-compile the agent from a more powerful machine:
- [Cross-compilation guide](./docs/cross-compiling.md) - Instructions for cross-compiling from Linux, macOS, or Windows hosts
### Quick demo (no agent setup)
Spin up a temporary local agent on port 3231 and connect automatically:
```bash
socktop --demo
```
Or just run `socktop` with no arguments and pick the builtin `demo` entry from the interactive profile list (if you have saved profiles, `demo` is appended). The demo agent:
- Runs locally (`ws://127.0.0.1:3231/ws`)
- Stops automatically (you'll see "Stopped demo agent on port 3231") when you quit the TUI or press Ctrl-C
---
## Install (from crates.io)
You dont need to clone this repo to use socktop. Install the published binaries with cargo:
```bash
# TUI (client)
cargo install socktop
# Agent (server)
cargo install socktop_agent
```
This drops socktop and socktop_agent into ~/.cargo/bin (add it to PATH).
Notes:
- After installing Rust via rustup, reload your shell (e.g., exec bash) so cargo is on PATH.
- Windows: you can also grab prebuilt EXEs from GitHub Actions artifacts if rustup scares you. It shouldnt. Be brave.
System-wide agent (Linux)
```bash
# If you installed with cargo, binaries are in ~/.cargo/bin
sudo install -o root -g root -m 0755 "$HOME/.cargo/bin/socktop_agent" /usr/local/bin/socktop_agent
# Install and enable the systemd service (example unit in docs/)
sudo install -o root -g root -m 0644 docs/socktop-agent.service /etc/systemd/system/socktop-agent.service
sudo systemctl daemon-reload
sudo systemctl enable --now socktop-agent
```
```bash
# Enable SSL
# Stop service
sudo systemctl stop socktop-agent
# Edit service to append SSL option and port
sudo micro /etc/systemd/system/socktop-agent.service
--
ExecStart=/usr/local/bin/socktop_agent --enableSSL --port 8443
--
# Reload
sudo systemctl daemon-reload
# Restart
sudo systemctl start socktop-agent
# check logs for certificate location
sudo journalctl -u socktop-agent -f
--
Aug 22 22:25:26 rpi-master socktop_agent[2913998]: socktop_agent: generated self-signed TLS certificate at /var/lib/socktop/.config/socktop_agent/tls/cert.pem
--
```
---
## Usage
Agent (server):
```bash
socktop_agent --port 3000
# or env: SOCKTOP_PORT=3000 socktop_agent
# optional auth: SOCKTOP_TOKEN=changeme socktop_agent
# enable TLS (selfsigned cert, default port 8443; you can also use -p):
socktop_agent --enableSSL --port 8443
```
Client (TUI):
```bash
socktop ws://HOST:3000/ws
# with token:
socktop "ws://HOST:3000/ws?token=changeme"
# TLS with pinned server certificate (recommended over the internet):
socktop --tls-ca /path/to/cert.pem wss://HOST:8443/ws
# (By default hostname/SAN verification is skipped for ease on home networks. To enforce it add --verify-hostname)
socktop --verify-hostname --tls-ca /path/to/cert.pem wss://HOST:8443/ws
# shorthand:
socktop -t /path/to/cert.pem wss://HOST:8443/ws
# Note: providing --tls-ca/-t automatically upgrades ws:// to wss:// if you forget
# force the small-window layout at any terminal size (normally automatic):
socktop --compact ws://HOST:3000/ws
```
Intervals (client-driven):
- Fast metrics: ~500 ms
- Processes: ~2 s
- Disks: ~5 s
The agent stays idle unless queried. When queried, it collects just whats needed.
---
## Compact mode
In a short terminal the fixed layout runs out of rows and the CPU graph and per-core bars
are the first things to collapse — exactly the panes you are most likely watching. Once
the window is too short for the Disks pane to show even one disk, socktop switches to a
compact layout:
- **Disks is dropped.** It is the pane that degrades worst when partially drawn.
- **Memory and Swap move side by side** into the row Disks vacated.
- **GPU shrinks to a single line** — utilisation and VRAM only, no device name. On a host
with no GPU the pane disappears entirely.
- **Everything reclaimed goes to the CPU graph and per-core bars**, which stay usable well
below the size where they used to vanish.
The switch is automatic and needs no configuration. Pass `--compact` to pin the compact
layout at any window size:
```bash
socktop --compact ws://HOST:3000/ws
```
---
## Connection Profiles (Named)
You can save frequently used connection settings (URL + optional TLS CA path) under a short name and reuse them later.
Config file location:
- Linux (XDG): `$XDG_CONFIG_HOME/socktop/profiles.json`
- Fallback (when XDG not set): `~/.config/socktop/profiles.json`
### Creating a profile
First time you specify a new `--profile/-P` name together with a URL (and optional `--tls-ca`), it is saved automatically:
```bash
socktop --profile prod ws://prod-host:3000/ws
# With TLS pinning:
socktop --profile prod-tls --tls-ca /path/to/cert.pem wss://prod-host:8443/ws
You can also set custom intervals (milliseconds):
```bash
socktop --profile prod --metrics-interval-ms 750 --processes-interval-ms 3000 ws://prod-host:3000/ws
```
```
If a profile already exists you will be prompted before overwriting:
```
$ socktop --profile prod ws://new-host:3000/ws
Overwrite existing profile 'prod'? [y/N]: y
```
To overwrite without an interactive prompt pass `--save`:
```bash
socktop --profile prod --save ws://new-host:3000/ws
```
### Using a saved profile
Just pass the profile name (no URL needed):
```bash
socktop --profile prod
socktop -P prod-tls # short flag
```
The stored URL (and TLS CA path, if any) plus any saved intervals will be used. TLS auto-upgrade still applies if a CA path is stored alongside a ws:// URL.
### Interactive selection (no args)
If you run `socktop` with no arguments and at least one profile exists, you will be shown a numbered list to pick from:
```
$ socktop
Select profile:
1. prod
2. prod-tls
Enter number (or blank to abort): 2
```
Choosing a number starts the TUI with that profile. A builtin `demo` option is always appended; selecting it launches a local agent on port 3231 (no TLS) and connects to `ws://127.0.0.1:3231/ws`. Pressing Enter on blank aborts without connecting.
### JSON format
An example `profiles.json` (prettyprinted):
```json
{
"profiles": {
"prod": { "url": "ws://prod-host:3000/ws" },
"prod-tls": {
"url": "wss://prod-host:8443/ws",
"tls_ca": "/home/user/certs/prod-cert.pem",
"metrics_interval_ms": 500,
"processes_interval_ms": 2000
}
},
"version": 0
}
```
Notes:
- The `tls_ca` path is stored as given; if you move or rotate the certificate update the profile by re-running with `--profile NAME --save`.
- Deleting a profile: edit the JSON file and remove the entry (TUI does not yet have an in-app delete command).
- Profiles are client-side convenience only; they do not affect the agent.
- Intervals: `metrics_interval_ms` controls the fast metrics poll (default 500 ms). `processes_interval_ms` controls process list polling (default 2000 ms). Values below 100 ms (metrics) or 200 ms (processes) are clamped.
---
## Updating
Update the agent (systemd):
```bash
# on the server running the agent
cargo install socktop_agent --force
sudo systemctl stop socktop-agent
sudo install -o root -g root -m 0755 "$HOME/.cargo/bin/socktop_agent" /usr/local/bin/socktop_agent
# if you changed the unit file:
# sudo install -o root -g root -m 0644 docs/socktop-agent.service /etc/systemd/system/socktop-agent.service
# sudo systemctl daemon-reload
sudo systemctl start socktop-agent
sudo systemctl status socktop-agent --no-pager
# logs:
# journalctl -u socktop-agent -f
```
Update the TUI (client):
```bash
cargo install socktop --force
socktop ws://HOST:3000/ws
```
Tip: If only the binary changed, restart is enough. If the unit file changed, run sudo systemctl daemon-reload.
---
## Configuration (agent)
- Port:
- Flag: --port 8080 or -p 8080
- Positional: socktop_agent 8080
- Env: SOCKTOP_PORT=8080
- TLS (selfsigned):
- Enable: --enableSSL
- Default TLS port: 8443 (override with --port/-p)
- Certificate/Key location (created on first TLS run):
- Linux (XDG): $XDG_CONFIG_HOME/socktop_agent/tls/{cert.pem,key.pem} (defaults to ~/.config)
- The agent prints these paths on creation.
- You can set XDG_CONFIG_HOME before first run to control where certs are written.
- Additional SANs: set `SOCKTOP_AGENT_EXTRA_SANS` (commaseparated) before first TLS start to include extra IPs/DNS names in the cert. Example:
```bash
SOCKTOP_AGENT_EXTRA_SANS="192.168.1.101,myhost.internal" socktop_agent --enableSSL
```
This prevents client errors like `NotValidForName` when connecting via an IP not present in the default cert SAN list.
- Expiry / rotation: the generated cert is valid for ~397 days from creation. If the agent fails to start with an "ExpiredCertificate" error (or your client reports expiry), simply delete the existing cert and key:
```bash
rm ~/.config/socktop_agent/tls/cert.pem ~/.config/socktop_agent/tls/key.pem
# (adjust path if XDG_CONFIG_HOME is set or different user)
systemctl restart socktop-agent # if running under systemd
```
On next TLS start the agent will generate a fresh pair. Only distribute the new cert.pem to clients (never the key).
- Auth token (optional): SOCKTOP_TOKEN=changeme
- Disable GPU metrics: SOCKTOP_AGENT_GPU=0
- Disable CPU temperature: SOCKTOP_AGENT_TEMP=0
---
## Keyboard & Mouse
- Quit: q or Esc
- Processes pane:
- Click “CPU %” to sort by CPU descending
- Click “Mem” to sort by memory descending
- Mouse wheel: scroll
- Drag scrollbar: scroll
- Arrow/PageUp/PageDown/Home/End: scroll
---
## Example agent JSON
```json
{
"sampled_at_ms": 1786752000123,
"cpu_total": 12.4,
"cpu_per_core": [11.2, 15.7],
"mem_total": 33554432,
"mem_used": 18321408,
"swap_total": 0,
"swap_used": 0,
"process_count": 127,
"hostname": "myserver",
"cpu_temp_c": 42.5,
"disks": [{"name":"nvme0n1p2","total":512000000000,"available":320000000000}],
"networks": [{"name":"eth0","received":12345678,"transmitted":87654321}],
"top_processes": [
{"pid":1234,"name":"nginx","cpu_usage":1.2,"mem_bytes":12345678}
],
"gpus": null
}
```
Notes:
- process_count is merged into the main metrics on the client when processes are polled.
- top_processes are the current top 50 (sorting in the TUI is client-side).
---
## Security
Set a token on the agent and pass it as a query param from the client:
Server:
```bash
SOCKTOP_TOKEN=changeme socktop_agent --port 3000
```
Client:
```bash
socktop "ws://HOST:3000/ws?token=changeme"
```
### TLS / WSS
For encrypted connections, enable TLS on the agent and pin the server certificate on the client.
Server (generates selfsigned cert and key on first run):
```bash
socktop_agent --enableSSL --port 8443
```
Client (trust/pin the server cert; copy cert.pem from the agent):
```bash
socktop --tls-ca /path/to/agent/cert.pem wss://HOST:8443/ws
```
Notes:
- Do not copy the private key off the server; only the cert.pem is needed by clients.
- When --tls-ca/-t is supplied, the client autoupgrades ws:// to wss:// to avoid protocol mismatch.
- Hostname (SAN) verification is DISABLED by default; instead the client PINS the certificate: the agent must present a cert byte-identical to one in your `--tls-ca` file (expiry is ignored in this mode — you pinned that exact cert). Use `--verify-hostname` to switch to strict chain + SAN validation instead.
- You can run multiple clients with different cert paths by passing --tls-ca per invocation.
---
## Using tmux to monitor multiple hosts
You can use tmux to show multiple socktop instances in a single terminal.
![socktop screenshot](./docs/tmux_4_rpis_v3.jpg)
monitoring 4 Raspberry Pis using Tmux
Prerequisites:
- Install tmux (Ubuntu/Debian: `sudo apt-get install tmux`)
Key bindings (defaults):
- Split left/right: Ctrl-b %
- Split top/bottom: Ctrl-b "
- Move between panes: Ctrl-b + Arrow keys
- Show pane numbers: Ctrl-b q
- Close a pane: Ctrl-b x
- Detach from session: Ctrl-b d
Two panes (left/right)
- This creates a session named "socktop", splits it horizontally, and starts two socktops.
```bash
tmux new-session -d -s socktop 'socktop ws://HOST1:3000/ws' \; \
split-window -h 'socktop ws://HOST2:3000/ws' \; \
select-layout even-horizontal \; \
attach
```
Four panes (top-left, top-right, bottom-left, bottom-right)
- This creates a 2x2 grid with one socktop per pane.
```bash
tmux new-session -d -s socktop 'socktop ws://HOST1:3000/ws' \; \
split-window -h 'socktop ws://HOST2:3000/ws' \; \
select-pane -t 0 \; split-window -v 'socktop ws://HOST3:3000/ws' \; \
select-pane -t 1 \; split-window -v 'socktop ws://HOST4:3000/ws' \; \
select-layout tiled \; \
attach
```
Tips:
- Replace HOST1..HOST4 (and ports) with your targets.
- Reattach later: `tmux attach -t socktop`
---
## Platform notes
- Linux: fully supported (agent and client).
- Raspberry Pi:
- 64-bit: aarch64-unknown-linux-gnu
- 32-bit: armv7-unknown-linux-gnueabihf
- Windows:
- TUI + agent can build with stable Rust; bring your own MSVC. Youre on Windows; you know the drill.
- CPU temperature may be unavailable.
- binary exe for both available in build artifacts under actions.
- macOS:
- TUI works; agent is primarily targeted at Linux. Agent will run just fine on macos for debugging but I have not documented how to run as a service, I may not given the "security" feautures with applications on macos. We will see.
---
## Development
```bash
cargo fmt
cargo clippy --all-targets --all-features
cargo run -p socktop -- ws://127.0.0.1:3000/ws
# TLS (dev): first run will create certs under ~/.config/socktop_agent/tls/
cargo run -p socktop_agent -- --enableSSL --port 8443
```
### Auto-format on commit
A sample pre-commit hook that runs `cargo fmt --all` is provided in `.githooks/pre-commit`.
Enable it (one-time):
```bash
git config core.hooksPath .githooks
chmod +x .githooks/pre-commit
```
Every commit will then format Rust sources and restage them automatically.
---
## Roadmap
- [x] Agent authentication (token)
- [x] Hide per-thread entries; only show processes
- [x] Sort top processes in the TUI
- [x] Configurable refresh intervals (client)
- [ ] Export metrics to file
- [x] TLS / WSS support (selfsigned server cert + client pinning)
- [x] Split processes/disks to separate WS calls with independent cadences (already logical on client; formalize API)
- [ ] Outage notifications and reconnect.
- [ ] Per process detailed statistics pane
- [ ] cleanup of Disks section, properly display physical disks / partitions, remove duplicate entries
---
## License
MIT — see LICENSE.
---
## Acknowledgements
- ratatui for the TUI
- sysinfo for system metrics
- tokio-tungstenite for WebSockets
-351
View File
@@ -1,351 +0,0 @@
# Setting Up GitHub Pages for socktop APT Repository
This guide walks you through the initial setup of your APT repository on GitHub Pages using the `gh-pages` branch.
## Prerequisites
- [ ] You've run `./scripts/setup-apt-repo.sh` or manually created `apt-repo/`
- [ ] `apt-repo/` contains signed packages and metadata
- [ ] You have a GitHub repository for socktop
## Step-by-Step Setup
### 1. Verify Your Local Repository
First, make sure everything is ready:
```bash
# Check that apt-repo exists and has content
ls -la apt-repo/
# You should see:
# - dists/stable/Release, Release.gpg, InRelease
# - pool/main/*.deb
# - KEY.gpg
# - index.html, README.md
```
### 2. Create and Switch to gh-pages Branch
```bash
# Create a new orphan branch (no history from main)
git checkout --orphan gh-pages
# Remove all files from staging
git rm -rf .
```
**Important:** This creates a completely separate branch. Don't worry - your main branch is safe!
### 3. Copy APT Repository to Root
```bash
# Copy CONTENTS of apt-repo to root of gh-pages
cp -r apt-repo/* .
# Remove the apt-repo directory itself
rm -rf apt-repo
# Verify the structure
ls -la
# You should see in the current directory:
# - dists/
# - pool/
# - KEY.gpg
# - index.html
# - README.md
```
**Why root?** GitHub Pages can only serve from:
- `/` (root) - what we're doing
- `/docs` directory
- NOT from custom directories like `/apt-repo`
### 4. Commit and Push
```bash
# Add all files
git add .
# Commit
git commit -m "Initialize APT repository for GitHub Pages"
# Push to gh-pages branch
git push -u origin gh-pages
```
### 5. Return to Main Branch
```bash
# Switch back to your main development branch
git checkout main
# Verify you're back on main
git branch
# Should show: * main
```
### 6. Enable GitHub Pages
1. Go to your repository on GitHub
2. Click **Settings** (top right)
3. Click **Pages** (left sidebar)
4. Under "Build and deployment":
- Source: **Deploy from a branch**
- Branch: **gh-pages**
- Folder: **/ (root)**
- Click **Save**
### 7. Wait for Deployment
GitHub will deploy your site. This usually takes 1-2 minutes.
You can watch the progress:
- Go to **Actions** tab
- Look for "pages build and deployment" workflow
### 8. Verify Your Repository is Live
Once deployed, your repository will be at:
```
https://YOUR-USERNAME.github.io/socktop/
```
Test it:
```bash
# Check the public key is accessible
curl -I https://YOUR-USERNAME.github.io/socktop/KEY.gpg
# Should return: HTTP/2 200
# Check the Release file
curl -I https://YOUR-USERNAME.github.io/socktop/dists/stable/Release
# Should return: HTTP/2 200
```
### 9. Test Installation (Optional but Recommended)
On a Debian/Ubuntu VM or system:
```bash
# Add GPG key
curl -fsSL https://YOUR-USERNAME.github.io/socktop/KEY.gpg | \
sudo gpg --dearmor -o /usr/share/keyrings/socktop-archive-keyring.gpg
# Add repository
echo "deb [signed-by=/usr/share/keyrings/socktop-archive-keyring.gpg] https://YOUR-USERNAME.github.io/socktop stable main" | \
sudo tee /etc/apt/sources.list.d/socktop.list
# Update package lists
sudo apt update
# You should see:
# Get:1 https://YOUR-USERNAME.github.io/socktop stable InRelease [xxx B]
# Install packages
sudo apt install socktop socktop-agent
# Verify
socktop --version
```
## Understanding the Two Branches
After setup, you'll have two branches:
### `main` branch (development)
```
main/
├── src/
├── Cargo.toml
├── scripts/
├── docs/
├── apt-repo/ ← Local build artifact (not published)
└── ...
```
**Purpose:** Source code, development, building packages
### `gh-pages` branch (published)
```
gh-pages/
├── dists/
├── pool/
├── KEY.gpg
├── index.html ← Customize this for a nice landing page!
└── README.md
```
**Purpose:** Published APT repository served by GitHub Pages
## Workflow Going Forward
### Manual Updates
When you release a new version:
```bash
# 1. On main branch, build new packages
git checkout main
cargo deb --package socktop
cargo deb --package socktop_agent
# 2. Update local apt-repo
./scripts/add-package-to-repo.sh target/debian/socktop_*.deb
./scripts/add-package-to-repo.sh target/debian/socktop-agent_*.deb
./scripts/sign-apt-repo.sh apt-repo stable YOUR-GPG-KEY-ID
# 3. Switch to gh-pages and update
git checkout gh-pages
cp -r apt-repo/* .
git add .
git commit -m "Release v1.51.0"
git push origin gh-pages
# 4. Return to main
git checkout main
```
### Automated Updates (Recommended)
Set up GitHub Actions to do this automatically:
1. Add GitHub Secrets (Settings → Secrets → Actions):
- `GPG_PRIVATE_KEY` - Your exported private key
- `GPG_KEY_ID` - Your GPG key ID
- `GPG_PASSPHRASE` - Your GPG passphrase (if any)
2. Tag and push:
```bash
git tag v1.51.0
git push origin main --tags
```
3. GitHub Actions will automatically:
- Build packages for AMD64 and ARM64
- Update apt-repo
- Sign with your GPG key
- Push to gh-pages
- Create GitHub Release
See `.github/workflows/publish-apt-repo.yml` for details.
## Customizing Your GitHub Pages Site
The `gh-pages` branch contains `index.html` which users see when they visit:
`https://YOUR-USERNAME.github.io/socktop/`
You can customize this! On the `gh-pages` branch:
```bash
git checkout gh-pages
# Edit index.html
nano index.html
# Add features, badges, screenshots, etc.
git add index.html
git commit -m "Improve landing page"
git push origin gh-pages
git checkout main
```
## Troubleshooting
### "404 Not Found" on GitHub Pages
**Check:**
- Settings → Pages shows "Your site is live at..."
- Wait 2-3 minutes after pushing
- Verify branch is `gh-pages` and folder is `/`
- Check Actions tab for deployment errors
### "Repository not found" when installing
**Check:**
- URL is correct: `https://USERNAME.github.io/REPO/` (no trailing /apt-repo)
- Files exist at the URLs:
```bash
curl -I https://USERNAME.github.io/REPO/dists/stable/InRelease
curl -I https://USERNAME.github.io/REPO/KEY.gpg
```
### "GPG error" when installing
**Check:**
- Repository is signed: `ls gh-pages/dists/stable/Release.gpg`
- Users imported the key: `curl https://USERNAME.github.io/REPO/KEY.gpg | gpg --import`
### Changes not appearing
**Check:**
- You committed and pushed to `gh-pages` (not `main`)
- Wait 1-2 minutes for GitHub to redeploy
- Clear browser cache if viewing index.html
- For apt: `sudo apt clean && sudo apt update`
## Success Checklist
After completing this guide, you should have:
- [ ] `gh-pages` branch created and pushed
- [ ] GitHub Pages enabled and deployed
- [ ] Site accessible at `https://USERNAME.github.io/socktop/`
- [ ] `KEY.gpg` downloadable
- [ ] `dists/stable/InRelease` accessible
- [ ] Packages in `pool/main/*.deb` downloadable
- [ ] Successfully tested installation on a test system
- [ ] Understand the workflow for future updates
## Next Steps
1. **Update your main README.md** with installation instructions
2. **Set up GitHub Actions** for automated releases
3. **Customize index.html** on gh-pages for a nice landing page
4. **Test on multiple architectures** (AMD64, ARM64)
5. **Share your repository** with users
## Quick Reference
**Switch branches:**
```bash
git checkout main # Development
git checkout gh-pages # Published site
```
**Update published site manually:**
```bash
git checkout main
# ... build packages, update apt-repo ...
git checkout gh-pages
cp -r apt-repo/* .
git add . && git commit -m "Update" && git push
git checkout main
```
**Your repository URL:**
```
https://YOUR-USERNAME.github.io/socktop/
```
**User installation command:**
```bash
curl -fsSL https://YOUR-USERNAME.github.io/socktop/KEY.gpg | \
sudo gpg --dearmor -o /usr/share/keyrings/socktop-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/socktop-archive-keyring.gpg] https://YOUR-USERNAME.github.io/socktop stable main" | \
sudo tee /etc/apt/sources.list.d/socktop.list
sudo apt update && sudo apt install socktop socktop-agent
```
---
**Need help?** See:
- `QUICK_START_APT_REPO.md` - Overall quick start
- `docs/APT_REPOSITORY.md` - Comprehensive guide
- `docs/APT_WORKFLOW.md` - Visual workflow diagrams
-119
View File
@@ -1,119 +0,0 @@
# Why We Use the gh-pages Branch
## The Problem
GitHub Pages has a limitation - it can only serve static sites from:
1. **`/` (root)** of a branch
2. **`/docs`** directory of a branch
3. **NOT** from custom directories like `/apt-repo`
## Why Not `/docs`?
When you tried to enable GitHub Pages with `apt-repo/` checked into main, you couldn't select it because:
```
main/
├── src/
├── Cargo.toml
├── apt-repo/ ← GitHub Pages can't serve from here!
└── ...
```
You could move it to `/docs`:
```
main/
├── src/
├── Cargo.toml
├── docs/ ← GitHub Pages CAN serve from here
│ ├── dists/
│ ├── pool/
│ └── ...
└── ...
```
But this has downsides:
- ❌ Mixed source code and published content
- ❌ Large .deb files bloat the main branch
- ❌ Can't easily customize the site without affecting source
- ❌ Messy git history with binary files
## Why gh-pages Branch (Our Solution)
Using a separate `gh-pages` branch is cleaner:
```
main branch (source code):
├── src/
├── Cargo.toml
├── scripts/
└── docs/ ← Documentation source
gh-pages branch (published):
├── dists/
├── pool/
├── KEY.gpg
├── index.html ← Customizable landing page
└── README.md
```
### Benefits
**Clean separation**: Source code stays in `main`, published content in `gh-pages`
**No binary bloat**: .deb files don't clutter your main branch history
**Easy automation**: GitHub Actions can push to gh-pages without affecting main
**Customizable**: You can make a beautiful landing page on gh-pages
**Standard practice**: Most GitHub Pages projects use gh-pages branch
**Root URL**: Your repo is at `https://username.github.io/socktop/` (not `/apt-repo`)
### Workflow
```
Developer (main branch)
Build packages
Update apt-repo/ (local)
Push to gh-pages branch
GitHub Pages serves
Users: apt install socktop
```
## The Setup
**One-time setup:**
```bash
git checkout --orphan gh-pages
git rm -rf .
cp -r apt-repo/* .
rm -rf apt-repo
git add . && git commit -m "Initialize APT repository"
git push -u origin gh-pages
git checkout main
```
**Going forward:**
- Work on `main` branch for development
- `gh-pages` branch gets updated by GitHub Actions (or manually)
- Never need to switch branches manually after automation is set up!
## Comparison
| Approach | Location | URL | Pros | Cons |
|----------|----------|-----|------|------|
| **gh-pages branch** ✅ | gh-pages:/ | `username.github.io/socktop/` | Clean, automated, customizable | Two branches |
| `/docs` on main | main:/docs | `username.github.io/socktop/` | One branch | Mixed content, binary bloat |
| `/apt-repo` on main | main:/apt-repo | ❌ Not possible | - | GitHub Pages won't allow it |
## Conclusion
The `gh-pages` branch approach is:
- The **cleanest** solution
- The **most flexible** for customization
- The **easiest to automate**
- **Industry standard** for GitHub Pages
That's why we chose it! 🚀
View File
+38
View File
@@ -0,0 +1,38 @@
# socktop APT Repository
This repository contains Debian packages for socktop and socktop-agent.
## Adding this repository
Add the repository to your system:
```bash
# Add the GPG key
curl -fsSL https://jasonwitty.github.io/socktop/KEY.gpg | sudo gpg --dearmor -o /usr/share/keyrings/socktop-archive-keyring.gpg
# Add the repository
echo "deb [signed-by=/usr/share/keyrings/socktop-archive-keyring.gpg] https://jasonwitty.github.io/socktop stable main" | sudo tee /etc/apt/sources.list.d/socktop.list
# Update and install
sudo apt update
sudo apt install socktop socktop-agent
```
## Manual Installation
You can also download and install packages manually from the `pool/main/` directory.
```bash
wget https://jasonwitty.github.io/socktop/pool/main/socktop_VERSION_ARCH.deb
sudo dpkg -i socktop_VERSION_ARCH.deb
```
## Supported Architectures
- amd64 (x86_64)
- arm64 (aarch64)
- armhf (32-bit ARM)
## Building from Source
See the main repository at https://github.com/jasonwitty/socktop
+32
View File
@@ -0,0 +1,32 @@
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512
Origin: socktop
Label: socktop
Suite: stable
Codename: stable
Architectures: amd64 arm64 armhf
Components: main
Description: socktop APT repository
Date: Sun, 23 Nov 2025 04:05:21 +0000
MD5Sum:
0bddefb2f13cb7c86cd05fe1ce20310f 1549 main/binary-amd64/Packages
674f0e552cbb7dc65380651a2a8d279e 799 main/binary-amd64/Packages.gz
SHA256:
babfbb4839e7fdfbc83742c16996791b0402a1315889b530330b338380398263 1549 main/binary-amd64/Packages
f8c48d0f7bf53eb02c6dbf5f1cdd046fe71b87273cf763c5bb2e95d9757a7a82 799 main/binary-amd64/Packages.gz
-----BEGIN PGP SIGNATURE-----
iQGzBAEBCgAdFiEEHnVWqAU5uDlLwoINESwaeYRl+/IFAmkiiAYACgkQESwaeYRl
+/KBsAv/eYhnK/XrNtPhLyw/zX2cGfUtBsBZrypFhV/n+TvudAIwQaqxDEvLlBUn
HBAhMKDQXGs7V45+nOgDX4rKWUqJh4SPbJgNbVte2PX7U+hsMpZBsYp3vkjApgTO
pq2CCkViyBXgTY+6vUigtvfJ9afTTWI6Qm4dLXZ7hxErBxgHQyowOoO/sF92cNOu
AosBMpE+qSy7sVqJU5g/JXJh0kddKFotXHSGA1kFMzJafJC/n5nLrusDzFJRQqyH
Io+6inYWjlb5o79z0tJzAvG1mgplLRppMBjoVJ/RJ+gT+QE70kokR6wvsgDqsKNd
mvB0TNj0zY0g6Is6V3XMyf0u+6BtLTbua913HPiqBfErgeV58vzsst+y0It42TXi
aw+UF2Kw/YhPq1rZFxgnAVcMja3qlXWpH57gmgIPovBCsPsiywWiHLsSHRzAI22b
zeTsUST/4toR/ruZVbUZvWoWAR4tzsSuwXJFx/hhinTQQTNHErXASOX986UaL9L7
o2/pTKLe
=IeBY
-----END PGP SIGNATURE-----
+14
View File
@@ -0,0 +1,14 @@
Origin: socktop
Label: socktop
Suite: stable
Codename: stable
Architectures: amd64 arm64 armhf
Components: main
Description: socktop APT repository
Date: Sun, 23 Nov 2025 04:05:21 +0000
MD5Sum:
0bddefb2f13cb7c86cd05fe1ce20310f 1549 main/binary-amd64/Packages
674f0e552cbb7dc65380651a2a8d279e 799 main/binary-amd64/Packages.gz
SHA256:
babfbb4839e7fdfbc83742c16996791b0402a1315889b530330b338380398263 1549 main/binary-amd64/Packages
f8c48d0f7bf53eb02c6dbf5f1cdd046fe71b87273cf763c5bb2e95d9757a7a82 799 main/binary-amd64/Packages.gz
+14
View File
@@ -0,0 +1,14 @@
-----BEGIN PGP SIGNATURE-----
iQGzBAABCgAdFiEEHnVWqAU5uDlLwoINESwaeYRl+/IFAmkiiAEACgkQESwaeYRl
+/KzeAv+OUIbxud5FboerwpAJULV+rS3+VX4kvwg/daVZ3yX3tJNrsyNCHgmWLVu
fLeEFFc2Ax9GvFW4jrbxRAGD+3TXQEEFkb5lGzYyDjlgVzR6wLiVTTrmzWoK+cbB
4DMozqeLiZFfQjq4UFn3+mwiYFX9Dj7PVF0M60XAUJSObbJFmaEPZIfx6wcZfkiL
lLLk1eeU5MPiyudPOhVGgaD76KrUCw+8DBNKoCKIEcCY0LvuKtUK8mWYXRSPSved
4Znd3QZz063Z6R+Lj1XlGLoTPResna28T/Nca+2JgLhbrihsLMcHoFxmrvFP9FpT
MChKngj7NnGt0yqHH5J16hdwMra/vvhmF0yoQ0loIcy+q06tYEqOcau8tvAjfbId
k3rgQgnxxVE8WUmV9Bugp7jhNMO+ImKWMwzEr6wGd9ZHqpknUlAaWeO73VP+qtAN
6mEqWhkqvXGg+srH6qp3Sg0W28dYG29X3Kx8jOp7HeyvA/gLZRN7L+bq/XaA7WFA
1hba6LIY
=QoLf
-----END PGP SIGNATURE-----
@@ -1,14 +1,13 @@
Package: socktop
Version: 1.60.2-1
Version: 1.50.0-1
Architecture: amd64
Maintainer: Jason Witty <jasonpwitty+socktop@proton.me>
Installed-Size: 3441
Depends: libc6 (>= 2.34)
Filename: pool/main/socktop_1.60.2-1_amd64.deb
Size: 1313748
MD5sum: 24517013f7e9683f2bbbbf07debdffca
SHA1: c5c9498bfcc8a8d21342f1f4b5797e4c000462d7
SHA256: b5d21f5f322af61e7ea6846ba337e5e48697969cf40b098d01ad4927c912d6e6
Installed-Size: 3459
Filename: pool/main/socktop_1.50.0-1_amd64.deb
Size: 1278940
MD5sum: 0215e178e306d9379669065e8c78582b
SHA1: 04e0416389f5cecd584fd1f6b3568711f2645eee
SHA256: 69eb04b1de48541c95950a97b16357fcd9c51ffaceb143f63de4a9d758fad297
Section: admin
Priority: optional
Homepage: https://github.com/jasonwitty/socktop
@@ -19,16 +18,15 @@ Description: Remote system monitor over WebSocket, TUI like top
interface similar to the traditional 'top' command.
Package: socktop-agent
Version: 1.60.2-1
Version: 1.50.2-1
Architecture: amd64
Maintainer: Jason Witty <jasonpwitty+socktop@proton.me>
Installed-Size: 6537
Depends: libc6 (>= 2.34), libdrm-amdgpu1 (>= 2.4.80)
Filename: pool/main/socktop-agent_1.60.2-1_amd64.deb
Size: 1858208
MD5sum: fa4f1a29b22fe191140787da50c70cd1
SHA1: b310e7f5a29be4d18add88a6b30437eb34d2e6a1
SHA256: 328975156e28ffc2d38a23c317406b9220f0062992f97bfea327403ba6d26d71
Installed-Size: 6793
Filename: pool/main/socktop-agent_1.50.2-1_amd64.deb
Size: 1896272
MD5sum: 22e78d03e83dcf84d6ec4a009b285902
SHA1: 26a9f4fedfdba06a047044027223f2944cf72ba6
SHA256: 11922af475146f60347a9c52cff4bbce1ce524bdb4293b2c436f3c71876e17d5
Section: admin
Priority: optional
Homepage: https://github.com/jasonwitty/socktop
Binary file not shown.
+58
View File
@@ -0,0 +1,58 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>socktop APT Repository</title>
<style>
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
max-width: 800px;
margin: 50px auto;
padding: 20px;
line-height: 1.6;
}
code {
background: #f4f4f4;
padding: 2px 6px;
border-radius: 3px;
}
pre {
background: #f4f4f4;
padding: 15px;
border-radius: 5px;
overflow-x: auto;
}
h1 { color: #333; }
h2 { color: #555; margin-top: 30px; }
</style>
</head>
<body>
<h1>socktop APT Repository</h1>
<p>System monitor with remote agent support for Linux systems.</p>
<h2>Adding this repository</h2>
<pre><code># Add the GPG key
curl -fsSL https://jasonwitty.github.io/socktop/KEY.gpg | sudo gpg --dearmor -o /usr/share/keyrings/socktop-archive-keyring.gpg
# Add the repository
echo "deb [signed-by=/usr/share/keyrings/socktop-archive-keyring.gpg] https://jasonwitty.github.io/socktop stable main" | sudo tee /etc/apt/sources.list.d/socktop.list
# Update and install
sudo apt update
sudo apt install socktop socktop-agent</code></pre>
<h2>Manual Installation</h2>
<p>Download packages from <a href="pool/main/">pool/main/</a></p>
<h2>Supported Architectures</h2>
<ul>
<li>amd64 (x86_64)</li>
<li>arm64 (aarch64)</li>
<li>armhf (32-bit ARM)</li>
</ul>
<h2>Source Code</h2>
<p>Visit the <a href="https://github.com/jasonwitty/socktop">GitHub repository</a></p>
</body>
</html>
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
-43
View File
@@ -1,43 +0,0 @@
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512
Origin: socktop
Label: socktop
Suite: stable
Codename: stable
Architectures: amd64 arm64 armhf riscv64
Components: main
Description: socktop APT repository
Date: Mon, 24 Aug 2026 14:30:55 +0000
MD5Sum:
ada07cbd3ac088cecb5dc9d08518823d 1627 main/binary-amd64/Packages
fbb8924917960d65b5bcad003ccb90c2 830 main/binary-amd64/Packages.gz
71b8d2e69d19d4db385bc3f2be603b72 1627 main/binary-arm64/Packages
70831c731ff47542094fe3417e385aa6 830 main/binary-arm64/Packages.gz
129d1b34bf48c75861a188d6ae8fba77 1611 main/binary-armhf/Packages
54e691233b47bb1f0d89f82b00d9403f 814 main/binary-armhf/Packages.gz
4c3fc0b399405dd682dac1318adda05f 1623 main/binary-riscv64/Packages
15bcbe1806bf2577849090556c3a2a81 817 main/binary-riscv64/Packages.gz
SHA256:
88a907a84f4d292e34426d71e328561aba9658440e588f62f0f3b5d7f5c5f121 1627 main/binary-amd64/Packages
3a87b0b38cb79d231b8ed66e1fdc9a54369d0d3f2f0686f6513cece15f0dc967 830 main/binary-amd64/Packages.gz
84a43993bf58648174ef5bf1d4542e96f5d7903acedc0405f8f3aeab4fdbb4e7 1627 main/binary-arm64/Packages
fd8e6a7ec2b7c438659b0fe8fa825670ccfbeb2298c01b55020cbdad2acb3313 830 main/binary-arm64/Packages.gz
63a89cdee8e5c93867b2dd5193df162304ea97855ad68135c5c5d0753700102c 1611 main/binary-armhf/Packages
c81f19a798757bd1806bb860aba238757edf1b902338554e30bcddba86b3c02b 814 main/binary-armhf/Packages.gz
fa590edf01fbdd63817bd1cee4ab49d93bd47d60d74ecdae961cfa927e5b0526 1623 main/binary-riscv64/Packages
3815e37b15c4ac150e23ce76786bfda0165e325d00b3650466442356ac39221b 817 main/binary-riscv64/Packages.gz
-----BEGIN PGP SIGNATURE-----
iQGzBAEBCgAdFiEEHnVWqAU5uDlLwoINESwaeYRl+/IFAmqMVaEACgkQESwaeYRl
+/JqUQv+PFvgvw2yMwX1jfCeyKAfc/BmWIitVo5eOYS4P4iMqnOLGP9M44okbhgH
Ss7l9kg13Bmtn3TdF6eWOoyfhb/Zchpf5O4xeaXLCBsaTjFtX2BAgg7Z441AkEVP
AzaGcmbev6+R7EM3EEqk0fvVLyYHWw9qY9ADC+ArZ7GxYgVgAkIcM2V1bzjJQtOw
dYR2XwGWiFZet62DXVsCs6g26tUyvmR062GcKmk1xQY/g9SbOqPXYP7Uou5hw+UZ
QAY9LFnCWDz0OATclIKZzqhp7oMjWe3T96d/25lV+fQ2Cmk7ayPGaTrpeTnvCfzO
u46DIQkkTpyalhZPcC0hgCg9tbh2rzAF6ETy+oKmYYE8wEA8wqIvJdGt1RZT/IUg
SQEma61GavK0nBVjPjEjchT5hfTgS03YBea15lA5sZiEAD0SOV4QHxbbVmszGEaQ
Ha4AnRLBji9Ea5E3848QTJLPq1BZ7zLvU6Tn8Nlutuh2doizSQlX3xSozvUV9BYp
bWU/J6Ye
=8uE3
-----END PGP SIGNATURE-----
-26
View File
@@ -1,26 +0,0 @@
Origin: socktop
Label: socktop
Suite: stable
Codename: stable
Architectures: amd64 arm64 armhf riscv64
Components: main
Description: socktop APT repository
Date: Mon, 24 Aug 2026 14:30:55 +0000
MD5Sum:
ada07cbd3ac088cecb5dc9d08518823d 1627 main/binary-amd64/Packages
fbb8924917960d65b5bcad003ccb90c2 830 main/binary-amd64/Packages.gz
71b8d2e69d19d4db385bc3f2be603b72 1627 main/binary-arm64/Packages
70831c731ff47542094fe3417e385aa6 830 main/binary-arm64/Packages.gz
129d1b34bf48c75861a188d6ae8fba77 1611 main/binary-armhf/Packages
54e691233b47bb1f0d89f82b00d9403f 814 main/binary-armhf/Packages.gz
4c3fc0b399405dd682dac1318adda05f 1623 main/binary-riscv64/Packages
15bcbe1806bf2577849090556c3a2a81 817 main/binary-riscv64/Packages.gz
SHA256:
88a907a84f4d292e34426d71e328561aba9658440e588f62f0f3b5d7f5c5f121 1627 main/binary-amd64/Packages
3a87b0b38cb79d231b8ed66e1fdc9a54369d0d3f2f0686f6513cece15f0dc967 830 main/binary-amd64/Packages.gz
84a43993bf58648174ef5bf1d4542e96f5d7903acedc0405f8f3aeab4fdbb4e7 1627 main/binary-arm64/Packages
fd8e6a7ec2b7c438659b0fe8fa825670ccfbeb2298c01b55020cbdad2acb3313 830 main/binary-arm64/Packages.gz
63a89cdee8e5c93867b2dd5193df162304ea97855ad68135c5c5d0753700102c 1611 main/binary-armhf/Packages
c81f19a798757bd1806bb860aba238757edf1b902338554e30bcddba86b3c02b 814 main/binary-armhf/Packages.gz
fa590edf01fbdd63817bd1cee4ab49d93bd47d60d74ecdae961cfa927e5b0526 1623 main/binary-riscv64/Packages
3815e37b15c4ac150e23ce76786bfda0165e325d00b3650466442356ac39221b 817 main/binary-riscv64/Packages.gz
-14
View File
@@ -1,14 +0,0 @@
-----BEGIN PGP SIGNATURE-----
iQGzBAABCgAdFiEEHnVWqAU5uDlLwoINESwaeYRl+/IFAmqMVZ8ACgkQESwaeYRl
+/JgAgwA1xKy+N7n4S4bjP1LxoLDa0fOHnxORd2dajYHkA6NqORSd2KPgWqBwtlA
TGA8wJ8Gurdluu6kaZ8rJ55PUVZFX2qU/UsXy0Pn1Kp2NMuMhdkzXUuYI/oKILof
TtYKqubJ4+LZvfrCdOWusDGhybA4DXaPGm+/EjJ6xKJDm0N6Ht4YhUlb9uTFH8jr
y/hzl9Qcp2GoaDIXoLQCYPfUePHSH7JRn77uuKu3DKC3rwP2QXyBDNfWRJY0X89L
fGBzAxgj2jE7/Gn/T3X3QGTsSAlZeuEIu88/+qwyi3kq7SeBWFf70kGHFS3RPAmh
ULMpQe44N0H3faBIC1wER/P12NIDCi633XkL5WVwA+HvSWk8DZGu+cV4s7BcmWbD
8KOcJe9dEoYpcGbxpZMqe0iCc6pr7vQ5FBlt0Zj0LzvONSL55kH8L7tG/uX4VXcM
g6LLLJjm6oLWT8U8QNskOgAVxTgyZgHUVa2cAG0jZp0BErSegg38mHLs3QXtdySc
xd4t41hM
=OG4V
-----END PGP SIGNATURE-----
Binary file not shown.
-40
View File
@@ -1,40 +0,0 @@
Package: socktop
Version: 1.60.2-1
Architecture: arm64
Maintainer: Jason Witty <jasonpwitty+socktop@proton.me>
Installed-Size: 2994
Depends: libc6 (>= 2.34)
Filename: pool/main/socktop_1.60.2-1_arm64.deb
Size: 1176428
MD5sum: 6c628e55b118550964fdd3429ade9013
SHA1: 814407491af72cc8c03dfc4aca1fcd29676d84e7
SHA256: fb3f29fe439d7e8a6813c52811a4acb9dc5a390acbbe5c8b5a7d77301bf7df39
Section: admin
Priority: optional
Homepage: https://github.com/jasonwitty/socktop
Description: Remote system monitor over WebSocket, TUI like top
socktop is a remote system monitor with a rich terminal user interface (TUI)
that connects to remote hosts running the socktop_agent over WebSocket. It
provides real-time monitoring of CPU, memory, processes, and more with an
interface similar to the traditional 'top' command.
Package: socktop-agent
Version: 1.60.2-1
Architecture: arm64
Maintainer: Jason Witty <jasonpwitty+socktop@proton.me>
Installed-Size: 5158
Depends: libc6 (>= 2.34), libdrm-amdgpu1 (>= 2.4.80)
Filename: pool/main/socktop-agent_1.60.2-1_arm64.deb
Size: 1648768
MD5sum: d40c11e1a82a4deee69a8f09b99b8a3c
SHA1: bb17940a085d9cdda0d0ae26aa73843f3b293705
SHA256: 9f0779dafe9e2c5029c65201e2d45abb2cc9b9dfae38deb6d650f6c9a5fd07ce
Section: admin
Priority: optional
Homepage: https://github.com/jasonwitty/socktop
Description: Socktop agent daemon. Serves host metrics over WebSocket.
socktop_agent is the daemon component that runs on remote hosts to collect and
serve system metrics over WebSocket. It gathers CPU, memory, disk, network,
GPU, and process information that can be monitored remotely by the socktop TUI
client.
Binary file not shown.
-40
View File
@@ -1,40 +0,0 @@
Package: socktop
Version: 1.60.2-1
Architecture: armhf
Maintainer: Jason Witty <jasonpwitty+socktop@proton.me>
Installed-Size: 2764
Depends: libc6:armhf (>= 2.35)
Filename: pool/main/socktop_1.60.2-1_armhf.deb
Size: 1029920
MD5sum: 731d71c8450006624db51f802a1b75fa
SHA1: 7a797ecb089208171bc762a2602af8048b9d74fa
SHA256: bfd6d29c18826ed20a9f0e3af2e0f5cc2d24dd23f621110f9d58aed60f7ca1a5
Section: admin
Priority: optional
Homepage: https://github.com/jasonwitty/socktop
Description: Remote system monitor over WebSocket, TUI like top
socktop is a remote system monitor with a rich terminal user interface (TUI)
that connects to remote hosts running the socktop_agent over WebSocket. It
provides real-time monitoring of CPU, memory, processes, and more with an
interface similar to the traditional 'top' command.
Package: socktop-agent
Version: 1.60.2-1
Architecture: armhf
Maintainer: Jason Witty <jasonpwitty+socktop@proton.me>
Installed-Size: 3821
Depends: libc6:armhf (>= 2.35)
Filename: pool/main/socktop-agent_1.60.2-1_armhf.deb
Size: 1462340
MD5sum: b987e05b88a9a32fb3379c54413a1eb0
SHA1: c751d0bf6ced067c667895f36379df4bc7b1170c
SHA256: c2bcce2e679d96cc9076d118abd9a766ed413f306d88dcc59912814c1962ba04
Section: admin
Priority: optional
Homepage: https://github.com/jasonwitty/socktop
Description: Socktop agent daemon. Serves host metrics over WebSocket.
socktop_agent is the daemon component that runs on remote hosts to collect and
serve system metrics over WebSocket. It gathers CPU, memory, disk, network,
GPU, and process information that can be monitored remotely by the socktop TUI
client.
Binary file not shown.
-40
View File
@@ -1,40 +0,0 @@
Package: socktop
Version: 1.60.2-1
Architecture: riscv64
Maintainer: Jason Witty <jasonpwitty+socktop@proton.me>
Installed-Size: 2668
Depends: libc6:riscv64 (>= 2.35)
Filename: pool/main/socktop_1.60.2-1_riscv64.deb
Size: 1166192
MD5sum: 11e89c1f7909fc90047a74d2880d1362
SHA1: 4089962ff3864209a026b585fe2b6490cfe014a2
SHA256: e1fad743c74934a11e49808d0bba80c26f05e6d75c231f239870866ba50e1e38
Section: admin
Priority: optional
Homepage: https://github.com/jasonwitty/socktop
Description: Remote system monitor over WebSocket, TUI like top
socktop is a remote system monitor with a rich terminal user interface (TUI)
that connects to remote hosts running the socktop_agent over WebSocket. It
provides real-time monitoring of CPU, memory, processes, and more with an
interface similar to the traditional 'top' command.
Package: socktop-agent
Version: 1.60.2-1
Architecture: riscv64
Maintainer: Jason Witty <jasonpwitty+socktop@proton.me>
Installed-Size: 3846
Depends: libc6:riscv64 (>= 2.35)
Filename: pool/main/socktop-agent_1.60.2-1_riscv64.deb
Size: 1637096
MD5sum: 98347f203e942073464ff8b8d16796bb
SHA1: dec2ae6fdd5bea71f43f9e24842a0851150e24fd
SHA256: fd4070c6e0b29adf5bb9de32f098431e9dcf7456e1fc7f4460a5e9a5708496cc
Section: admin
Priority: optional
Homepage: https://github.com/jasonwitty/socktop
Description: Socktop agent daemon. Serves host metrics over WebSocket.
socktop_agent is the daemon component that runs on remote hosts to collect and
serve system metrics over WebSocket. It gathers CPU, memory, disk, network,
GPU, and process information that can be monitored remotely by the socktop TUI
client.
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 775 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 879 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 MiB

+274
View File
@@ -0,0 +1,274 @@
# Debian Packaging for socktop
This document describes how to build and use Debian packages for socktop and socktop_agent.
## Prerequisites
Install `cargo-deb`:
```bash
cargo install cargo-deb
```
## Building Packages Locally
### Build for your current architecture (x86_64)
```bash
# Build socktop TUI client
cargo deb --package socktop
# Build socktop_agent daemon
cargo deb --package socktop_agent
```
The `.deb` files will be created in `target/debian/`.
### Cross-compile for ARM64 (Raspberry Pi, etc.)
First, install cross-compilation tools:
```bash
sudo apt-get update
sudo apt-get install gcc-aarch64-linux-gnu libc6-dev-arm64-cross
```
Add the ARM64 target:
```bash
rustup target add aarch64-unknown-linux-gnu
```
Configure the linker by creating `.cargo/config.toml`:
```toml
[target.aarch64-unknown-linux-gnu]
linker = "aarch64-linux-gnu-gcc"
```
Build the packages:
```bash
# Build for ARM64
cargo deb --package socktop --target aarch64-unknown-linux-gnu
cargo deb --package socktop_agent --target aarch64-unknown-linux-gnu
```
## Installing Packages
### Install socktop TUI client
```bash
sudo dpkg -i socktop_*.deb
```
### Install socktop_agent daemon
```bash
sudo dpkg -i socktop_agent_*.deb
```
The agent package will:
- Create a `socktop` system user and group
- Install the binary to `/usr/bin/socktop_agent`
- Install a systemd service file (disabled by default)
- Create `/var/lib/socktop` for state files
### Enable and start the agent service
```bash
# Enable to start on boot
sudo systemctl enable socktop-agent
# Start the service
sudo systemctl start socktop-agent
# Check status
sudo systemctl status socktop-agent
```
### Configure the agent
Edit the systemd service to customize settings:
```bash
sudo systemctl edit socktop-agent
```
Add configuration in the override section:
```ini
[Service]
Environment=SOCKTOP_PORT=8080
Environment=SOCKTOP_TOKEN=your-secret-token
Environment=RUST_LOG=info
```
Then restart:
```bash
sudo systemctl restart socktop-agent
```
## GitHub Actions
The project includes a GitHub Actions workflow (`.github/workflows/build-deb.yml`) that automatically builds `.deb` packages for both x86_64 and ARM64 architectures on every push to master or when tags are created.
### Downloading pre-built packages
1. Go to the [Actions tab](https://github.com/jasonwitty/socktop/actions)
2. Click on the latest "Build Debian Packages" workflow run
3. Download the artifacts:
- `debian-packages-amd64` - x86_64 packages
- `debian-packages-arm64` - ARM64 packages
- `all-debian-packages` - All packages combined
- `checksums` - SHA256 checksums
### Release packages
When you create a git tag starting with `v` (e.g., `v1.50.0`), the workflow will automatically create a GitHub Release with all `.deb` packages attached.
```bash
git tag v1.50.0
git push origin v1.50.0
```
## Package Details
### socktop package
- **Binary**: `/usr/bin/socktop`
- **Documentation**: `/usr/share/doc/socktop/`
- **Size**: ~5-8 MB (depends on architecture)
### socktop_agent package
- **Binary**: `/usr/bin/socktop_agent`
- **Service**: `socktop-agent.service`
- **User/Group**: `socktop`
- **State directory**: `/var/lib/socktop`
- **Config directory**: `/etc/socktop` (created but empty by default)
- **Documentation**: `/usr/share/doc/socktop_agent/`
- **Size**: ~5-8 MB (depends on architecture)
## Uninstalling
```bash
# Remove packages but keep configuration
sudo apt remove socktop socktop_agent
# Remove packages and all configuration (purge)
sudo apt purge socktop socktop_agent
```
When purging `socktop_agent`, the following are removed:
- The `socktop` user and group
- `/var/lib/socktop` directory
- Empty `/etc/socktop` directory (if empty)
## Verifying Packages
Check package contents:
```bash
dpkg -c socktop_*.deb
dpkg -c socktop_agent_*.deb
```
Check package information:
```bash
dpkg -I socktop_*.deb
dpkg -I socktop_agent_*.deb
```
After installation, verify files:
```bash
dpkg -L socktop
dpkg -L socktop-agent
```
## Troubleshooting
### Service fails to start
Check logs:
```bash
sudo journalctl -u socktop-agent -f
```
Verify the socktop user exists:
```bash
id socktop
```
### Permission issues
Ensure the state directory has correct permissions:
```bash
sudo chown -R socktop:socktop /var/lib/socktop
sudo chmod 755 /var/lib/socktop
```
### Missing dependencies
If installation fails due to missing dependencies:
```bash
sudo apt --fix-broken install
```
## Creating a Local APT Repository (Advanced)
To create your own APT repository for easy installation:
1. Install required tools:
```bash
sudo apt install dpkg-dev
```
2. Create repository structure:
```bash
mkdir -p ~/socktop-repo/pool/main
cp *.deb ~/socktop-repo/pool/main/
```
3. Generate package index:
```bash
cd ~/socktop-repo
dpkg-scanpackages pool/main /dev/null | gzip -9c > pool/main/Packages.gz
```
4. Serve via HTTP (for testing):
```bash
cd ~/socktop-repo
python3 -m http.server 8000
```
5. Add to sources on client machines:
```bash
echo "deb [trusted=yes] http://your-server:8000 pool/main/" | \
sudo tee /etc/apt/sources.list.d/socktop.list
sudo apt update
sudo apt install socktop socktop-agent
```
## Contributing
When adding new features that affect packaging:
1. Update `Cargo.toml` metadata in the `[package.metadata.deb]` section
2. Add new assets to the `assets` array if needed
3. Update maintainer scripts in `socktop_agent/debian/` if needed
4. Test package building locally before committing
5. Update this documentation
## References
- [cargo-deb documentation](https://github.com/kornelski/cargo-deb)
- [Debian Policy Manual](https://www.debian.org/doc/debian-policy/)
- [systemd service files](https://www.freedesktop.org/software/systemd/man/systemd.service.html)
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 152 KiB

+207
View File
@@ -0,0 +1,207 @@
# Cross-Compiling socktop_agent for Raspberry Pi
This guide explains how to cross-compile the socktop_agent on various host systems and deploy it to a Raspberry Pi. Cross-compiling is particularly useful for older or resource-constrained Pi models where native compilation might be slow.
**Note:** GPU monitoring support is not available on ARMv7 (32-bit) and RISC-V architectures due to library limitations. When building for these platforms, the `--no-default-features` flag must be used to disable GPU support.
## Cross-Compilation Host Setup
Choose your host operating system:
- [Debian/Ubuntu](#debianubuntu-based-systems)
- [Arch Linux](#arch-linux-based-systems)
- [macOS](#macos)
- [Windows](#windows)
## Debian/Ubuntu Based Systems
### Prerequisites
Install the cross-compilation toolchain for your target Raspberry Pi architecture:
```bash
# For 64-bit Raspberry Pi (aarch64)
sudo apt update
sudo apt install gcc-aarch64-linux-gnu libc6-dev-arm64-cross libdrm-dev:arm64
# For 32-bit Raspberry Pi (armv7)
# Note: GPU support not available on armv7
sudo apt update
sudo apt install gcc-arm-linux-gnueabihf libc6-dev-armhf-cross
```
### Setup Rust Cross-Compilation Targets
```bash
# For 64-bit Raspberry Pi
rustup target add aarch64-unknown-linux-gnu
# For 32-bit Raspberry Pi
rustup target add armv7-unknown-linux-gnueabihf
```
### Configure Cargo for Cross-Compilation
Create or edit `~/.cargo/config.toml`:
```toml
[target.aarch64-unknown-linux-gnu]
linker = "aarch64-linux-gnu-gcc"
[target.armv7-unknown-linux-gnueabihf]
linker = "arm-linux-gnueabihf-gcc"
```
## Arch Linux Based Systems
### Prerequisites
Install the cross-compilation toolchain using pacman and AUR:
```bash
# Install base dependencies
sudo pacman -S base-devel
# For 64-bit Raspberry Pi (aarch64)
sudo pacman -S aarch64-linux-gnu-gcc
# Install libdrm for aarch64 using an AUR helper (e.g., yay, paru)
yay -S aarch64-linux-gnu-libdrm
# For 32-bit Raspberry Pi (armv7)
# Note: GPU support not available on armv7
sudo pacman -S arm-linux-gnueabihf-gcc
```
### Setup Rust Cross-Compilation Targets
```bash
# For 64-bit Raspberry Pi
rustup target add aarch64-unknown-linux-gnu
# For 32-bit Raspberry Pi
rustup target add armv7-unknown-linux-gnueabihf
```
### Configure Cargo for Cross-Compilation
Create or edit `~/.cargo/config.toml`:
```toml
[target.aarch64-unknown-linux-gnu]
linker = "aarch64-linux-gnu-gcc"
[target.armv7-unknown-linux-gnueabihf]
linker = "arm-linux-gnueabihf-gcc"
```
## macOS
The recommended approach for cross-compiling from macOS is to use Docker:
```bash
# Install Docker
brew install --cask docker
# Pull a cross-compilation Docker image
docker pull messense/rust-musl-cross:armv7-musleabihf # For 32-bit Pi
docker pull messense/rust-musl-cross:aarch64-musl # For 64-bit Pi
```
### Using Docker for Cross-Compilation
```bash
# Navigate to your socktop project directory
cd path/to/socktop
# For 64-bit Raspberry Pi
docker run --rm -it -v "$(pwd)":/home/rust/src messense/rust-musl-cross:aarch64-musl cargo build --release --target aarch64-unknown-linux-musl -p socktop_agent
# For 32-bit Raspberry Pi (without GPU support)
docker run --rm -it -v "$(pwd)":/home/rust/src messense/rust-musl-cross:armv7-musleabihf cargo build --release --target armv7-unknown-linux-musleabihf -p socktop_agent --no-default-features
```
The compiled binaries will be available in your local target directory.
## Windows
The recommended approach for Windows is to use Windows Subsystem for Linux (WSL2):
1. Install WSL2 with a Debian/Ubuntu distribution by following the [official Microsoft documentation](https://docs.microsoft.com/en-us/windows/wsl/install).
2. Once WSL2 is set up with a Debian/Ubuntu distribution, open your WSL terminal and follow the [Debian/Ubuntu instructions](#debianubuntu-based-systems) above.
## Cross-Compile the Agent
After setting up your environment, build the socktop_agent for your target Raspberry Pi:
```bash
# For 64-bit Raspberry Pi (with GPU support)
cargo build --release --target aarch64-unknown-linux-gnu -p socktop_agent
# For 32-bit Raspberry Pi (without GPU support)
cargo build --release --target armv7-unknown-linux-gnueabihf -p socktop_agent --no-default-features
```
## Transfer the Binary to Your Raspberry Pi
Use SCP to transfer the compiled binary to your Raspberry Pi:
```bash
# For 64-bit Raspberry Pi
scp target/aarch64-unknown-linux-gnu/release/socktop_agent pi@raspberry-pi-ip:~/
# For 32-bit Raspberry Pi
scp target/armv7-unknown-linux-gnueabihf/release/socktop_agent pi@raspberry-pi-ip:~/
```
Replace `raspberry-pi-ip` with your Raspberry Pi's IP address and `pi` with your username.
## Install Dependencies on the Raspberry Pi
SSH into your Raspberry Pi and install the required dependencies:
```bash
ssh pi@raspberry-pi-ip
# For Raspberry Pi OS (Debian-based) - 64-bit only
# (32-bit armv7 builds don't require these)
sudo apt update
sudo apt install libdrm-dev libdrm-amdgpu1
# For Arch Linux ARM - 64-bit only
sudo pacman -Syu
sudo pacman -S libdrm
```
## Make the Binary Executable and Install
```bash
chmod +x ~/socktop_agent
# Optional: Install system-wide
sudo install -o root -g root -m 0755 ~/socktop_agent /usr/local/bin/socktop_agent
# Optional: Set up as a systemd service
sudo install -o root -g root -m 0644 ~/socktop-agent.service /etc/systemd/system/socktop-agent.service
sudo systemctl daemon-reload
sudo systemctl enable --now socktop-agent
```
## Troubleshooting
If you encounter issues with the cross-compiled binary:
1. **Incorrect Architecture**: Ensure you've chosen the correct target for your Raspberry Pi model:
- For Raspberry Pi 2: use `armv7-unknown-linux-gnueabihf`
- For Raspberry Pi 3/4/5 in 64-bit mode: use `aarch64-unknown-linux-gnu`
- For Raspberry Pi 3/4/5 in 32-bit mode: use `armv7-unknown-linux-gnueabihf`
2. **Dependency Issues**: Check for missing libraries:
```bash
ldd ~/socktop_agent
```
3. **Run with Backtrace**: Get detailed error information:
```bash
RUST_BACKTRACE=1 ~/socktop_agent
```
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 616 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 MiB

+18
View File
@@ -0,0 +1,18 @@
[Unit]
Description=Socktop agent
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
ExecStart=/usr/local/bin/socktop_agent --port 3000
Environment=RUST_LOG=info
# Optional auth:
# Environment=SOCKTOP_TOKEN=changeme
Restart=on-failure
User=socktop
Group=socktop
NoNewPrivileges=true
[Install]
WantedBy=multi-user.target
Binary file not shown.

After

Width:  |  Height:  |  Size: 151 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 MiB

-364
View File
@@ -1,364 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>socktop APT Repository</title>
<style>
/* Catppuccin Frappe Color Palette */
:root {
--ctp-base: #303446;
--ctp-mantle: #292c3c;
--ctp-crust: #232634;
--ctp-text: #c6d0f5;
--ctp-subtext1: #b5bfe2;
--ctp-subtext0: #a5adce;
--ctp-overlay2: #949cbb;
--ctp-overlay1: #838ba7;
--ctp-overlay0: #737994;
--ctp-surface2: #626880;
--ctp-surface1: #51576d;
--ctp-surface0: #414559;
--ctp-lavender: #babbf1;
--ctp-blue: #8caaee;
--ctp-sapphire: #85c1dc;
--ctp-sky: #99d1db;
--ctp-teal: #81c8be;
--ctp-green: #a6d189;
--ctp-yellow: #e5c890;
--ctp-peach: #ef9f76;
--ctp-maroon: #ea999c;
--ctp-red: #e78284;
--ctp-mauve: #ca9ee6;
--ctp-pink: #f4b8e4;
--ctp-flamingo: #eebebe;
--ctp-rosewater: #f2d5cf;
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family:
-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
"Helvetica Neue", Arial, sans-serif;
background-color: var(--ctp-base);
color: var(--ctp-text);
line-height: 1.6;
padding: 20px;
}
.container {
max-width: 900px;
margin: 0 auto;
background-color: var(--ctp-mantle);
border-radius: 12px;
padding: 40px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.3);
}
h1 {
color: var(--ctp-blue);
font-size: 2.5em;
margin-bottom: 10px;
border-bottom: 3px solid var(--ctp-surface0);
padding-bottom: 15px;
}
h2 {
color: var(--ctp-mauve);
font-size: 1.8em;
margin-top: 35px;
margin-bottom: 15px;
}
h3 {
color: var(--ctp-sapphire);
font-size: 1.3em;
margin-top: 25px;
margin-bottom: 10px;
}
p {
margin-bottom: 15px;
color: var(--ctp-subtext0);
}
.subtitle {
color: var(--ctp-subtext1);
font-size: 1.2em;
margin-bottom: 30px;
}
code {
background-color: var(--ctp-surface0);
color: var(--ctp-green);
padding: 3px 8px;
border-radius: 5px;
font-family: "Courier New", Courier, monospace;
font-size: 0.95em;
}
pre {
background-color: var(--ctp-crust);
border: 1px solid var(--ctp-surface0);
border-radius: 8px;
padding: 20px;
overflow-x: auto;
margin: 15px 0;
position: relative;
padding-top: 18px; /* leave space for top-right button */
}
pre code {
background: transparent;
color: var(--ctp-text);
display: block;
white-space: pre;
font-family: "Courier New", Courier, monospace;
font-size: 0.95em;
}
/* Copy button styles */
.copy-btn {
position: absolute;
top: 8px;
right: 8px;
background: var(--ctp-surface1);
color: var(--ctp-text);
border: 1px solid var(--ctp-surface2);
padding: 6px 8px;
border-radius: 6px;
cursor: pointer;
font-size: 0.9rem;
display: inline-flex;
align-items: center;
gap: 6px;
transition:
background 0.12s ease,
transform 0.08s ease;
}
.copy-btn:hover {
background: var(--ctp-surface2);
transform: translateY(-1px);
}
.copy-btn:active {
transform: translateY(0);
}
.copy-btn.copied {
background: var(--ctp-green);
color: var(--ctp-crust);
border-color: transparent;
}
.badge {
display: inline-block;
background-color: var(--ctp-surface1);
color: var(--ctp-text);
padding: 5px 12px;
border-radius: 6px;
font-size: 0.9em;
margin: 5px 5px 5px 0;
border: 1px solid var(--ctp-surface2);
}
.badge.arch {
background-color: var(--ctp-surface0);
color: var(--ctp-lavender);
}
.note {
background-color: var(--ctp-surface0);
border-left: 4px solid var(--ctp-yellow);
padding: 15px;
margin: 20px 0;
border-radius: 5px;
}
.note strong {
color: var(--ctp-yellow);
}
.footer {
margin-top: 50px;
padding-top: 20px;
border-top: 2px solid var(--ctp-surface0);
text-align: center;
color: var(--ctp-overlay1);
font-size: 0.9em;
}
.command-comment {
color: var(--ctp-overlay1);
display: block;
margin-bottom: 6px;
}
.highlight-blue {
color: var(--ctp-blue);
}
.highlight-green {
color: var(--ctp-green);
}
.highlight-yellow {
color: var(--ctp-yellow);
}
.highlight-mauve {
color: var(--ctp-mauve);
}
.highlight-peach {
color: var(--ctp-peach);
}
@media (max-width: 768px) {
.container {
padding: 25px;
}
h1 {
font-size: 2em;
}
h2 {
font-size: 1.5em;
}
}
</style>
</head>
<body>
<div class="container">
<h1>socktop APT Repository</h1>
<p class="subtitle">
System monitor with remote agent support for Linux systems
</p>
<h2>📦 Quick Installation</h2>
<p>Add this repository to your Debian/Ubuntu system:</p>
<h3>Step 1: Add GPG Key</h3>
<pre><code># Add the repository's GPG signing key
curl -fsSL https://jasonwitty.github.io/socktop/KEY.gpg | \
sudo gpg --dearmor -o /usr/share/keyrings/socktop-archive-keyring.gpg</code></pre>
<h3>Step 2: Add Repository</h3>
<pre><code># Add the APT repository to your sources
echo "deb [signed-by=/usr/share/keyrings/socktop-archive-keyring.gpg] https://jasonwitty.github.io/socktop stable main" | \
sudo tee /etc/apt/sources.list.d/socktop.list</code></pre>
<h3>Step 3: Install</h3>
<pre><code># Update package lists and install
sudo apt update
sudo apt install socktop socktop-agent</code></pre>
<h2>📋 What's Included</h2>
<ul>
<li>
<strong class="highlight-blue">socktop</strong> - Terminal
UI client for monitoring systems
</li>
<li>
<strong class="highlight-mauve">socktop-agent</strong> -
Background agent that reports system metrics
</li>
</ul>
<div class="note">
<strong>Note:</strong> The agent package automatically installs
and configures a systemd service. Enable it with:
<code>sudo systemctl enable --now socktop-agent</code>
</div>
<h2>🏗️ Supported Architectures</h2>
<div>
<span class="badge arch">amd64</span>
<span class="badge arch">arm64</span>
<span class="badge arch">armhf</span>
<span class="badge arch">riscv64</span>
</div>
<h2>🔧 Usage</h2>
<p>After installation:</p>
<pre><code># Start the TUI client
socktop
# Connect to a remote agent
socktop ws://hostname:3000
# Start the agent (if not using systemd)
socktop_agent</code></pre>
<h2>🔗 Links</h2>
<ul>
<li>
<a href="https://github.com/jasonwitty/socktop"
>Source Code on GitHub</a
>
</li>
<li>
<a href="https://github.com/jasonwitty/socktop/issues"
>Report Issues</a
>
</li>
<li><a href="README.md">Repository Documentation</a></li>
</ul>
<div class="footer">
<p>Hosted on GitHub Pages | Packages signed with GPG</p>
<p>
Theme:
<a href="https://github.com/catppuccin/catppuccin"
>Catppuccin Frappe</a
>
</p>
</div>
</div>
<script>
// Attach copy buttons to all <pre> blocks and enable copy-to-clipboard.
document.addEventListener("DOMContentLoaded", function () {
const pres = document.querySelectorAll("pre");
pres.forEach((pre) => {
// Create button
const btn = document.createElement("button");
btn.type = "button";
btn.className = "copy-btn";
btn.setAttribute("aria-label", "Copy code to clipboard");
// Use emoji for simplicity; you can replace with SVG if desired
btn.innerText = "📋";
// Append to pre
pre.appendChild(btn);
// Click handler
btn.addEventListener("click", async (e) => {
e.stopPropagation();
const code = pre.querySelector("code");
const text = code ? code.innerText : pre.innerText;
try {
if (!navigator.clipboard) {
// Fallback method
const textarea =
document.createElement("textarea");
textarea.value = text;
textarea.style.position = "fixed";
textarea.style.left = "-9999px";
document.body.appendChild(textarea);
textarea.select();
document.execCommand("copy");
document.body.removeChild(textarea);
} else {
await navigator.clipboard.writeText(text);
}
// feedback
btn.classList.add("copied");
const prior = btn.innerText;
btn.innerText = "✓ Copied";
setTimeout(() => {
btn.classList.remove("copied");
btn.innerText = "📋";
}, 1800);
} catch (err) {
btn.innerText = "✖";
setTimeout(() => (btn.innerText = "📋"), 1500);
console.error("Copy failed", err);
}
});
});
});
</script>
</body>
</html>
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More