NixOS 18.03 puts Nix 2.0 into the stable system
NixOS 18.03 adopts Nix 2.0 and updates the system base, with module changes that distinguish declarative configuration from persistent service state.
An operating-system upgrade changes more than the versions of installed programs. It can alter how a service configuration is generated, which defaults a module selects, and where an application keeps its state. The NixOS 18.03 release notes, dated April 4, make those distinctions visible. Impala adopts Nix 2.0 while changing both the system base and the configuration interfaces for several services.
NixOS is interesting to me because a machine can be described declaratively. That does not make every upgrade consequence disappear into a package version. The value is that many of those consequences have explicit options and documented defaults, so the configuration can state the intended result. Persistent application data still needs its own transition rules.
The release moves the default kernel from 4.9 to 4.14, glibc from 2.25 to 2.26, GCC from 6 to 7, and systemd from 234 to 237. Its desktop updates include GNOME 3.26 and Plasma Desktop 5.12. These establish the new base, but the operational detail lies in how the distribution integrates it.
Nix 2.0 becomes the default
The Nix 2.0 release notes describe an experimental unified nix command and a broader store interface. NixOS 18.03 makes that package manager the default. This places the implementation changes in the stable distribution without making the experimental command interface a completed replacement for every older tool.
Store access becomes more consistent across local stores, daemon access, and binary caches. nix copy generalizes transfers that previously used separate commands. nix path-info can inspect different store types, and nix log can try a configured substituter when a build log is unavailable locally. These capabilities affect the operations surrounding a system build, including inspection of its dependencies and retrieval of diagnostics.
Nix 2.0 also changes substitution trust defaults and propagates signatures when copying paths. Its notes distinguish signatures from the local ultimately trusted marker, which does not propagate. That distinction remains relevant when distributing a system built elsewhere. A common store interface does not eliminate the receiving machine acceptance policy.
The package manager update therefore supplies more than a revised command spelling. It changes how tools address the stores that hold system results and how trust evidence follows those results. The NixOS release integrates those changes with its own module and package updates.
State compatibility has an explicit version boundary
The Impala notes identify changes that apply when stateVersion is set to 18.03 or higher. For older values, the previous behaviour is preserved. Their example is Matrix Synapse, whose default database changes from SQLite to PostgreSQL under the newer state setting. That is a different compatibility issue from selecting a newer executable.
A database default affects persistent data and service operation. It cannot be understood solely as another entry in the list of compiler or desktop updates. The explicit state-version condition lets a system use the newer distribution while retaining the older default for that service. The release notes link migration instructions for the database transition.
This is a useful boundary in a declarative system. The configuration can describe a new collection of packages without claiming that existing stored data has already migrated to every new preferred layout. A versioned default provides continuity until that transition is chosen and carried out. It also makes the reason for apparently older behaviour visible in the configuration.
I regard this distinction as central to evaluating declarative infrastructure. Rebuilding a system description and converting an application database are different operations. An upgrade mechanism is more useful when it names that difference than when it assumes a new package set can settle both automatically.
Renaming a service reaches beyond an option
The change from Piwik to Matomo is a concrete example. Package and service names change, but the release also renames the data directory and service user. It says files move automatically on first startup and ownership adjusts for the data directory. Those automatic steps cover specific parts of the transition.
Other references can remain outside those steps. Backup scripts that name the old directory need corresponding changes. Unix socket database authentication may require granting the renamed user access and changing the database username in the application configuration. A declared service rename does not rewrite every external consumer of its old identity.
The generated nginx server name changes too, including the configured domain when present. If the chosen server name changes, the application trusted-hosts setting must agree. This is a relationship between the generated web-server configuration and application state. The release describes both sides rather than treating the public hostname as an isolated option.
These details show why a module can automate some work while still documenting manual relationships. Moving files is a defined local action. Knowing every backup script or database access rule that refers to those files or their owner is a broader problem. The release states where its automatic transition ends.
Configuration generation has semantics
Postfix receives a different kind of correction. Dollar signs in list-valued service options now pass through to Postfix just as they already did for string-valued options. Postfix interprets them as parameter expressions, so a literal dollar sign requires doubling. The option type previously changed how the generated configuration treated the same punctuation.
The notes also repair merging in services.postfix.config. Options selected indirectly by other service settings can now merge correctly with user configuration. Where a value really needs to override another definition, the documented mechanisms are lib.mkForce or lib.mkOverride. Correct generation therefore depends on both string treatment and option merge rules.
This matters because a declarative value is not necessarily the final text an application reads. A module translates and combines definitions. Its semantics determine whether an expression remains literal, invokes application expansion, or replaces another contribution. The Postfix changes identify those semantics at the point where the previous behaviour was inconsistent.
Networking options become more explicit as well. Interface addresses use ipv4.addresses and ipv6.addresses, replacing older singular and abbreviated options. Separate route options describe static routing. These changes organize address and route declarations within the interface configuration, so existing descriptions need the corresponding option names.
Defaults alter exposure and access
The default Logstash listen address changes to 127.0.0.1, where the previous default listened on all interfaces. The same declarative omission therefore selects a different network exposure after the change. A configuration that requires remote access must express that requirement explicitly under the new default.
OpenSSH no longer enables DSA keys by default, and the release notes warn that this can prevent access for a system relying on them. They point to the earlier OpenSSH deprecation and document the compatibility setting. This is an authentication consequence of an updated default, distinct from whether the SSH service still starts.
Other defaults affect local behaviour. sound.enable becomes false. Libinput handles all input devices when enabled, which can interact with custom Xorg settings. ZNC mutable configuration defaults to true, so changing NixOS options no longer overwrites its old configuration by default. Each case changes what an omitted option means.
That is why version lists alone cannot explain an upgrade of a module-based distribution. Defaults are executable policy. They can alter a listener, access method, or application configuration ownership while leaving the general service name intact. The release notes make those policy changes explicit enough to compare with a machine description.
Platform support remains qualified
The release notes distinguish supported platform targets from the presence of binaries. They list x86_64 Linux and Darwin package support at release time, while pointing out that Darwin is not NixOS. They also say AArch64 Linux binaries are available but a channel is not yet available pending test fixes. A successful package build and a released distribution channel are separate milestones.
The release therefore combines a new package manager, a newer system base, and specific changes in configuration policy. Its more useful details are often the boundaries between those things. State-version conditions preserve selected old service defaults, module code performs defined migrations, and external references still require their corresponding identities and paths. Those distinctions explain what the stable system upgrade actually changes.
Prometheus exporter configuration also moves to submodules under services.prometheus.exporters. This gives the release another concrete configuration transition, where the relevant change is the module organization used to declare an exporter.