cc69486cead8
add flake.nix, nixos-module.nix; rewrite install.sh with ASCII banner, NixOS nix profile/nix-shell paths, and update reminder
- time
- 2026-06-04 16:15 UTC · 4 months ago
- machine
- koh2
- agent
- claude-sonnet-4-6
- session
- install script and kepr setup
- parent
- c10740f41f1a
↓ nina-cc69486c.tar.gzatlas at this save
files changed3 files
flake.nix+59 −0install.sh+157 −50nixos-module.nix+43 −0flake.nix+59 −0
@@ -0,0 +1,59 @@1+{2+ description = "nina — the nix helper";3+4+ inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";5+6+ outputs = { self, nixpkgs }:7+ let8+ systems = [ "x86_64-linux" "aarch64-linux" "aarch64-darwin" "x86_64-darwin" ];9+ forSystems = f: nixpkgs.lib.genAttrs systems f;10+ version = builtins.replaceStrings [ "\n" "\r" " " "\t" ] [ "" "" "" "" ]11+ (builtins.readFile ./VERSION);12+ in {13+ packages = forSystems (system:14+ let pkgs = nixpkgs.legacyPackages.${system};15+ in rec {16+ nina = pkgs.stdenv.mkDerivation {17+ pname = "nina";18+ inherit version;19+ src = self;20+ nativeBuildInputs = [ pkgs.zig_0_16 ];21+ dontConfigure = true;22+ buildPhase = ''23+ export ZIG_GLOBAL_CACHE_DIR="$TMPDIR/zig-cache"24+ zig build -Doptimize=ReleaseSafe25+ '';26+ installPhase = ''27+ install -Dm755 zig-out/bin/nina $out/bin/nina28+ '';29+ meta = with nixpkgs.lib; {30+ description = "The nix helper — manage your NixOS system from the command line";31+ mainProgram = "nina";32+ platforms = platforms.unix;33+ license = licenses.mit;34+ };35+ };36+ default = nina;37+ }38+ );39+40+ nixosModules.default = { config, pkgs, lib, ... }:41+ let cfg = config.programs.nina;42+ in {43+ options.programs.nina = {44+ enable = lib.mkEnableOption "nina, the NixOS helper";45+ package = lib.mkOption {46+ type = lib.types.package;47+ default = self.packages.${pkgs.system}.default;48+ defaultText = lib.literalExpression "nina.packages.\${pkgs.system}.default";49+ description = "The nina package to install.";50+ };51+ };52+ config = lib.mkIf cfg.enable {53+ environment.systemPackages = [ cfg.package ];54+ };55+ };56+57+ nixosModules.nina = self.nixosModules.default;58+ };59+}install.sh+157 −50
@@ -2,18 +2,14 @@22 # nina install script33 # Run: curl -fsSL kepr.uk/nina/install.sh | sh44 # Or: NINA_INSTALL_DIR=/usr/local/bin sh install.sh5-#6-# Downloads the pre-built binary from Kepr for your platform.7-# Falls back to building from source (requires Zig 0.16+) if unavailable.85 96 set -e107 8+FLAKE_URL="https://kepr.uk/nina/archive/HEAD.tar.gz"119 RELEASES_URL="https://kepr.uk/api/nina/releases/latest"12-SOURCE_URL="https://kepr.uk/nina/archive/HEAD.tar.gz"1310 INSTALL_DIR="${NINA_INSTALL_DIR:-$HOME/.local/bin}"1411 MIN_ZIG_MINOR=161512 16-# Detect platform1713 os="$(uname -s)"1814 arch="$(uname -m)"1915 case "${os}-${arch}" in@@ -22,28 +18,55 @@2218 Darwin-arm64) platform="macos-aarch64" ;;2319 Darwin-x86_64) platform="macos-x86_64" ;;2420 *)25- printf 'nina install: unsupported platform %s-%s\n' "$os" "$arch" >&226- printf ' build from source with Zig 0.%s+:\n' "$MIN_ZIG_MINOR" >&227- printf ' zig build -Doptimize=ReleaseSafe\n' >&221+ printf 'nina: unsupported platform %s-%s\n' "$os" "$arch" >&22822 exit 1 ;;2923 esac3024 31-have() { command -v "$1" >/dev/null 2>&1; }32-say() { printf 'nina install: %s\n' "$1"; }33-die() { say "error: $1" >&2; exit 1; }25+have() { command -v "$1" >/dev/null 2>&1; }26+say() { printf 'nina: %s\n' "$1"; }27+die() { say "error: $1" >&2; exit 1; }28+blank() { printf '\n'; }29+is_nixos() { [ -e /etc/NIXOS ]; }3430 3531 fetch_text() {3632 if have curl; then curl -fsSL "$1"3733 elif have wget; then wget -qO- "$1"38- else die "curl or wget is required"; fi34+ else die "curl or wget required"; fi3935 }4036 4137 fetch_file() {4238 if have curl; then curl -fsSL "$1" -o "$2"4339 elif have wget; then wget -qO "$2" "$1"44- else die "curl or wget is required"; fi40+ else die "curl or wget required"; fi4541 }4642 43+# ── banner ────────────────────────────────────────────────────────────────────44+45+banner() {46+ cat <<'BANNER'47+48+ _ __ _ _ __ __ _49+ | '_ \ (_)| '_ \ / _` |50+ | | | || || | | || (_| |51+ |_| |_||_||_| |_| \__,_|52+53+ the nix helper · kepr.uk/nina54+55+BANNER56+}57+58+# ── fetch source archive ──────────────────────────────────────────────────────59+60+fetch_source() {61+ srcdir="$(mktemp -d /tmp/nina-src.XXXXXX)"62+ say "fetching source from Kepr..."63+ fetch_file "$FLAKE_URL" "${srcdir}/nina.tar.gz" \64+ || die "could not download source archive — check your connection"65+ tar -xzf "${srcdir}/nina.tar.gz" -C "$srcdir" --strip-components=1 \66+ || die "could not extract source archive"67+ printf '%s' "$srcdir"68+}69+4770 # ── binary install from Kepr ─────────────────────────────────────────────────4871 4972 install_binary() {@@ -75,7 +98,6 @@7598 cksum_raw="$(printf '%s' "$meta" | jq -r ".platforms.\"${platform}\".blake3 // .platforms.\"${platform}\".checksum // empty")"7699 cksum="${cksum_raw#blake3:}"77100 else78- # Minimal grep/sed fallback for compact JSON79101 version="$(printf '%s' "$meta" | grep -o '"version":"[^"]*"' | sed 's/"version":"//;s/"//')"80102 plat_block="$(printf '%s' "$meta" | grep -o "\"${platform}\":{[^}]*}" | head -1)"81103 dl_url="$(printf '%s' "$plat_block" | grep -o '"url":"[^"]*"' | sed 's/"url":"//;s/"//')"@@ -92,7 +114,7 @@92114 if [ -n "$cksum" ] && have b3sum; then93115 actual="$(b3sum --no-names "$tmpfile" 2>/dev/null | awk '{print $1}')"94116 if [ "$actual" != "$cksum" ]; then95- say "blake3 checksum mismatch — aborting"117+ say "checksum mismatch — aborting"96118 rm -f "$tmpfile"97119 return 198120 fi@@ -106,68 +128,128 @@106128 return 0107129 }108130 131+# ── NixOS: nix profile install (primary) ─────────────────────────────────────132+133+nixos_profile_install() {134+ have nix || return 1135+ say "installing via nix profile install..."136+ blank137+ if nix profile install "$FLAKE_URL"; then138+ return 0139+ fi140+ blank141+ say "nix profile install failed. Common causes:"142+ say " flakes not enabled — add to /etc/nix/nix.conf or ~/.config/nix/nix.conf:"143+ say " experimental-features = nix-command flakes"144+ say " once nina is installed: nina setup enables this automatically"145+ blank146+ return 1147+}148+149+# ── NixOS: nix-shell source build (fallback) ──────────────────────────────────150+151+nixos_shell_build() {152+ have nix-shell || return 1153+ say "opening nix-shell with zig_0_16 and building nina from source..."154+ blank155+ srcdir="$(fetch_source)"156+ nix-shell -p zig_0_16 \157+ --run "cd '${srcdir}' && zig build -Doptimize=ReleaseSafe" \158+ || die "build failed — see output above"159+ mkdir -p "$INSTALL_DIR"160+ cp "${srcdir}/zig-out/bin/nina" "${INSTALL_DIR}/nina"161+ chmod +x "${INSTALL_DIR}/nina"162+ blank163+ say "installed from source → ${INSTALL_DIR}/nina"164+ say "note: this binary was built outside of nix — adopt ~/nina.nix into your"165+ say "configuration.nix to make it nix-managed."166+}167+168+# ── generate ~/nina.nix ───────────────────────────────────────────────────────169+170+generate_nixos_module() {171+ # Write ~/nina.nix without invoking shell substitution on the nix code inside.172+ cat > "$HOME/nina.nix" <<'NIXEOF'173+# ~/nina.nix — generated by the nina installer174+#175+# Declares nina as a NixOS system package.176+#177+# Add to /etc/nixos/configuration.nix:178+# imports = [ /home/YOUR_USER/nina.nix ];179+# Then: sudo nixos-rebuild switch180+#181+# For flake-based configurations, add nina as a flake input instead:182+# inputs.nina.url = "https://kepr.uk/nina/archive/HEAD.tar.gz";183+# # in your modules: nina.nixosModules.default184+# # then set: programs.nina.enable = true;185+#186+# To update nina: nina update187+{ ... }:188+{189+ imports = [190+ "${builtins.fetchTarball "https://kepr.uk/nina/archive/HEAD.tar.gz"}/nixos-module.nix"191+ ];192+ programs.nina.enable = true;193+}194+NIXEOF195+ blank196+ say "generated ~/nina.nix for system-wide installation:"197+ say " 1. add to /etc/nixos/configuration.nix:"198+ say " imports = [ /home/$(id -un)/nina.nix ];"199+ say " 2. sudo nixos-rebuild switch"200+}201+109202 # ── Zig version check ─────────────────────────────────────────────────────────110203 111204 check_zig() {112205 if ! have zig; then113- say ""114- say "Zig not found. Building nina from source requires Zig 0.${MIN_ZIG_MINOR} or later."115- say ""116- say " NixOS:"117- say " nix profile install 'nixpkgs#zig_0_16' # if your channel has it"118- say " nix-shell -p zig_0_16 --run 'sh install.sh'"119- say " # or add 'pkgs.zig_0_16' to environment.systemPackages and rebuild"120- say ""121- say " Direct download: https://ziglang.org/download/"122- say ""123- die "Zig 0.${MIN_ZIG_MINOR}+ required for source build"206+ blank207+ say "Zig not found. Building nina requires Zig 0.${MIN_ZIG_MINOR}+."208+ blank209+ say " Download: https://ziglang.org/download/"210+ if is_nixos; then211+ say " NixOS: nix-shell -p zig_0_16 --run 'sh install.sh'"212+ fi213+ blank214+ die "Zig 0.${MIN_ZIG_MINOR}+ required"124215 fi125216 126217 zig_ver="$(zig version 2>/dev/null)"127218 major="$(printf '%s' "$zig_ver" | cut -d. -f1)"128219 minor="$(printf '%s' "$zig_ver" | cut -d. -f2)"129-130220 ok=0131221 [ "$major" -ge 1 ] 2>/dev/null && ok=1132222 [ "$major" -eq 0 ] 2>/dev/null && [ "$minor" -ge "$MIN_ZIG_MINOR" ] 2>/dev/null && ok=1133223 134224 if [ "$ok" -ne 1 ]; then135- say ""136- say "Found zig ${zig_ver}, but nina requires Zig 0.${MIN_ZIG_MINOR} or later."137- say ""138- say " NixOS: the system 'zig' package is ${zig_ver}. To get 0.16:"139- say " nix profile install 'nixpkgs#zig_0_16'"140- say " nix-shell -p zig_0_16 --run 'sh install.sh'"141- say " # or check nixpkgs-unstable if your stable channel lacks zig_0_16"142- say ""143- say " Direct download: https://ziglang.org/download/"144- say ""225+ blank226+ say "found zig ${zig_ver}, but nina requires Zig 0.${MIN_ZIG_MINOR}+."227+ if is_nixos; then228+ say " run: nix-shell -p zig_0_16 --run 'sh install.sh'"229+ else230+ say " update: https://ziglang.org/download/"231+ fi232+ blank145233 die "Zig 0.${MIN_ZIG_MINOR}+ required; found ${zig_ver}"146234 fi147235 148236 say "zig ${zig_ver} found"149237 }150238 151-# ── source build fallback ─────────────────────────────────────────────────────239+# ── generic source build (non-NixOS) ─────────────────────────────────────────152240 153241 build_from_source() {154- say "falling back to build from source..."242+ say "building from source..."155243 check_zig156244 157245 if [ -f "build.zig" ] && [ -f "src/main.zig" ]; then158246 srcdir="."159247 else160- say "fetching source archive from Kepr..."161- srcdir="$(mktemp -d /tmp/nina-src.XXXXXX)"162- fetch_file "$SOURCE_URL" "${srcdir}/nina.tar.gz" \163- || die "could not download source archive"164- tar -xzf "${srcdir}/nina.tar.gz" -C "$srcdir" --strip-components=1 \165- || die "could not extract source archive"248+ srcdir="$(fetch_source)"166249 fi167250 168- say "building (this may take a moment)..."169251 (cd "$srcdir" && zig build -Doptimize=ReleaseSafe) \170- || die "build failed — see output above for details"252+ || die "build failed — see output above"171253 172254 mkdir -p "$INSTALL_DIR"173255 cp "${srcdir}/zig-out/bin/nina" "${INSTALL_DIR}/nina"@@ -181,22 +263,47 @@181263 case ":${PATH}:" in182264 *":${INSTALL_DIR}:"*) ;;183265 *)184- say ""266+ blank185267 say "${INSTALL_DIR} is not in your PATH. Add it:"186268 say " export PATH=\"\${PATH}:${INSTALL_DIR}\""187269 say " echo 'export PATH=\"\${PATH}:${INSTALL_DIR}\"' >> ~/.bashrc"188- say " # NixOS: add '${INSTALL_DIR}' to environment.sessionVariables in configuration.nix"270+ if is_nixos; then271+ say " NixOS: add to environment.sessionVariables in configuration.nix"272+ fi189273 ;;190274 esac191275 }192276 193277 # ── main ──────────────────────────────────────────────────────────────────────194278 279+banner280+281+if is_nixos; then282+ say "NixOS detected"283+ if nixos_profile_install; then284+ generate_nixos_module285+ blank286+ say "to update nina: nina update"287+ exit 0288+ fi289+ nixos_shell_build290+ generate_nixos_module291+ check_path292+ blank293+ say "to update nina: nina update"294+ exit 0295+fi296+297+# macOS / generic Linux: download binary, fall back to source build195298 if install_binary; then196299 check_path300+ blank301+ say "to update nina: nina update"197302 exit 0198303 fi199304 200-say "pre-built binary unavailable for ${platform} — trying source build"305+say "no pre-built binary for ${platform} — falling back to source build"201306 build_from_source202307 check_path308+blank309+say "to update nina: nina update"nixos-module.nix+43 −0
@@ -0,0 +1,43 @@1+# Standalone NixOS module for nina — no flake inputs needed.2+# Generated by the installer into ~/nina.nix. Also importable directly.3+#4+# Usage (in configuration.nix):5+# imports = [6+# "${builtins.fetchTarball "https://kepr.uk/nina/archive/HEAD.tar.gz"}/nixos-module.nix"7+# ];8+# programs.nina.enable = true;9+#10+# For flake-based configs use the flake input instead — see flake.nix.11+{ config, pkgs, lib, ... }:12+let13+ nina-pkg = pkgs.stdenv.mkDerivation {14+ pname = "nina";15+ version = builtins.replaceStrings [ "\n" "\r" " " "\t" ] [ "" "" "" "" ]16+ (builtins.readFile ./VERSION);17+ src = ./.;18+ nativeBuildInputs = [ pkgs.zig_0_16 ];19+ dontConfigure = true;20+ buildPhase = ''21+ export ZIG_GLOBAL_CACHE_DIR="$TMPDIR/zig-cache"22+ zig build -Doptimize=ReleaseSafe23+ '';24+ installPhase = "install -Dm755 zig-out/bin/nina $out/bin/nina";25+ meta = {26+ description = "The nix helper — manage your NixOS system from the command line";27+ mainProgram = "nina";28+ };29+ };30+ cfg = config.programs.nina;31+in {32+ options.programs.nina = {33+ enable = lib.mkEnableOption "nina, the NixOS helper";34+ package = lib.mkOption {35+ type = lib.types.package;36+ default = nina-pkg;37+ description = "The nina package to install.";38+ };39+ };40+ config = lib.mkIf cfg.enable {41+ environment.systemPackages = [ cfg.package ];42+ };43+}