on master help sign in
Make container.nix an attrset with packages and mounts; support ~/ expansion
commit69bd57314159a37117e98a9c0240655cb5785f19 authoriko <mail@iko.soy> dateSun 28 Jun 2026, 10:04 (3 months ago) parenta7ab8b2
3 files changed+33−19
README.md+19−11 c+11−6 flake.nix+3−2
README.md+19−11
@@ -27,18 +27,25 @@ per-project `container.nix`.
2727
2828## Packages
2929
30−`init` builds the image from a **`container.nix`** in the current directory — a
31−`{ pkgs, nur }` function returning the package list (`nur` is
32−[NUR](https://github.com/nix-community/NUR), for packages outside nixpkgs). It
33−is **required**; there is no default set.
30+`init` builds the image from a **`container.nix`** in the current directory — an
31+attrset with a `packages` function (`{ pkgs, nur }` returning the package list;
32+`nur` is [NUR](https://github.com/nix-community/NUR), for packages outside
33+nixpkgs) and an optional `mounts` list. It is **required**; there is no default.
3434
3535```nix
3636# ./container.nix
37−{ pkgs, nur }: with pkgs; [
38− git
39− go
40− nur.repos.charmbracelet.crush
41−]
37+{
38+ packages = { pkgs, nur }: with pkgs; [
39+ git
40+ go
41+ nur.repos.charmbracelet.crush
42+ ];
43+ # Extra "host:container" bind mounts, on top of $PWD → /workspace. A leading
44+ # ~/ in the host path expands to $HOME. Optional.
45+ mounts = [
46+ "~/data:/data"
47+ ];
48+}
4249```
4350
4451Your **host login shell** (detected by `c init`, bash fallback), **coreutils**,
@@ -70,7 +77,8 @@ nix run github:ilyakooo0/nix-container -- start
7077 directory at `/workspace` (the container's working directory).
7178- `--ssh` forwards your host SSH agent socket into the container (so `git` over
7279 SSH works with your keys).
73−- Add more mounts by passing them through (mounts can only be set at creation):
80+- Add more mounts persistently via `mounts` in `container.nix` (above), or
81+ ad-hoc by passing them through to `create` (mounts can only be set at creation):
7482
7583 ```sh
7684 nix run github:ilyakooo0/nix-container -- init -v $HOME/data:/data
@@ -99,7 +107,7 @@ name — in [`flake.nix`](./flake.nix). The flake also exposes build helpers:
99107
100108 ```sh
101109 drv=$(nix build --no-link --print-out-paths --impure --expr \
102− '(builtins.getFlake "github:ilyakooo0/nix-container").lib.${builtins.currentSystem}.copyWith (import ./container.nix)')
110+ '(builtins.getFlake "github:ilyakooo0/nix-container").lib.${builtins.currentSystem}.copyWith (import ./container.nix).packages')
103111 $drv/bin/copy-to docker://ghcr.io/me/img:latest
104112 ```
105113- `lib.<system>.mkImage <name> <shell>` → the underlying OCI image (`copyWith`
c+11−6
@@ -1,7 +1,7 @@
11#!/usr/bin/env fish
22# Manage a container named after the current directory.
33# c init [-c FILE] [extra create args] build + load the image, then (re)create it
4−# (packages from FILE, default ./container.nix)
4+# (config from FILE, default ./container.nix)
55# c start start it and attach
66
77set -l name (path basename $PWD)
@@ -22,8 +22,8 @@ switch $argv[1]
2222 end
2323
2424 if not test -e $config
25− echo "c: package file not found: $config" >&2
26− echo " create one ('{ pkgs, nur }: [ ... ]') or pass -c FILE" >&2
25+ echo "c: config file not found: $config" >&2
26+ echo " create one ('{ packages = { pkgs, nur }: [ ... ]; mounts = [ ]; }') or pass -c FILE" >&2
2727 exit 1
2828 end
2929
@@ -33,12 +33,12 @@ switch $argv[1]
3333 set -l shell bash
3434 test -n "$SHELL"; and set shell (path basename $SHELL)
3535
36− # Build an image with the packages from $config (plus the shell) into a
36+ # Build an image with the config's `packages` (plus the shell) into a
3737 # temp dir, load it, then clean up.
3838 set -l tmp (mktemp -d)
3939 set -l archive $tmp/image.tar.gz
4040 set -lx NIX_CONTAINER_PKGS (path resolve $config)
41− set -l expr "(builtins.getFlake \"$flake\").lib.\${builtins.currentSystem}.copyWithShell \"nix-container-$name\" \"$shell\" (import (/. + builtins.getEnv \"NIX_CONTAINER_PKGS\"))"
41+ set -l expr "(builtins.getFlake \"$flake\").lib.\${builtins.currentSystem}.copyWithShell \"nix-container-$name\" \"$shell\" (import (/. + builtins.getEnv \"NIX_CONTAINER_PKGS\")).packages"
4242 set -l copyer (nix build --impure --no-link --print-out-paths --expr "$expr")
4343 set -l rc $status
4444 if test $rc -eq 0
@@ -53,8 +53,13 @@ switch $argv[1]
5353 rm -rf $tmp
5454 test $rc -eq 0; or exit $rc
5555
56− # Mount the project at /workspace (the default cwd).
56+ # Mount the project at /workspace (the default cwd), plus any extra
57+ # mounts from the config (`mounts = [ "host:container" … ]`). A leading
58+ # ~/ in the host path expands to $HOME (nix leaves it literal).
5759 set -l mounts -v "$PWD:/workspace"
60+ for m in (nix eval --impure --raw --expr "builtins.concatStringsSep \"\n\" ((import (/. + builtins.getEnv \"NIX_CONTAINER_PKGS\")).mounts or [])")
61+ set -a mounts -v (string replace -r '^~/' "$HOME/" -- $m)
62+ end
5863
5964 # TERM to bake into the container env (`-e TERM`): the runtime hands the
6065 # `start -ai` session a bare "xterm", so set the host's real terminal,
flake.nix+3−2
@@ -176,10 +176,11 @@
176176 default = flake-utils.lib.mkApp { drv = cApp; };
177177 };
178178
179− # Build helpers honour a per-project `container.nix`. `c init` uses
179+ # Build helpers take a `{ pkgs, nur }: [ ... ]` packages function (the
180+ # `packages` attr of a project's `container.nix`). `c init` uses
180181 # `copyWithShell` (host shell baked in); `copyWith` is the generic form:
181182 # (builtins.getFlake "github:…/nix-container")
182− # .lib.<system>.copyWith (import ./container.nix)
183+ # .lib.<system>.copyWith (import ./container.nix).packages
183184 lib = {
184185 inherit mkImage;
185186 # Build the image's `copyTo` script (a skopeo-copy wrapper) from a