{"id":41012932,"url":"https://github.com/trusch/jamesd","last_synced_at":"2026-01-22T09:10:43.039Z","repository":{"id":64307571,"uuid":"73453581","full_name":"trusch/jamesd","owner":"trusch","description":"A universal packetmanager for heterogeneous fleets of machines with server side version control","archived":false,"fork":false,"pushed_at":"2017-02-27T08:59:19.000Z","size":81,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":4,"default_branch":"master","last_synced_at":"2024-06-20T11:55:31.578Z","etag":null,"topics":["architecture","iot","packet-manager"],"latest_commit_sha":null,"homepage":null,"language":"Go","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/trusch.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}},"created_at":"2016-11-11T06:56:10.000Z","updated_at":"2017-03-09T19:57:56.000Z","dependencies_parsed_at":"2023-01-15T11:00:41.357Z","dependency_job_id":null,"html_url":"https://github.com/trusch/jamesd","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/trusch/jamesd","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trusch%2Fjamesd","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trusch%2Fjamesd/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trusch%2Fjamesd/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trusch%2Fjamesd/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/trusch","download_url":"https://codeload.github.com/trusch/jamesd/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trusch%2Fjamesd/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28660048,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-22T01:17:37.254Z","status":"online","status_checked_at":"2026-01-22T02:00:07.137Z","response_time":144,"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":["architecture","iot","packet-manager"],"created_at":"2026-01-22T09:10:42.418Z","updated_at":"2026-01-22T09:10:43.034Z","avatar_url":"https://github.com/trusch.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"JamesD\n======\n\nA universal packetmanager for heterogeneous fleets of machines with server side version control.\n\nJamesD is a centralistic packet management system for heterogenous device fleets.\nYou can use it to manage multiple versions for each packet you maintain, and to automatically distribute updates.\n\n## Problem\nImagine you have to maintain multiple fleets of devices, with many different architectures, operating systems, libc versions and so on. You may have ended fucked up like this because the devices your company is selling have a long support duration, or you're retrofitting many different old devices etc...\n\nHow do you organize and distribute software for all those devices?\n\nYou can not simply use common packet repositories, because they are designed to support one OS with at least support for diffent architectures. So how to deal with diffent OS or same OS and different base library versions? Another problem is that classical packet management solutions assume that the repository holds the packets, and the clients decide which packets they want to install. This is another no-go since our devices are smart-devices whicht are rather stupid when it comes to intelligent decisions like which packets should be installed. There is no operator who could decide this, sometimes there is not even physical access to the devices.\n\n## Solution\nJamesD is here to rescue you! It is completly agnostic about anything in your software packets, so you can supply packets for every possible scenario. The following core features support you:\n\n* upload arbitary packets\n* get packets based on device labels\n* specify which packets should be installed\n* powerfull command line interface to manage specs and packets\n* client side daemon which polls for changes and installs/uninstalls accordingly\n\n## Concept\n### Parts\n\nJamesD consist of three main parts:\n* repository server (`jamesd`)\n  * hosts packets\n  * hosts specs\n  * provides restfull api\n* client-side daemon (`jamesc`)\n  * asks server what should be installed\n  * installs packets\n  * uninstalls deprecated packets\n* commandline tool (`jamesd-ctl`)\n  * manage packets\n  * manage specs\n  * manually install / uninstall packets\n\nSo the repository server hosts your packets and specification about what should be installed on which machines and the client-daemon acts according to the specs.\nTo create or upload packets and specs you can use the commandline tool, or speak directly to the HTTP api.\n\n### Labels\nThe matching which packets should be installed is done via labels. A `label` is a simple pair of two strings like (version, 1.0.0), (arch, armv7l) or (fleet, temp-sensors). You can specify labels as you like, as long as it makes sense for your usecase.\n\nLabels are used to identify packets and devices.\n\nTo identify a single packet, you would need the `name` of the packet and a `labelset`.\nA `labelset` is a collection of zero or more labels, where the key part of the has to be unique (so an invalid `labelset` would be { (arch, amd64), (arch, armhf) } ).\nThere can't be two packets with the same `name` and the same `labelset`.\n\nIf a device asks for packets, it tells its device `labelset`. This typically contains two types of labels:\n* labels to identify the devices usecase\n* labels about the devices requierements (architecture, libc version etc.)\n\n### Specs\nA spec is simply a definition of what packets should be installed on which devices.\nTherefore a spec definition looks quiet simple:\n```yaml\nid: logger-spec\ntarget:\n  fleet: alpha\napps:\n  - name: logger\n    labels:\n      version: 1.0.0\n```\nIt contains:\n  * an ID to identify the spec\n  * a target `labelset` which says \"this spec should be applied to all devices with (fleet, alpha) in its labelset\"\n  * a list of apps to be installed\n    * this is not a specific packet!\n    * it says: \"give each device the best matching logger packet which contains (version, 1.0.0) in its labelset\"\n\n### Packet Matching\nAssume we have the following server config in our repository:\n```yaml\npackets:\n- name: logger\n  labels:\n    version: 1.0.0\n    arch: amd64\n\n- name: logger\n  labels:\n    version: 1.0.0\n    arch: armv6l\n\n- name: logger\n  labels:\n    version: 1.0.0\n    arch: armv7l\n\nspecs:\n- id: logger-spec\n  target:\n    fleet: alpha\n  apps:\n    - name: logger\n      labels:\n        version: 1.0.0\n\n```\n\nIf a client asks for packets, he sends its device `labelset`, for example:\n```yaml\nfleet: alpha\narch: armv7l\n```\n\nAt first the server searches for matching specs, and will find the logger spec. This spec tells him, that the logger packet should be installed in version 1.0.0.\n\nTo find the best packet, the server now merges the device labels with the logger labels from the spec, resulting in this new `labelset`:\n```yaml\nversion: 1.0.0\nfleet: alpha\narch: armv7l\n```\nNow the database is queried for a packet whichs `labelset` is a subset of this merged `labelset`. As a result the correct logger packet (with armv7l and 1.0.0) will be returned and the ID of it will be reported to the client.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftrusch%2Fjamesd","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftrusch%2Fjamesd","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftrusch%2Fjamesd/lists"}