Nix
Copland OS uses Nix to evaluate its configuration and build the system. It provides its own system modules and activation process rather than using the full upstream NixOS module stack.
Many design decisions and parts of the implementation come from nixpkgs and finix. Both projects deserve credit for that foundation.
OpenRC
Copland OS uses OpenRC for init and service management. We prefer its shell-based service scripts and explicit dependencies because they make service behavior straightforward to inspect and adapt. Services are declared in Nix, and Copland generates the corresponding OpenRC scripts and runlevel entries.
Generations
A system generation is a built version of your system configuration. It contains the selected software, generated configuration files, boot files and activation scripts.
Modules
Nix modules describe the desired configuration. For example, this module adds Git to the system packages and selects the system timezone:
{ pkgs,
...
}:
{
environment.systemPackages = [
pkgs.git
];
time.timeZone = "Europe/Berlin";
}
Evaluation
The module system combines the imported modules, resolves option values and checks their types. Nix uses the resulting configuration to describe the packages, files and scripts to build.
Build
The build produces a system at its own Nix store path, building dependencies or obtaining them from a configured binary cache. The previous generation stays intact, and the running system remains unchanged until activation.
Activation
Activation applies the generation to the machine by preparing system files, accounts, declared storage and secrets. During a live switch, Copland then updates the running OpenRC services to match the new configuration.
Switching and rollback
When switching to another system generation, Copland applies the new configuration and updates the running services. Changed or removed services are stopped using their old definitions. OpenRC then starts the services selected by the new configuration, and Copland checks their status before completing the switch.
Automatic rollback
If the new configuration cannot be activated or its services fail to start, Copland switches back to the previous generation and starts its services again. This helps keep the system usable when an update fails.
We are aware that not every service failure needs to trigger a rollback. Sometimes it is fine to complete the switch and start a service manually later. We plan to make this configurable.
Generations and snapshots
System generations and ZFS snapshots serve different purposes. A generation keeps the system configuration and software available, while a snapshot preserves the contents of a dataset. Copland does not create or restore ZFS snapshots as part of a system switch, so rolling back a generation leaves application data in place.
ZFS
ZFS is the primary filesystem supported by Copland OS. The native Live ISO includes ZFS support and installs the kernel-matched modules through Nix.
Datasets
ZFS is also used for persistent service state. A stateful service can declare its own dataset, mountpoint, ownership, and quota. During activation, Copland creates missing datasets, mounts them, applies their settings, and verifies that the expected dataset is mounted at the expected path.
The service configuration remains reproducible while its data stays outside the Nix store. The dataset can then use the normal ZFS tools for snapshots, backups, exports, and transfers between systems.
Secrets
Secret management is built into Copland through its native age module. No separate integration such as sops-nix is needed to declare encrypted secrets alongside the system configuration.
Encrypted files can stay in the repository and are decrypted on the target machine during activation. Copland manages their installation paths, ownership, permissions, and lifecycle, with decrypted files normally stored below /run/secrets.
A secret can also declare which OpenRC services should restart when its encrypted source changes. This connects secret updates to the normal system switch without requiring a separate manual restart.
Copland Home
Copland Home covers the same general area as upstream Home Manager, but takes a different approach and uses its own evaluator and activation program instead of importing Home Manager.
Non-editable configuration
Generated configuration and other stable files belong to the "set and forget" side of a Home generation. Their installed files are read-only links into the Nix store. To change them, edit their source or Nix declaration and build and activate a new Home generation.
Editable configuration
Editable files are linked directly to their source outside the Nix store. A Mango or shell configuration can be changed by editing the original file, without translating it into Nix syntax or rebuilding the Home configuration after every change. These links use string sources and depend on the original file being available.
Hybrid configuration
Hybrid files combine direct editing with a stored fallback. With a Nix path and live = true, activation links the editable checkout file when it is available and otherwise links the read-only copy from the Home generation. This keeps the configuration usable on a machine without the checkout.
Home activation
A Home generation also contains managed directories, session variables, and OpenRC user services. Its activation checks for conflicting files before changing anything and restores the previous links and profile if the switch fails.