2 description = "A Nix-built OCI image for Apple's `container` CLI";
5 nixpkgs.url = "github:NixOS/nixpkgs";
6 flake-utils.url = "github:numtide/flake-utils";
7 nur.url = "github:nix-community/NUR";
9 url = "github:nlewo/nix2container";
10 inputs.nixpkgs.follows = "nixpkgs";
22 # Iterate over the systems you might run `nix run` from. The image
23 # *contents* are always Linux; the system here only decides where the
24 # `copyTo`/skopeo step executes (e.g. your Mac).
25 flake-utils.lib.eachSystem
35 # Map the host system to the Linux system the container targets, so
36 # `nix run` on a Mac still produces a Linux image.
39 aarch64-darwin = "aarch64-linux";
40 x86_64-darwin = "x86_64-linux";
41 aarch64-linux = "aarch64-linux";
42 x86_64-linux = "x86_64-linux";
48 aarch64-linux = "arm64";
49 x86_64-linux = "amd64";
53 pkgsLinux = import nixpkgs {
55 config.allowUnfree = true;
58 # NUR for the container's Linux arch. Pass BOTH `pkgs` and `nurpkgs`
59 # explicitly: otherwise the unset one defaults to `import <nixpkgs>`,
60 # which fails in pure flake eval. `pkgs` builds the repo packages, so
61 # give it `allowUnfree` (charmbracelet.crush is unfree); `nurpkgs` is
62 # only NUR's own machinery and can stay the plain set.
63 nurPkgs = import nur {
68 # nix2container instantiated for the host system, so `copyTo` and its
69 # skopeo run natively here while contents come from `pkgsLinux`.
70 n2c = nix2container.packages.${system}.nix2container;
72 # Host package set, for the wrapper app below.
73 pkgsHost = nixpkgs.legacyPackages.${system};
75 # Default image name (for `copyWith`); `c init` passes a per-directory
76 # name (`nix-container-<dir>`) to `copyWithShell` instead.
77 imageName = "nix-container";
80 # Build the OCI image (named `name`) from a `{ pkgs, nur }: [ ... ]`
81 # package function, for the named shell. The image's `cmd` is herdr
82 # (the session `c start` attaches to); the shell is the default `$SHELL`
83 # (what herdr panes spawn) and is added automatically, so `container.nix`
84 # lists only your extras. Nix (+ CA certs) and the ncurses terminfo
85 # database are always shipped too. Nothing here is fish-specific: the
86 # TERM fixup happens host-side in `c` (passed via `-e TERM` at create).
88 name: shell: packages:
94 # A plain, single-process root filesystem. No NixOS, no systemd.
95 # buildEnv only *symlinks* paths (never runs them), so build it on
96 # the host arch — the tree is arch-neutral and links the
97 # (substituted) Linux store paths, sparing the Linux builder.
98 copyToRoot = pkgsHost.buildEnv {
105 # The shell (cmd + $SHELL), when it exists in nixpkgs.
106 ++ pkgsLinux.lib.optional (pkgsLinux ? ${shell}) pkgsLinux.${shell}
110 # Basic userland (ls, cat, cp, sleep, …) so the container is
111 # usable out of the box and tools that shell out don't fail.
112 pkgsLinux.coreutils-full
113 # Networking glue glibc needs: /etc/nsswitch.conf (+passwd,
114 # group) so DNS/host lookups resolve, and /etc/protocols,
115 # /etc/services. Without these, hostname resolution fails.
118 # The terminfo database (+ tput/clear/reset) so TUIs find the
119 # entry for whatever TERM `c` passes in and render correctly.
121 # The session `c start` always launches.
124 # Link all of /etc so the above files (nsswitch.conf, protocols,
125 # services, passwd, group, ssl certs) are present.
132 initializeNixDatabase = true;
135 # `cmd` (not `entrypoint`): the default command, *replaced* by any
136 # command passed to `container run/create`. Plain herdr here;
137 # `c init` overrides it with `herdr session attach <dir>-container` so
138 # the session is named per project. `c start` attaches via
139 # `container start -ai`; exiting herdr (PID1) stops the container.
140 cmd = [ "/bin/herdr" ];
144 # Default shell for tools that spawn one (herdr panes, etc.).
145 "SHELL=/bin/${shell}"
146 # Marker so shells/scripts can detect they're in here.
148 # Advertise truecolor for 24-bit-aware tools; `c` passes the
149 # resolved TERM via -e (the runtime would otherwise force xterm).
150 "COLORTERM=truecolor"
151 # A UTF-8 locale so tools handle multibyte/wide characters
152 # correctly. glibc ships C.UTF-8 built in, so this needs no
155 # CA trust for every TLS client (curl/git/…) and Nix.
156 "SSL_CERT_FILE=/etc/ssl/certs/ca-bundle.crt"
157 "NIX_SSL_CERT_FILE=/etc/ssl/certs/ca-bundle.crt"
158 # Make the bundled Nix usable: flake commands on, and
159 # single-user (no daemon/nixbld).
160 "NIX_CONFIG=experimental-features = nix-command flakes\nbuild-users-group =\nsandbox = false"
165 # `nix run . -- init|start` runs the bundled `c` manager script. Its
166 # `init` builds the image from the project's `container.nix` (via
167 # `lib.copyWithShell`); the script finds the flake from its own (store)
168 # location, so this works from a checkout or straight from
169 # `nix run github:…/nix-container`.
170 cApp = pkgsHost.writeShellScriptBin "c" ''
171 exec ${pkgsHost.fish}/bin/fish ${self}/c "$@"
176 # nix run . -- init|start → build+load+create / start a container
177 default = flake-utils.lib.mkApp { drv = cApp; };
180 # Build helpers take a `{ pkgs, nur }: [ ... ]` packages function (the
181 # `packages` attr of a project's `container.nix`). `c init` uses
182 # `copyWithShell` (host shell baked in); `copyWith` is the generic form:
183 # (builtins.getFlake "github:…/nix-container")
184 # .lib.<system>.copyWith (import ./container.nix).packages
187 # Build the image's `copyTo` script (a skopeo-copy wrapper) from a
188 # `{ pkgs, nur }: [ ... ]` function, named `imageName`. Defaults the
189 # shell (cmd + $SHELL) to bash; use `copyWithShell` to pick another.
190 copyWith = packages: (mkImage imageName "bash" packages).copyTo;
191 # Like `copyWith`, but for the given image `name` and shell — `c init`
192 # passes `nix-container-<dir>` and the host login shell, which is added
193 # to the image and used as cmd + $SHELL without being listed in
195 copyWithShell = name: shell: packages: (mkImage name shell packages).copyTo;
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list