GITHUB_TOKEN bump pushes never start other workflows, so inverting the docker build trigger alone left :dev unpublished. version-bump-dev now dispatches docker-publish with tag=dev after a successful bump. Refs #401 Thanks: INSOLVE (Honorary); Marco Jakobs (@jacotec); MyNameisStitch (@MyNameisStitch); Redspin (@playerumpknow)
9.2 KiB
BetterDesk Update Flow
Panel (in-app) update
- Browser self-update restart confirmation should use lightweight
/api/settings/restart-status, not heavy/authenticated/api/settings/info; DB/Go backend warmup can cause false restart-timeout reports. - Use
window.BetterDesk.cacheVersionto distinguish the old Node.js process from the restarted one, and reload with a cache-busting query after update. GET /api/settings/updates/preflight?serverUpdate=1when server files change — blocks install if Go/prebuilt unavailable.- After update, if server source changed but binary build/deploy failed,
applyUpdateattempts auto-rebuild viarebuildServerBinarybefore leaving a stale marker. - Server binaries use the exact update commit: the panel checks the
release-server.ymlGitHub Actions run and its platform artifact first, then an exact Release asset with a manifest. A genericreleases/latestbinary is informational only and is never installed for a different SHA. - The artifact manifest contains commit, Go target, size and SHA-256. The panel validates all fields before moving the binary into the server source directory; missing/expired artifacts or failed jobs fall back to a local Go build.
- Console update merges new keys from
web-nodejs/.env.exampleinto existing.envusingbuildEnvSubstitutions()(resolved paths, no raw__PLACEHOLDER__values). - After server updates,
patchServiceDefinitions()sanitizes writable/NSSM units in place; protected Linux systemd units require the explicit root maintenance step below. - Linux privilege boundary: the panel never executes a repository JavaScript file through
sudoand never writes root-owned systemd units or Go binaries. A root operator must runsudo node web-nodejs/scripts/linux-ensure-console-user.jsafter installation or after a privileged layout change; this installs the fixed root-owned update broker at/usr/local/libexec/betterdesk/betterdesk-privileged-update.js. The broker only permitssystemctl daemon-reloadand restart ofbetterdesk-console/betterdesk-server. - Root-owned Go binary: when the Go server target is not writable by the console user, the panel leaves the binary unchanged and reports the documented manual root deploy step. Do not add a sudoers rule for
linux-deploy-server-binary.js,linux-ensure-console-user.js, or any script under the writable console tree. - Migration: a root operator must rerun the ensure script once to replace older broad sudoers entries and remove any legacy
ExecStartPre=+...linux-ensure-console-user.jsline from the console unit. Verify withsudo visudo -cf /etc/sudoers.d/betterdesk-console-updatesandsudo systemctl cat betterdesk-console. - Windows path root (#272):
resolveProjectRoot()must never resolve to a drive root (C:\). Default layoutC:\BetterDeskConsole+C:\BetterDeskwrites Scripts & Docker files under the console directory.ensureParentDirForFile()skipsmkdiron filesystem roots (Node throwsEPERMonmkdir('C:\\')). NSSM OpenService Access Denied when restartingBetterDeskServeris non-critical — restart the Go service manually or viabetterdesk.ps1if needed.
Support Agent generator phase
When an update changes Support Agent inputs, applyUpdate() records
.agent_rebuild_pending with the deployed commit and returns without syncing
or queueing agent builds. After the console restarts,
agentBuildWorker.processPendingRebuildOnStartup() synchronizes the complete
agent source tree first and then requeues non-revoked Support Agent bundles.
The worker retries safely if either step fails, while Agent Client and RdClient
workers remain independent.
Issue #158 — server build / config preservation
Root cause (original report)
GitHub compare API caps files at 300, so large diffs are truncated and changed Go callee files were not downloaded → inconsistent on-disk source and undefined build errors.
Fix: ensureServerSource(remoteSHA, { force: true }) before every server compile/rebuild (panel update + Rebuild button).
Installer GitHub update
- Bash:
cp -rf src/. dest/— PS1:Copy-Item "$src\*" $dest(never nest source inside existing dir if rename failed).
Configuration merge (Skansmer / boruto79 follow-ups)
.env:web-nodejs/lib/envMerge.js,scripts/merge-env.js,scripts/write-installer-env-subst.js(JSON subst file — safe for special characters in passwords). Update paths append missing keys only with resolved values.- Passwords: Panel login uses
users.password_hashinauth.db/ PostgreSQL. Updates must not change DB passwords. - Services:
patch_service_definitions/Patch-ServiceDefinitionson every update when units exist; fullSetup-Servicesonly when missing or when operator confirms recreate ([y/N]prompt) /UPDATE_REFRESH_SERVICES=true. - Script update failure: GitHub update returns non-zero if Go server binary compile fails.
- Tracked commit: both Bash and PowerShell installers resolve the downloaded commit SHA through Git or the GitHub API. Tar/ZIP fallback updates refuse to advance tracking when the commit cannot be verified.
- Failure recovery: panel updates create a manifest for changed console,
server and installer files. Critical failures automatically restore the
manifest and any deployed server binary backup unless
autoRollbackis explicitly disabled.
Stale panel warning after script / Docker update (#192)
data/.last_update_result.json stores the last in-panel update outcome. A failed panel attempt (e.g. EACCES on root-owned /opt/ files) can leave a red banner even when a later script or Docker update succeeded.
An update is not considered complete until the critical source/binary steps
finish. .update_sha, .agent_source_sha and the stale-result marker are
updated only after that point. Before applying changes, the panel also checks
the writable data path and available disk space (override the 512 MiB minimum
with UPDATE_MIN_FREE_MB when a deployment has a documented different
requirement). If the host exposes statfsSync without usable block
statistics, the check is reported as unsupported rather than blocking every
Windows update.
The same cross-platform protocol harness is available after installation:
node scripts/installer-protocol-check.js \
--api-url http://127.0.0.1:21114/api/health \
--panel-url http://127.0.0.1:5000/health \
--port 127.0.0.1:21116
Use 21121 instead of 21114 for the Docker single-container layout. The
harness distinguishes TCP reachability from HTTP success, accepts a recorded
3xx redirect, validates HTTPS certificate SANs by default, and supports
--insecure only for explicitly disposable/self-signed checks.
| Update path | Clears stale banner |
|---|---|
| Settings → Updates (panel, success) | Yes — or only critical failures persisted |
betterdesk.sh GitHub update |
Yes — removes .last_update_result.json when writing .update_sha |
betterdesk.ps1 GitHub update |
Yes — same as Bash |
betterdesk-docker.sh GitHub rebuild |
Yes — host web-nodejs/data + running console volume |
docker compose pull (GHCR images) |
Yes — console startup syncs image SHA and prunes stale result |
Docker Compose (GHCR images)
When the console runs from ghcr.io/.../betterdesk-console (see docker-compose.quick.yml):
- Updates are image-based, not in-app GitHub file download + Go compile.
- Each console image embeds the build commit (
BETTERDESK_IMAGE_SHA//app/.image-commit). On startup the panel syncsdata/.update_shato that value, clears stale.server_binary_stalemarkers, and drops obsoletedata/.last_update_result.jsonfrom earlier in-app attempts (#192). - Settings → Updates shows pull instructions (
docker compose pull && docker compose up -d) instead of Install / Rebuild server binary. POST /api/settings/updates/installandrebuildServerBinary()are rejected in this mode.
After pulling new images, recreate containers so the console picks up the embedded commit from the new image tag.
GHCR tags: prefer pinning BETTERDESK_IMAGE_TAG to a release semver (compose / install.sh default). latest is the rolling tip of the last successful stable image publish (Release / main); dev tracks development builds and is republished after each dev version bump via an explicit workflow dispatch (#401 — GITHUB_TOKEN bump pushes do not start image builds by themselves). See DOCKER_QUICKSTART.md, #387, and #401.
Update channel (stable / development)
Native installs track GitHub branch HEAD (not tags) via UPDATE_GITHUB_BRANCH in web-nodejs/.env:
| Channel | Branch | Default |
|---|---|---|
| Stable | main |
Yes — production releases |
| Development | dev |
Opt-in — latest work-in-progress |
Operators can switch in Settings → Updates → Update channel, or via installer scripts (Update → Switch update channel). See branching-and-versioning.md.
Changing channel does not reset data/.update_sha; the next update check may show a large diff against the new branch.