~/bend-docscommunity

domain/architecture/system/deployment/nix_darwin/ops.bend source

domain/architecture/system/deployment/nix_darwin/ops.bend on the hub · documented module

import Baseimport ./type.bend as NDimport ./service/type.bend as Svimport ./service/ops.bend as SvOimport ../../container/type.bend as Ctdef user(nd: ND.NixDarwin) -> String:  match nd:    case ND.NixDarwin{_, _, u, _, _, _, _, _, _, _, _, _, _, _}:      udef tailscale(nd: ND.NixDarwin) -> Bool:  match nd:    case ND.NixDarwin{_, _, _, _, t, _, _, _, _, _, _, _, _, _}:      tdef services(nd: ND.NixDarwin) -> List<&2, Sv.Service>:  match nd:    case ND.NixDarwin{_, _, _, _, _, _, _, _, ss, _, _, _, _, _}:      ssdef serves(nd: ND.NixDarwin) -> List<&2, ND.Serve>:  match nd:    case ND.NixDarwin{_, _, _, _, _, _, _, _, _, ss, _, _, _, _}:      ssdef listeners(nd: ND.NixDarwin) -> List<&2, ND.Listening>:  match nd:    case ND.NixDarwin{_, _, _, _, _, _, _, _, _, _, ls, _, _, _}:      lsdef kept(nd: ND.NixDarwin) -> List<&2, String>:  match nd:    case ND.NixDarwin{_, _, _, _, _, _, _, _, _, _, _, k, _, _}:      kdef serve_container(s: ND.Serve) -> String:  match s:    case ND.Serve{c, _, _, _}:      cdef serve_https(s: ND.Serve) -> U32:  match s:    case ND.Serve{_, h, _, _}:      hdef serve_port(s: ND.Serve) -> U32:  match s:    case ND.Serve{_, _, p, _}:      p# What Tailscale proxies a serve to.def serve_target(s: ND.Serve) -> String:  match s:    case ND.Serve{_, _, p, path}:      "http://127.0.0.1:" ++ U32.show(p) ++ pathdef listening_process(l: ND.Listening) -> String:  match l:    case ND.Listening{p, _}:      pdef listening_processes(xs: List<&2, ND.Listening>) -> List<&2, String>:  match xs:    case []:      []    case l <> rest:      listening_process(l) <> listening_processes(rest)# ---- the nix-darwin flake: pinned inputs, the Mac's module, and one launchd job per service ----def tailscale_line(on: Bool) -> String:  match on:    case True{}:      "      services.tailscale.enable = true;\n"    case False{}:      ""# `lets` are Nix bindings the jobs may use (e.g. a derivation); `config` is extra nix-darwin config lines.def flake(nd: ND.NixDarwin) -> String:  match nd:    case ND.NixDarwin{host, platform, +u, +logs, t, _, _, _, ss, _, _, _, lets, config}:      "# Generated by V from the architecture. Do not edit.\n" ++      "{\n" ++      "  inputs.nixpkgs.url = \"github:NixOS/nixpkgs/nixpkgs-unstable\";\n" ++      "  inputs.nix-darwin.url = \"github:nix-darwin/nix-darwin/master\";\n" ++      "  inputs.nix-darwin.inputs.nixpkgs.follows = \"nixpkgs\";\n" ++      "  outputs = { nixpkgs, nix-darwin, ... }: {\n" ++      "    darwinConfigurations." ++ host ++ " = nix-darwin.lib.darwinSystem {\n" ++      "      system = \"" ++ platform ++ "\";\n" ++      "      modules = [ ./mac.nix ({ pkgs, ... }: let\n" ++ lets ++      "      in {\n" ++ config ++ tailscale_line(t) ++ SvO.jobs(ss, u, logs) ++ "      }) ];\n    };\n  };\n}"# The Tailscale CLI: Nix's when Nix runs Tailscale, else the app's.def tailscale_command(nd: ND.NixDarwin) -> String:  Bool.pick(String, tailscale(nd), "/run/current-system/sw/bin/tailscale", "/Applications/Tailscale.app/Contents/MacOS/Tailscale")# ---- laws of a system with this node ----# 0 is not a port.def fresh(+p: U32, ps: List<&2, U32>) -> Bool:  U32.is_eq(p, 0) || Bool.not(List.contains(~U32, ~U32.is_eq, ps, p))def distinct(ps: List<&2, U32>) -> Bool:  match ps:    case []:      True{}    case +p <> +rest:      fresh(p, rest) && distinct(rest)def https_ports(xs: List<&2, ND.Serve>) -> List<&2, U32>:  match xs:    case []:      []    case s <> rest:      serve_https(s) <> https_ports(rest)# No two serves share a tailnet HTTPS port.def serve_ports_distinct(nd: ND.NixDarwin) -> Bool:  distinct(https_ports(serves(nd)))def belongs(l: ND.Listening, +keys: List<&2, String>) -> Bool:  match l:    case ND.Listening{_, +o}:      String.eq(o, "macos") || List.contains(~String, ~String.eq, keys, o)def all_belong(xs: List<&2, ND.Listening>, +keys: List<&2, String>) -> Bool:  match xs:    case []:      True{}    case l <> rest:      belongs(l, keys) && all_belong(rest, keys)# Every allowed listener belongs to macOS or to one of `keys` (the system's containers and nodes).def listeners_belong(nd: ND.NixDarwin, +keys: List<&2, String>) -> Bool:  all_belong(listeners(nd), keys)def services_among(xs: List<&2, Sv.Service>, +instances: List<&2, String>) -> Bool:  match xs:    case []:      True{}    case s <> rest:      List.contains(~String, ~String.eq, instances, SvO.container(s)) && services_among(rest, instances)def serves_among(xs: List<&2, ND.Serve>, +instances: List<&2, String>) -> Bool:  match xs:    case []:      True{}    case s <> rest:      List.contains(~String, ~String.eq, instances, serve_container(s)) && serves_among(rest, instances)# Services and serves run only containers this node runs.def services_on(+nd: ND.NixDarwin, +instances: List<&2, String>) -> Bool:  services_among(services(nd), instances) && serves_among(serves(nd), instances)def served(+k: String, xs: List<&2, ND.Serve>) -> Bool:  match xs:    case []:      False{}    case s <> rest:      String.eq(k, serve_container(s)) || served(k, rest)def is_tailnet(e: Ct.Exposure) -> Bool:  match e:    case Ct.Tailnet{}:      True{}    case _:      False{}def honest(c: Ct.Container, +ss: List<&2, ND.Serve>, +instances: List<&2, String>) -> Bool:  match c:    case Ct.Container{+k, _, _, _, _, e, _, _, _, _, _, _, _, _, _}:      Bool.not(List.contains(~String, ~String.eq, instances, k)) || Bool.not(Bool.xor(is_tailnet(e), served(k, ss)))def all_honest(cs: List<&2, Ct.Container>, +ss: List<&2, ND.Serve>, +instances: List<&2, String>) -> Bool:  match cs:    case []:      True{}    case c <> rest:      honest(c, ss, instances) && all_honest(rest, ss, instances)# A container on this node is on the tailnet exactly when a serve names it.def exposure_honest(nd: ND.NixDarwin, +cs: List<&2, Ct.Container>, +instances: List<&2, String>) -> Bool:  all_honest(cs, serves(nd), instances)# Services that start at login need the Mac to log its user in by itself.def survives_reboot(+nd: ND.NixDarwin, auto_login_user: String) -> Bool:  Bool.not(SvO.needs_login(services(nd))) || String.eq(auto_login_user, user(nd))