Skip to content

KRINT desktop app ​

KRINT ships two ways from one codebase:

DistributionDatabaseAuthUse case
Docker image (docs/self-host.md)PostgreSQLYour OIDC provider, or local loginServers, multi-user, always-on
Desktop app (this doc)SQLiteLocal login, signed in automaticallySingle 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:

PlatformFile
WindowsKRINT_<version>_x64-setup.exe (installer) or KRINT-portable-win-x64.exe (no install)
macOS (Apple Silicon)KRINT-portable-osx-arm64.zip
LinuxKRINT_<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):

  1. Creates an app-data dir and a stable vault.key (AES-256, generated once, reused).
  2. Creates a stable local-login.key next 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.
  3. Spawns KRINT.API as a sidecar with Database__Provider=Sqlite and the SQLite file in the app-data dir.
  4. 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.
  5. 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.
  6. 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 ​

Install JS deps and the Tauri CLI once:

bash
bun install

Build & 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:

bash
bun run publish:sidecar          # publishes for the host triple
# cross-publish a specific runtime:
RID=osx-arm64 bun run publish:sidecar

Then:

bash
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:

bash
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 RIDTauri triple suffix
Windows x64win-x64x86_64-pc-windows-msvc
macOS Apple Siliconosx-arm64aarch64-apple-darwin
macOS Intelosx-x64x86_64-apple-darwin
Linux x64linux-x64x86_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.endpoints points at https://github.com/PianoNic/KRINT/releases/latest/download/latest.json, and pubkey holds the public signing key.
  • bundle.createUpdaterArtifacts: true makes tauri build emit signed updater bundles + .sig.
  • The release workflow signs them and uploads latest.json (the update manifest).
  • Windows ships the NSIS .exe installer only (per-user, x64 + arm64, best updater support); MSI is intentionally not built.
  • Updatable formats: AppImage (Linux), NSIS .exe (Windows), .app (macOS). .deb/.rpm are install-only (no self-update) - that's a Tauri limitation, not ours.

One-time setup (required before releases self-update) ​

  1. Generate a signing keypair:
    bash
    bunx tauri signer generate -w ~/.tauri/krint-updater.key
  2. Put the public key into tauri.conf.json → plugins.updater.pubkey (replaces the REPLACE_WITH_... placeholder). The public key is safe to commit.
  3. Add the private key + its password as GitHub Actions secrets (never commit them):
    • TAURI_SIGNING_PRIVATE_KEY
    • TAURI_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 InvariantGlobalization because 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).

Made with care by PianoNic.