default.ix

default.ix

default.ix declares the machine: every package, service, and open port in one file. syntax is javascript, semantics are nix. the config lives in your repo, so the machine’s definition has a history, a diff, and a review like the rest of your code.

the platform’s first-class features are config options in the same file: secrets and network are declared next to the machine’s packages and services, in .ix or plain nix.

start a project

$ix initcreated default.ix$ix apply

ix init writes a minimal default.ix and touches nothing else. the first ix apply boots the machine and scaffolds flake.nix next to the config, pinning exactly what your machine builds from. commit both.

ix init -t github:owner/repo starts from a template instead: the generated flake points at the template and re-exports its configurations, so you edit your flake to diverge from it.

converge

ix apply makes the machine match the config, every time: edit, re-apply, converge. a re-apply of an unchanged config changes nothing. this is the nixos-rebuild switch contract, with the machine in the cloud instead of under your desk.

it splits as it grows

app/
// JavaScript syntax, Nix semantics. One VM; `ix apply` builds and
// activates it. The scaffold starts with one inline module; this project
// has grown into files.
export default ({ index }) => ({
  modules: [
    import("./modules/tools.ix"),
    import("./modules/web.ix"),
  ],
});

the config starts as one file and splits into modules when it grows. the project stays the single source of truth for the machine: group membership, public addresses, exposed ports, and secrets are all declared here rather than remembered by whoever typed a flag. see network and secrets.