{"id":19719977,"url":"https://github.com/timboudreau/meta-update-center","last_synced_at":"2026-04-01T17:02:11.936Z","repository":{"id":9501364,"uuid":"11394582","full_name":"timboudreau/meta-update-center","owner":"timboudreau","description":"An update server for NetBeans Plugins which serves remotely built NBM files","archived":false,"fork":false,"pushed_at":"2022-10-27T04:44:54.000Z","size":296,"stargazers_count":10,"open_issues_count":0,"forks_count":3,"subscribers_count":3,"default_branch":"master","last_synced_at":"2026-03-27T23:42:20.951Z","etag":null,"topics":["nbm","netbeans","plugin","server"],"latest_commit_sha":null,"homepage":null,"language":"Java","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/timboudreau.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":"2013-07-13T21:40:53.000Z","updated_at":"2022-11-04T12:31:19.000Z","dependencies_parsed_at":"2023-01-11T20:12:30.619Z","dependency_job_id":null,"html_url":"https://github.com/timboudreau/meta-update-center","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/timboudreau/meta-update-center","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/timboudreau%2Fmeta-update-center","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/timboudreau%2Fmeta-update-center/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/timboudreau%2Fmeta-update-center/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/timboudreau%2Fmeta-update-center/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/timboudreau","download_url":"https://codeload.github.com/timboudreau/meta-update-center/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/timboudreau%2Fmeta-update-center/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31290538,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-01T13:12:26.723Z","status":"ssl_error","status_checked_at":"2026-04-01T13:12:25.102Z","response_time":53,"last_error":"SSL_read: 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":["nbm","netbeans","plugin","server"],"created_at":"2024-11-11T23:09:51.113Z","updated_at":"2026-04-01T17:02:11.889Z","avatar_url":"https://github.com/timboudreau.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"NetBeans Meta Update Server\n===========================\n\nA simple standalone update server for [NetBeans](http://netbeans.org) and \n[NetBeans Platform application](http://platform.netbeans.org) plugins.  \n\nJust run it using ``java -jar``. It will serve whatever plugins you tell it about, and\nautomatically check for updates.  Download it [from timboudreau.com](http://timboudreau.com/builds/job/meta-update-server/).\n\nYour users can simply get updates using Tools | Plugins, with no additional\nsteps.\n\nThe server will generate and serve a plugin which registers it with Tools | Plugins\nin NetBeans.  That's generated for you on startup and is always-up-to-date.\n\n\nFeatures\n--------\n\n * You give it URLs where your plugin (NBM) files live on the web.  \n * It downloads them and serves them.  \n * It processes metadata in the downloaded NBM files and uses that to figure out the rest.\n * It periodically checks for new versions and updates what it is serving automatically.\n * Automatically generates and serves a NetBeans plugin which registers your server as an update server - your users install that, and from then on the IDE/application will automatically check your server for updates\n * Logs hit and download statistics using in easily analyzed [bunyan-compatible JSON](https://github.com/trentm/node-bunyan) using [bunyan-java](https://github.com/timboudreau/bunyan-java-v2)\n\nUsage fairly self-explanatory - start it and navigate to it in a browser.  Try the [demo server](http://timboudreau.com/modules) to see what it does.\n\nIt serves NBM (NetBeans module) files with appropriate metadata so that the\nNetBeans update center (Tools | Plugins) can download plugins from it.  It \ngive you a way to distribute updates, where simply publishing a new version\nat the same URL will make the new version automatically available to your users.\n\n\nUse Case\n--------\n\nThis was written to scratch an itch.  I have a [Jenkins](http://timboudreau.com/builds) \ncontinuous integration server which builds modules.  I want to publish them to users\nso it is easy for them to get updates.  And I want no manual steps for me to provide them.\n\nI briefly considered writing a Jenkins extension like its Maven Repository plugin,\nwhich would serve this stuff. Then I thought, why be tied to Jenkins at all?  This solution\nwill serve whatever you want, wherever it is.\n\nIf you use this with Jenkins, one small change is useful to your Maven `pom.xml` - this\nserver relies on the download URLs for modules not changing, but by default Maven includes\nthe version in the NBM name.  To fix this, add `\u003cfinalName\u003eYourModuleName\u003c/finalName\u003e` to\nthe `configuration` section for **both** the `nbm-maven-plugin` and the `maven-jar-plugin`.\n\nUsage\n-----\n\nPlugins are added to the server by adding remote URLs to NBM files via a web form on the home page the server serves.  The\nprimary use-case is wanting to distribute some modules built by a continuous\nbuild.\n\nOnce a plugin is added, its URL is polled once per-hour to check for updates\n(this will use the ``If-Modified-Since`` HTTP header to avoid excessive\ndownloading).  If an update is found, it is downloaded;  if its specification\nverion is greater than an existing copy on the server, the old one is replaced.\n\nThe primary use-case is continuous builds - in fact, it came out of a discussion\nof writing a Jenkins/Hudson plugin for this purpose.  This project accomplishes\nthe same thing in a simpler way.  So, this is an update server which serves ``nbm``\nfiles which are available elsewhere via HTTP.  It has a small HTTP web api which\nlets you add new NBMs.\n\nThe server uses [Acteur](http://github.com/timboudreau/acteur), an asynchronous\nserver framework based on [Netty](http://netty.io).  HTTP downloads from\nremote servers are also asynchronous - meaning that this tiny web application can serve **a lot** of traffic while consuming minimal system resources.\n\n\nRunning The Server\n------------------\n\nBuild it or download a binary.  Run it with ``java -jar``\n\nIf no directory path is passed to it, it will store and serve data from\n``/tmp/nbmserver``\n\nIn a web browser, navigate to ``/`` to see a web page containing a list of\nall modules served and an upload form. Uploading requires HTTP basic\nauthentication - for the password, either pass ``--password``\non the command line, or make a note of the generated password logged on\nstartup.\n\n\nWeb API / Adding NBMs\n---------------------\n\nThe server has an extremely simple web API:\n\n * An HTTP GET to ``/modules`` lists the modules being served in XML, using the\nNetBeans autoupdate DTD\n   * Add ``?json=true`` to get this data in JSON format instead, if you want\nto get this data in a usable form for client-side Javascript\n * An HTTP GET/PUT/POST to ``/add`` with the parameter ``url`` set to the\nremote URL of an NBM file\n   * This call requires HTTP Basic authentication\n * An HTTP GET to ``/download/$CODE_NAME/$HASH.nbm`` will download the cached\ncopy of an NBM file\n\nThere is one caveat:  If the URL to an NBM incorporates the version number of that\nNBM, and an update will have a different version number, then you will need to manually\nadd the new URL every time you publish an update.  For automatic updates, \nchange your build script not to do that.  HTTP does not do wild-cards, so \nthere really is no other fix.\n\n\nConfiguring The Server\n----------------------\n\nAll of the following properties can be set via the command-line by prefixing the \nproperty name with ``--`` - for example\n\n    java -jar nbmserver-standalone.jar --port 3572 --external.port 80 --password hoohah\n\nThe system will also look for, and load if present, the following files:\n\n * /etc/nbmserver.properties\n * ~/nbmserver.properties\n * ./nbmserver.properties\n\nany duplicates in the previous one being overridden in the next;  command-line\narguments override them all.\n\nThe following are useful properties\n\n * ``nbm.dir`` - the path to the folder to store NBM files in.  Will be created if non-existent.  If not set,\nuses ``/tmp/nbmserver`` or OS-specific equivalent.\n * ``port`` - the port to run on\n * ``external.port`` - if you are running it behind a reverse proxy such \nas [NginX](http://nginx.org), this sets what port URLs to files this server is \nserving should have - the module catalogue it serves includes download URLs, \nwhich must be canonicalized.\n * ``password`` - the password used to authenticate the administrator (needed to\nadd URLs to the system).  If not set, a random one is generated on startup and logged.\n * ``hostname`` - the host name to use in external URLs in the module catalog\n * ``basepath`` - path to prepend to all URLs served and in the module catalog\n * ``workerThreads``, ``backgroundThreads`` - control the size of thread pools used for servicing events and background tasks\n    * See note below\n * ``download.threads`` - how many concurrent downloads from remote update/build servers should be attempted simultaneously\n    * See note below\n * ``poll.interval.minutes`` - the interval in minutes between checks of remote servers for newer \nversions of the NBMs served.  The default is hourly.\n * ``admin.user.name`` - sets the user name expected for basic authentication for adding modules.  The default is ``admin``.\n * ``log.file`` - the file to log stats and other information to - default is `nbmserver.log` in the process' working directory\n * ``log.level`` - defaults to `info` - see [bunyan-java](https://github.com/timboudreau/bunyan-java) for details\n\nSee the documentation for [Acteur](http://github.com/timboudreau/acteur) for \nadditional settings.  The properties are loaded using [Giulius](http://github.com/timboudreau/giulius)\nand follow its rules for what overrides what.\n\n_Note:_ Since Netty and Acteur are asynchronous, threads are used much more efficiently - a single\nthread can simultaneously service hundreds or thousands of connections.\n\nIf you use files instead of command-line arguments, the server periodically checks and reloads these.  To guarantee changes are picked up, restart the server (it starts very fast!).\n\n\nThe Generated Update Center Module\n----------------------------------\n\nOn startup, the server generates a NetBeans module on-the-fly which can be \ninstalled and will register your server as an update server.  Once a user has\ndone that, NetBeans will automatically check back with your server for updates.\n\nSome care is taken to ensure the generated module is not updated unless something has\nchanged, but is if something has:\n\n * The implementation version is a SHA-1 hash of the sorted keys and values used to generate it\n * The package name and module code name are derived from the server's update catalogue URL, so multiple servers can be hosted on one domain but will generate unique modules\n * The module's specification version incorporates\n   * The version of the server\n   * A munged timestamp from the first time the server was run\n   * A number which is incremented every time the generated bits differ from the preceding run\n\nThis does mean you should take some care choosing your host name and base path, as the module will not know if you change them later (a new one will be generated, but the old one will be broken).\n\nThe following settings can be set as described above, and affect only the module:\n\n * ``update.url.https`` - use https for the update URL\n * ``serverDisplayName`` - what the server is called in descriptions (e.g. \"Joe Blow's modules\")\n * ``module.author`` - the name to show for the module author;  uses ``System.getProperty(\"user.name\")`` if unset\n\n\nBuild and Run\n-------------\n\nBuild with Maven and run the JAR.  Builds can be downloaded [here](http://timboudreau.com/builds).\n_Requires JDK 7 or greater._\n\nThe build creates a merged JAR file which contains all of the project's dependencies, called ``nbmserver-standalone.jar`` which is suitable for deployment and can be run with ``java -jar``.\n\n\nSecurity \u0026 Reverse Proxy Setup\n------------------------------\n\nCalls which modify server state use HTTP Basic Authentication and require the\nadministrator user name and password (see configuration below).\n\nBasic authentication is not secure unless you use HTTPs.  The standard way to\ndo that is to run the server behind a reverse proxy such as \n[NginX](http://nginx.org).\n\nThe following is an example NginX configuration which reverse-proxies the application\nand redirects secured requests to HTTPS:\n\n\tlocation\t /modules {\n\t\tproxy_set_header\tX-Real-IP\t$remote_addr;\n\t\tproxy_set_header\tX-Forwarded-For $proxy_add_x_forwarded_for;\n\t\tproxy_set_header\tX-Forwarded-Host $host;\n\t\tproxy_set_header\tHost $http_host;\n\t\tproxy_pass\thttp://localhost:8959;\n\t\tproxy_redirect\toff;\n\t}\n        location        /modules/add {\n                if ($scheme = http) {\n                        rewrite  ^/(.*)$  https://my.host.name/$1  permanent;\n                }\n                proxy_set_header        X-Real-IP       $remote_addr;\n                proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;\n                proxy_set_header        X-Forwarded-Host $host;\n                proxy_set_header        Host $http_host;\n                proxy_buffering         off;\n                proxy_pass      http://localhost:8959;\n                proxy_redirect  off;\n        }\n\nReplace ``my.host.name`` with the actual host name of the server.  To use this\nconfiguration, you would want to start the server with ``--hostname my.host.name``\nso that generated URLs will be correct.\n\nHere is an example set of arguments for a [Debian](http://debian.org) launch\nscript (start from ``/etc/init.d/skeleton``):\n\n```\nDAEMON_ARGS=\"-jar \n    /home/tim/nbmserver-standalone.jar --password somepassword --basepath modules \n    --nbm.dir /var/nbmserver --port 8959 \n    --hostname my.host.name --external.port 80 --external.secure.port=443\"\n```\n\nThe salient details of what this does:\n \n * Save and load NBM files using the folder ``/var/nbmserver``\n * Use port 8859\n * Use the hostname ``my.host.name`` in generated URLs in its module catalog\n * Set the ports used in generated URLs (we are behind a reverse proxy, so\nwe don't want to ask normal users to connet over port 8859)\n\n\n### Forcing Updates\n\nThe URL path `/tickle?token=...` can be used to stop the refresh interval timer,\nforce an immediate update attempt on all modules being served, and then restart\nthe timer.  The passed token can either be set on the command-line or in Settings\nusing the key `tickleToken`, or by default it is set to a random string which is\nlogged to system out (not the log file, which can be read online) on startup.\n\n\nInternals\n---------\n\nThe server stores files in the folder specified by the property/argument ``nbm.dir``.  This is\nlaid out as follows:\n\n * nbm.dir\n   * first.module.code.name.base\n      * nbm-sha1-hash.json - JSON representation of the information in the module's ``Info/info.xml`` file, plus the original URL, download time, etc.\n      * nbm-sha1-hash.nbm - the actual nbm file\n   * second.module.code.name.base\n      * ...\n\nSo, each module is stored in a directory with the module's code name as its name.\nA version of a module is represented by a JSON file and an NBM file.  The name portion\nof each file is the SHA-1 hash of the nbm file's bits.\n\nThe version of the module served is the one with the highest specification version in\nits manifest.  If there is more than one build of the same version, the most recently\ndownloaded is used.\n\n``Caveat:`` The above algorithm does mean that if you add url-to-nbm A pointing to\ncom.foo.mymodule 1.2 and later you add url-to-nbm B pointing to com.foo.mymodule 1.0,\nthe version served will be 1.2.\n\nThe server honors the ``If-Modified-Since`` and ``If-None-Match`` headers to reduce\nserver load.\n\n\nStats\n-----\n\nThe server logs simple stats as lines of JSON to ``stats.log`` in the folder NBMs are\nserved from.  The activity can be identified by the combination of property names.\n\n * ``{\"ref\"=\"-\", \"addr\"=\"/0:0:0:0:0:0:0:1:51328\", \"time\"=\"Sun, 14 Jul 2013 06:46:31 GMT\"}`` - an index page hit with referrer\n * ``{\"id\"=\"abcd\", \"addr\"=\"/0:0:0:0:0:0:0:1:51328\", \"time\"=\"Sun, 14 Jul 2013 06:46:39 GMT\"}`` - a\nrequest for the NBM catalog, possibly with an installation ID identifying a unique user\n * ``{\"pth\"=\"com.foo.bar/sha1-hash.nbm\", \"addr\"=\"/0:0:0:0:0:0:0:1:51288\", \"time\"=\"Sun, 14 Jul 2013 06:37:29 GMT\"}`` - a download of an NBM\n\nServer start and shutdown events are also logged.\n\n\nTo-Dos\n------\n\n * Repack jars using pack200\n * Automatically sign JARs if a certificate is provided\n * More admin UI for configuring some of the settings described above\n * Auto-generate version numbers and repack (and possibly re-sign) NBM bits \n[as described here](http://wiki.netbeans.org/AggregatingUC#Version-aware_push) so that even if the remote bits version didn't change, if the bits did, it increments\n\nMetrics\n-------\n\nLogging is done in a format compatible with [bunyan](https://github.com/trentm/node-bunyan). Bunyan is quite\nuseful for monitoring and filtering logs in real time.\n\nA couple of scripts\nare included in the project root directory for analyzing logs to determine the geographic distribution of users.\nThey require NodeJS, bunyan and geoiplookup to be available on the path.  For a simple geographic distribution,\ntweak the uniqueAddresses script to point to your `nbmserver.log` is and run `./uniqueAddresses | ./listaddrs`.\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftimboudreau%2Fmeta-update-center","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftimboudreau%2Fmeta-update-center","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftimboudreau%2Fmeta-update-center/lists"}