Nix Flake 模板实战:从零搭建多语言项目脚手架

Nix Flake 模板实战:flake 模板体系、常用模板(多语言/多场景)、自建模板、模板引用与参数化、多输出组织(devShells/packages/checks)、模板与 CI 集成、常见坑与最佳实践。

引言

每个新项目都要「从零配一遍环境」——语言版本、工具链、CI 配置,换个机器又得重来。Nix Flake 模板把这些固化成一个可复用的 flake init 模板:一条命令初始化出带 devShell、构建、检查、CI 的项目骨架。本文讲清模板体系、常用模板、以及如何自建团队的标准化模板。

前置:/nix-flakes/(Flake 基础)、/nix-flakes-best-practices/(工程化)、/nix-devenv-reproducible-dev/(开发环境)。


目录


1. 为什么需要 Flake 模板

1.1 新项目的重复劳动

每个新项目:
  ✗ 装语言运行时(版本可能不同)
  ✗ 装包管理器、lint、格式化工具
  ✗ 写 CI 配置(版本又可能漂移)
  ✗ 换台机器重新踩坑

1.2 模板的价值

一条命令 → 完整可复现的项目骨架:
  flake.nix(devShell + package + checks)
  + 目录结构
  + CI 配置(GitHub Actions)
  → 所有人、所有机器、完全一致

记忆:Flake 模板把「环境+构建+CI」固化成一条命令的项目骨架;消除新项目重复配置与环境漂移。


2. 模板机制:templates 输出

2.1 Flake 的 templates 输出

{
  outputs = { self, nixpkgs }: {
    templates = {
      python = {
        path = ./python-template;    # 模板文件目录
        description = "Python project template";
      };
    };
    # 默认模板
    defaultTemplate = { ... };
  };
}

2.2 使用模板

nix flake init -t github:nix-community/templates#python
# 或引用本机
nix flake init -t .#python

path 指向的目录内容会被复制到当前目录,并把所有占位符($...)替换。

记忆:templates..path 指向模板目录;nix flake init -t # 复制模板并替换占位符。


3. 内置常用模板

3.1 官方默认模板

nix flake init   # 默认 templates.default

生成一个最小 flake.nix:

{
  description = "A very basic flake";
  inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.11";
  outputs = { self, nixpkgs }: {
    packages.x86_64-linux.default = ...;
  };
}

3.2 常用社区模板

模板来源内容
pythonnix-community/templatespyproject + devShell
rustnix-community/fenixrust-toolchain + cargo
nodenix-community/nix4nodejsnpm + devShell
gonixpkgs 自带go mod + devShell
devenvdevenv.shdevenv 配置

记忆:内置/社区模板覆盖主流语言;nix flake init -t github:xxx# 一键初始化。


4. 自建模板:目录结构

4.1 模板目录布局

templates/
└── python/
    ├── flake.nix          # 模板主文件
    ├── pyproject.toml
    ├── src/
    │   └── main.py
    └── .github/
        └── workflows/ci.yml

4.2 带占位符的模板文件

# templates/python/flake.nix
{
  description = "$PROJECT_DESC";   # 占位符
  inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.11";
  outputs = { self, nixpkgs }: {
    devShells.default = nixpkgs.legacyPackages.${system}.mkShell {
      packages = with pkgs; [ python312 poetry ruff ];
    };
  };
}

占位符形如 $VAR,nix flake init 时按交互输入替换。

记忆:自建模板 = 一个目录 + flake.nix + 支持占位符 $VAR;nix flake init 时交互替换占位符。


5. 模板参数化与多模板

5.1 交互式参数

nix flake init 会提示填占位符值。模板里可写:

{
  description = "$PROJECT_DESC";
  # 支持 $VAR 形式占位符,init 时提示
}

5.2 多模板输出

templates = {
  minimal = { path = ./minimal; description = "Minimal"; };
  full = { path = ./full; description = "Full CI setup"; };
  python = { path = ./python; description = "Python + ruff + CI"; };
};

按项目复杂度选模板:-t .#minimal 或 -t .#full。

记忆:多模板 = templates 输出多个 ;按场景选 minimal/full/python 等模板;占位符支持 init 时交互填值。


6. 组织输出:devShells/packages/checks

6.1 标准模板的输出组织

outputs = { self, nixpkgs }: let
  system = "x86_64-linux";
  pkgs = nixpkgs.legacyPackages.${system};
in {
  devShells.${system}.default = pkgs.mkShell {
    packages = with pkgs; [ python312 poetry ruff ];
  };
  packages.${system}.default = pkgs.python312.buildPythonPackage { ... };
  checks.${system}.default = ...;    # nix flake check 运行
};

6.2 使用

nix develop          # 进入 devShell
nix build .#         # 构建
nix flake check      # 运行所有 checks

记忆:模板骨架输出三类——devShells.default(开发环境)、packages.default(构建产物)、checks.default(检查);nix develop/build/check 各取所需。


7. 模板 + CI:一步到位

7.1 模板内嵌 CI

# .github/workflows/ci.yml(模板自带)
name: CI
on: [push, pull_request]
jobs:
  check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: nix-community/setup-nix-action@v6
      - run: nix develop --command make check
      - run: nix flake check

7.2 模板里引用缓存

      - uses: cachix/cachix-action@v15
        with:
          name: mycache
          authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'

记忆:模板自带 CI 配置(setup-nix + nix flake check);配合 cachix 缓存让初始化后的第一个 CI 跑得快。


8. 常见坑与最佳实践

8.1 坑

坑解法
模板复制后占位符残留检查是否所有 $VAR 都被替换
多 system 硬编码用 nixpkgs.lib.genAttrs 遍历 system
模板 flake.lock 过期复制后 nix flake update
目录里混入无关文件path 目录只放必要文件

8.2 最佳实践

✓ 模板自带 README 与 CI
✓ 输出按 system 泛化
✓ 提供 minimal/full 两档
✓ 占位符覆盖项目名、描述、版本
✓ 模板版本化(tag 或 channel)

记忆:模板坑在占位符残留、system 硬编码、lock 过期;最佳实践是输出按 system 泛化、提供多档模板、自带 README+CI、版本化管理。


9. 模板演进与团队共享

9.1 集中式模板源

把团队模板放进一个 git 仓库,用 URL 引用:

nix flake init -t git+ssh://git@github.com/team/nix-templates#service

9.2 模板迭代

模板仓库 PR 改 → tag 发版 → 各项目按需更新
新项目永远拿到最新骨架
存量项目可 nix flake init 对比 diff

记忆:团队共享模板 = 模板入 git 仓库、按 URL 引用、tag 版本化;新项目用最新骨架,存量项目 diff 对齐。


10. 速查表与一句话记忆

环节做法
使用模板nix flake init -t #
内置模板nix flake init(默认)
自建模板templates..path = 目录
占位符$VAR,init 交互替换
输出组织devShells/packages/checks
内嵌 CIsetup-nix-action + flake check
团队共享模板入 git、URL 引用、tag 发版

一句话记忆:Nix Flake 模板 = 用 templates..path 固化项目骨架——nix flake init -t # 一条命令复制模板并替换 $VAR 占位符;骨架组织三类输出(devShells 开发环境、packages 构建、checks 检查),内嵌 CI 配置与 cachix 缓存让初始化即能跑;自建模板按 system 泛化、提供 minimal/full 多档、占位符覆盖项目名/描述;团队模板入 git 仓库用 URL 引用、tag 版本化,新项目永远拿到可复现的最新骨架。


延伸阅读

  • /nix-flakes/ — Flake 基础
  • /nix-flakes-best-practices/ — Flake 工程化最佳实践
  • /nix-devenv-reproducible-dev/ — devenv 开发环境
  • /nix-ci-cachix/ — CI 与缓存集成
  • /nix-cross-compilation-overlay/ — 交叉编译与 overlay
  • [[devops]] — 基础设施即代码
  • [[tools]] — 开发工具链
  • Nix 官方模板文档

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「nix」更多文章

  1. NixOS 运维实战:升级、回滚、GC 与日常维护
  2. NixOS 网络与防火墙配置:声明式网络管理实战
  3. NixOS 服务管理实战:systemd 声明、NixOS 容器与常用服务部署