Pins for the Client, Iota, Omikron, Omega and MTP (incl. Type Maps) for a consistent production environment
  • Nix 50%
  • Python 42.3%
  • Shell 7.7%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Alois 4ad0faf307
Some checks failed
action.yml / Fix release validation and packaging with latest sources (push) Failing after 0s
Canary release / release (push) Failing after 21s
Fix release validation and packaging with latest sources
2026-10-04 22:02:56 +02:00
.forgejo/workflows Centralize Tensamin packages modules and release automation 2026-10-04 19:19:56 +02:00
lib Centralize Tensamin packages modules and release automation 2026-10-04 19:19:56 +02:00
modules Centralize Tensamin packages modules and release automation 2026-10-04 19:19:56 +02:00
packages Centralize Tensamin packages modules and release automation 2026-10-04 19:19:56 +02:00
scripts Fix release validation and packaging with latest sources 2026-10-04 22:02:56 +02:00
flake.lock Fix release validation and packaging with latest sources 2026-10-04 22:02:56 +02:00
flake.nix Centralize Tensamin packages modules and release automation 2026-10-04 19:19:56 +02:00
LICENSE Init 2026-10-04 14:00:20 +02:00
README.md Centralize Tensamin packages modules and release automation 2026-10-04 19:19:56 +02:00

Tensamin production pins

Shared sources and builds for the client, Iota, Omikron, Omega, MTP, and type maps.

Build usage

Linux x86_64 and aarch64 packages use one nixpkgs, Rust toolchain, MTP source, and type-map source. The default package is the Electron client.

nix build .
nix run .#client
nix build .#client-web
nix build .#iota .#iota-daemon .#iota-ui .#omikron .#omega
nix develop .#iota
nix develop .#client

client-web contains the static site at its output root. iota contains iota, iota-daemon, iota-updater, iota-release, and iota-bundle. iota-ui exposes the terminal UI as bin/iota-ui. iota-bundle adds upstream systemd files, release scripts, and artifact contracts under share/iota. Signed release manifests and deployment-specific update URLs must be supplied to those scripts. iota-portable builds musl-static binaries using the same sources and Cargo vendor dependencies. Releases use these binaries for ordinary Linux, with no Nix installation required. share/iota/web contains the pinned static assets. iota-container, omikron-container and omega-container produce Docker-loadable images. Mount runtime configuration, identity files, and certificates in their working directories, /var/lib/omikron and /var/lib/omega.

mtp-sdk builds the SDK from the shared MTP source.

Iota's image runs the daemon as UID/GID 1000 and persists /var/lib/iota. Bind mounts must be writable by that user. Supply writable configuration at /var/lib/iota/config/config.yaml, with web.mode: network, web.bind: 0.0.0.0, web.port: 1984, and web.certificate/web.key pointing to mounted TLS files. Publish both 1984/tcp and 1984/udp. Review and accept terms interactively with docker exec -it CONTAINER /bin/iota terms accept, then restart the container. Use --restart on-failure to handle the daemon's restart exit 75. Images update by pulling a new release and recreating the container.

Updating builds

nix run .#update-all
# Recalculate dependency locks and hashes without moving source inputs:
nix run .#update-all -- --no-update

Run this from the checkout with SSH access to git@methanium.net. The command supplies Cargo, pnpm, Python, Git, and Nix. It refreshes flake.lock, resolves the transformed Cargo and pnpm dependency graphs into packages/locks, and rebuilds every dependency fetcher to verify packages/hashes.nix. Review all generated changes and build the affected packages before committing.

MTP git dependencies become local paths to the shared input before vendoring. Omega's identity crate comes from the same Iota input as the Iota binaries. Both YAML and Rust type-map includes come from mtp-type-maps. The SDK and WASM compile from MTP source, with WASM generated for these same maps. The packaged Vite plugin reuses that WASM and still generates JavaScript type maps. Client dependency manifests and pnpm overrides cannot select a release SDK.

Project shells are iota, omikron, omega, mtp, and client. The default shell supplies update-all. Android/Tauri shells are a followup.

Source overrides for CI

Override raw source inputs when building current project sources:

nix build .#iota --override-input iota path:../iota

Packages expose passthru.source; Rust packages also expose passthru.transformedSource, passthru.mtp, and passthru.mtp-type-maps. lib.mkPackages { system = "x86_64-linux"; sources = { iota = ../iota; }; } returns packages and devShells, and accepts a replacement hashes attrset. Dependency-changing overrides require regenerated locks and vendor hashes. Use update-all in a disposable checkout with the desired input overrides.

nix run .#update-all -- --no-update --override-input iota path:../iota

NixOS modules

Add this flake as inputs.tensamin, pass inputs through specialArgs, and import the combined module:

{ inputs, pkgs, ... }: {
  imports = [ inputs.tensamin.nixosModules.default ];
  environment.systemPackages = [
    inputs.tensamin.packages.${pkgs.stdenv.hostPlatform.system}.client
  ];
  tensamin.client.enable = true;
}

Individual imports are nixosModules.iota, .omikron, .omega, and .client. All options live under tensamin.*, and services are disabled by default. The client module serves client-web through nginx on 127.0.0.1:8080 by default; installing Electron is separate. Public TLS and Anubis routing belong to the infrastructure. Production routes host nginx through host Anubis and a loopback origin to nginx in the internal production VM.

Iota requires TLS for enabled listeners. Omikron and Omega require runtime certificates; Omikron also needs its ID and Omega trust bundle, and Omega needs DB_URL. Use runtime path strings for secrets. See modules/README.md for options and state handling. New module files must be present in the Git-backed flake source before consumers can import them; local path: evaluation includes untracked files.

Releases and updates

Combined publication belongs to this repository. Stable and canary releases should contain artifacts built from the same pinned graph. Client dev builds are local and verification-only, with no dev releases. Android IDs are net.tensamin.client, net.tensamin.client.canary, and net.tensamin.client.dev; canary uses yellow icons and dev uses blue outline branding. Android signing identity must stay consistent and version codes must increase per application ID.

Images publish to the Forgejo registry as SERVER/tensamin/SERVICE:IMMUTABLE_TAG-ARCH, including iota, omikron, and omega. Local image revision tags differ from the immutable publication tags. See scripts/releases.md for workflow configuration.

For unmanaged per-user Linux, extract iota-portable-linux-ARCH.tar.gz and run ./bin/iota. The CLI discovers its sibling daemon and packaged assets. User IPC defaults to $XDG_RUNTIME_DIR/iota/iota.sock, or $XDG_STATE_HOME/iota/iota.sock, with ~/.local/state as the fallback. Explicit absolute IOTA_SOCKET and IOTA_DATA_ROOT overrides still work. TLS clients use the host CA trust store.

Unmanaged system-wide Linux Iota uses CLI bootstrap with a trusted signed bundle, then explicit iota update channel stable, iota update check, and iota update apply operations. Trust lives in /etc/iota/update.env and cannot be replaced by process environment. The pinned upstream bootstrap enables iota-update.timer; disable it with sudo systemctl disable --now iota-update.timer for manual-only updates. NixOS deployments update through their infrastructure flake.

The infrastructure and this flake have separate nixpkgs locks. Refresh both when required for security fixes, then build and deploy the affected outputs. update-all verifies dependency fetchers, not full application builds or live deployment. Infrastructure lunitely update pulls published configuration changes; lunitely rebuild activates the local checkout without pulling. lunitely boot and update --boot stage the next boot without rebooting.

The production deploy wrapper pins an exact prod-pins SHA, rebuilds with --no-update-lock-file, checks health, and restores the previous generation on failure. It does not roll back mutable application data. Record successful runtime pins in the infrastructure lock for later administrator updates.

See the documentation site's deployment, updates, and release guide. Its Obtainium configuration uses a real JSON import and explicit self-hosted Forgejo source override. Sync it with release titles and APK layout after the central publication pipeline is finalized.