KRINT desktop app
KRINT ships two ways from one codebase:
| Distribution | Database | Auth | Use case |
|---|---|---|---|
Docker image (docs/self-host.md) | PostgreSQL | Your OIDC provider, or local login | Servers, multi-user, always-on |
| Desktop app (this doc) | SQLite | Local login, signed in automatically | Single user on their own machine |
The desktop build is a Tauri v2 window wrapped around the same KRINT.API binary the Docker image runs. The API serves the SPA itself (Production MapFallbackToFile), so the webview just points at the local backend - no separate frontend build, no API changes.
Download
Installers for every release are on the GitHub Releases page:
| Platform | File |
|---|---|
| Windows | KRINT_<version>_x64-setup.exe (installer) or KRINT-portable-win-x64.exe (no install) |
| macOS (Apple Silicon) | KRINT-portable-osx-arm64.zip |
| Linux | KRINT_<version>_amd64.AppImage, .deb or .rpm |
Docker Desktop (or a Docker daemon) must be running: the app provisions databases as containers. When it is not, the app shows a banner until Docker answers again. Updates are manual for now: download the new installer from the Releases page (see Auto-updates). Everything below is for building the app from source.
How it works
On launch the desktop shell (src-tauri/src/lib.rs):
- Creates an app-data dir and a stable
vault.key(AES-256, generated once, reused). - Creates a stable
local-login.keynext to it: the password of the one local account (desktop) the API seeds on first boot. No identity provider, no Docker or Java for auth. - Spawns
KRINT.APIas a sidecar withDatabase__Provider=Sqliteand the SQLite file in the app-data dir. - Picks a free loopback port at launch, polls it until the API answers, then navigates the window to
/login#krint_desktop=…. The fragment carries the desktop credentials, never reaches the API, and the login page signs in with it and clears it. - Points the API's backups at
<app-data>/backups(Backup__Directory): the default next to the binary is read-only inside the macOS bundle and the Linux packages. - On exit, kills the API child.
The desktop account's password belongs to the shell: it is read from local-login.key on every launch. The Settings page therefore hides the Password card and does not offer a reset for the signed-in account in the desktop app (Desktop__Enabled=true); changing it would lock you out.
Why Docker is still required
KRINT provisions database instances as sibling Docker containers, so the desktop app - like the server - needs a Docker engine (Docker Desktop on Windows/macOS) running on the host. Auth needs nothing at all: it is the API's own local login, signed in automatically.
Prerequisites
- Rust + the Tauri system deps for your OS (see https://v2.tauri.app/start/prerequisites/).
- The .NET 10 SDK.
- Bun (frontend build) and Node.js (runs the sidecar publish script).
- Docker Desktop / a running Docker engine (for provisioning database instances).
Install JS deps and the Tauri CLI once:
bun installBuild & run
The sidecar (KRINT.API) is published self-contained and copied into src-tauri/binaries/ with the target-triple suffix Tauri expects. This runs automatically via beforeBuildCommand, or manually:
bun run publish:sidecar # publishes for the host triple
# cross-publish a specific runtime:
RID=osx-arm64 bun run publish:sidecarThen:
bun run desktop:dev # dev window
bun run desktop:build # installers under src-tauri/target/release/bundle/Portable single exe (Windows)
For a no-install build, compile with the portable Cargo feature. It embeds the API sidecar + resources into krint-desktop.exe and self-extracts them to %APPDATA%/app.krint.desktop/runtime-<version>/ on first launch - one ~150 MB double-clickable file:
bun run publish:sidecar # produce the sidecar + wwwroot to embed
cargo build --release --features portable --manifest-path src-tauri/Cargo.toml
# -> src-tauri/target/release/krint-desktop.exe (rename to KRINT.exe)The release workflow builds and uploads this as KRINT-portable-win-x64.exe alongside the NSIS installer.
TIP
First run also needs app icons. Generate them once with bun run tauri icon path/to/icon.png (writes into src-tauri/icons/, which is gitignored).
.NET RID ↔ Tauri target triple
| Platform | .NET RID | Tauri triple suffix |
|---|---|---|
| Windows x64 | win-x64 | x86_64-pc-windows-msvc |
| macOS Apple Silicon | osx-arm64 | aarch64-apple-darwin |
| macOS Intel | osx-x64 | x86_64-apple-darwin |
| Linux x64 | linux-x64 | x86_64-unknown-linux-gnu |
Find the host triple with rustc --print host-tuple.
Auto-updates
Currently disabled
Releases are not signed yet: plugins.updater.pubkey is still a placeholder and bundle.createUpdaterArtifacts is false, so no latest.json is published and a check could never succeed. The check is switched off with UPDATER_ENABLED = false in src-tauri/src/lib.rs. Once the one-time setup below is done, set createUpdaterArtifacts to true and flip UPDATER_ENABLED to turn it back on. Until then, install new releases by hand.
Once enabled, the app checks for updates on launch (tauri-plugin-updater). If a newer signed release is available it downloads, installs, and restarts - replacing the whole bundle (API sidecar + resources included), so one update covers everything.
How it fits together:
tauri.conf.json→plugins.updater.endpointspoints athttps://github.com/PianoNic/KRINT/releases/latest/download/latest.json, andpubkeyholds the public signing key.bundle.createUpdaterArtifacts: truemakestauri buildemit signed updater bundles +.sig.- The release workflow signs them and uploads
latest.json(the update manifest). - Windows ships the NSIS
.exeinstaller only (per-user, x64 + arm64, best updater support); MSI is intentionally not built. - Updatable formats: AppImage (Linux), NSIS
.exe(Windows), .app (macOS)..deb/.rpmare install-only (no self-update) - that's a Tauri limitation, not ours.
One-time setup (required before releases self-update)
- Generate a signing keypair:bash
bunx tauri signer generate -w ~/.tauri/krint-updater.key - Put the public key into
tauri.conf.json→plugins.updater.pubkey(replaces theREPLACE_WITH_...placeholder). The public key is safe to commit. - Add the private key + its password as GitHub Actions secrets (never commit them):
TAURI_SIGNING_PRIVATE_KEYTAURI_SIGNING_PRIVATE_KEY_PASSWORD
Until the real pubkey + secrets are in place, signed builds (tauri build) and auto-update won't work - the rest of the desktop build still does.
Notes / TODO
- Keep ICU: the sidecar is published without
InvariantGlobalizationbecause the MSSQL client needs ICU. Single-file self-contained bundles ICU by default. - The desktop SQLite database lives in the OS app-data dir (e.g.
%APPDATA%/app.krint.desktop,~/Library/Application Support/app.krint.desktop,~/.local/share/app.krint.desktop).