{"id":30540806,"url":"https://github.com/jasonwitty/socktop","last_synced_at":"2026-02-28T23:03:03.741Z","repository":{"id":308950108,"uuid":"1034328270","full_name":"jasonwitty/socktop","owner":"jasonwitty","description":"socktop is a remote system monitor with a rich TUI interface, inspired by `top` and `btop`, that communicates with a lightweight remote agent over WebSockets.","archived":false,"fork":false,"pushed_at":"2025-08-23T09:18:13.000Z","size":13510,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-08-24T03:36:37.943Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jasonwitty.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-08-08T08:05:13.000Z","updated_at":"2025-08-23T09:18:16.000Z","dependencies_parsed_at":"2025-08-08T22:10:04.197Z","dependency_job_id":"7e48fd03-0a25-434c-b5a7-ff6b2e4fbaf4","html_url":"https://github.com/jasonwitty/socktop","commit_stats":null,"previous_names":["jasonwitty/socktop"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/jasonwitty/socktop","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jasonwitty%2Fsocktop","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jasonwitty%2Fsocktop/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jasonwitty%2Fsocktop/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jasonwitty%2Fsocktop/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jasonwitty","download_url":"https://codeload.github.com/jasonwitty/socktop/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jasonwitty%2Fsocktop/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":272394375,"owners_count":24927201,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-27T02:00:09.397Z","response_time":76,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-08-27T23:00:48.865Z","updated_at":"2026-02-28T23:02:58.706Z","avatar_url":"https://github.com/jasonwitty.png","language":"Rust","funding_links":[],"categories":["Rust","Table of Contents"],"sub_categories":[],"readme":"# socktop\n\nsocktop is a remote system monitor with a rich TUI, inspired by top/btop, talking to a lightweight agent over WebSockets.\n\n- Linux agent: near-zero CPU when idle (request-driven, no always-on sampler)\n- TUI: smooth graphs, sortable process table, scrollbars, readable colors\n\n\u003cimg src=\"./docs/socktop_demo.apng\" width=\"100%\"\u003e\n\n---\n\n## Features\n\n- Remote monitoring via WebSocket (JSON over WS)\n- Optional WSS (TLS): agent auto‑generates a self‑signed cert on first run; client pins the cert via --tls-ca/-t \n- TUI built with ratatui\n- CPU\n  - Overall sparkline + per-core mini bars\n  - Accurate per-process CPU% (Linux /proc deltas), normalized to 0–100%\n- Memory/Swap gauges with human units\n- Disks: per-device usage\n- Network: per-interface throughput with sparklines and peak markers\n- Temperatures: CPU (optional)\n- Top processes (top 50)\n  - PID, name, CPU%, memory, and memory%\n  - Click-to-sort by CPU% or Mem (descending)\n  - Scrollbar and mouse/keyboard scrolling\n  - Total process count shown in the header\n  - Only top-level processes listed (threads hidden) — matches btop/top\n- Optional GPU metrics (can be disabled)\n- Optional auth token for the agent\n\n---\n\n## Prerequisites: Install Rust (rustup)\n\nRust is fast, safe, and cross‑platform. Installing it will make your machine better. Consider yourself privileged.\n\nLinux/macOS:\n```bash\ncurl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh\n# load cargo for this shell\nsource \"$HOME/.cargo/env\"\n# ensure stable is up to date\nrustup update stable\nrustc --version\ncargo --version\n# after install you may need to reload your shell, e.g.:\nexec bash   # or: exec zsh / exec fish\n```\n\nWindows (for the brave): install from https://rustup.rs with the MSVC toolchain. Yes, you’ll need Visual Studio Build Tools. You chose Windows — enjoy the ride.\n\n### Raspberry Pi / Ubuntu / PopOS (required)\n\nInstall GPU support with apt command below\n\n```bash\nsudo apt-get update\nsudo apt-get install libdrm-dev libdrm-amdgpu1\n```\n\n---\n\n## Architecture\n\nTwo components:\n\n1) 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.\n\n2) Client (local): TUI that connects to ws://HOST:PORT/ws (or wss://HOST:PORT/ws when TLS is enabled) and renders updates.\n\n---\n\n## Quick start\n\n- Build both binaries:\n\n```bash\ngit clone https://github.com/jasonwitty/socktop.git\ncd socktop\ncargo build --release\n```\n\n- Start the agent on the target machine (default port 3000):\n\n```bash\n./target/release/socktop_agent --port 3000\n```\n\n- Connect with the TUI from your local machine:\n\n```bash\n./target/release/socktop ws://REMOTE_HOST:3000/ws\n```\n\n### Quick demo (no agent setup)\n\nSpin up a temporary local agent on port 3231 and connect automatically:\n\n```bash\nsocktop --demo\n```\n\nOr just run `socktop` with no arguments and pick the built‑in `demo` entry from the interactive profile list (if you have saved profiles, `demo` is appended). The demo agent:\n\n- Runs locally (`ws://127.0.0.1:3231/ws`)\n- Stops automatically (you'll see \"Stopped demo agent on port 3231\") when you quit the TUI or press Ctrl-C\n\n---\n\n## Install (from crates.io)\n\nYou don’t need to clone this repo to use socktop. Install the published binaries with cargo:\n\n```bash\n# TUI (client)\ncargo install socktop\n# Agent (server)\ncargo install socktop_agent\n```\n\nThis drops socktop and socktop_agent into ~/.cargo/bin (add it to PATH).\n\nNotes:\n- After installing Rust via rustup, reload your shell (e.g., exec bash) so cargo is on PATH.\n- Windows: you can also grab prebuilt EXEs from GitHub Actions artifacts if rustup scares you. It shouldn’t. Be brave.\n\nSystem-wide agent (Linux)\n\n```bash\n# If you installed with cargo, binaries are in ~/.cargo/bin\nsudo install -o root -g root -m 0755 \"$HOME/.cargo/bin/socktop_agent\" /usr/local/bin/socktop_agent\n\n# Install and enable the systemd service (example unit in docs/)\nsudo install -o root -g root -m 0644 docs/socktop-agent.service /etc/systemd/system/socktop-agent.service\nsudo systemctl daemon-reload\nsudo systemctl enable --now socktop-agent\n```\n\n```bash\n\n# Enable SSL\n\n# Stop service\nsudo systemctl stop socktop-agent\n\n# Edit service to append SSL option and port\nsudo micro /etc/systemd/system/socktop-agent.service\n\n--\nExecStart=/usr/local/bin/socktop_agent --enableSSL --port 8443\n--\n\n# Reload\nsudo systemctl daemon-reload\n\n# Restart\nsudo systemctl start socktop-agent\n\n# check logs for certificate location\nsudo journalctl -u socktop-agent -f\n\n--\nAug 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\n--\n\n```\n\n\n---\n\n## Usage\n\nAgent (server):\n\n```bash\nsocktop_agent --port 3000\n# or env: SOCKTOP_PORT=3000 socktop_agent\n# optional auth: SOCKTOP_TOKEN=changeme socktop_agent\n# enable TLS (self‑signed cert, default port 8443; you can also use -p):\nsocktop_agent --enableSSL --port 8443\n```\n\nClient (TUI):\n\n```bash\nsocktop ws://HOST:3000/ws\n# with token:\nsocktop \"ws://HOST:3000/ws?token=changeme\"\n# TLS with pinned server certificate (recommended over the internet):\nsocktop --tls-ca /path/to/cert.pem wss://HOST:8443/ws\n# (By default hostname/SAN verification is skipped for ease on home networks. To enforce it add --verify-hostname)\nsocktop --verify-hostname --tls-ca /path/to/cert.pem wss://HOST:8443/ws\n# shorthand:\nsocktop -t /path/to/cert.pem wss://HOST:8443/ws\n# Note: providing --tls-ca/-t automatically upgrades ws:// to wss:// if you forget\n```\n\nIntervals (client-driven):\n- Fast metrics: ~500 ms\n- Processes: ~2 s (top 50)\n- Disks: ~5 s\n\nThe agent stays idle unless queried. When queried, it collects just what’s needed.\n\n---\n\n## Connection Profiles (Named)\n\nYou can save frequently used connection settings (URL + optional TLS CA path) under a short name and reuse them later.\n\nConfig file location:\n\n- Linux (XDG): `$XDG_CONFIG_HOME/socktop/profiles.json`\n- Fallback (when XDG not set): `~/.config/socktop/profiles.json`\n\n### Creating a profile\n\nFirst time you specify a new `--profile/-P` name together with a URL (and optional `--tls-ca`), it is saved automatically:\n\n```bash\nsocktop --profile prod ws://prod-host:3000/ws\n# With TLS pinning:\nsocktop --profile prod-tls --tls-ca /path/to/cert.pem wss://prod-host:8443/ws\n\nYou can also set custom intervals (milliseconds):\n\n```bash\nsocktop --profile prod --metrics-interval-ms 750 --processes-interval-ms 3000 ws://prod-host:3000/ws\n```\n```\n\nIf a profile already exists you will be prompted before overwriting:\n\n```\n$ socktop --profile prod ws://new-host:3000/ws\nOverwrite existing profile 'prod'? [y/N]: y\n```\n\nTo overwrite without an interactive prompt pass `--save`:\n\n```bash\nsocktop --profile prod --save ws://new-host:3000/ws\n```\n\n### Using a saved profile\n\nJust pass the profile name (no URL needed):\n\n```bash\nsocktop --profile prod\nsocktop -P prod-tls      # short flag\n```\n\nThe 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.\n\n### Interactive selection (no args)\n\nIf you run `socktop` with no arguments and at least one profile exists, you will be shown a numbered list to pick from:\n\n```\n$ socktop\nSelect profile:\n  1. prod\n  2. prod-tls\nEnter number (or blank to abort): 2\n```\n\nChoosing a number starts the TUI with that profile. A built‑in `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.\n\n### JSON format\n\nAn example `profiles.json` (pretty‑printed):\n\n```json\n{\n  \"profiles\": {\n    \"prod\": { \"url\": \"ws://prod-host:3000/ws\" },\n    \"prod-tls\": {\n      \"url\": \"wss://prod-host:8443/ws\",\n      \"tls_ca\": \"/home/user/certs/prod-cert.pem\",\n      \"metrics_interval_ms\": 500,\n      \"processes_interval_ms\": 2000\n    }\n  },\n  \"version\": 0\n}\n```\n\nNotes:\n- 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`.\n- Deleting a profile: edit the JSON file and remove the entry (TUI does not yet have an in-app delete command).\n- Profiles are client-side convenience only; they do not affect the agent.\n- 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.\n\n---\n\n## Updating\n\nUpdate the agent (systemd):\n\n```bash\n# on the server running the agent\ncargo install socktop_agent --force\nsudo systemctl stop socktop-agent\nsudo install -o root -g root -m 0755 \"$HOME/.cargo/bin/socktop_agent\" /usr/local/bin/socktop_agent\n# if you changed the unit file:\n# sudo install -o root -g root -m 0644 docs/socktop-agent.service /etc/systemd/system/socktop-agent.service\n# sudo systemctl daemon-reload\nsudo systemctl start socktop-agent\nsudo systemctl status socktop-agent --no-pager\n# logs:\n# journalctl -u socktop-agent -f\n```\n\nUpdate the TUI (client):\n```bash\ncargo install socktop --force\nsocktop ws://HOST:3000/ws\n```\n\nTip: If only the binary changed, restart is enough. If the unit file changed, run sudo systemctl daemon-reload.\n\n---\n\n## Configuration (agent)\n\n- Port:\n  - Flag: --port 8080 or -p 8080\n  - Positional: socktop_agent 8080\n  - Env: SOCKTOP_PORT=8080\n- TLS (self‑signed):\n  - Enable: --enableSSL\n  - Default TLS port: 8443 (override with --port/-p)\n  - Certificate/Key location (created on first TLS run):\n    - Linux (XDG): $XDG_CONFIG_HOME/socktop_agent/tls/{cert.pem,key.pem} (defaults to ~/.config)\n    - The agent prints these paths on creation.\n  - You can set XDG_CONFIG_HOME before first run to control where certs are written.\n  - Additional SANs: set `SOCKTOP_AGENT_EXTRA_SANS` (comma‑separated) before first TLS start to include extra IPs/DNS names in the cert. Example:\n    ```bash\n    SOCKTOP_AGENT_EXTRA_SANS=\"192.168.1.101,myhost.internal\" socktop_agent --enableSSL\n    ```\n    This prevents client errors like `NotValidForName` when connecting via an IP not present in the default cert SAN list.\n  - 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:\n    ```bash\n    rm ~/.config/socktop_agent/tls/cert.pem ~/.config/socktop_agent/tls/key.pem\n    # (adjust path if XDG_CONFIG_HOME is set or different user)\n    systemctl restart socktop-agent   # if running under systemd\n    ```\n    On next TLS start the agent will generate a fresh pair. Only distribute the new cert.pem to clients (never the key).\n- Auth token (optional): SOCKTOP_TOKEN=changeme\n- Disable GPU metrics: SOCKTOP_AGENT_GPU=0\n- Disable CPU temperature: SOCKTOP_AGENT_TEMP=0\n\n---\n\n## Keyboard \u0026 Mouse\n\n- Quit: q or Esc\n- Processes pane:\n  - Click “CPU %” to sort by CPU descending\n  - Click “Mem” to sort by memory descending\n  - Mouse wheel: scroll\n  - Drag scrollbar: scroll\n  - Arrow/PageUp/PageDown/Home/End: scroll\n\n---\n\n## Example agent JSON\n\n```json\n{\n  \"cpu_total\": 12.4,\n  \"cpu_per_core\": [11.2, 15.7],\n  \"mem_total\": 33554432,\n  \"mem_used\": 18321408,\n  \"swap_total\": 0,\n  \"swap_used\": 0,\n  \"process_count\": 127,\n  \"hostname\": \"myserver\",\n  \"cpu_temp_c\": 42.5,\n  \"disks\": [{\"name\":\"nvme0n1p2\",\"total\":512000000000,\"available\":320000000000}],\n  \"networks\": [{\"name\":\"eth0\",\"received\":12345678,\"transmitted\":87654321}],\n  \"top_processes\": [\n    {\"pid\":1234,\"name\":\"nginx\",\"cpu_usage\":1.2,\"mem_bytes\":12345678}\n  ],\n  \"gpus\": null\n}\n```\n\nNotes:\n- process_count is merged into the main metrics on the client when processes are polled.\n- top_processes are the current top 50 (sorting in the TUI is client-side).\n\n---\n\n## Security\n\nSet a token on the agent and pass it as a query param from the client:\n\nServer:\n\n```bash\nSOCKTOP_TOKEN=changeme socktop_agent --port 3000\n```\n\nClient:\n\n```bash\nsocktop \"ws://HOST:3000/ws?token=changeme\"\n```\n\n### TLS / WSS\n\nFor encrypted connections, enable TLS on the agent and pin the server certificate on the client.\n\nServer (generates self‑signed cert and key on first run):\n\n```bash\nsocktop_agent --enableSSL --port 8443\n```\n\nClient (trust/pin the server cert; copy cert.pem from the agent):\n\n```bash\nsocktop --tls-ca /path/to/agent/cert.pem wss://HOST:8443/ws\n```\n\nNotes:\n- Do not copy the private key off the server; only the cert.pem is needed by clients.\n- When --tls-ca/-t is supplied, the client auto‑upgrades ws:// to wss:// to avoid protocol mismatch.\n- Hostname (SAN) verification is DISABLED by default (the cert is still pinned). Use `--verify-hostname` to enable strict SAN checking.\n- You can run multiple clients with different cert paths by passing --tls-ca per invocation.\n\n---\n\n## Using tmux to monitor multiple hosts\n\nYou can use tmux to show multiple socktop instances in a single terminal.\n\n![socktop screenshot](./docs/tmux_4_rpis_v3.jpg)\nmonitoring 4 Raspberry Pis using Tmux\n\nPrerequisites:\n- Install tmux (Ubuntu/Debian: `sudo apt-get install tmux`)\n\nKey bindings (defaults):\n- Split left/right: Ctrl-b %\n- Split top/bottom: Ctrl-b \"\n- Move between panes: Ctrl-b + Arrow keys\n- Show pane numbers: Ctrl-b q\n- Close a pane: Ctrl-b x\n- Detach from session: Ctrl-b d\n\nTwo panes (left/right)\n- This creates a session named \"socktop\", splits it horizontally, and starts two socktops.\n\n```bash\ntmux new-session -d -s socktop 'socktop ws://HOST1:3000/ws' \\; \\\n  split-window -h 'socktop ws://HOST2:3000/ws' \\; \\\n  select-layout even-horizontal \\; \\\n  attach\n```\n\nFour panes (top-left, top-right, bottom-left, bottom-right)\n- This creates a 2x2 grid with one socktop per pane.\n\n```bash\ntmux new-session -d -s socktop 'socktop ws://HOST1:3000/ws' \\; \\\n  split-window -h 'socktop ws://HOST2:3000/ws' \\; \\\n  select-pane -t 0 \\; split-window -v 'socktop ws://HOST3:3000/ws' \\; \\\n  select-pane -t 1 \\; split-window -v 'socktop ws://HOST4:3000/ws' \\; \\\n  select-layout tiled \\; \\\n  attach\n```\n\nTips:\n- Replace HOST1..HOST4 (and ports) with your targets.\n- Reattach later: `tmux attach -t socktop`\n\n---\n\n## Platform notes\n\n- Linux: fully supported (agent and client).\n- Raspberry Pi:\n  - 64-bit: aarch64-unknown-linux-gnu\n  - 32-bit: armv7-unknown-linux-gnueabihf\n- Windows:\n  - TUI + agent can build with stable Rust; bring your own MSVC. You’re on Windows; you know the drill.\n  - CPU temperature may be unavailable.\n  - binary exe for both available in build artifacts under actions.\n- macOS:\n  - 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. \n\n---\n\n## Development\n\n```bash\ncargo fmt\ncargo clippy --all-targets --all-features\ncargo run -p socktop -- ws://127.0.0.1:3000/ws\n# TLS (dev): first run will create certs under ~/.config/socktop_agent/tls/\ncargo run -p socktop_agent -- --enableSSL --port 8443\n```\n\n### Auto-format on commit\n\nA sample pre-commit hook that runs `cargo fmt --all` is provided in `.githooks/pre-commit`.\nEnable it (one-time):\n\n```bash\ngit config core.hooksPath .githooks\nchmod +x .githooks/pre-commit\n```\n\nEvery commit will then format Rust sources and restage them automatically.\n\n---\n\n## Roadmap\n\n- [x] Agent authentication (token)\n- [x] Hide per-thread entries; only show processes\n- [x] Sort top processes in the TUI\n- [ ] Configurable refresh intervals (client)\n- [ ] Export metrics to file\n- [x] TLS / WSS support (self‑signed server cert + client pinning)\n- [x] Split processes/disks to separate WS calls with independent cadences (already logical on client; formalize API)\n\n---\n\n## License\n\nMIT — see LICENSE.\n\n---\n\n## Acknowledgements\n\n- ratatui for the TUI\n- sysinfo for system metrics\n- tokio-tungstenite for WebSockets\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjasonwitty%2Fsocktop","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjasonwitty%2Fsocktop","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjasonwitty%2Fsocktop/lists"}