Giter Club home page Giter Club logo

nixos-pi's Introduction

NixOS on Raspberry Pi

My personal notes on how to setup NixOS on Raspberry Pi

Model:

  • Pi 3B+

Using prebuilt image available on Hydra

The latest image is on Hydra:

sd-image

If the image have extension .img.zst , then you need to uncompress it.

unzstd sd-image.img.zst

Flash the image to your sd card using dd. Follow the instruction in NixOS wiki that links to the raspberry pi original docs.

With this setup, you have a bare minimum image that you can access via HDMI and keyboard.

Further configuration are done via /etc/nixos/configuration.nix (the image is a NixOS). Create the file and fill in your configuration. Here's some example from mine: configuration.nix

Build the configuration

nixos-rebuild test -p test

This will build the configuration but not set it as the default boot. You can try if everything works okay and then reboot. From the boot menu, choose this profile to test if everything works after reboot. If you do nothing in the boot menu, it will choose your last default profile instead of this test profile. It is also possible to create different nixos-config file and build it accordingly to test several config:

nixos-rebuild test -p test-1 -I nixos-config=./test.nix

Building using Github Action

We can leverage Github Action to build our image. We can reuse existing action to setup qemu-user-static and then build and deploy the image as workflow artifact. You can then download the artifact from Github, which is the zipped sd-image.img file.

I already setup a workflow manual dispatch Github Action in this repo, so to build your own customized NixOS raspi image, follow this steps.

  1. Fork the repo so you can build your own custom image
  2. Create your build/deployment environment.

From your repo settings page, click the Environments menu. Click New environment. Give it a name other than default. Define environment secrets called CONFIGURATION_NIX. The content should be your sd Image Nix recipe (not your future NixOS configuration.nix). See the sample template file in: configuration.default.sdImage.nix or configuration.sdImage.nix

  1. Run your workflow

In the Actions page, select nix-build-on-demand-docker action and then click Run workflow. You will be given an option to specify the environment name. Fill in the name of the environment you set up in step 2. Click Run workflow. If you use default environment name, it will build configuration.default.sdImage.nix as the recipe.

  1. Wait for it to finish

  2. Retrieve the artifact

When the build finish, in your action job page, there will be Artifacts panel with artifacts named sd-image.img. Click on it and it will download a zipped file. Extract the zipfile and it will contain the image, as .img or .img.zstd depending on your config you provided.

Building on x86/64 machine

The reason you may want to build your image yourself is because you want to store the initial config as an image. For example, it may include your own initial service like SSH, or network configuration (static IP, WIFI password, etc).

You need NixOS or just Nix package manager

You need QEMU ARM if you only have Nix.

Example in Ubuntu

For example to use it in Ubuntu:

notes for some reason, sd image build failed to build if we are using latest Linux kernel (5.4 currently). So, we need to use latest QEMU user-static that is available on debian sid (currently) or QEMU user-static version 5.x.x. Adding the repository is beyond the scope of this README and please do so if you understand that it is coming from and unstable apt repo.

sudo apt -y install qemu-user-static

Since we are going to run aarch64 binaries inside our x86_64 box, we need qemu-user-static to run aarch64 executable transparently. Check that binfmt_misc now support this:

ls -l /proc/sys/fs/binfmt_misc | grep aarch64

If it returns something (qemu-aarch64), you are on the right track.

Add the following line to /etc/nix/nix.conf: extra-platforms = aarch64-linux . If the file doesn't exist, create it.

Create a base nix file for SD Card image build. Typically this contains some config for basic setup that you want to make it work right after flashing the image. For example, public SSH keys, or static IP address settings, or WI-FI password, list of system packages and services, etc.

The nix file must import the SD Image packages

{ config, pkgs, lib, ... }:
{

  imports = [
    <nixpkgs/nixos/modules/installer/cd-dvd/sd-image-aarch64.nix>
  ];
  
  # Do not compress the image as we want to use it straight away
  sdImage.compressImage = false;

  # The rest of user config goes here
}

See example in: configuration.sdImage.nix

Then build the image:

nix-build '<nixpkgs/nixos>' -A config.system.build.sdImage -I nixos-config=./configuration.sdImage.nix \
  --argstr system aarch64-linux \
  --option sandbox false

When the image finally built (normally you don't want to compress it), you can flash it to SD card like in the above instructions. Boot your pi and access it (via Keyboard + HDMI, or over SSH), then you need to fix your /etc/nixos/configuration.nix. The nixos config that you made for building the image is for installation image, meanwhile you may have different nixos config after that. Typical configuration includes deleting the import lines for sd-image (So you don't rebuild image again), specifying basic fs mount (or additionally swap).

Example in NixOS

If you have NixOS, adding binfmt support is super easy.

Just add the binfmt support in your /etc/nixos/configuration.nix

# add this line inside the nix function
  boot.binfmt.emulatedSystems = [ "aarch64-linux" ];

Then, nixos-rebuild switch your configuration and your NixOS is ready to be used for cross-compilation.

The rest of the steps are the same with the Ubuntu example above after installing qemu-user-static

Building on ARM machine with Linux

Same as above, but you don't need to install QEMU. You just need Nix or NixOS.

The build command:

# notice that we don't need to specify --argstr system aarch64-linux
nix-build '<nixpkgs/nixos>' -A config.system.build.sdImage -I nixos-config=./configuration.sdImage.nix \
  --option sandbox false

Building using Docker

Theoritically we can also build cross-platform using Docker container. Normally this is used to build cross platform docker images, but we can also use it to build cross-platform in the host.

You need docker or podman installed as a prerequisite.

First we need to register the binfmt from a docker image. We use this repository: https://hub.docker.com/r/multiarch/qemu-user-static.

docker run --rm --privileged multiarch/qemu-user-static --reset -p yes

The trick works like this. Normally the image above is used to register qemu-user-static interpreter inside the container. Since /proc/sys/fs/binfmt_misc are the same in the host and container, if the image were run using --privileged, then the binfmt in the host are also registered with the binaries inside the docker image. So basically the docker image serves as a convenient packaging library for qemu-user-static.

According to the documentation, the -p yes flag tells the image to register the binfmt and persists it even if the container exits. So the interpreter are also available in the host kernel. However you can't check the interpreter version directly in the host, since the binaries don't exists in the host (but in the image above). To check the version, the author uses the convention like this:

# supply the platform as image tag, e.g. aarch64
docker run --rm --privileged multiarch/qemu-user-static:aarch64 /usr/bin/qemu-aarch64-static --version

Now your kernel can execute aarch64 binaries and you can cross-compile. There rest of the steps are the same.

Reference

nixos-pi's People

Contributors

lucernae avatar renovate[bot] avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

nixos-pi's Issues

Dependency Dashboard

This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.

Open

These updates have all been created already. Click a checkbox below to force a retry/rebase of any.

Detected dependencies

docker-compose
nixos/pihole/docker-compose.cloudflared.yml
nixos/pihole/docker-compose.dhcpd.yml
nixos/pihole/docker-compose.pihole.yml
nixos/pihole/docker-compose.yml
dockerfile
nixos/pihole/dhcp-helper/Dockerfile
github-actions
.github/workflows/nix-build-using-debian.yaml
  • actions/checkout v3.5.3
  • cachix/install-nix-action v20
  • myci-actions/add-deb-repo 11
  • actions/upload-artifact v3
  • actions/checkout v3.5.3
  • cachix/install-nix-action v20
  • myci-actions/add-deb-repo 11
  • actions/upload-artifact v3
  • ubuntu 22.04
  • ubuntu 22.04
.github/workflows/nix-build-using-docker.yaml
  • actions/checkout v3.5.3
  • cachix/install-nix-action v20
  • actions/upload-artifact v3
  • actions/checkout v3.5.3
  • cachix/install-nix-action v20
  • actions/upload-artifact v3
  • ubuntu 22.04
  • ubuntu 22.04
pip_requirements
nixos/pihole/requirements.txt

  • Check this box to trigger a request for Renovate to run again on this repository

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.