以 nix.dev 的树莓派教程为起点整理,另有硬件、服务与维护扩展;不是官方教程的逐字翻译: Installing NixOS on a Raspberry Pi
在树莓派上运行 NixOS,打造可复现的 ARM 设备。
支持的树莓派型号#
| 型号 | 使用范围 | 注意事项 |
|---|---|---|
| Raspberry Pi 4B | 本篇基础安装路径的主要对象 | 以具体镜像和固件验证启动 |
| Raspberry Pi 3/3B+ | 官方教程说明可以调整后使用 | 不应直接套用 Pi 4 的内核和硬件选项 |
| Raspberry Pi Zero 2 W | 需要单独核对镜像与硬件模块 | 内存约束和设备支持需检查 |
| Raspberry Pi 5 | 需要单独的型号支持路径 | 不能把“安装最新内核”当作完整方案 |
本文保留以 24.05 为背景的示例;它不是当前版本或所有型号的兼容承诺。nix.dev 的参考教程仍以 Pi 4B 为对象。选择 nixos-hardware 模块时固定其修订,并查看对应型号的 README。
准备 SD 卡#
1. 下载预构建镜像
# Raspberry Pi 4 (64位)
nix-shell -p wget zstd
# 从对应 Hydra 任务的成功构建复制实际 build-product URL
IMAGE_URL='https://hydra.nixos.org/build/<build-id>/download/1/<image>.img.zst'
wget -O nixos-sd-image-aarch64-linux.img.zst "$IMAGE_URL"
# 解压
unzstd nixos-sd-image-aarch64-linux.img.zst2. 写入 SD 卡
以下 dd 会覆盖目标设备全部内容。先备份 SD 卡,使用 lsblk 核对容量、型号和挂载点,卸载其分区;确认 /dev/sdX 是整张 SD 卡而不是系统盘。占位路径不能直接执行。
# 查找 SD 卡设备
lsblk
# 写入(替换 /dev/sdX)
sudo dd if=nixos-sd-image-aarch64-linux.img of=/dev/sdX bs=4M conv=fsync status=progress
# 同步
sync首次启动配置#
1. 基础配置
以下是 Pi 4 历史配置骨架;根文件系统、引导分区和内核由已验证镜像及硬件模块决定,先保留生成的 hardware-configuration.nix。不要把 SD 镜像生成模块当成所有已安装系统都应导入的硬件配置:
{ config, pkgs, lib, ... }:
{
# 导入硬件配置
imports = [
./hardware-configuration.nix
];
# 启动配置
boot = {
kernelPackages = pkgs.linuxKernel.packages.linux_rpi4;
loader.grub.enable = false;
loader.generic-extlinux-compatible.enable = true;
};
# 固件
hardware.enableRedistributableFirmware = true;
hardware.firmware = [ pkgs.wireless-regdb ];
# 网络
networking = {
hostName = "workstation";
wireless.enable = true;
interfaces.wlan0.useDHCP = true;
};
# SSH
services.openssh = {
enable = true;
settings = {
PermitRootLogin = "no";
PasswordAuthentication = false;
};
};
# 用户
users.users.user = {
isNormalUser = true;
extraGroups = [ "wheel" "video" "audio" ];
openssh.authorizedKeys.keyFiles = [ ./keys/user.pub ];
# 本地登录密码通过运行时密码文件或首次控制台设置处理
};
# 系统版本
system.stateVersion = "24.05";
}2. 配置 WiFi
# 仅展示字段形状;不要把真实 WiFi 密码写入 Nix/store
# networking.wireless.networks."ExampleSSID".psk = "<wifi-password>";使用仅 root 可读的运行时环境文件;密钥不要通过 Nix 路径值复制到 store:
{
networking.wireless.environmentFile = "/var/secrets/wireless.env";
networking.wireless.networks = {
"ExampleSSID".psk = "@PASS@";
};
}硬件特性支持#
GPIO
{ pkgs, ... }:
{
# 真实 GPIO 依赖对应型号的内核与 device tree;gpio-mockup 仅模拟 GPIO
# boot.kernelModules = [ "gpio-mockup" ];
# 安装工具
environment.systemPackages = with pkgs; [
libgpiod
raspberrypifw
];
# 用户权限
users.groups.gpio = {};
users.users.user.extraGroups = [ "gpio" ];
services.udev.extraRules = ''
KERNEL=="gpiochip*", GROUP="gpio", MODE="0660"
'';
}I2C
{
boot.kernelModules = [ "i2c-dev" ];
hardware.i2c.enable = true;
users.users.user.extraGroups = [ "i2c" ];
}SPI
{
boot.kernelModules = [ "spidev" ];
# SPI controller 还须由对应板卡的 device-tree overlay 启用
# hardware.spi.enable 不是通用 NixOS 选项
}摄像头
原笔记使用旧 Raspberry Pi 固件相机路径。现代相机栈和选项随板型、固件与 nixos-hardware 模块变化;以下保留固件配置的历史语义,不能直接当作当前 NixOS 模块:
{
boot.loader.raspberryPi.firmwareConfig = ''
start_x=1
gpu_mem=256
'';
# hardware.raspberry-pi.camera.enable 并非所有 NixOS 都有的选项
# 应先核对目标型号模块,再启用对应相机栈
}常用服务配置#
家庭自动化 (Home Assistant)
{
services.home-assistant = {
enable = true;
openFirewall = true;
config = {
homeassistant = {
name = "Home";
latitude = 0.0; # 示例坐标,部署时使用所需位置
longitude = 0.0;
elevation = 0;
unit_system = "metric";
time_zone = "Asia/Shanghai";
};
};
};
}媒体中心 (Kodi)
{
services.xserver.desktopManager.kodi = {
enable = true;
};
services.displayManager.autoLogin = {
enable = true;
user = "kodi";
};
users.users.kodi = {
isNormalUser = true;
extraGroups = [ "audio" "video" ];
};
}AdGuard Home(DNS 过滤)
监听所有接口并开防火墙会扩大 DNS 服务范围;部署时限制到目标局域网接口,并核对 53 端口冲突。
{
services.adguardhome = {
enable = true;
openFirewall = true;
settings = {
dns = {
bind_hosts = [ "0.0.0.0" ];
port = 53;
};
};
};
}性能优化#
内存优化
{
# ZRAM 交换
zramSwap.enable = true;
zramSwap.memoryPercent = 50;
# 减少日志保留
services.journald.extraConfig = ''
SystemMaxUse=100M
MaxFileSec=7day
'';
# 禁用不需要的服务
documentation.nixos.enable = false;
services.xserver.enable = false; # 无图形界面
}存储优化
fstrim 仅在存储设备和整条块设备链支持 discard 时有效;并非所有 SD 卡都支持。tmpfs 会占用内存和可能的交换空间,需要与小内存设备预算一起设置。
{
# 启用 discard 支持
services.fstrim.enable = true;
# 临时文件使用 tmpfs
boot.tmp.useTmpfs = true;
boot.tmp.tmpfsSize = "50%";
}SD 卡持久性优化#
减少持续写入可延缓磨损;volatile 日志重启后丢失,需要外部日志才能排查跨重启问题:
{
# 限制日志写入
services.journald.storage = "volatile";
# RAM 中的 /tmp
boot.tmp.useTmpfs = true;
# 禁用不必要的服务
systemd.services.systemd-journal-flush.enable = false;
}排查问题#
无法启动
检查 config.txt:
cat /boot/firmware/config.txtWiFi 不工作
# 检查固件
sudo dmesg | grep -i wifi
# 重新加载驱动
sudo modprobe -r brcmfmac
sudo modprobe brcmfmac温度过高
先检查散热、电源和负载。CPU governor 调整是性能/功耗策略,不等于加装散热,也不保证直接限制最高频率:
{
# 限制 CPU 频率
powerManagement.cpuFreqGovernor = "conservative";
}初次应用与恢复
镜像能启动后,先构建自己的系统配置,再安排 nixos-rebuild boot 和重启。保留已知可启动世代、串口或本地控制台恢复路径。网络驱动卸载会中断连接,远程会话不要盲目执行。SSH 公钥占位文件需实际存在;这些配置未在实体树莓派上运行测试。
参考与延伸
根据技术笔记重新整理,示例使用通用名称。