Skip to main content

Updates

GEM includes an over-the-air update system that distributes new versions from a central update server to registered installations. The update server also hosts the public installer and distributable artifacts (command sets, web services, database artifacts).

Overview

The update architecture has three components:

  1. Update Server (gem_updater) -- Central server at updates.mygem.us that stores and distributes updates, installers, and artifacts
  2. GEM Installations -- Production systems that check for and download updates
  3. Publish Scripts -- Developer tools that build and push new versions to the update server

How Updates Work

Update Flow

  1. A GEM installation sends its installation_id to the update server (POST /check_update)
  2. The server verifies the installation is registered and enabled
  3. If a newer version exists, it returns the version, checksum, and encryption key
  4. The installation downloads the encrypted archive (POST /pull_update)
  5. The archive is decrypted and extracted to update the application files

Security

  • Each installation has a unique installation_id (32-character MD5 hash)
  • Updates are encrypted with AES -- each version has a unique encryption key
  • Only enabled installations can download updates
  • The update server authenticates publish requests with an update_key

Installation Registration

Auto-Discovery

When a new GEM installation checks for updates for the first time:

  1. The update server creates a disabled entry for that installation_id
  2. The check returns 401 Unauthorized (no update is served)
  3. An administrator must enable the installation in the update server admin panel

Managing Installations

Access the update server admin panel at https://updates.mygem.us/admin.

For each installation you can:

  • Enable/Disable -- Control whether the installation receives updates
  • Name -- Assign a friendly name for identification
  • View creation and last-updated timestamps

Duplicate installations (same installation_id) are automatically cleaned up on server startup.

Update Server

The update server (gem_updater) is a standalone Express.js application running on port 3131.

Architecture

ComponentPurpose
app.jsExpress server, routes, middleware
lib/updates.jsUpdate/installer upload handling, distribution routes
lib/admin.jsAdmin panel authentication and management routes
lib/artifacts.jsArtifact storage, listing, search, and distribution
lib/data.jsJSON file database with in-memory indexes and LRU cache
data/database.jsonPersistent storage (installations, updates, artifacts, admin config)

Data Storage

The update server uses a JSON file database (data/database.json) rather than PostgreSQL. It features:

  • In-memory indexes for O(1) lookups by ID, version, and installation_id
  • LRU cache for frequently accessed installations
  • Debounced writes to minimize disk I/O
  • File watcher that reloads data on external changes
  • Automatic deduplication of installation records on startup

Admin Panel

Password-protected web interface at /admin:

  • Installations -- View, enable/disable, and name registered installations
  • Updates -- View and delete published update versions
  • Artifacts -- View uploaded artifacts (command sets, web services, database artifacts)
  • Password -- Change the admin password

The admin password is auto-generated on first run and printed to the console. Sessions expire after 24 hours.

API Endpoints

Public:

MethodPathDescription
GET/install.shDynamic install script (downloads latest installer)
GET/installers/:versionDownload installer by version
GET/artifacts/typesList available artifact types

Authenticated (installation_id required):

MethodPathDescription
POST/check_updateCheck if a new version is available
POST/pull_updateDownload an update archive
POST/:type/listList artifacts of a given type
POST/:type/download/:filenameDownload a specific artifact
POST/:type/searchSearch artifacts by tags or text query

Authenticated (update_key required):

MethodPathDescription
POST/push_updateUpload a new update (.tar.gz.enc, max 500 MB)
POST/push_installerUpload a new installer (.run, max 500 MB)

Artifacts

The update server distributes three types of artifacts to GEM installations:

TypeDirectoryDescription
command_setdata/command_sets/Device command set JSON files
web_servicedata/web_services/Web service integration JSON files
database_artifactdata/database_artifacts/Database seed/migration JSON files

Artifacts are JSON files with metadata stored in the database (name, description, version, tags, user, rating). Files on disk are auto-discovered and registered on server startup.

Artifact Management

Upload (admin panel):

  • Upload .json files with type, metadata, and optional overwrite flag
  • Maximum 10 MB per file

Search (API):

  • Filter by tags (OR matching)
  • Text search across name, description, and filename
  • Results include file size and modification date

Publishing Updates

Prerequisites

Your gem.json must contain:

{
"update_url": "https://updates.mygem.us",
"update_key": "your-secret-key"
}

The update_key must match the key stored in the update server's data/database.json.

Publish an Update

node scripts/publish-update.js

This:

  1. Runs npm run build (version bump + full build)
  2. Creates an encrypted .tar.gz.enc archive of dist/
  3. Uploads to /push_update with the encryption key in headers
  4. The server stores the archive and records the version, checksum, and encryption key

Publish an Installer

node scripts/publish-installer.js

This:

  1. Runs npm run build:installer (creates .run file via makeself)
  2. Uploads to /push_installer with the version in headers
  3. The server stores the installer and records the version and checksum

The public install.sh endpoint automatically serves the latest installer version.

Configuration

GEM Installation Settings

In gem.json:

KeyDescription
update_urlURL of the update server (e.g., https://updates.mygem.us)
update_keySecret key for publishing updates

Update Server Settings

In data/database.json:

KeyDescription
update_keySecret key that must match publish requests
admin.passwordAdmin panel password (auto-generated on first run)
installations[]Registered GEM installations
updates[]Published update versions with checksums and encryption keys
installers[]Published installer versions with checksums
artifacts[]Artifact metadata records

Troubleshooting

Installation Not Receiving Updates

  1. Verify the installation_id is registered on the update server
  2. Check that the installation is enabled in the admin panel
  3. Confirm update_url in gem.json is correct
  4. Test network connectivity to the update server

Publish Fails

ErrorSolution
Missing update_url or update_keyAdd both to gem.json
401 Unauthorizedupdate_key doesn't match the server's stored key
Upload timeoutLarge file or slow connection -- timeout is 5-10 minutes
dist/ not foundRun npm run build before publishing

Admin Panel Access

If you've lost the admin password:

  1. Check the server console output (password is printed on startup)
  2. Or read data/database.json directly: admin.password