Skip to content

From configuration.nix to Flake

On this page

With less than 240 days until the Gaokao, time is tight and I don’t have much time to blog. But after getting roasted by my group chat friends — “at least write one post, otherwise this site will just sit here empty forever” — here I am. I do keep a diary, but it’s too personal to share with everyone.

Amid the chaos I did manage to get some things done. For example, last weekend I finally set up Flake, which I’d been wanting to do for ages. With the help of CodeX CLI it didn’t take much time — I let the AI Agent handle the trickiest parts and it was almost a one-shot. Here’s the current directory structure:

.
├── flake.lock
├── flake.nix
├── home
│ └── modules
│ ├── dae.nix
│ ├── fzf.nix
│ └── niri.nix
├── Justfile
└── nixos
├── configs
│ ├── dae
│ │ └── config.dae
│ └── niri
│ └── config.kdl
├── hosts
│ └── kokosa
│ ├── default.nix
│ └── hardware.nix
└── modules
├── boot.nix
├── desktop.nix
├── locale.nix
├── networking.nix
├── nix-settings.nix
├── packages.nix
├── security.nix
├── services.nix
└── users.nix

Of the programs managed by Home Manager, only fzf is actually in use. The other two are planned for future use, so I wrote the configs in advance but they’re disabled in the settings.


Compared to configuration.nix, Flake solves many problems. It can lock all packages and their dependency versions — one config file can restore the entire system precisely down to version numbers and commits, which configuration seemingly can’t do since it follows Channel updates.

FeatureChannelsFlakes
DependenciesImplicit (channels)Explicit (inputs)
Rebuildsudo nixos-rebuild switchnh os switch .
ReproducibilityDepends on individual channel versionsflake.lock ensures consistency
Developmentnix-shellnix develop

nh is a NixOS helper tool, but its configuration-mode support was a bit mysterious. After switching to Flake I found it to be a really nice tool — appreciated and recommended.

Additionally, Flake can easily reference other Flakes through Inputs, like sodiboo/niri-flake, enabling declarative management of software that isn’t officially supported. I don’t actually plan to use HM to manage Niri.

On the development environment side, you might have noticed that many open-source projects on GitHub/Codeberg now have a flake.nix file in their root directory. With this file you can easily reproduce the entire dev environment with Nix, isolated from your main system — with just a single nix develop. Most modern Nix projects (even non-Nix projects) are adopting this, because it genuinely works well.

Of course there are some drawbacks, like an unstable API (still “experimental” since 2019) and a mandatory Git dependency, among other pitfalls. Determinate Nix solves quite a few of these, but it’s partially closed-source (e.g. nixd). Despite Flake’s rough edges, it’s still more convenient than Channels. And now with AI managing my config, the migration wasn’t particularly complex.


First, flake.nix:

{
description = "Kokosa's Nix Flake";
inputs = {
# Nixpkgs & NUR
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
nur.url = "github:nix-community/NUR";
# Flake-parts
flake-parts.url = "github:hercules-ci/flake-parts";
# Home Manager
home-manager = {
url = "github:nix-community/home-manager";
inputs.nixpkgs.follows = "nixpkgs";
};
# Other
hid-bpf-uclogic.url = "github:dramforever/hid-bpf-uclogic";
};
outputs = inputs @ {
nixpkgs,
flake-parts,
...
}:
flake-parts.lib.mkFlake {inherit inputs;} {
systems = ["x86_64-linux"];
perSystem = {pkgs, ...}: {
formatter = pkgs.alejandra;
};
flake = {
nixosConfigurations.kokosa = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
specialArgs = {
inherit inputs;
};
modules = [
./nixos/hosts/kokosa/default.nix
];
};
};
};
}

The single file imported, default.nix, is what used to be my machine’s configuration.nix. It’s now been transformed beyond recognition — the original massive file has been sliced into many smaller files and unified through imports. Aside from that, this file only contains some Home Manager settings.

imports = [
inputs.home-manager.nixosModules.home-manager
../../modules/nix-settings.nix
../../modules/networking.nix
../../modules/security.nix
../../modules/packages.nix
../../modules/services.nix
../../modules/desktop.nix
../../modules/locale.nix
../../modules/users.nix
../../modules/boot.nix
./hardware.nix
];

The rest isn’t much different from my old config. They haven’t been uploaded to GitHub yet — I’ll probably get around to it when I have time. To wrap up, here’s a screenshot:

Feeling good
Feeling good