{"id":48521172,"url":"https://github.com/yodakohl/pushme-netnode","last_synced_at":"2026-04-07T21:01:36.099Z","repository":{"id":342814463,"uuid":"1175272517","full_name":"yodakohl/pushme-netnode","owner":"yodakohl","description":"Lightweight netnode publisher for PushMe that emits structured connectivity events from real vantage points.","archived":false,"fork":false,"pushed_at":"2026-03-27T12:52:24.000Z","size":220,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-03-27T20:38:06.987Z","etag":null,"topics":["ai-agents","connectivity","homelab","mcp","monitoring","network-monitoring","openclaw","raspberry-pi","self-hosted"],"latest_commit_sha":null,"homepage":"https://pushme.site/netnode","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/yodakohl.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-07T13:35:44.000Z","updated_at":"2026-03-27T12:52:28.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/yodakohl/pushme-netnode","commit_stats":null,"previous_names":["yodakohl/pushme-netnode"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/yodakohl/pushme-netnode","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yodakohl%2Fpushme-netnode","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yodakohl%2Fpushme-netnode/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yodakohl%2Fpushme-netnode/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yodakohl%2Fpushme-netnode/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/yodakohl","download_url":"https://codeload.github.com/yodakohl/pushme-netnode/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yodakohl%2Fpushme-netnode/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31528751,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-07T16:28:08.000Z","status":"ssl_error","status_checked_at":"2026-04-07T16:28:06.951Z","response_time":105,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["ai-agents","connectivity","homelab","mcp","monitoring","network-monitoring","openclaw","raspberry-pi","self-hosted"],"created_at":"2026-04-07T21:01:13.906Z","updated_at":"2026-04-07T21:01:36.084Z","avatar_url":"https://github.com/yodakohl.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# pushme-netnode\n\n`pushme-netnode` is the main low-footprint netnode runtime for PushMe.\n\nIt keeps the same default probe set and one-minute cadence as the older\nNode-based implementation, but replaces the resident JavaScript runtime with a\nsmall shell-based loop plus short-lived probe tools.\n\nPublished container targets:\n\n- `linux/amd64`\n- `linux/arm64`\n\nThat means small x86 Linux hosts and Apple Silicon machines such as a Mac mini\ncan run the published image through Docker or another Linux-container runtime.\nThis repo does not target a native macOS process outside a container.\n\n## Quick start\n\nInstall the published container:\n\n```sh\n./install.sh\n```\n\nOn an Apple Silicon Mac mini, use Docker Desktop, Colima, or another local\nDocker-compatible runtime. Once the multi-arch image is published, Docker will\nselect the `linux/arm64` image automatically.\n\nRemove it:\n\n```sh\n./uninstall.sh\n```\n\nRemove it and delete persisted state:\n\n```sh\nNETNODE_PURGE_DATA=1 ./uninstall.sh\n```\n\nLocal dry run:\n\n```sh\nNETNODE_LOCATION=test-node NETNODE_PUBLISH_MODE=changes sh ./netnode.sh --once --dry-run\n```\n\n## Operator contract\n\n- default profiles: 9\n- default cadence: 60 seconds\n- default ICMP packets per packet-enabled target: 4\n- published event types:\n  - `net.connectivity.degraded`\n  - `net.connectivity.down`\n  - `net.connectivity.recovered`\n  - `net.provider.degraded`\n  - `net.provider.down`\n  - `net.provider.recovered`\n- startup endpoint: `POST /api/bot/netnode/startup`\n- heartbeat endpoint: `POST /api/bot/netnode/heartbeat`\n- publish endpoint: `POST /api/bot/publish`\n- status endpoint: `GET /api/bot/netnode/status`\n- state path: `/data/netnode-state.tsv`\n- env path: `/data/netnode.env`\n\n## Runtime model\n\n- runtime is `sh` + `curl` + `getent/nslookup` + `ping`\n- normal web targets prefer `HEAD`; provider-status endpoints fetch bodies\n- server-facing liveness uses a heartbeat every probe loop; payouts and live map\n  status do not depend only on incident publishes\n- provider-reported incidents are emitted separately from direct connectivity\n  incidents so official status pages do not masquerade as broken internet paths\n- the full event payload is only assembled when a publish is required\n- env/state files are strict tab-separated key/value files, not sourced as shell\n  code\n- startup and publish traffic must use `https://` unless explicitly pointed at a\n  localhost-style development URL\n\n## Recommended container flags\n\nUse these limits in production:\n\n- `--read-only`\n- `--tmpfs /tmp:rw,noexec,nosuid,size=8m`\n- `--cap-drop ALL`\n- `--cap-add NET_RAW`\n- `--pids-limit 32`\n- `--memory 16m`\n- `--cpus 0.10`\n\n`no-new-privileges` is intentionally not part of the default contract yet,\nbecause it failed on the tested Docker/runtime stack while launching even\n`/bin/sh`.\n\n## Verification\n\nGenerate a machine-readable verification report:\n\n```sh\n./verify.sh\n```\n\nThat report includes:\n\n- pinned base image digest\n- source file hashes\n- image file hashes\n- whether source and built image match\n- published `stable`, `edge`, and version-tag manifest platforms\n- installed packages from the Dockerfile\n- default probe set\n- required runtime restrictions\n\n## Test harness\n\nHermetic smoke test:\n\n```sh\n./smoke-test.sh\n```\n\nHermetic soak test under the hardened container profile:\n\n```sh\nSOAK_DURATION_SECONDS=600 ./soak-test.sh\n```\n\nTo target a real PushMe deployment instead of the local mock control plane:\n\n```sh\nPUSHME_BOT_URL=https://pushme.site PUSHME_REPO_ROOT=/home/PushMe ./smoke-test.sh\n```\n\nBoth tests expect Docker, `curl`, and `jq`.\n\nWhen `PUSHME_BOT_URL` points at a real PushMe deployment and you want automatic\norg cleanup after the test, they also use `DATABASE_URL` from either:\n\n- `DATABASE_URL` already being set\n- `PUSHME_REPO_ROOT/backend/.env`\n\n## Supported configuration\n\n- `PUSHME_API_KEY`\n- `PUSHME_BOT_URL`\n- `NETNODE_ALLOW_HTTP_BASE_URLS`\n- `PUSHME_AUTO_SETUP=1`\n- `PUSHME_SETUP_ORG_NAME`\n- `PUSHME_SETUP_LOCATION`\n- `PUSHME_SETUP_DESCRIPTION`\n- `PUSHME_SETUP_WEBSITE_URL`\n- `NETNODE_LOCATION`\n- `NETNODE_PACKET_COUNT`\n- `NETNODE_INTERVAL_MS`\n- `NETNODE_PUBLISH_MODE`\n- `NETNODE_RELEASE_CHANNEL`\n- `NETNODE_IMAGE_REPOSITORY`\n- `NETNODE_IMAGE`\n- `NETNODE_VERSION`\n- `NETNODE_VERSION_FILE`\n- `NETNODE_STATE_FILE`\n- `NETNODE_ENV_FILE`\n- `NETNODE_SOURCE_URL`\n- `NETNODE_COUNTRY_CODE`\n- `NETNODE_COUNTRY`\n- `NETNODE_REGION`\n- `NETNODE_CITY`\n- `NETNODE_PROVIDER`\n- `NETNODE_PROVIDER_DOMAIN`\n- `NETNODE_ASN`\n- `NETNODE_NETWORK_TYPE`\n\n`NETNODE_ALLOW_HTTP_BASE_URLS` is a comma-separated exact allowlist for additional\nnon-HTTPS control-plane base URLs. It is intended for hermetic local tests; real\ndeployments should keep using `https://` endpoints.\n\n## Current limits\n\n- default profiles are compiled into the script; custom profile JSON is not yet\n  supported\n- targets small Linux hosts and Linux containers, including Apple Silicon Macs\n  running Linux containers, not bare microcontrollers\n- much smaller than the older Node runtime, but not claiming a hard 8 MB peak on\n  every environment\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyodakohl%2Fpushme-netnode","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fyodakohl%2Fpushme-netnode","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyodakohl%2Fpushme-netnode/lists"}