This package contains the desktop application build configuration and distribution server.
All builds are published to Docker registry and can be served via the haiodo/desktop-distro container.
To check the latest auto-updatable distributions:
- MacOS:
<your-server>/latest-mac.yml - Linux:
<your-server>/latest-linux.yml - Windows:
<your-server>/latest.yml
The intabiahaiodofusion/desktop-distro Docker image serves all desktop distribution files via HTTP, enabling:
- Desktop app downloads for all platforms (macOS, Windows, Linux)
- Auto-update functionality for Electron apps via
electron-updater
docker run -d -p 8080:8080 haiodo/desktop-distro:latest| Variable | Default | Description |
|---|---|---|
PORT |
8080 |
HTTP server port |
DIST_DIR |
/app/dist |
Directory containing distribution files |
| Endpoint | Description |
|---|---|
GET /health |
Health check endpoint |
GET /api/files |
List all available distribution files with metadata |
GET /api/downloads |
Aggregated download manifests (parsed from latest-.yml / latest-.yaml). Supports ?refresh=1 to reload manifests on demand. |
Usage example
- Basic request:
curl -s http://localhost:8080/api/downloads | jq .- Force reload manifests:
curl -s 'http://localhost:8080/api/downloads?refresh=1' | jq .Example response
{
"platforms": [
{
"platform": "linux",
"name": "Linux",
"variants": [
{
"manifest": "latest-linux.yml",
"variant": "x64",
"version": "0.7.0",
"releaseDate": "2026-01-18T16:06:02.401Z",
"artifacts": [
{
"filename": "Platform-linux-0.7.0-x86_64.AppImage",
"url": "/Platform-linux-0.7.0-x86_64.AppImage",
"size": 218565199,
"sha512": "...",
"arch": "x64",
"archLabel": "Linux - x64"
}
]
},
{
"manifest": "latest-linux-arm64.yml",
"variant": "arm64",
"version": "0.7.0",
"artifacts": [
{
"filename": "Platform-linux-0.7.0-arm64.AppImage",
"url": "/Platform-linux-0.7.0-arm64.AppImage",
"size": 219259279,
"sha512": "...",
"arch": "arm64",
"archLabel": "Linux - ARM64"
}
]
}
]
},
{
"platform": "mac",
"name": "macOS",
"variants": [
{
"manifest": "latest-mac.yml",
"version": "0.7.0",
"artifacts": [
{
"filename": "Platform-macos-0.7.0-x64.zip",
"url": "/Platform-macos-0.7.0-x64.zip",
"size": 212924743,
"sha512": "...",
"arch": "x64",
"archLabel": "macOS - Intel"
},
{
"filename": "Platform-macos-0.7.0-arm64.zip",
"url": "/Platform-macos-0.7.0-arm64.zip",
"size": 208249487,
"sha512": "...",
"arch": "arm64",
"archLabel": "macOS - Apple Silicon"
}
]
}
]
}
],
"lastUpdated": "2026-01-18T16:16:18.093Z"
}Notes
-
artifacts[].urlis a relative path usable directly in the UI to construct download links (e.g.https://your-server.com${artifact.url}). -
artifacts[].arch— machine-readable architecture identifier:arm64,x64,x86, etc. -
artifacts[].archLabel— human-friendly platform + architecture description, e.g.macOS - Apple Silicon,macOS - Intel,Windows - x64,Linux - ARM64. -
lastUpdatedshows when the manifests were last scanned by the server. -
ETagandLast-Modifiedheaders are provided onGET /api/downloadsresponses to enable HTTP caching:ETag— a SHA-1 tag representing the current payload. Clients may sendIf-None-Matchwith this ETag to receive304 Not Modifiedwhen there are no changes.Last-Modified— timestamp of the last scan (HTTP-date). Clients may sendIf-Modified-Since; if the content is not newer, server returns304 Not Modified.
-
On a conditional request where the resource hasn't changed, the server responds
304 Not Modifiedwith an empty body. You can also useHEADto fetch headers only. -
You can force re-parse of manifests via
?refresh=1; after refresh theETagandLast-Modifiedvalues are updated accordingly. -
Defaults for generic manifests:
latest.yml(Windows) — interpreted asx64by default if no explicit variant is present.latest-linux.yml— interpreted asx64by default if no explicit variant (e.g.latest-linux-arm64.yml) is present. |GET /<filename>| Download specific distribution file | |GET /latest.yml| Windows update manifest | |GET /latest-mac.yml| macOS update manifest | |GET /latest-linux.yml| Linux update manifest |
The container includes the following files for each release:
Platform-macos-<version>-x64.dmg- macOS Intel buildPlatform-macos-<version>-arm64.dmg- macOS Apple Silicon buildPlatform-windows-<version>.zip- Windows portable buildPlatform-windows-<version>.exe- Windows installer (NSIS)Platform-linux-<version>.zip- Linux portable buildPlatform-linux-<version>.AppImage- Linux AppImagePlatform-linux-<version>.deb- Debian package*.blockmap- Delta update files for efficient updateslatest*.yml- Update manifest files for electron-updater
To configure the Platform desktop app to use your custom update server, set the update URL before building:
In package.json build configuration:
{
"build": {
"mac": {
"publish": {
"provider": "generic",
"url": "https://your-server.com"
}
},
"win": {
"publish": {
"provider": "generic",
"url": "https://your-server.com"
}
},
"linux": {
"publish": {
"provider": "generic",
"url": "https://your-server.com"
}
}
}
}version: '3.8'
services:
desktop-distro:
image: haiodo/desktop-distro:latest
ports:
- "8080:8080"
restart: unless-stopped
labels:
- "traefik.enable=true"
- "traefik.http.routers.desktop.rule=Host(`dist.example.com`)"
- "traefik.http.services.desktop.loadbalancer.server.port=8080"# Install dependencies
rush install
# Build the distribution server
cd desktop-package
rushx bundle:server
# Build desktop app
rushx package
rushx dist --linux --windows --macos
# Build Docker image locally
docker build -t desktop-distro .The GitHub Actions workflow automatically:
- Builds desktop apps for all platforms in the
dist-buildjob - Creates and pushes the
haiodo/desktop-distroDocker image in thedesktop-distro-buildjob
This happens automatically when a version tag (v* or s*) is pushed.