Vic's machines, homes and dev envs in Ren (built on Gen), a re-take on Den.
Generated file: edit modules/docs/, then run nix run .#write-files.
| Ren | in vix |
|---|---|
ren.kinds.<k> |
typed data: host, home, user, env |
ren.<k>.<name> |
an instance: ren.host.frodo, ren.user.vic, ren.env.rustenv |
below, spawns |
the scope tree: host → user, host → guest, system → vim |
is |
subkinds: a host is a machine, a guest is a host |
ren.aspects.<a> |
one feature: git, kvm-amd, vic-gui |
at |
where an aspect is on: at = ren.aspects.vic-headless |
includes, excludes |
add or drop aspects below a scope: frodo includes its hardware, its guests exclude it |
ren.classes.<c> |
a module system an aspect key feeds: nixos, vim |
into |
how a class builds: nixosConfigurations.<host> |
ren.channels.<c> |
data a feature emits for a receiver: git-ignores, checks |
fold, to |
how a channel merges, and who reads it: checks folds attrs into the fleet |
and, anyOf, not, within, has, when |
predicates for at and to: when (s: s.host.cpu == "amd") |
same |
identity: a guest runs on the host it names in on |
nix build .#nixosConfigurations.frodo.config.system.build.toplevel
nix build '.#homeConfigurations."vic@bitstream".activationPackage'
nix run .#write-files # regenerate this README
nix flake check # includes checks.x86_64-linux."files/README.md"
nix eval --json .#ci.matrix # every CI build job: host, mac, home, devshellGenerated from live Ren instances (ren.host, ren.mac, ren.guest, ren.home). JSON: nix build .#fleet-ir.
Scope tree: [host] (mac) [[guest]] [/home/] ((user)), grouped by system. Each machine spawns its own vic scope; drawn once.
flowchart LR
fleet_vix["vix"]
subgraph system_aarch64_darwin ["aarch64-darwin"]
mac_bert("bert")
mac_varda("varda")
end
subgraph system_aarch64_linux ["aarch64-linux"]
host_bill["bill"]
end
subgraph system_x86_64_linux ["x86_64-linux"]
host_annatar["annatar"]
host_bombadil["bombadil"]
host_frodo["frodo"]
host_mordor["mordor"]
host_nargun["nargun"]
host_nienna["nienna"]
host_smaug["smaug"]
host_tom["tom"]
guest_dnx[["dnx"]]
guest_gen[["gen"]]
home_bitstream[/"bitstream"/]
home_nargun[/"nargun"/]
end
user_vic(("vic"))
fleet_vix --> system_aarch64_darwin
fleet_vix --> system_aarch64_linux
fleet_vix --> system_x86_64_linux
host_frodo -->|"guest"| guest_dnx
host_frodo -->|"guest"| guest_gen
host_annatar --> user_vic
host_bombadil --> user_vic
host_frodo --> user_vic
host_mordor --> user_vic
host_nargun --> user_vic
host_nienna --> user_vic
host_smaug --> user_vic
mac_varda --> user_vic
guest_dnx --> user_vic
guest_gen --> user_vic
home_bitstream --> user_vic
home_nargun --> user_vic
Channels and class forwarding (diagrams)
Channels: emitter to receiver, one edge per ren.channels name.
flowchart LR
emitter_any_scope["any scope"]
emitter_env["env"]
emitter_env_lang_aspects["env-lang aspects"]
emitter_fmt_README_flake_nix_no_gui["fmt README flake.nix no-gui"]
emitter_host_mac_home_devshell["host mac home devshell"]
emitter_system["system"]
emitter_user["user"]
emitter_user_feature["user feature"]
receiver_ai_claude("ai-claude")
receiver_env_devshell_and_users("env devshell and users")
receiver_fish("fish")
receiver_flake_file_class("flake-file class")
receiver_flake_outputs("flake outputs")
receiver_git("git")
receiver_machine("machine")
receiver_machine_or_home("machine or home")
receiver_vic_dots("vic-dots")
receiver_vic_secrets("vic-secrets")
emitter_fmt_README_flake_nix_no_gui -->|"checks"| receiver_flake_outputs
emitter_host_mac_home_devshell -->|"ci-jobs"| receiver_flake_outputs
emitter_user_feature -->|"claude-allow"| receiver_ai_claude
emitter_env -->|"devshells"| receiver_flake_outputs
emitter_user_feature -->|"dots"| receiver_vic_dots
emitter_env_lang_aspects -->|"env-packages"| receiver_env_devshell_and_users
emitter_user_feature -->|"fish-functions"| receiver_fish
emitter_any_scope -->|"flake-inputs"| receiver_flake_file_class
emitter_system -->|"formatter"| receiver_flake_outputs
emitter_user_feature -->|"git-ignores"| receiver_git
emitter_user -->|"login-shells"| receiver_machine
emitter_any_scope -->|"nix-features"| receiver_machine
emitter_system -->|"packages"| receiver_flake_outputs
emitter_user_feature -->|"secrets"| receiver_vic_secrets
emitter_any_scope -->|"unfree"| receiver_machine_or_home
Class forwarding: solid edges carry live instance names, dashed edges are static.
flowchart LR
account["account"]
checks("checks")
darwin["darwin"]
darwinConfigurations("darwinConfigurations")
files["files"]
flake_file["flake-file"]
homeConfigurations("homeConfigurations")
homeDarwin["homeDarwin"]
homeLinux["homeLinux"]
homeManager["homeManager"]
microvm_vms("microvm.vms")
nixos["nixos"]
nixosConfigurations("nixosConfigurations")
os["os"]
packages("packages")
vim["vim"]
homeLinux -.->|"on linux"| homeManager
homeDarwin -.->|"on darwin"| homeManager
homeManager -->|"annatar, bombadil, frodo, mordor, nargun, nienna, smaug"| nixos
homeManager -->|"varda"| darwin
homeManager -->|"vic@bitstream, vic@nargun"| homeConfigurations
os -.-> nixos
os -.-> darwin
account -.->|"users.users"| nixos
account -.->|"users.users"| darwin
nixos -->|"dnx, gen in frodo"| microvm_vms
nixos -->|"annatar, bill, bombadil, frodo, mordor, nargun, nienna, smaug, tom"| nixosConfigurations
darwin -->|"bert, varda"| darwinConfigurations
vim -->|"astrovim, lazyvim, neovim, nvim, vscode-vim"| packages
files -.->|"write-files"| packages
files -.->|"files/README.md"| checks
flake_file -.->|"write-flake"| packages
flake_file -.->|"flake-file"| checks
Vocabulary: kinds, classes, channels, profiles
| kind | what it is | instances (ren.<kind>.<name>) |
|---|---|---|
channel |
the nixpkgs, home-manager and nix-darwin pins a machine builds with | unstable |
emacs |
an emacs distribution (data only, no scopes) | doom, spc |
env |
a dev environment: langs become a devshell and user packages | fullenv, goenv, nixenv, nodeenv, pyenv, rustenv |
fleet |
root scope; everything lives below it | vix |
guest |
a microvm on a host (is host): its own nixos and users, built inside the host | dnx, gen |
home |
a standalone home-manager home of one user | bitstream, nargun |
host |
a NixOS machine (is machine) | annatar, bill, bombadil, frodo, mordor, nargun, nienna, smaug, tom |
mac |
a nix-darwin machine (is machine) | bert, varda |
machine |
abstract: typed facts (cpu, form, desktops, users, envs) hosts and macs share | - (abstract) |
secret |
a sops secret a feature asks for | anthropic-api-key, copilot-api-key, edge-token, gemini-eco-key, groq-api-key, hello, openrouter-api-key, ssh-conf, ssh-id-ed25519, ssh-localhost-run |
ssh-host |
one ssh client matchBlock | edge, sini, uptermd.upterm.dev, vini, vini-tunnel |
system |
a nix system; machines, homes and envs are built for one | aarch64-darwin, aarch64-linux, x86_64-linux |
user |
a person: full name, email, login shell, admin | vic |
vim |
a neovim profile: a feature list built per system into one nvf package (+ a gui wrapper) | astrovim, lazyvim, neovim, nvim, vscode-vim |
workspace |
a project an isolated claude guest works on (data): repo path; one guest each | dnx, gen |
| class | builds |
|---|---|
account |
users.users.<user> on the user's machine |
darwin |
darwinConfigurations.<mac> |
files |
repo files (this README): packages.write-files + checks |
flake-file |
this flake.nix from flake-inputs: packages.write-flake + checks.<sys>.flake-file |
homeDarwin |
homeManager on darwin only |
homeLinux |
homeManager on linux only |
homeManager |
a user's home: on a host, on a mac, or homeConfigurations.<user>@<home> |
nixos |
nixosConfigurations.<host> |
os |
either OS: forwards to nixos or darwin |
vim |
nvf: one neovim per vim profile, emitted as packages. |
| channel | emitted by | received by |
|---|---|---|
checks |
formatter (fmt), files (README), flake-file (flake.nix), no-gui (headless homes and guests) | flake checks.<sys>.<name> |
ci-jobs |
every buildable host, mac, home and linux devshell | flake ci.matrix: one GitHub build job each |
claude-allow |
user features | ai-claude settings.json permissions |
devshells |
the devshell aspect, per env |
flake devShells.<sys> |
dots |
user features: { "<home path>" = "<dots path>"; } |
vic-dots: links into $HOME |
env-packages |
env-<lang> aspects |
the env's devshell, and users whose machine lists the env |
fish-functions |
user features | fish writes them once |
flake-inputs |
any aspect: the inputs it uses | forwarded into the flake-file class (x86_64-linux) |
formatter |
each system (treefmt) | flake formatter.<sys> (nix fmt) |
git-ignores |
user features | git global ignores |
login-shells |
users with a shell | their machine enables programs.<shell> |
nix-features |
any scope (base: nix-command flakes on every machine) | each machine's nix.settings.experimental-features |
packages |
aspects at a system | flake packages.<sys>, read back as (vix.perSystem pkgs inputs.self).packages |
secrets |
user features: [ ren.secret.x ] |
vic-secrets: sops-nix config |
unfree |
any scope: vix.allowUnfree [ … ] |
the machine or home's allowUnfreePredicate |
| name | active |
|---|---|
vic-full |
not on iso images (not within installer) |
vic-gui |
on-graphical: every gui program lives here |
vic-headless |
everywhere vic lives: terminal tools only (homes, guests, servers) |
vic-secrets |
on-trusted; also the sops consumer |
role graphical |
hosts with desktops or wsl, workstation macs (from facts) |
role installer |
iso hosts (from facts) |
role metal |
a nixos host that is not a guest: builds nixosConfigurations |
role on-darwin |
a user on a mac or darwin home (homeDarwin) |
role on-graphical |
a user within graphical, no non-graphical guest between |
role on-linux |
a user on a linux machine or home (homeLinux) |
role on-trusted |
a user within trusted, no untrusted guest between |
role trusted |
included by a machine: holds vic's secrets |
206 aspects live under modules/; ren.aspects.<name> each.
Directory structure
import-tree loads every .nix file under modules/. Paths with /_ are skipped.
Dir names are for humans only. Ren does not read them.
| dir | purpose |
|---|---|
modules/community/ |
shared hardware and desktop aspects; they key on machine facts |
modules/docs/ |
this README: generators, vocabulary, recipes |
modules/editors/ |
vim profiles (nvf) and emacs distributions |
modules/envs/ |
dev environments and one aspect per language |
modules/features/ |
flake plumbing: ci, checks, formatter, packages, unfree, accounts |
modules/homes/ |
standalone home-manager homes |
modules/hosts/ |
NixOS and darwin machines, and frodo's guests |
modules/net/ |
ssh hosts and remote desktop |
modules/packages/ |
own packages and scripts |
modules/people/ |
users, and the vic-* feature tier aspects |
modules/platforms/ |
channels (nixpkgs pins) and how machines are built |
modules/security/ |
secrets declared as data |
modules/topology/ |
kinds and the scope tree: fleet, machines, users |
modules/vic/ |
vic's own features, by area (below) |
Inside modules/vic/:
| dir | purpose |
|---|---|
modules/vic/ai/ |
claude, agents, mcp servers, skills |
modules/vic/dev/ |
dev tools and security ops |
modules/vic/dots/ |
dotfiles linked into $HOME |
modules/vic/edit/ |
browsers, editors and terminals |
modules/vic/nvf/ |
neovim features, one file each |
modules/vic/secrets/ |
sops setup for vic's secrets |
modules/vic/shell/ |
fish and shell tools |
modules/vic/sys/ |
fonts, ssh and system bits |
modules/vic/vcs/ |
git and jujutsu |
Recipes: add a host, feature, env, ssh host, secret
Add a host: facts only; community aspects key on them (modules/hosts/<name>.nix).
ren.host.nargun = {
system = ren.system.x86_64-linux;
users = [ ren.user.vic ];
workstation = true;
cpu = "amd";
desktops = [ "kde" "niri" ];
};Add a user feature: one aspect, gated by a tier (modules/vic/<area>/<name>.nix).
ren.aspects.dev-tools = {
at = ren.aspects.vic-full;
homeManager = { pkgs, ... }: { home.packages = [ pkgs.gh pkgs.jq ]; };
};Add a dev env: an instance, then list it on a machine or home (envs = [ ren.env.goenv ];).
ren.env.goenv.langs = [ "go" ];
ren.aspects.env-go = {
at = ren.lib.and [ ren.kinds.env (ren.lib.when (s: builtins.elem "go" s.env.langs)) ];
env-packages = { system, ... }: [ system.legacyPackages.go ];
};Add an ssh host: one instance becomes one programs.ssh matchBlock (modules/net/ssh-host.nix).
ren.ssh-host.edge = {
host = "edge";
hostname = "192.168.192.168";
};Add a secret: declare it, then emit it from the feature that reads it.
ren.secret.groq-api-key.sopsKey = "groq_api_key"; # modules/security/secret.nix
ren.aspects.my-feature.secrets = { ... }: [ ren.secret.groq-api-key ];History
- Ren (current)
- Den without flakes
- Den with flakes + flake-parts
- Dendritic flake-parts only
- blueprint
- flake-parts
- old m1 flake with mk-darwin-system
- other with snowfall-lib lost