From a52b575051a2d93fb5333df3e8c6f8086babea7b Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Wed, 26 Aug 2026 22:07:07 -0700 Subject: [PATCH 1/3] docs(self-hosting): correct what a server change clears, and the cert requirement MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The page said the built-in browser's profile survives a server change. It does not — the teardown clears the browser's saved sessions and the agent's folder grants along with the saved route, because those are capabilities granted to a specific deployment. The page now lists what is cleared and what is kept, says why, and notes that a change which cannot complete is refused rather than half-applied. Adds two things a self-hoster hits in practice. Certificate errors are rejected outright with no "continue anyway", so a private CA that is not in the system trust store will not load however correct the URL is — worth saying, since a private CA is a normal self-host setup. And packaging your own shell needs Xcode 26 or newer, which otherwise fails with an opaque actool error. Also notes that the CLI asks which deployment you mean when a machine has more than one configuration, and states signing/notarization for a self-built shell as a requirement rather than predicting what happens without credentials. --- .../docs/en/platform/self-hosting/desktop.mdx | 29 +++++++++++++++---- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/apps/docs/content/docs/en/platform/self-hosting/desktop.mdx b/apps/docs/content/docs/en/platform/self-hosting/desktop.mdx index 2b7cfb11b80..6a733e245d4 100644 --- a/apps/docs/content/docs/en/platform/self-hosting/desktop.mdx +++ b/apps/docs/content/docs/en/platform/self-hosting/desktop.mdx @@ -39,7 +39,9 @@ The Sim server needs outbound access to `api.github.com` and `github.com` for th npx sim-setup desktop ``` -This reads your deployment URL from your configuration, checks that the installer and update feed both resolve, and prints the download link plus the server URL to enter. Pass `--url https://sim.example.com` when running the CLI somewhere that reaches Sim at a different address. +This reads your deployment URL from your configuration, checks that the installer and update feed both resolve, and prints the download link plus the server URL to enter. + +Pass `--url https://sim.example.com` when running the CLI somewhere that reaches Sim at a different address — or when the machine has more than one Sim configuration, in which case the command lists what it found and asks you to say which deployment you mean rather than guessing. Without the CLI, open `https://your-sim-url/api/desktop/update/download` in a browser. @@ -61,7 +63,18 @@ Launch Sim, then choose **Sim → Server…** in the menu bar. Enter your deploy The app relaunches against your server and stays there — the setting persists across updates, and every later update is fetched from your deployment's feed. -Each server keeps its own session, so you sign in again on the new one, and the relaunched app opens on the workspace picker rather than whatever workspace the old server had open. Everything else — window size, zoom, notification preferences, and the built-in browser's own profile — is device state and is kept. +Changing servers deliberately clears what the previous deployment was trusted with, so the new one cannot inherit it: + +- **Your session.** Each server gets its own storage, so you sign in again. +- **The saved route.** The app opens on the workspace picker, not the workspace the old server had open. +- **Folder access.** Directories you let the agent read are forgotten; grant them again when you need them. +- **Built-in browser sessions.** Sites you were signed into in the built-in browser are signed out. + +The last two are capabilities you granted to a *specific* Sim server, so carrying them across would hand the new deployment access it was never given — the same reasoning that clears them when you sign out. + +Device settings are kept: window size, zoom, theme, notification preferences, tray, and launch-at-login. + +If something cannot be cleared, the change is refused and the app stays on your current server rather than switching with the old deployment's access still in place. Retrying finishes the job. @@ -81,19 +94,25 @@ Each server gets its own isolated cookie and storage partition, so you can move ## Recovering from a wrong server URL -If the app is pointed at a server it cannot reach, it shows its **Can't connect** page. That page has a **Change server** button that opens the same picker, so a typo is always recoverable without touching the filesystem. +If the app is pointed at a server it cannot reach, it shows its **Can't connect** page, which names the reason — a DNS failure, a timeout, or a TLS problem. That page has a **Change server** button that opens the same picker, pre-filled with the current value, so a typo is always recoverable without touching the filesystem. + + + **Your TLS certificate must be trusted by the operating system.** The app rejects certificate errors outright and offers no "continue anyway" — a self-signed certificate or a private CA that is not in the system trust store shows `Connection isn't secure` and will not load, however correct the URL is. Install your CA in the system keychain, or use a publicly trusted certificate. + ## Building your own shell You almost certainly do not need this. It is worth it only if you need your own bundle identity or your own signing identity — for example, to distribute through MDM under your organization's Developer ID. +Packaging needs **macOS with Xcode 26 or newer** — the app icon is an Icon Composer asset, and an older toolchain fails with `Failed to check actool version`. + ```bash cd apps/desktop SIM_DESKTOP_DEFAULT_ORIGIN=https://sim.example.com bun run package:share ``` -This bakes your origin in as the default for fresh installs, so users never see the server picker. Artifacts land in `apps/desktop/release/sim/`, named `sim--.dmg`. +This bakes your origin in as the default for fresh installs, so nobody has to set the server by hand (the picker stays available in the menu). Artifacts land in `apps/desktop/release/sim/`, named `sim--.dmg`. - A build packaged this way is signed with whatever identity is on the build machine, and without App Store Connect credentials it is **not** notarized — so macOS quarantines it on download. Before distributing it, supply your own Developer ID via `CSC_LINK` and `CSC_KEY_PASSWORD`, and notarization credentials via `APPLE_API_KEY`, `APPLE_API_KEY_ID`, `APPLE_API_ISSUER`, and `APPLE_TEAM_ID`. + Signing and notarization become your responsibility with this route, and macOS quarantines anything downloaded that is not notarized. Supply your own Developer ID via `CSC_LINK` and `CSC_KEY_PASSWORD`, and App Store Connect notarization credentials via `APPLE_API_KEY`, `APPLE_API_KEY_ID`, `APPLE_API_ISSUER`, and `APPLE_TEAM_ID`. From ec5b3b745effdc1f9a09656806a158c09c415a2e Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Wed, 26 Aug 2026 22:14:16 -0700 Subject: [PATCH 2/3] docs(self-hosting): point custom builds at package:mac, not package:share MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit package:share is the "send someone a build to try" path. It passes -c.mac.timestamp=none to skip the per-file round trip to Apple's timestamp authority, and its own docstring notes distribution builds need those timestamps. Apple's notary service requires a secure timestamp, so a build made that way cannot be notarized however many credentials the operator supplies — which is exactly what the section was telling them to do. package:mac inherits notarize and hardenedRuntime from electron-builder.yml and leaves timestamps on, and bun run build honours SIM_DESKTOP_DEFAULT_ORIGIN the same way, so the baked-origin instruction is unchanged. Its artifact path and name differ from the share script's per-channel overrides, so those are corrected too, and the two stacked warnings are merged into one. --- apps/docs/content/docs/en/platform/self-hosting/desktop.mdx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/docs/content/docs/en/platform/self-hosting/desktop.mdx b/apps/docs/content/docs/en/platform/self-hosting/desktop.mdx index 6a733e245d4..0db832aa765 100644 --- a/apps/docs/content/docs/en/platform/self-hosting/desktop.mdx +++ b/apps/docs/content/docs/en/platform/self-hosting/desktop.mdx @@ -108,11 +108,13 @@ Packaging needs **macOS with Xcode 26 or newer** — the app icon is an Icon Com ```bash cd apps/desktop -SIM_DESKTOP_DEFAULT_ORIGIN=https://sim.example.com bun run package:share +SIM_DESKTOP_DEFAULT_ORIGIN=https://sim.example.com bun run package:mac ``` -This bakes your origin in as the default for fresh installs, so nobody has to set the server by hand (the picker stays available in the menu). Artifacts land in `apps/desktop/release/sim/`, named `sim--.dmg`. +This bakes your origin in as the default for fresh installs, so nobody has to set the server by hand (the picker stays available in the menu). Artifacts land in `apps/desktop/release/`, named `Sim--.dmg`. Add `-c.appId=com.example.sim` if you want your own bundle identifier rather than Sim's. Signing and notarization become your responsibility with this route, and macOS quarantines anything downloaded that is not notarized. Supply your own Developer ID via `CSC_LINK` and `CSC_KEY_PASSWORD`, and App Store Connect notarization credentials via `APPLE_API_KEY`, `APPLE_API_KEY_ID`, `APPLE_API_ISSUER`, and `APPLE_TEAM_ID`. + + Use `package:mac` for this, **not** `package:share`. The share script is the "send someone a build to try" path: it passes `-c.mac.timestamp=none` to skip the per-file round trip to Apple's timestamp authority. Apple's notary service requires a secure timestamp, so a build made that way cannot be notarized however many credentials you supply. From a3645b80ef7dd792f16c9759d3eb617b68d906fd Mon Sep 17 00:00:00 2001 From: Waleed Latif Date: Wed, 26 Aug 2026 22:18:25 -0700 Subject: [PATCH 3/3] docs(self-hosting): spell out that APPLE_API_KEY is a path to the .p8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The variable holds an absolute filesystem path to the App Store Connect key file, not the key material, and @electron/notarize reads it through Node fs so a leading ~ is not expanded — the release workflow carries a comment saying exactly that. Listed alongside the other credentials with no explanation, it reads like somewhere to paste the key, and notarization then fails while every variable looks set. --- apps/docs/content/docs/en/platform/self-hosting/desktop.mdx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/docs/content/docs/en/platform/self-hosting/desktop.mdx b/apps/docs/content/docs/en/platform/self-hosting/desktop.mdx index 0db832aa765..8c6904686f3 100644 --- a/apps/docs/content/docs/en/platform/self-hosting/desktop.mdx +++ b/apps/docs/content/docs/en/platform/self-hosting/desktop.mdx @@ -114,7 +114,9 @@ SIM_DESKTOP_DEFAULT_ORIGIN=https://sim.example.com bun run package:mac This bakes your origin in as the default for fresh installs, so nobody has to set the server by hand (the picker stays available in the menu). Artifacts land in `apps/desktop/release/`, named `Sim--.dmg`. Add `-c.appId=com.example.sim` if you want your own bundle identifier rather than Sim's. - Signing and notarization become your responsibility with this route, and macOS quarantines anything downloaded that is not notarized. Supply your own Developer ID via `CSC_LINK` and `CSC_KEY_PASSWORD`, and App Store Connect notarization credentials via `APPLE_API_KEY`, `APPLE_API_KEY_ID`, `APPLE_API_ISSUER`, and `APPLE_TEAM_ID`. + Signing and notarization become your responsibility with this route, and macOS quarantines anything downloaded that is not notarized. + + Supply your own Developer ID via `CSC_LINK` and `CSC_KEY_PASSWORD`. For notarization, save your App Store Connect key as a `.p8` file and point `APPLE_API_KEY` at its **absolute filesystem path** — it is a path, not the key itself, and a leading `~` is not expanded — then set `APPLE_API_KEY_ID`, `APPLE_API_ISSUER`, and `APPLE_TEAM_ID`. Use `package:mac` for this, **not** `package:share`. The share script is the "send someone a build to try" path: it passes `-c.mac.timestamp=none` to skip the per-file round trip to Apple's timestamp authority. Apple's notary service requires a secure timestamp, so a build made that way cannot be notarized however many credentials you supply.