An unofficial Linux port and build toolchain for Factory Desktop. It converts an authorized copy of the official macOS application into Linux packages while keeping Factory's proprietary payload outside the source repository.
Important
This project is not affiliated with, endorsed by, or supported by Factory.
It does not redistribute Factory Desktop, its DMG, app.asar, assets, or the
Droid binary.
Install · Features · Architecture · Updates · Build · Troubleshooting · Documentation
Accepted builds are published through GitHub Releases. The repository produces these x86_64 formats:
| Format | Installation | Native update manager |
|---|---|---|
.deb |
Debian package tools | Included |
.rpm |
RPM package tools | Included |
| AppImage | Portable executable | Not included |
The project does not publish a supported distribution matrix. Review your package manager's output and the release acceptance metadata before installing.
Download the package for your system from the
latest release.
Each release includes checksums.txt, build-info.json, patch-report.json,
and acceptance-summary.json alongside the packages.
Verify downloaded files against the release checksum manifest:
sha256sum --check --ignore-missing checksums.txtInstall a native package with the appropriate system package manager:
# Debian package
sudo apt install ./factory-desktop_<version>_amd64.deb
# RPM package
sudo rpm -Uvh ./factory-desktop-<version>.x86_64.rpmRun an AppImage without a system install:
chmod +x Factory-*-x86_64.AppImage
./Factory-*-x86_64.AppImageAppImage is portable and does not include the privileged native updater,
polkit policy, or systemd user services.
- Deterministic, exact-version DMG acquisition with content-addressed caching.
- Fail-closed ASAR patching. Required patches and post-patch validators must all pass before a candidate can be packaged.
- Linux Electron runtime staging with desktop integration, protocol registration, and a product-named executable.
- Package hygiene checks for staged and extracted
.deb,.rpm, and AppImage artifacts. - A Rust update manager for native packages with after-exit installation, package-manager verification, known-good retention, and rollback support.
- Package-bound provenance, checksums, bounded diagnostics, and a manual release acceptance workflow.
The build pipeline keeps source, generated candidates, and privileged installation responsibilities separate:
authorized Factory DMG
|
v
exact-version acquisition and structural acceptance
|
v
fail-closed ASAR patching and JavaScript validation
|
v
Linux Electron runtime staging
|
v
package build, extraction, hygiene, and provenance checks
|
v
.deb / .rpm / AppImage
| Area | Responsibility |
|---|---|
patcher/ |
Patch contracts, transforms, reports, and validators |
scripts/ |
Acquisition, staging, packaging, inspection, and release gates |
launcher/ |
Linux runtime environment and process launch |
packaging/ |
Native package and AppImage integration files |
updater/ |
Rust state machine, candidate validation, install, and rollback |
release/ |
Accepted upstream version authority |
tests/ |
Synthetic contracts, package acceptance, and local bundle regression |
Candidates are built in sibling workspaces and promoted only after the acceptance profile passes. See Architecture, Patching, and Build and packaging for the detailed contracts.
Native .deb and .rpm packages install factory-update-manager and a
systemd --user service. The manager checks on a six-hour default interval,
builds candidates as the desktop user, accepts them only after package
inspection, and waits for Factory Desktop to exit before requesting
installation. Successful install and rollback states require an exact
package-manager version query.
The normal privileged path requires polkit authentication. If polkit is unavailable or denied, the updater records an explicit terminal command for the user to run manually. The unattended approval architecture exists as an explicit opt-in, but passwordless installation is not active:
install-approved-packageremainsallow_active=no.unattended = trueprepares approval requests but does not bypass authentication.- Fully unattended updates are neither enabled nor claimed.
- AppImage does not have a privileged native updater.
Read Update manager for the state machine, commands, and privilege boundary.
The pipeline treats upstream metadata, package contents, renderer input, caches, and package-manager results as untrusted until they pass their corresponding checks. The main boundaries are:
- exact-version downloads are restricted to the documented Factory HTTPS host and path contract;
- DMGs become accepted only after structure, version, and hash validation;
- complete patched JavaScript bundles are parsed again at patch, staging, and extracted-package boundaries;
- native install approvals bind root-owned records to package identity, hashes, expiry, ownership, and confined paths;
- CI build jobs have read-only repository permissions, and only the final
release publication job receives
contents: write; - proprietary DMGs, ASARs, extracted apps, screenshots, and generated packages remain outside git.
The full trust and privilege model is documented in Security model and Legal and artifact policy.
Clone the wrapper and install the Node.js, Rust, Electron packaging, and native
package tools required by the workflows. The CI definitions use Node.js 22,
the stable Rust toolchain, 7-Zip, cpio, rpm, squashfs-tools, and
desktop-file-utils.
git clone https://github.com/fiks9/factory-desktop-linux.git
cd factory-desktop-linux
make check
make test
make build-app DMG=/absolute/path/to/Factory.dmg VERSION=0.139.0make build-app can also discover the current version and acquire the official
DMG. A pinned build copies the authorized local DMG into the content-addressed
cache and never modifies the original.
Build packages from an accepted staged app:
make deb APP_DIR=work/latest/app VERSION=0.139.0 DIST_DIR=dist
make rpm APP_DIR=work/latest/app VERSION=0.139.0 DIST_DIR=dist
make appimage APP_DIR=work/latest/app VERSION=0.139.0 DIST_DIR=distGenerated packages, downloads, caches, extracted payloads, node_modules, and
Rust target directories are ignored and must not be committed. See
Build and packaging for acceptance and hygiene
details.
Run the blocking local checks before preparing a release:
make check
make test
make package-smoke VERSION=0.139.0 DIST_DIR=/tmp/factory-package-smoke
make test-real-bundles
make release-checkGitHub Releases are created only through the manually dispatched
Release workflow.
Maintainers provide an exact Factory version, an explicit linux.N wrapper
revision, and a reviewed source ref from the protected branch history. The
workflow builds and accepts the complete bundle before its separate publication
job can create a release.
The scheduled upstream watcher reports drift but does not change
release/accepted-upstream.json, create a release, or treat tags and drafts as
accepted upstream evidence. Default releases are checksum-only unless detached
.asc signatures are actually present.
See the Maintainer runbook and Release process before publishing.
| Problem | First check |
|---|---|
| Version mismatch | Compare the requested version, DMG metadata, and accepted version. Do not override the mismatch. |
| Patch or JavaScript syntax failure | Preserve the bounded diagnostics and follow the patch drift guide. Do not package the candidate. |
| App starts in development mode | Confirm the installed ELF is /opt/Factory/factory-desktop, not electron. |
| OAuth or protocol callback fails | Check FACTORY_DISABLE_KEYRING=1 and the factory-desktop:// MIME handler. |
| Update UI is unavailable | Native packages require the fixed helper and bridge. AppImage reports the updater as unavailable by design. |
| Install needs manual action | Use the updater-owned manualCommand, then run reconcile-install after installation. |
More diagnostics and recovery steps are in Troubleshooting.
- This is an unofficial compatibility port built from an authorized upstream macOS application, not a native Factory release for Linux.
- Upstream application changes can cause patch drift. Required patch failures stop the build instead of producing a partially patched package.
- AppImage does not include native update services or privileged self-update.
- Passwordless installation and fully unattended updates remain disabled pending a separate privileged live end-to-end verdict.
- The repository does not claim support for specific Linux distributions or Factory versions beyond artifacts that have passed the release workflow.
- Releases are checksum-only unless their assets include detached signatures.
The implemented roadmap covers deterministic acquisition, fail-closed patching, all three package formats, the Rust updater lifecycle, in-app update integration, and manual release acceptance. Remaining security-sensitive work, including any future passwordless update policy, requires a separate privileged live end-to-end review. See Roadmap.
- Architecture
- Build and packaging
- Patching
- Update manager
- Security model
- Release process
- Maintainer runbook
- Troubleshooting
- Roadmap
- Legal and artifact policy
This repository's original wrapper, tooling, Linux compatibility code, tests, and documentation are available under the MIT License. The license does not grant rights to Factory Desktop, Factory services, trademarks, upstream application code, assets, or Droid.
Users are responsible for obtaining and using authorized upstream software. Use of Factory Desktop and Factory services remains subject to Factory's terms and server-side availability.