364 lines
9.7 KiB
Nix
364 lines
9.7 KiB
Nix
{
|
|
description = "Noisebell - door monitor system";
|
|
|
|
inputs = {
|
|
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
|
nixos-hardware.url = "github:NixOS/nixos-hardware/master";
|
|
agenix = {
|
|
url = "github:ryantm/agenix";
|
|
inputs.nixpkgs.follows = "nixpkgs";
|
|
};
|
|
crane.url = "github:ipetkov/crane";
|
|
rust-overlay = {
|
|
url = "github:oxalica/rust-overlay";
|
|
inputs.nixpkgs.follows = "nixpkgs";
|
|
};
|
|
nixos-raspberrypi = {
|
|
url = "github:nvmd/nixos-raspberrypi/main";
|
|
inputs.nixpkgs.follows = "nixpkgs";
|
|
};
|
|
};
|
|
|
|
outputs =
|
|
{
|
|
self,
|
|
nixpkgs,
|
|
nixos-hardware,
|
|
nixos-raspberrypi,
|
|
agenix,
|
|
crane,
|
|
rust-overlay,
|
|
}:
|
|
let
|
|
system = "x86_64-linux";
|
|
pkgs = import nixpkgs {
|
|
inherit system;
|
|
overlays = [ rust-overlay.overlays.default ];
|
|
};
|
|
|
|
rustToolchain = pkgs.rust-bin.stable.latest.default;
|
|
craneLib = (crane.mkLib pkgs).overrideToolchain rustToolchain;
|
|
|
|
src = pkgs.lib.cleanSourceWith {
|
|
src = ./.;
|
|
filter =
|
|
path: type: (builtins.match ".*\.png$" path != null) || (craneLib.filterCargoSources path type);
|
|
};
|
|
|
|
remoteArgs = {
|
|
inherit src;
|
|
pname = "noisebell";
|
|
version = "0.1.0";
|
|
strictDeps = true;
|
|
doCheck = false;
|
|
};
|
|
|
|
remoteArtifacts = craneLib.buildDepsOnly remoteArgs;
|
|
|
|
buildRemoteMember =
|
|
name:
|
|
craneLib.buildPackage (
|
|
remoteArgs
|
|
// {
|
|
cargoArtifacts = remoteArtifacts;
|
|
cargoExtraArgs = "-p ${name}";
|
|
}
|
|
);
|
|
|
|
noisebell-cache = buildRemoteMember "noisebell-cache";
|
|
noisebell-discord = buildRemoteMember "noisebell-discord";
|
|
|
|
crossPkgs = import nixpkgs {
|
|
inherit system;
|
|
crossSystem.config = "aarch64-unknown-linux-gnu";
|
|
overlays = [ rust-overlay.overlays.default ];
|
|
};
|
|
|
|
piRustToolchain = pkgs.rust-bin.stable.latest.default.override {
|
|
targets = [ "aarch64-unknown-linux-gnu" ];
|
|
};
|
|
|
|
piCraneLib = (crane.mkLib pkgs).overrideToolchain piRustToolchain;
|
|
|
|
piArgs = {
|
|
inherit src;
|
|
pname = "noisebell-pi";
|
|
version = "0.1.0";
|
|
strictDeps = true;
|
|
doCheck = false;
|
|
|
|
CARGO_BUILD_TARGET = "aarch64-unknown-linux-gnu";
|
|
CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER = "${crossPkgs.stdenv.cc.targetPrefix}cc";
|
|
TARGET_CC = "${crossPkgs.stdenv.cc.targetPrefix}cc";
|
|
CC_aarch64_unknown_linux_gnu = "${crossPkgs.stdenv.cc.targetPrefix}cc";
|
|
HOST_CC = "${pkgs.stdenv.cc.nativePrefix}cc";
|
|
|
|
depsBuildBuild = [ crossPkgs.stdenv.cc ];
|
|
cargoExtraArgs = "-p noisebell";
|
|
};
|
|
|
|
piArtifacts = piCraneLib.buildDepsOnly piArgs;
|
|
|
|
noisebell-pi = piCraneLib.buildPackage (
|
|
piArgs
|
|
// {
|
|
cargoArtifacts = piArtifacts;
|
|
}
|
|
);
|
|
|
|
bootstrapModule =
|
|
{
|
|
lib,
|
|
nixos-raspberrypi,
|
|
pkgs,
|
|
...
|
|
}:
|
|
{
|
|
imports = with nixos-raspberrypi.nixosModules; [
|
|
default
|
|
usb-gadget-ethernet
|
|
];
|
|
|
|
system.stateVersion = "24.11";
|
|
|
|
boot.loader.raspberry-pi = {
|
|
variant = "02";
|
|
firmwarePackage = nixos-raspberrypi.packages.${pkgs.stdenv.hostPlatform.system}.raspberrypifw;
|
|
bootloader = "kernel";
|
|
};
|
|
boot.supportedFilesystems = lib.mkForce [
|
|
"ext4"
|
|
"vfat"
|
|
];
|
|
boot.kernelParams = lib.mkAfter [ "cfg80211.ieee80211_regdom=US" ];
|
|
|
|
networking.hostName = "noisebridge-pi";
|
|
networking.networkmanager.enable = lib.mkForce false;
|
|
networking.wireless = {
|
|
enable = true;
|
|
networks."Noisebridge".psk = "noisebridge";
|
|
};
|
|
|
|
services.avahi = {
|
|
enable = true;
|
|
nssmdns4 = true;
|
|
openFirewall = true;
|
|
};
|
|
|
|
services.openssh = {
|
|
enable = true;
|
|
settings = {
|
|
PasswordAuthentication = false;
|
|
PermitRootLogin = "prohibit-password";
|
|
};
|
|
};
|
|
|
|
users.users.root.openssh.authorizedKeys.keys = [
|
|
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIE40ISu3ydCqfdpb26JYD5cIN0Fu0id/FDS+xjB5zpqu"
|
|
];
|
|
};
|
|
|
|
flash-bootstrap-sd = pkgs.writeShellApplication {
|
|
name = "flash-bootstrap-sd";
|
|
runtimeInputs = [
|
|
pkgs.coreutils
|
|
pkgs.nix
|
|
pkgs.zstd
|
|
];
|
|
text = ''
|
|
set -euo pipefail
|
|
|
|
if [ "$#" -ne 1 ]; then
|
|
echo "usage: flash-bootstrap-sd /dev/sdX" >&2
|
|
exit 1
|
|
fi
|
|
|
|
device="$1"
|
|
flake_path=${builtins.toString ./.}
|
|
zstd_bin=${pkgs.zstd}/bin/zstd
|
|
|
|
if [ ! -b "$device" ]; then
|
|
echo "not a block device: $device" >&2
|
|
exit 1
|
|
fi
|
|
|
|
echo "Requesting sudo access before build and flash..."
|
|
sudo -v
|
|
echo "Sudo authentication successful."
|
|
|
|
echo "Building bootstrap NixOS Raspberry Pi Zero 2 W image..."
|
|
image_out="$(nix build \
|
|
--print-out-paths \
|
|
--cores 0 \
|
|
--max-jobs auto \
|
|
"$flake_path#nixosConfigurations.bootstrap.config.system.build.sdImage")"
|
|
|
|
image="$(echo "$image_out"/sd-image/*.img*)"
|
|
if [ ! -f "$image" ]; then
|
|
echo "failed to locate SD image under $image_out/sd-image" >&2
|
|
exit 1
|
|
fi
|
|
|
|
echo "Flashing $image to $device..."
|
|
if [ "''${image##*.}" = "zst" ]; then
|
|
"$zstd_bin" -d --stdout "$image" | sudo dd of="$device" bs=16M conv=fsync status=progress
|
|
else
|
|
sudo dd if="$image" of="$device" bs=16M conv=fsync status=progress
|
|
fi
|
|
sync
|
|
|
|
echo "Done. This is the custom bootstrap NixOS image."
|
|
'';
|
|
};
|
|
|
|
pi-serial = pkgs.writeShellApplication {
|
|
name = "pi-serial";
|
|
runtimeInputs = [
|
|
pkgs.coreutils
|
|
pkgs.procps
|
|
pkgs.tio
|
|
pkgs.util-linux
|
|
];
|
|
text = ''
|
|
set -euo pipefail
|
|
|
|
baud_rate=115200
|
|
data_bits=8
|
|
stop_bits=1
|
|
parity=none
|
|
flow_control=none
|
|
serial_tools="screen tio minicom picocom"
|
|
|
|
port=""
|
|
|
|
if [ "$#" -gt 1 ]; then
|
|
echo "usage: pi-serial [device]" >&2
|
|
exit 1
|
|
fi
|
|
|
|
if [ "$#" -eq 1 ]; then
|
|
port="$1"
|
|
else
|
|
for candidate in /dev/serial/by-id/* /dev/ttyUSB* /dev/ttyACM*; do
|
|
if [ -e "$candidate" ]; then
|
|
port="$candidate"
|
|
break
|
|
fi
|
|
done
|
|
fi
|
|
|
|
if [ -z "$port" ]; then
|
|
echo "No serial device found." >&2
|
|
echo "Check the adapter and run: ls -l /dev/serial/by-id /dev/ttyUSB* /dev/ttyACM* 2>/dev/null" >&2
|
|
exit 1
|
|
fi
|
|
|
|
log_file="pi-serial-$(date +%Y%m%d-%H%M%S).log"
|
|
|
|
echo "Stopping old serial sessions for this user"
|
|
for tool in $serial_tools; do
|
|
pkill -x -u "$USER" "$tool" 2>/dev/null || true
|
|
done
|
|
sleep 1
|
|
|
|
echo "Waiting for port to become free: $port"
|
|
while fuser "$port" >/dev/null 2>&1; do
|
|
sleep 1
|
|
done
|
|
|
|
echo "Using serial port: $port"
|
|
echo "Logging to: $log_file"
|
|
echo "Start this before powering the Pi."
|
|
|
|
exec sudo tio \
|
|
-b "$baud_rate" \
|
|
-d "$data_bits" \
|
|
-s "$stop_bits" \
|
|
-p "$parity" \
|
|
-f "$flow_control" \
|
|
-t \
|
|
--log \
|
|
--log-file "$log_file" \
|
|
"$port"
|
|
'';
|
|
};
|
|
in
|
|
{
|
|
packages.${system} = {
|
|
inherit
|
|
noisebell-cache
|
|
noisebell-discord
|
|
flash-bootstrap-sd
|
|
pi-serial
|
|
;
|
|
default = noisebell-cache;
|
|
};
|
|
|
|
packages.aarch64-linux = {
|
|
noisebell = noisebell-pi;
|
|
default = noisebell-pi;
|
|
};
|
|
|
|
nixosModules = {
|
|
cache = import ./remote/cache-service/module.nix noisebell-cache;
|
|
discord = import ./remote/discord-bot/module.nix noisebell-discord;
|
|
default = {
|
|
imports = [
|
|
(import ./remote/cache-service/module.nix noisebell-cache)
|
|
(import ./remote/discord-bot/module.nix noisebell-discord)
|
|
(import ./remote/hosted-module.nix {
|
|
inherit self agenix;
|
|
})
|
|
];
|
|
};
|
|
};
|
|
|
|
nixosConfigurations.pi = nixpkgs.lib.nixosSystem {
|
|
system = "aarch64-linux";
|
|
modules = [
|
|
agenix.nixosModules.default
|
|
nixos-hardware.nixosModules.raspberry-pi-3
|
|
(import ./pi/module.nix {
|
|
pkg = noisebell-pi;
|
|
rev = self.shortRev or "dirty";
|
|
})
|
|
./pi/configuration.nix
|
|
./pi/hardware-configuration.nix
|
|
];
|
|
};
|
|
|
|
nixosConfigurations.bootstrap = nixos-raspberrypi.lib.nixosSystem {
|
|
specialArgs = {
|
|
inherit nixos-raspberrypi;
|
|
};
|
|
modules = [
|
|
nixos-raspberrypi.nixosModules.sd-image
|
|
bootstrapModule
|
|
];
|
|
};
|
|
|
|
devShells.${system}.default = craneLib.devShell {
|
|
packages = [
|
|
flash-bootstrap-sd
|
|
pi-serial
|
|
pkgs.nix
|
|
pkgs.parted
|
|
pkgs.rust-analyzer
|
|
pkgs.tio
|
|
pkgs.zstd
|
|
];
|
|
};
|
|
|
|
apps.${system} = {
|
|
flash-bootstrap-sd = {
|
|
type = "app";
|
|
program = "${flash-bootstrap-sd}/bin/flash-bootstrap-sd";
|
|
};
|
|
|
|
pi-serial = {
|
|
type = "app";
|
|
program = "${pi-serial}/bin/pi-serial";
|
|
};
|
|
};
|
|
};
|
|
}
|