I've been working on getting the desktop app functional with a self-hosted instance (including SSO login via an external OIDC provider). More context on self-hosting in general in my discussion post.
Connecting to a self-hosted instance
As @bmlzootown mentioned, the desktop app reads settings.json from the user data directory:
This works — the desktop app loads the web UI from your self-hosted instance. However, it currently requires creating this file manually. The InstanceSelector component exists in the codebase but isn't wired up to the login page, and even if it were, it wouldn't help: on first launch (without settings.json), the app loads the official web app from web.fluxer.app, which wouldn't have any self-hosted customizations. A proper solution would need a first-run instance picker built into the Electron shell itself (before any remote web app is loaded).
Building the desktop app
The fluxer_desktop package on the refactor branch needs a few fixes to build successfully:
Preload ESM/CJS conflict: package.json has "type": "module", so .js files are treated as ESM, but the preload script is built as CJS. Fix: output preload as index.cjs in scripts/build.mjs and update the preload path in Window.tsx.
ESM banner collision: The esbuild banner import { createRequire } from 'module' collides with esbuild's own bundled createRequire import. Fix: rename to _createRequire in the banner.
electron-builder config: linux.desktop.Name/Comment/Categories/StartupWMClass need to be nested under linux.desktop.entry for electron-builder ≥26.
Missing package.json metadata: electron-builder deb generation requires description, homepage, and author fields in fluxer_desktop/package.json.
SSO login from the desktop app
This was the bigger challenge. The normal SSO flow redirects the browser to the OIDC provider, which then redirects back to https://your-instance.example.com/auth/sso/callback. In the desktop app, the SSO page opens in the system browser (needed for passkey/WebAuthn support), but there's no way for the browser callback to get back to the Electron app.
The solution uses the fluxer:// deep link protocol that the desktop app already registers:
API changes (SsoService, AuthRequestService, AuthSchemas):
Added desktop boolean to SsoStartRequest
When desktop: true, the API uses fluxer://auth/sso/callback as the OIDC redirect_uri instead of the web callback URL
The desktop flag is stored in the SSO state payload so completeLogin uses the matching redirect_uri for the code exchange
Web app changes (AuthLoginLayout, AuthFlow, AuthenticationActionCreators):
When running in the desktop app, handleStartSso passes desktop: true and opens the authorization URL via electronApi.openExternal() (system browser) instead of window.location.assign()
Deep link handler (DeepLinkUtils):
Added handling for fluxer://auth/sso/callback?code=...&state=... deep links
Uses dynamic imports to avoid a circular dependency (DeepLinkUtils is loaded early from App.tsx)
OIDC provider config:
fluxer://auth/sso/callback must be added as an allowed redirect URI in your OIDC provider
The flow: click SSO → browser opens → authenticate (passkeys work!) → browser redirects to fluxer://auth/sso/callback?code=...&state=... → OS routes to desktop app → token exchange completes → logged in.
Note: this also requires the SSO token exchange fixes from my discussion post #5 — without those, the OIDC code exchange fails regardless of desktop vs web.
Branch & builds
All changes are on mgabor3141/fluxer@feat/desktop-custom-instance-url-clean (based on refactor).
There are CI-built artifacts (Linux x64, macOS arm64, Windows x64) from that branch here — though as always, the usual caveat applies: don't install binaries from random forks unless you've reviewed the source and trust the build pipeline.
Thread
Comment by @mgabor3141
Connecting to a self-hosted instance
As @bmlzootown mentioned, the desktop app readssettings.jsonfrom the user data directory:~/.config/fluxer/settings.json~/Library/Application Support/fluxer/settings.json%APPDATA%\fluxer\settings.jsonInstanceSelectorcomponent exists in the codebase but isn't wired up to the login page, and even if it were, it wouldn't help: on first launch (withoutsettings.json), the app loads the official web app fromweb.fluxer.app, which wouldn't have any self-hosted customizations. A proper solution would need a first-run instance picker built into the Electron shell itself (before any remote web app is loaded).Building the desktop app
Thefluxer_desktoppackage on therefactorbranch needs a few fixes to build successfully:package.jsonhas"type": "module", so.jsfiles are treated as ESM, but the preload script is built as CJS. Fix: output preload asindex.cjsinscripts/build.mjsand update the preload path inWindow.tsx.import { createRequire } from 'module'collides with esbuild's own bundledcreateRequireimport. Fix: rename to_createRequirein the banner.linux.desktop.Name/Comment/Categories/StartupWMClassneed to be nested underlinux.desktop.entryfor electron-builder ≥26.description,homepage, andauthorfields influxer_desktop/package.json.SSO login from the desktop app
This was the bigger challenge. The normal SSO flow redirects the browser to the OIDC provider, which then redirects back tohttps://your-instance.example.com/auth/sso/callback. In the desktop app, the SSO page opens in the system browser (needed for passkey/WebAuthn support), but there's no way for the browser callback to get back to the Electron app. The solution uses thefluxer://deep link protocol that the desktop app already registers: API changes (SsoService,AuthRequestService,AuthSchemas):- Added
- When
- The
Web app changes (desktopboolean toSsoStartRequestdesktop: true, the API usesfluxer://auth/sso/callbackas the OIDCredirect_uriinstead of the web callback URLdesktopflag is stored in the SSO state payload socompleteLoginuses the matchingredirect_urifor the code exchangeAuthLoginLayout,AuthFlow,AuthenticationActionCreators):- When running in the desktop app,
Deep link handler (handleStartSsopassesdesktop: trueand opens the authorization URL viaelectronApi.openExternal()(system browser) instead ofwindow.location.assign()DeepLinkUtils):- Added handling for
- Uses dynamic imports to avoid a circular dependency (DeepLinkUtils is loaded early from App.tsx)
OIDC provider config:fluxer://auth/sso/callback?code=...&state=...deep links
The flow: click SSO → browser opens → authenticate (passkeys work!) → browser redirects tofluxer://auth/sso/callbackmust be added as an allowed redirect URI in your OIDC providerfluxer://auth/sso/callback?code=...&state=...→ OS routes to desktop app → token exchange completes → logged in. Note: this also requires the SSO token exchange fixes from my discussion post #5 — without those, the OIDC code exchange fails regardless of desktop vs web.Branch & builds
All changes are onmgabor3141/fluxer@feat/desktop-custom-instance-url-clean(based onrefactor). There are CI-built artifacts (Linux x64, macOS arm64, Windows x64) from that branch here — though as always, the usual caveat applies: don't install binaries from random forks unless you've reviewed the source and trust the build pipeline.