Installation
GEM can be installed on any Debian-based Linux system (Ubuntu, Debian, etc.) using either the remote installer or a local development setup. This includes Windows systems running WSL (Windows Subsystem for Linux). The installer handles system dependencies, database configuration, notifications, and service creation through a web-based installer.
System Requirements
- OS: Ubuntu 20.04+ or compatible Debian-based Linux distribution (including WSL on Windows)
- RAM: 2 GB minimum
- Disk: 10 GB free space
- Network: Internet connectivity (for package installation)
- Privileges: Root / sudo access
Quick Install
Install GEM with a single command:
curl -fsSL https://updates.mygem.us/install.sh | sudo sh
This downloads the latest self-extracting installer (.run file), verifies its checksum, and runs it. The installer:
- Prompts for an installation directory (default:
~/Apps/GEM) - Installs system dependencies (build tools, PostgreSQL, Node.js 22, FFmpeg, etc.)
- Installs npm packages
- Launches the installer in a browser
Installation Methods
Remote Installer (Production)
The recommended method for production deployments. The install.sh script served by the update server:
- Downloads the latest versioned
.runinstaller - Verifies the MD5 checksum
- Makes the installer executable and runs it
The .run file is a self-extracting archive (built with makeself) containing the pre-built GEM application and a setup.sh script.
Local Install (Development)
For development environments where you have the source code:
sudo ./bin/install.sh
This script:
- Installs system dependencies via
apt-get - Installs or upgrades Node.js to v22
- Runs
npm install - Launches the installer (
bin/install.js)
Installation progress is logged to logs/install.log.
Installer
After dependencies are installed, the installer launches as a local web server and opens in your browser. It walks through six steps:
Step 1: Welcome & Preflight
Displays system requirements and runs automatic preflight checks:
| Check | Requirement |
|---|---|
| Disk space | 10 GB free |
| Memory | 2 GB RAM |
| Sudo access | Running as root |
| PostgreSQL | Installed (or will be) |
| Network | Internet connectivity |
| Architecture | x86_64 or ARM |
| GEM service | Detects existing installation |
Node.js v22 is bundled with the installer, so a system Node install is not required.
If an existing gem.json is found, the installer loads the current configuration and creates a timestamped backup (gem.json.bak.YYYY-MM-DDTHHMMSS).
Step 2: Dependencies
Select which components to install. Each dependency is installed individually with progress tracking:
| Component | Description | Default |
|---|---|---|
| PostgreSQL | Database server | Checked |
| Node.js | JavaScript runtime (v22) | Checked |
| System Dependencies | build-essential, git, mDNS, nmap, arp-scan, FFmpeg, adb | Checked |
| Python & Modules | Python 3, pyatv (Apple TV), lennoxs30api, netaudio | Unchecked |
| Matter (chip-tool) | BlueZ, Avahi, and chip-tool for Matter device commissioning | Unchecked |
Dependencies use two installation mechanisms:
[apt]packages are installed viaapt install -ywith a 5-minute timeout per package[cmd]commands are executed via bash with a 10-minute timeout
Step 3: Database
Configure the PostgreSQL connection. For fresh PostgreSQL installations, the installer can create the database user and database automatically.
Fields:
| Field | Default | Description |
|---|---|---|
| Host | localhost | Database server address |
| Port | 5432 | PostgreSQL port |
| Username | (empty) | Database user (created if "Create Database" is checked) |
| Password | (empty) | Database password (use "Generate" for a random password) |
| Database Name | gem_db | Database name |
Options:
- Create Database -- Creates the PostgreSQL user, database,
gemschema, all tables, and transfers ownership. Also configurespg_hba.conffor TCP password authentication if needed. - Seed Database -- Populates the database with the default theme data (
create_theme.sql). - Test Connection -- Verifies Sequelize can connect with the provided credentials.
GEM Admin Account:
| Field | Default | Description |
|---|---|---|
| Admin Username | admin | The login you will use to access the GEM web interface. Recommended to change from the default. |
| Admin Password | (empty) | Leave blank to auto-generate a strong password — it is shown on the final screen and nowhere else. |
If you set the password manually, it must be at least 12 characters and mix at least three of: lowercase, uppercase, digit, symbol. Click Generate for a strong default that satisfies the rule automatically.
The password you provide here is handed to the GEM server on first boot, used to seed the admin user, and then scrubbed from gem.json (the key is only ever encrypted at rest in the database after that).
Step 4: Notifications (Optional)
Configure email and SMS for system alerts. This step can be skipped and configured later from the admin panel.
Email (SMTP):
- Host, port, username, password
- From/to addresses
- Test button sends a verification email
SMS (Telnyx):
- From/to phone numbers
- Telnyx API key
- Test button sends a verification SMS
Step 5: Server Configuration
| Setting | Default | Description |
|---|---|---|
| Location Name | (empty) | Friendly name for this installation |
| External URL | (empty) | Public URL (for remote access / mobile app) |
| Service Port | 3000 | HTTP port for the GEM web interface |
| Timezone | (auto-detected) | Server timezone for schedules and logs |
| Enable SSL | Off | Run over HTTPS with auto-generated certificates |
| HTTPS Port | 8443 | Port for HTTPS traffic (when SSL enabled) |
| HTTP Port | 8080 | Port for HTTP redirect / CA download (when SSL enabled) |
| Auto-Regenerate Certs | On | Renew certificates on expiry or IP change |
| Enable REST API | On | Allow external API access |
| Device Alerts | On | Send alerts for device communication failures |
| Install as Service | On | Create a systemd service unit |
| Start Service | On | Start GEM immediately after installation |
The port field checks whether the chosen port is already in use before proceeding.
Step 6: Complete
Displays an installation summary and provides:
- The URL to access GEM (e.g.,
http://localhost:3000/admin/setup) - The admin username and password you configured in Step 3 (if the password was auto-generated, it is shown here — copy it now; it is not shown again)
- Service management command:
sudo systemctl status gem
If "Start Service" was selected, the installer installs and starts the systemd service, then exits automatically.
Systemd Service
When "Install as Service" is selected, the installer creates /etc/systemd/system/gem.service:
[Unit]
Description=GEM by Harness Automation
After=network-online.target postgresql.service
[Service]
ExecStart=[dir]/node/bin/node [dir]/server.js
WorkingDirectory=[dir]
Restart=on-failure
RestartSec=5
StandardOutput=journal
StandardError=journal
SyslogIdentifier=gem
Environment=NODE_ENV=production PORT=[port]
[Install]
WantedBy=multi-user.target
[dir] and [port] are replaced with the actual installation path and configured port.
Service Commands
# Check status
sudo systemctl status gem
# Start / stop / restart
sudo systemctl start gem
sudo systemctl stop gem
sudo systemctl restart gem
# View logs
sudo journalctl -u gem -f
# Enable / disable auto-start
sudo systemctl enable gem
sudo systemctl disable gem
WSL (Windows Subsystem for Linux)
GEM runs on WSL with Ubuntu or Debian. The installer automatically detects WSL and adapts:
systemd Requirement
The GEM service requires systemd, which is not enabled by default in WSL. If systemd is not active:
- The installer disables the "Install as Service" and "Start Service" checkboxes
- You can start GEM manually:
./node/bin/node server.js
To enable systemd in WSL, add to /etc/wsl.conf:
[boot]
systemd=true
Then restart WSL from PowerShell:
wsl --shutdown
After restarting, systemd will be active and the installer can create the GEM service normally.
PostgreSQL on WSL
PostgreSQL installs normally on WSL but may not auto-start. The installer handles this by explicitly starting and enabling PostgreSQL after installation, and checking its status before database operations.
Headless / SSH Installation
When no display server is detected (no DISPLAY or WAYLAND_DISPLAY environment variable), the installer runs in headless mode:
- The browser is not auto-opened
- The installer URL is displayed prominently in the terminal with a bordered banner
- The installer is accessible from any browser on the network
This is useful when installing GEM over SSH on a remote server. Open the displayed URL in a browser on your local machine to complete the installer.
Configuration File
The installer saves all settings to gem.json in the project root. Key sections:
| Section | Contents |
|---|---|
data.connection | PostgreSQL host, port, user, password, database |
data.sequelize | Sequelize options (dialect, schema, timezone, etc.) |
mail | SMTP host, port, auth, from/to addresses |
sms | Telnyx from/to numbers and API key |
ssl | SSL enabled, HTTPS port, HTTP port, auto-regenerate |
rest_api | REST API enabled |
device_alerts | Device failure alerts enabled |
external_url | Public-facing URL |
location | Installation location name |
update_url | Update server URL |
Resume Support
The install.sh script tracks completed stages in logs/install_state.json. If the install is interrupted (network drop, reboot, crash), re-running install.sh skips already-completed steps:
- System dependencies
- Node.js installation
- npm package installation
The state file is automatically removed after successful completion.
Existing Installation Detection
When the installer detects an existing gem.json:
- Creates a timestamped backup of the current config
- Loads existing configuration values into the installer fields
- Allows reviewing and modifying settings
- Supports Save & Exit to save configuration changes without re-running dependency installation
Uninstallation
Remove GEM using the uninstall script:
sudo ./bin/uninstall.sh
This interactively:
- Stops and disables the GEM systemd service
- Removes the service file and reloads systemd
- Optionally drops the PostgreSQL database and user (reads credentials from
gem.json) - Optionally removes the GEM application directory
The database is preserved by default unless explicitly confirmed.
Updates
GEM supports over-the-air updates from the update server (updates.mygem.us). The update system:
- Check: GEM periodically posts its
installation_idto/check_updateto see if a new version is available - Download: If an update exists, GEM downloads the encrypted archive (
.tar.gz.enc) from/pull_update - Apply: The archive is decrypted and extracted to replace the application files
Updates are encrypted with AES and each version has its own encryption key stored on the update server. Only installations that are registered and enabled on the update server can receive updates.
Installation Registration
Each GEM installation has a unique installation_id (MD5 hash). When a new installation checks for updates:
- The update server auto-discovers it and creates a disabled entry
- An administrator enables the installation in the update server admin panel
- Subsequent update checks succeed and return available versions
Build & Publish Pipeline
For developers building and distributing GEM:
Building an Installer
npm run build:installer
This runs scripts/build-installer.sh which:
- Verifies
dist/exists (runnpm run buildfirst) - Copies built files to a temp directory
- Generates a
setup.shbootstrap script - Packages everything into a self-extracting
.runfile using makeself - Outputs to
install/gem-installer-{version}.run
Publishing an Update
node scripts/publish-update.js
- Runs a full build (
npm run build) - Creates an encrypted
.tar.gz.encarchive ofdist/ - Uploads to the update server at
/push_updatewith authentication headers
Publishing an Installer
node scripts/publish-installer.js
- Runs
build:installerto create the.runfile - Uploads to the update server at
/push_installerwith authentication headers
Both publish scripts require update_url and update_key in gem.json.
Troubleshooting
Installer Won't Start
Symptoms: install.sh exits with an error
Causes:
- Not running as root -- use
sudo - Not a Debian-based system --
apt-getis required - No internet connectivity -- required for package downloads
Database Creation Fails
Symptoms: Step 3 shows an error after clicking "Create Database"
Common Causes:
| Error | Solution |
|---|---|
ECONNREFUSED | PostgreSQL is not running. Start it: sudo systemctl start postgresql |
pg_hba.conf rejection | The installer auto-configures this -- try again. Or manually add scram-sha-256 auth for 127.0.0.1/32 |
permission denied | Ensure the installer is running with sudo |
does not exist | Make sure "Create Database" is checked |
password authentication failed | User exists with a different password. The installer will update it if "Create Database" is checked |
Connection Lost During Installation
The installer shows a "Connection Lost" modal with automatic reconnection. If the installer process was killed:
- Re-run
sudo ./bin/install.sh(or the.runinstaller) - The installer detects the existing
gem.jsonand resumes from where you left off
Forgotten Admin Password
If you've lost the admin password and SMTP isn't configured for the email reset flow, run the recovery script with shell access to the host:
sudo -u gem node bin/reset-admin.js # resets the "admin" account
sudo -u gem node bin/reset-admin.js <username> # resets a named user
The script generates a random 16-character password, prints it to the terminal, and sets the must-change-password flag so you'll be prompted to choose a permanent password on first login. Shell ownership of the host is the security boundary — there is no equivalent network-exposed endpoint.
Service Won't Start
# Check service status and logs
sudo systemctl status gem
sudo journalctl -u gem --no-pager -n 50
Common Causes:
- Database not running --
sudo systemctl start postgresql - Port already in use -- change the port in
gem.jsonand the service file - Missing npm packages -- run
npm installin the GEM directory
Related Documentation
- Server -- SSL / TLS certificate configuration
- Backup & Restore -- Data protection and migration
- Subsystems -- Configuring subsystems after installation
- Devices -- Adding devices to GEM