Nuts is a simple (and smart) application to serve desktop-application releases.
It uses GitHub as a backend to store assets, and it can easily be deployed to Heroku as a stateless service. It supports GitHub private repositories (useful to store releases of a closed-source application available on GitHub).
- ✨ Store assets on GitHub releases
- ✨ Proxy releases from private repositories to your users
- ✨ Simple but powerful download urls
/download/latest
/download/latest/:os
/download/:version
/download/:version/:os
/download/channel/:channel
/download/channel/:channel/:os
- ✨ Support pre-release channels (
beta
,alpha
, ...) - ✨ Auto-updates with Squirrel
- For Mac using
/update?version=<x.x.x>&platform=osx
- For Windows using Squirrel.Windows and Nugets packages
- For Mac using
- ✨ Private API
- ✨ Use it as a middleware: add custom analytics, authentication
- ✨ Serve the perfect type of assets:
.zip
for Squirrel.Mac,.nupkg
for Squirrel.Windows,.dmg
for Mac users, ... - ✨ Up-to-date releases (GitHub webhooks)
Install dependencies using:
$ npm install
This service requires to be configured using environment variables:
# Set the port for the service
$ export PORT=6000
# Access token for the GitHub API (requires permissions to access the repository)
# you can also use GITHUB_USERNAME and GITHUB_PASSWORD
$ export GITHUB_TOKEN=...
# ID for the GitHub repository
$ export GITHUB_REPO=Username/MyApp
# Authentication for the private API
$ export API_USERNAME=hello
$ export API_PASSWORD=world
Then start the application using:
$ npm start
Nuts uses some filename/extension conventions to serve the correct asset to a specific request:
Platform will be detected from the filename:
- Windows: filename should contain
win
- Mac/OS X: filename should contain
mac
orosx
- Linux: filename should contain
linux
By default releases are tagged as 32-bits (except for OSX), but 64-bits will also be detected from filenames.
Filetype and usage will be detected from the extension:
.dmg
will be served in priority to Mac users.nupkg
will only be served to Squirrel.Windows requests- Otherwise,
.zip
are advised (Linux, Mac, Windows and Squirrel.Mac)
Nuts provides urls to access releases assets. These assets are cached on the disk.
- Latest version for detected platform:
http://download.myapp.com/download/latest
orhttp://download.myapp.com/download
- Latest version for specific platform:
http://download.myapp.com/download/latest/osx
or ``http://download.myapp.com/download/osx` - Specific version for detected platform:
http://download.myapp.com/download/1.1.0
- Specific version for specific platform:
http://download.myapp.com/download/1.2.0/osx
- Specific channel:
http://download.myapp.com/download/channel/beta
- Specific channel for specific platform:
http://download.myapp.com/download/channel/beta/osx
Platforms can be detected from user-agent and are normalized to values: osx
, osx_32
, osx_64
, linux
, linux_32
, linux_64
, windows
, windows_32
, windows_64
.
Non-prefixed platform will be resolve to 32 bits (except for OSX).
This server provides an endpoint for Squirrel auto-updater: http://download.myapp.com/update/osx/:currentVersion
.
This url requires different parameters to return a correct version: version
and platform
.
For example with Electron's auto-updater
module:
var app = require('app');
var os = require('os');
var autoUpdater = require('auto-updater');
var platform = os.platform() + '_' + os.arch();
var version = app.getVersion();
autoUpdater.setFeedUrl('http://download.myapp.com/update/'+platform+'/'+version);
Nuts will serve NuGet packages on http://download.myapp.com/update/win32/:version/RELEASES
.
Your application just need to configurer Update.exe
or Squirrel.Windows
to use http://download.myapp.com/update/win32/:version
as a feed url (:warning: without query parameters).
You'' just need to upload as release assets: RELEASES
, *-delta.nupkg
and -full.nupkg
(files generated by Squirrel.Windows
releaser).
A private API is available to access more infos about releases and stats. This API can be protected by HTTP basic auth (username/password) using configuration API_USERNAME
and API_PASSWORD
.
List versions:
GET http://download.myapp.com/api/versions
Get details about specific version:
GET http://download.myapp.com/api/version/1.1.0
Resolve a version:
GET http://download.myapp.com/api/resolve?platform=osx&channel=alpha
List channels:
GET http://download.myapp.com/api/channels
Get stats about downloads:
GET http://download.myapp.com/api/stats
Add http://download.myapp.com/refresh
as a GitHub webhook to refresh versions cache everytime you update a release on GitHub.
The secret can be configured using GITHUB_SECRET
(default value is secret
).
Nuts can be integrated into a Node.JS application as a middleware. Using the middleware, you can add custom authentication on downloads or analytics for downloads counts.
var express = require('express');
var Nuts = require('nuts-serve');
var app = express();
var nuts = Nuts(
// GitHub configuration
repository: "Me/MyRepo",
token: "my_api_token",
// Timeout for releases cache (seconds)
timeout: 60*60,
// Folder to cache assets (by default: a temporary folder)
cache: './assets',
// Pre-fetch list of releases at startup
preFetch: true,
// Secret for refresh webhook
refreshSecret: 'my-secret',
// Middlewares
onDownload: function(version, req, res, next) {
console.log('download', download.version.tag, "on channel", download.version.channel, "for", download.platform.type);
next();
},
onAPIAccess: function(req, res, next) {
next();
}
);
app.use('/myapp', nuts);
app.listen(4000);