Building the desktop client
Compile the Fosnie desktop client from source, and what that means for signing and updates.
Most people should install the desktop client from the published installer, the way they install the server images: it is signed, it updates itself, and it is the same build everybody else is running. This page is for the case where that is not acceptable – an organisation whose policy is that it compiles what it runs, or one that wants to read the source of the thing sitting on its laptops before any of them run it.
The client is a window onto an instance. It carries no model, no data and no second copy of the application: the interface it shows is built from the same frontend the server serves, so a client you compiled yourself and a browser pointed at the same instance are showing you the same thing.
Before you start
You need a Rust toolchain (stable), Node (an active LTS), and nothing else on Windows – the bundler fetches WiX itself the first time it needs it. On macOS you need Xcode command line tools; on Linux, the usual WebKitGTK development packages.
Windows also needs the WebView2 runtime at run time, which Windows 11 already has.
Building
git clone https://github.com/Fosnie/fosnie.git
cd fosnie
npm --prefix frontend install
npm --prefix desktop install
npm --prefix desktop run build:unsignedThe installer is written to desktop/src-tauri/target/release/bundle/msi/ on Windows, and to
bundle/dmg/ on macOS.
build:unsigned is the command to use. The plain build asks the bundler for a signed update
artefact as well, which needs our release key, so without it that command writes the installer and
then exits non-zero – confusingly, since the installer it just produced is perfectly good.
What a self-build is not
Two differences from the published installer, and both are worth knowing before you distribute one.
It is unsigned. Windows SmartScreen and endpoint protection have nothing to check it against, so they will warn about it – on every machine, every time, not once. For an application that connects to company systems and runs in the background, training people to click past that warning is a poor trade. If you are deploying at any scale, sign the build with your own code-signing certificate before it goes anywhere.
It will not take our updates. The client verifies an update against the signing key compiled into it, and a build you made carries the placeholder rather than ours. So a self-built client either updates from a manifest you sign with your own key pair, or does not update at all and is replaced by rebuilding. Both are legitimate; drifting into the second one without deciding is not, because a client that silently never updates is a client that silently never gets a security fix.
An instance can serve the client to its own users, installer and updates alike, which is usually what an organisation actually wants when it asks about building from source. A super-admin uploads the installer under Super-admin, Desktop client; everybody then gets it from their own server, and paired clients look there for updates before anywhere else. See Air-gap bundle.
The supported path
For an organisation that compiles everything it runs, the supported shape is: build once, sign with your own certificate, distribute through your own device management, and either point the client at a manifest you publish or replace the build when you want it moved. Nothing in that loop touches our infrastructure.
Reproducible builds
This version does not offer byte-for-byte reproducible builds. The installer bundler is not deterministic, and saying otherwise would be worse than saying nothing. What is published instead is the SHA-256 of every installer, shown in the instance's own admin panel and alongside the download, so a vetting pipeline can confirm that the file it received is the file that was published. If your security review needs true reproducibility, tell us – it is a piece of work we would rather do against a real requirement than a guess.