1
0
Fork
You've already forked reflake
0
Trying to implement flakes in stable Nix
  • Nix 100%
FrdrCkII 3730fd9c48 init
2026年01月02日 20:49:24 +08:00
systems init 2026年01月02日 20:49:24 +08:00
default.nix init 2026年01月02日 20:49:24 +08:00
lock.nix init 2026年01月02日 20:49:24 +08:00
README.md init 2026年01月02日 20:49:24 +08:00

Reflake: A flake-compatible alternative implemented in common nix code

So, all my attempts to get rid of flakes eventually led me to implement my own version of flakes in stable Nix. Still relies on the experimental fetchTree feature, which is part of flakes but can be enabled independently.

Features

  • Flat dependency management inspired by unflake
  • Input locking from nixlock and fetchTree features
  • Inspired by flake-file, the nix flake command implemented through nix-shell
  • Pure evaluation support implemented using Nix's lazy evaluation features

How to use

All functions are packaged in default.nix. Copy it, then find the config part in this file.

 config =
 let
 # Name of the lock file
 # The name of the lock file(lockName) and its content(lockFile) are two different things. The content should be a nix attribute set.
 # If you want, you can simply modify the `lockShell` function to use toml/json or any type you like in the lock file.
 lockName = "lock.nix";
 lockFile = import ./${lockName};
 # Place inputs similar to flakes here;
 # they can be written directly here, or placed in another file and then `import ./inputs.nix`.
 # You can use complete nix here, such as functions.
 # However, these should be able to be evaluated as simple nix attribute sets, just like flakes inputs.
 # This is a strange example from my configuration file, using mirror infrastructure located in China to speed up my network.
 inputsFile =
 let
 # git = url: args: (args // { type = "git"; } // { inherit url; });
 # file = url: args: (args // { type = "file"; } // { inherit url; });
 tarball = url: args: (args // { type = "tarball"; } // { inherit url; });
 nixpkgs =
 url: tarball ("https://mirror.nju.edu.cn/nix-channels/releases/" + url + "/nixexprs.tar.xz") { };
 archive = url: args: (args // { type = "gitArchive"; } // { inherit url; });
 github = url: args: archive ("https://v6.gh-proxy.org/https://github.com/" + url) args;
 codeberg = url: args: archive ("https://codeberg.org/" + url) args;
 path = path: args: (args // { type = "path"; } // { inherit path; });
 in
 {
 nixpkgs = nixpkgs "nixos-25.11@nixos-25.11.941.c97c47f2bac4";
 falake = codeberg "FrdrCkII/falake" { ref = "main"; };
 flake-aspects = github "vic/flake-aspects" { ref = "main"; };
 impermanence = github "nix-community/impermanence" { ref = "master"; };
 disko = github "nix-community/disko" { ref = "master"; };
 
 smfhhhh = github "feel-co/smfh" { ref = "master"; };
 hjem = github "feel-co/hjem" { 
 ref = "main";
 # Similar to 'follows' in flake inputs
 follows = {
 smfh = "smfhhhh";
 };
 };
 
 systems = path "systems" { };
 };
 mkLockShell = args: lockLib.lockShell ({ inherit inputsFile lockName lockFile; } // args);
 in
 {
 lock = mkLockShell { };
 update = mkLockShell { update = true; };
 # Sometimes nix doesn't immediately update cached inputs, and in this case, you need to use 
 # nix-shell -A update --option tarball-ttl 0
 inputsLock = lockLib.lockInputs {
 # The root directory of the entire git repository.
 # You must specify it manually.
 root = ./.;
 inherit lockFile;
 # Inputs alias.
 # In this example, you will get an input called `nixpkgs-stable`, which is copied from `nixpkgs`.
 # Basically it's the global version of `follows`.
 inputsAlias = {
 nixpkgs-stable = "nixpkgs";
 };
 };
 };

Then create an empty lock file

# Just like this
{ }

Finally, run nix-shell -A lock to lock it! And run nix-shell -A update to update the inputs.

Sometimes nix doesn't immediately update cached inputs, and in this case, you need to use nix-shell -A update --option tarball-ttl 0

Now you can use this method to get input:

let 
 inputs = (import ./default.nix).inputsLock;
in
{ ... }
# Or do you want to use `self`? Try the `mkOutputs` function from unflake.
(import ./default.nix).mkOutputs (
 inputs:
 { ... }
)

Input types

Currently, only five types are supported in default.nix, but adding new types should be very easy since all types are defined in the Nix code.

General Options

home-manager = {
 # Required, input type
 type = "git";
 # Optional, usually handled automatically, default is yes
 flake = false;
};

type = "git";

Lock a git repository

home-manager = {
 type = "git";
 # Required
 url = "https://github.com/nix-community/home-manager";
 # Optional
 ref = "master";
 # Optional, but usually not specified
 rev = "1234567890";
 # Optional, but usually not specified
 narHash = "1234567890";
 # Optional, default is false
 submodules = true;
 # Optional, default is true
 shallow = true;
};

type = "gitArchive";

A variant of 'git' that uses tarballs for downloads. It works similarly to 'GitHub', but is more flexible.

home-manager = {
 type = "gitArchive";
 ... # Same as git
 # Optional, default is "$url/archive/$rev.tar.gz"
 # $url and $rev will be replaced with the values of url and rev.
 archiveUrl = "https://mirror.of.github/archive/$rev.tar.gz";
};

type = "tarball";

Tarball

home-manager = {
 type = "tarball";
 # Required
 url = "...";
};

type = "file";

File

home-manager = {
 type = "file";
 # Required
 url = "...";
};

type = "path";

File

system = {
 type = "path";
 # Required, a string type relative path starting from the project root directory
 path = "system";
};