Configuration¶
pynix reads a default for the options that repeat across the commands, so a
profile does not have to state them on each invocation.
Where a value comes from¶
Four layers. The first one that names a value wins:
the flag on the command line
the environment
$XDG_CONFIG_HOME/pynix/config.tomlthe built-in default
$ pynix build --store local ... # the flag
$ PYNIX_STORE=daemon pynix build ... # the environment
XDG_CONFIG_HOME defaults to ~/.config. PYNIX_CONFIG names another file,
for a user who keeps more than one profile. A file that is not there is not an
error.
The file¶
[defaults]
store = "daemon"
verbosity = "notice"
print-build-logs = true
[nix]
substituters = ["https://cache.nixos.org/", "https://mine.example/"]
trusted-public-keys = ["cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY="]
max-jobs = 8
[defaults] holds the options of pynix itself. Each key is the option
without the leading dashes, and the environment variable is PYNIX_ with the
name in capitals: store is PYNIX_STORE.
[nix] holds the Nix settings, under the names that nix.conf uses. The
environment variable is PYNIX_NIX_ with the name in capitals: max-jobs is
PYNIX_NIX_MAX_JOBS.
A setting that takes more than one value takes a TOML array, and it also takes
the nix.conf spelling:
[nix]
substituters = "https://cache.nixos.org/ https://mine.example/"
The second spelling is the one that an environment variable needs, because a variable carries one string:
$ export PYNIX_NIX_SUBSTITUTERS='https://cache.nixos.org/ https://mine.example/'
$ export PYNIX_NIX_ACCESS_TOKENS='github.com=<token>'
Turning off an option that the file turns on¶
print-build-logs is a flag, so a file that sets it to true would leave no
way to turn it off. Each such option has a negative form:
$ pynix build --no-print-build-logs ...
The two variables a completion reads¶
A Tab evaluates Nix, so it has a budget. These two are read from the environment alone: they are not options of the command, they have no entry in the configuration file, and they do not go through the settings model. A completion runs on every keypress that ends in Tab, and a settings tree costs more than the number is worth.
variable |
default |
what it does |
|---|---|---|
|
|
Seconds a completion may take. When it runs out, the completion offers nothing, and the shell shows what it shows when no program answers. |
|
unset |
A file name. A completion that fails writes its traceback there. |
Raise the budget when you complete against something large and you would rather wait:
$ export PYNIX_COMPLETION_BUDGET=15
A completion that answers nothing looks the same whatever went wrong. That
is deliberate -- a traceback would land in the middle of your command line --
and it means a defect here is invisible. PYNIX_COMPLETION_DEBUG is the way
to look.
The budget does not stop a flake input that never answers. The fetch runs below the layer that the budget cancels, so a flake with an unreachable input outlasts it. Issue #231 holds that.
What a Tab for --flake reads¶
Before the #, --flake completes a flake reference, and it reads the same
three sources nix reads: the bare ., the directories under what you have
typed, and every layer of the flake registry.
The registry can download. The global layer names a URL in the
flake-registry setting, and Nix fetches it. That is what nix does on the
same keypress, and the result is cached for tarball-ttl seconds, so only the
first Tab of an hour pays for it. Measured: 0.54 s warm, 4.10 s with no
network and an expired cache, and Nix answers from the stale copy in that case
rather than failing.
A Tab downloads once, where a command downloads five times. Nix retries a
download download-attempts times with a backoff, waits connect-timeout
seconds for each, and lets a connected transfer go silent for
stalled-download-timeout seconds. The defaults are 5, 15 s and 300 s, and
each of them outlasts a keypress. A completion sets them to 1, 3 s and 3 s.
Only a completion reads these values; a real command keeps the patient ones.
Measured. With no network, the registry call gives up after 4.646 s at the defaults and after 0.002 s at one attempt, and the first figure is over the budget. Against a socket that accepts the connection and then never writes, the call outlasted 25 s at the default stall timeout and gave up after 3.004 s at three seconds.
Those three bound what Nix fetches with curl, which is the registry and any
tarball. A git+https: flake input runs git as a separate process, which
reads none of them, so a completion sets git's own pair as well:
GIT_HTTP_LOW_SPEED_LIMIT=1 and GIT_HTTP_LOW_SPEED_TIME=2. If you have set
either yourself, yours is kept.
Measured against a server that accepts the connection and then writes
nothing, completing a flake whose one input names it: at git's defaults the
completion outlasted 120 s and had to be killed, and with the pair it answered
nothing after 4.6 s and left no git process behind. Two seconds and not
three, because Nix retries the fetch once and the budget is five.
A Tab still completes with no network, and under nix it does not.
getRegistries builds all four registry layers before it returns any of them,
so nix throws away your /etc/nix/registry.json and your own
registry.json whenever it cannot reach the global one. Measured on a machine
that pins nixpkgs in its system registry: nix build nixp<TAB> with an
unreachable registry offers nothing at all. pynix asks again without the
global layer and offers what the local ones hold.
flake-registry in your nix.conf reaches this program. It did not
until issue #234. Nix keeps four settings registries, and nix.conf fills in
only what is registered with globalConfig; libcmd is what registers the
other three, and nanopynix does not link libcmd. So every fetch setting came
from the caller and none from the file, and flake-registry was absent from
nanopynix.list_settings().
nanopynix now registers one object of each kind, which is what
src/libcmd/common-eval-args.cc does. Each call still builds its own
settings, and it starts from what the file said rather than from the compiled
default. A value you pass still wins over the file, as it does in nix.
What pynix build does not need¶
nix build writes a result symlink, which is a GC root, and it prints
nothing unless it is told to. pynix build creates no symlink and no root,
and it prints the outputs as JSON. There is no --no-link to configure,
because there is no link.
To make a root, ask for one: pynix store add-root <path> <link>.